From 5f56314618d4733c83bb80c65f9181e952f051ed Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 20 Apr 2021 11:52:47 +0530 Subject: [PATCH] lib: utils/irqchip: Allow multiple FDT irqchip drivers We can have multiple FDT irqchip drivers to be probed when a RISC-V system has different types of interrupt controller in a hierarchy. This will be certainly the case when a RISC-V system has both RISC-V AIA IMSIC and RISC-V AIA APLIC implemented. We extend simple FDT irqchip framework to allow multiple FDT irqchip drivers to be used for same RISC-V platform. Signed-off-by: Anup Patel Signed-off-by: Anup Patel Reviewed-by: Atish Patra --- lib/utils/irqchip/fdt_irqchip.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c index 8dda661..bf6969a 100644 --- a/lib/utils/irqchip/fdt_irqchip.c +++ b/lib/utils/irqchip/fdt_irqchip.c @@ -18,23 +18,40 @@ static struct fdt_irqchip *irqchip_drivers[] = { &fdt_irqchip_plic }; -static struct fdt_irqchip *current_driver = NULL; +#define FDT_IRQCHIP_MAX_DRIVERS 8 + +static struct fdt_irqchip *current_drivers[FDT_IRQCHIP_MAX_DRIVERS] = {0}; +static int current_drivers_count; void fdt_irqchip_exit(void) { - if (current_driver && current_driver->exit) - current_driver->exit(); + int i; + + for (i = 0; i < current_drivers_count; i++) { + if (!current_drivers[i] || !current_drivers[i]->exit) + continue; + current_drivers[i]->exit(); + } } static int fdt_irqchip_warm_init(void) { - if (current_driver && current_driver->warm_init) - return current_driver->warm_init(); + int i, rc; + + for (i = 0; i < current_drivers_count; i++) { + if (!current_drivers[i] || !current_drivers[i]->warm_init) + continue; + rc = current_drivers[i]->warm_init(); + if (rc) + return rc; + } + return 0; } static int fdt_irqchip_cold_init(void) { + bool drv_added; int pos, noff, rc; struct fdt_irqchip *drv; const struct fdt_match *match; @@ -44,6 +61,7 @@ static int fdt_irqchip_cold_init(void) drv = irqchip_drivers[pos]; noff = -1; + drv_added = false; while ((noff = fdt_find_match(fdt, noff, drv->match_table, &match)) >= 0) { if (drv->cold_init) { @@ -53,10 +71,15 @@ static int fdt_irqchip_cold_init(void) if (rc) return rc; } - current_driver = drv; + + if (drv_added) + continue; + + current_drivers[current_drivers_count++] = drv; + drv_added = true; } - if (current_driver) + if (FDT_IRQCHIP_MAX_DRIVERS <= current_drivers_count) break; } -- 2.7.4