lib: utils/irqchip: Initialize all matching irqchip DT nodes
authorAnup Patel <anup.patel@wdc.com>
Tue, 12 May 2020 09:29:59 +0000 (14:59 +0530)
committerAnup Patel <anup@brainfault.org>
Sat, 23 May 2020 05:06:39 +0000 (10:36 +0530)
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>
lib/utils/irqchip/fdt_irqchip.c
lib/utils/irqchip/fdt_irqchip_plic.c

index 87def52..3630be6 100644 (file)
@@ -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;
index e0ad3e2..18d2797 100644 (file)
 #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[] = {