diff options
author | Anup Patel <anup.patel@wdc.com> | 2020-05-12 12:29:59 +0300 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2020-05-23 08:06:39 +0300 |
commit | d30bb684481b6be642a0eaa9e7f0778d6519cc15 (patch) | |
tree | 67178e797243d465a3e1e318dcaeaf09f7fb7947 /lib | |
parent | 2c685c214f2815c12f9d70422d85daa7f48003cf (diff) | |
download | opensbi-d30bb684481b6be642a0eaa9e7f0778d6519cc15.tar.xz |
lib: utils/irqchip: Initialize all matching irqchip DT nodes
We can have multiple matching DT nodes of the same FDT irqchip
driver so in this case we should call cold_init() for all matching
DT nodes instead of just first matching DT node.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/utils/irqchip/fdt_irqchip.c | 22 | ||||
-rw-r--r-- | lib/utils/irqchip/fdt_irqchip_plic.c | 40 |
2 files changed, 40 insertions, 22 deletions
diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c index 87def52..3630be6 100644 --- a/lib/utils/irqchip/fdt_irqchip.c +++ b/lib/utils/irqchip/fdt_irqchip.c @@ -42,17 +42,19 @@ static int fdt_irqchip_cold_init(void) for (pos = 0; pos < array_size(irqchip_drivers); pos++) { drv = irqchip_drivers[pos]; - noff = fdt_find_match(fdt, -1, drv->match_table, &match); - if (noff < 0) - continue; - - if (drv->cold_init) { - rc = drv->cold_init(fdt, noff, match); - if (rc) - return rc; + noff = -1; + while ((noff = fdt_find_match(fdt, noff, + drv->match_table, &match)) >= 0) { + if (drv->cold_init) { + rc = drv->cold_init(fdt, noff, match); + if (rc) + return rc; + } + current_driver = drv; } - current_driver = drv; - break; + + if (current_driver) + break; } return 0; diff --git a/lib/utils/irqchip/fdt_irqchip_plic.c b/lib/utils/irqchip/fdt_irqchip_plic.c index e0ad3e2..18d2797 100644 --- a/lib/utils/irqchip/fdt_irqchip_plic.c +++ b/lib/utils/irqchip/fdt_irqchip_plic.c @@ -15,28 +15,30 @@ #include <sbi_utils/irqchip/fdt_irqchip.h> #include <sbi_utils/irqchip/plic.h> -static struct plic_data plic; +#define PLIC_MAX_NR 16 + +static unsigned long plic_count = 0; +static struct plic_data plic[PLIC_MAX_NR]; + +static struct plic_data *plic_hartid2data[SBI_HARTMASK_MAX_BITS]; static int plic_hartid2context[SBI_HARTMASK_MAX_BITS][2]; static int irqchip_plic_warm_init(void) { u32 hartid = current_hartid(); - return plic_warm_irqchip_init(&plic, plic_hartid2context[hartid][0], + return plic_warm_irqchip_init(plic_hartid2data[hartid], + plic_hartid2context[hartid][0], plic_hartid2context[hartid][1]); } -static int irqchip_plic_parse_hartid2context(void *fdt, int nodeoff) +static int irqchip_plic_update_hartid_table(void *fdt, int nodeoff, + struct plic_data *pd) { const fdt32_t *val; u32 phandle, hwirq, hartid; int i, err, count, cpu_offset, cpu_intc_offset; - for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) { - plic_hartid2context[i][0] = -1; - plic_hartid2context[i][1] = -1; - } - val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count); if (!val || count < sizeof(fdt32_t)) return SBI_EINVAL; @@ -61,6 +63,7 @@ static int irqchip_plic_parse_hartid2context(void *fdt, int nodeoff) if (SBI_HARTMASK_MAX_BITS <= hartid) continue; + plic_hartid2data[hartid] = pd; switch (hwirq) { case IRQ_M_EXT: plic_hartid2context[hartid][0] = i / 2; @@ -77,17 +80,30 @@ static int irqchip_plic_parse_hartid2context(void *fdt, int nodeoff) static int irqchip_plic_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { - int rc; + int i, rc; + struct plic_data *pd; - rc = fdt_parse_plic_node(fdt, nodeoff, &plic); + if (PLIC_MAX_NR <= plic_count) + return SBI_ENOSPC; + pd = &plic[plic_count++]; + + rc = fdt_parse_plic_node(fdt, nodeoff, pd); if (rc) return rc; - rc = plic_cold_irqchip_init(&plic); + rc = plic_cold_irqchip_init(pd); if (rc) return rc; - return irqchip_plic_parse_hartid2context(fdt, nodeoff); + if (plic_count == 1) { + for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) { + plic_hartid2data[i] = NULL; + plic_hartid2context[i][0] = -1; + plic_hartid2context[i][1] = -1; + } + } + + return irqchip_plic_update_hartid_table(fdt, nodeoff, pd); } static const struct fdt_match irqchip_plic_match[] = { |