[PATCH 07/10] lib: utils: irqchip: derive APLIC targets from sysirq nodes
Raymond Mao <[email protected]>
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
From: Raymond Mao <[email protected]> Derive a per-HWIRQ target hartindex map from each sysirq node's target domain boot-hart, and store the result in aplic_data. This is used for setting IDC target per HWIRQ under irqchip driver instead of hardcoding to a specific target. Signed-off-by: Raymond Mao <[email protected]> --- include/sbi_utils/irqchip/aplic.h | 1 + lib/utils/irqchip/fdt_irqchip_aplic.c | 103 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h index 3461d1c7..d6e088f8 100644 --- a/include/sbi_utils/irqchip/aplic.h +++ b/include/sbi_utils/irqchip/aplic.h @@ -47,6 +47,7 @@ struct aplic_data { struct aplic_msicfg_data msicfg_smode; struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE]; u32 *idc_map; + u32 *hwirq_target_hartindex; }; int aplic_cold_irqchip_init(struct aplic_data *aplic); diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c index f9b567f5..cbbdf8d8 100644 --- a/lib/utils/irqchip/fdt_irqchip_aplic.c +++ b/lib/utils/irqchip/fdt_irqchip_aplic.c @@ -13,6 +13,7 @@ #include <sbi/sbi_console.h> #include <sbi/sbi_error.h> #include <sbi/sbi_heap.h> +#include <sbi/sbi_scratch.h> #include <sbi_utils/fdt/fdt_helper.h> #include <sbi_utils/irqchip/fdt_irqchip.h> #include <sbi_utils/irqchip/aplic.h> @@ -54,6 +55,88 @@ static int irqchip_aplic_update_idc_map(const void *fdt, int nodeoff, return 0; } +static u32 irqchip_aplic_domain_boot_hartindex(void *fdt, int domain_offset) +{ + int len, cpu_offset; + const fdt32_t *val; + + val = fdt_getprop(fdt, domain_offset, "boot-hart", &len); + if (val && len >= 4) { + cpu_offset = fdt_node_offset_by_phandle(fdt, + fdt32_to_cpu(*val)); + if (cpu_offset >= 0) { + u32 hartid; + + if (!fdt_parse_hart_id(fdt, cpu_offset, &hartid)) { + u32 hidx = sbi_hartid_to_hartindex(hartid); + + if (sbi_hartindex_valid(hidx)) + return hidx; + } + } + } + + return current_hartindex(); +} + +static void irqchip_aplic_fill_hwirq_targets_from_sysirq(const void *fdt, + int aplic_nodeoff, + struct aplic_data *pd) +{ + int chosen_off, nodeoff; + int len, rc, index; + const fdt32_t *val; + u32 boot_hartindex; + + if (!fdt || aplic_nodeoff < 0 || !pd || !pd->hwirq_target_hartindex) + return; + + chosen_off = fdt_path_offset(fdt, "/chosen/opensbi-domains"); + if (chosen_off < 0) + return; + + fdt_for_each_subnode(nodeoff, fdt, chosen_off) { + if (fdt_node_check_compatible(fdt, nodeoff, + "opensbi,mpxy-sysirq")) + continue; + + val = fdt_getprop(fdt, nodeoff, "opensbi,domain", &len); + if (!val || len < 4) + continue; + + rc = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val)); + if (rc < 0) + continue; + + boot_hartindex = irqchip_aplic_domain_boot_hartindex((void *)fdt, + rc); + + for (index = 0; ; index++) { + struct fdt_phandle_args args; + + rc = fdt_parse_phandle_with_args(fdt, nodeoff, + "interrupts-extended", + "#interrupt-cells", + index, &args); + if (rc) + break; + if (args.args_count < 1) + continue; + if (args.node_offset != aplic_nodeoff) + continue; + + u32 hwirq = args.args[0]; + + if (!hwirq || hwirq > pd->num_source) + continue; + + if (pd->hwirq_target_hartindex[hwirq] == -1U) + pd->hwirq_target_hartindex[hwirq] = + boot_hartindex; + } + } +} + static int irqchip_aplic_cold_init(const void *fdt, int nodeoff, const struct fdt_match *match) { @@ -85,6 +168,24 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff, goto fail_free_idc_map; } + /* Precompute target hartindex per HWIRQ from DT. */ + if (pd->targets_mmode) { + u32 i; + + pd->hwirq_target_hartindex = + sbi_zalloc(sizeof(*pd->hwirq_target_hartindex) * + (pd->num_source + 1)); + if (!pd->hwirq_target_hartindex) { + rc = SBI_ENOMEM; + goto fail_free_idc_map; + } + + for (i = 0; i <= pd->num_source; i++) + pd->hwirq_target_hartindex[i] = -1U; + + irqchip_aplic_fill_hwirq_targets_from_sysirq(fdt, nodeoff, pd); + } + rc = aplic_cold_irqchip_init(pd); if (rc) goto fail_free_idc_map; @@ -93,6 +194,8 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff, return 0; fail_free_idc_map: + if (pd->hwirq_target_hartindex) + sbi_free(pd->hwirq_target_hartindex); if (pd->num_idc) sbi_free(pd->idc_map); fail_free_data: -- 2.25.1 -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi