Wire all 160 SoC SPI interrupt lines through SplitIRQ splitters so
that each interrupt is delivered to both the Cortex-A53 GICv3 and the
Cortex-M7 NVIC simultaneously. As per i.MX8MP RM Table 7-2 the
same interrupt lines are routed to both cores.

Signed-off-by: Gaurav Sharma <[email protected]>
---
 hw/arm/fsl-imx8mp.c         | 59 +++++++++++++++++++++++++------------
 include/hw/arm/fsl-imx8mp.h |  2 ++
 2 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index e7dafa2403..17733c7270 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -200,6 +200,12 @@ static void fsl_imx8mp_init(Object *obj)
     FslImx8mpState *s = FSL_IMX8MP(obj);
     int i;
 
+    for (i = 0; i < FSL_IMX8MP_NUM_IRQS; i++) {
+        g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
+        object_initialize_child(obj, name, &s->cpu_irq_splitter[i],
+                                TYPE_SPLIT_IRQ);
+    }
+
     object_initialize_child(obj, "cm7", &s->cm7, TYPE_ARMV7M);
 
     object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
@@ -286,6 +292,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
     FslImx8mpState *s = FSL_IMX8MP(dev);
     DeviceState *gicdev = DEVICE(&s->gic);
     const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
+    qemu_irq spi_irq[FSL_IMX8MP_NUM_IRQS];
     int i;
 
     for (i = 0; i < FSL_IMX8MP_NUM_A53; i++) {
@@ -407,6 +414,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
         }
     }
 
+    for (i = 0; i < FSL_IMX8MP_NUM_IRQS; i++) {
+        DeviceState *splitter = DEVICE(&s->cpu_irq_splitter[i]);
+        qdev_prop_set_uint16(splitter, "num-lines", 2);
+        qdev_realize(splitter, NULL, &error_abort);
+        spi_irq[i] = qdev_get_gpio_in(splitter, 0);
+        qdev_connect_gpio_out(splitter, 0,
+                              qdev_get_gpio_in(gicdev, i));
+    }
+
     /* CCM */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
         return;
@@ -440,7 +456,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
-                           qdev_get_gpio_in(gicdev, serial_table[i].irq));
+                           spi_irq[serial_table[i].irq]);
     }
 
     /* GPC */
@@ -482,6 +498,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
         }
 
         arm_set_cpu_off(arm_cpu_mp_affinity(s->cm7.cpu));
+
+        for (i = 0; i < FSL_IMX8MP_NUM_IRQS; i++) {
+            qdev_connect_gpio_out(DEVICE(&s->cpu_irq_splitter[i]), 1,
+                                  qdev_get_gpio_in(DEVICE(&s->cm7), i));
+        }
     }
 
     qdev_prop_set_uint32(DEVICE(&s->src), "cm7-vector-base",
@@ -508,7 +529,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
     }
 
     qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
-                          qdev_get_gpio_in(gicdev, FSL_IMX8MP_GPT5_GPT6_IRQ));
+                          spi_irq[FSL_IMX8MP_GPT5_GPT6_IRQ]);
 
     for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
         hwaddr gpt_addrs[FSL_IMX8MP_NUM_GPTS] = {
@@ -537,7 +558,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
             };
 
             sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
-                               qdev_get_gpio_in(gicdev, gpt_irqs[i]));
+                               spi_irq[gpt_irqs[i]]);
         } else {
             int irq = i - FSL_IMX8MP_NUM_GPTS + 2;
 
@@ -572,7 +593,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
     }
 
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->mu[0].a), 0,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_MU1_A_IRQ));
+                       spi_irq[FSL_IMX8MP_MU1_A_IRQ]);
 
     /* I2Cs */
     for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
@@ -594,7 +615,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
-                           qdev_get_gpio_in(gicdev, i2c_table[i].irq));
+                           spi_irq[i2c_table[i].irq]);
     }
 
     /* GPIOs */
@@ -641,9 +662,9 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
-                           qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
+                           spi_irq[gpio_table[i].irq_low]);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
-                           qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
+                           spi_irq[gpio_table[i].irq_high]);
     }
 
     /* USDHCs */
@@ -663,7 +684,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
-                           qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
+                           spi_irq[usdhc_table[i].irq]);
     }
 
     /* USBs */
@@ -684,7 +705,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
         }
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
-                           qdev_get_gpio_in(gicdev, usb_table[i].irq));
+                           spi_irq[usb_table[i].irq]);
     }
 
     /* ECSPIs */
@@ -704,7 +725,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
-                           qdev_get_gpio_in(gicdev, spi_table[i].irq));
+                           spi_irq[spi_table[i].irq]);
     }
 
     /* ENET1 */
@@ -718,9 +739,9 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
                     fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
+                       spi_irq[FSL_IMX8MP_ENET1_MAC_IRQ]);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
-                       qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
+                       spi_irq[FSL_IMX6_ENET1_MAC_1588_IRQ]);
 
     /* SNVS */
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
@@ -748,7 +769,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
-                           qdev_get_gpio_in(gicdev, wdog_table[i].irq));
+                           spi_irq[wdog_table[i].irq]);
     }
 
     /* PCIe */
@@ -759,15 +780,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
                     fsl_imx8mp_memmap[FSL_IMX8MP_PCIE1].addr);
 
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTA_IRQ));
+                       spi_irq[FSL_IMX8MP_PCI_INTA_IRQ]);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTB_IRQ));
+                       spi_irq[FSL_IMX8MP_PCI_INTB_IRQ]);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTC_IRQ));
+                       spi_irq[FSL_IMX8MP_PCI_INTC_IRQ]);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTD_IRQ));
+                       spi_irq[FSL_IMX8MP_PCI_INTD_IRQ]);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4,
-                       qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_MSI_IRQ));
+                       spi_irq[FSL_IMX8MP_PCI_MSI_IRQ]);
 
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) {
         return;
@@ -800,7 +821,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error 
**errp)
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->flexcan[i]), 0,
                         flexcan_table[i].addr);
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->flexcan[i]), 0,
-                           qdev_get_gpio_in(gicdev, flexcan_table[i].irq));
+                           spi_irq[flexcan_table[i].irq]);
     }
 
     /* On-Chip RAM */
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index e8d84f82b5..1685938a0b 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -25,6 +25,7 @@
 #include "hw/net/flexcan.h"
 #include "hw/net/imx_fec.h"
 #include "hw/core/or-irq.h"
+#include "hw/core/split-irq.h"
 #include "hw/pci-host/designware.h"
 #include "hw/pci-host/fsl_imx8m_phy.h"
 #include "hw/sd/sdhci.h"
@@ -93,6 +94,7 @@ struct FslImx8mpState {
     FslImx8mPciePhyState   pcie_phy;
     FlexcanState       flexcan[FSL_IMX8MP_NUM_CANS];
     OrIRQState         gpt5_gpt6_irq;
+    SplitIRQ           cpu_irq_splitter[FSL_IMX8MP_NUM_IRQS];
     MemoryRegion       ocram;
     MemoryRegion       itcm;
     MemoryRegion       dtcm;
-- 
2.34.1


Reply via email to