aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Beschow <shentey@gmail.com>2025-01-11 19:37:02 +0100
committerPeter Maydell <peter.maydell@linaro.org>2025-01-27 13:50:14 +0000
commit1b326f278d05543425a71165a66b925922e532ac (patch)
treec84350f3f8e13ce6ea0f0575273f0700f0c8e540
parenta451cc11c47903242123def2717a86a56e5fb390 (diff)
downloadqemu-1b326f278d05543425a71165a66b925922e532ac.zip
qemu-1b326f278d05543425a71165a66b925922e532ac.tar.gz
qemu-1b326f278d05543425a71165a66b925922e532ac.tar.bz2
hw/pci-host/designware: Expose MSI IRQ
Fixes INTD and MSI interrupts poking the same IRQ line without keeping track of each other's IRQ level. Furthermore, SoCs such as the i.MX 8M Plus don't share the MSI IRQ with the INTx lines, so expose it as a dedicated pin. Signed-off-by: Bernhard Beschow <shentey@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/Kconfig2
-rw-r--r--hw/arm/fsl-imx6.c13
-rw-r--r--hw/arm/fsl-imx7.c13
-rw-r--r--hw/pci-host/designware.c7
-rw-r--r--include/hw/arm/fsl-imx6.h4
-rw-r--r--include/hw/arm/fsl-imx7.h4
-rw-r--r--include/hw/pci-host/designware.h1
7 files changed, 36 insertions, 8 deletions
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index e779b5a..256013c 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -516,6 +516,7 @@ config FSL_IMX6
select PL310 # cache controller
select PCI_EXPRESS_DESIGNWARE
select SDHCI
+ select OR_IRQ
config ASPEED_SOC
bool
@@ -573,6 +574,7 @@ config FSL_IMX7
select WDT_IMX2
select PCI_EXPRESS_DESIGNWARE
select SDHCI
+ select OR_IRQ
select UNIMP
config ARM_SMMUV3
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index ac8c66e..88b9ccf 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -106,6 +106,8 @@ static void fsl_imx6_init(Object *obj)
object_initialize_child(obj, "eth", &s->eth, TYPE_IMX_ENET);
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+ object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq,
+ TYPE_OR_IRQ);
}
static void fsl_imx6_realize(DeviceState *dev, Error **errp)
@@ -435,14 +437,23 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX6_PCIe_REG_ADDR);
+ object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2,
+ &error_abort);
+ qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort);
+
+ irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_MSI_IRQ);
+ qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq);
+
irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE1_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE2_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE3_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
- irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_IRQ);
+ irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
+ irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq);
/*
* PCIe PHY
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 05e3389..004bf49 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -150,6 +150,8 @@ static void fsl_imx7_init(Object *obj)
* PCIE
*/
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+ object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq,
+ TYPE_OR_IRQ);
/*
* USBs
@@ -597,14 +599,23 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
+ object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2,
+ &error_abort);
+ qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort);
+
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_MSI_IRQ);
+ qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq);
+
irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
- irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
+ irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
+ irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq);
/*
* USBs
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index c3fc37b..3e8c36e 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -55,8 +55,6 @@
#define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
#define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
-#define DESIGNWARE_PCIE_IRQ_MSI 3
-
static DesignwarePCIEHost *
designware_pcie_root_to_host(DesignwarePCIERoot *root)
{
@@ -90,7 +88,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
- qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1);
+ qemu_set_irq(host->pci.msi, 1);
}
}
@@ -335,7 +333,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
root->msi.intr[0].status ^= val;
if (!root->msi.intr[0].status) {
- qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0);
+ qemu_set_irq(host->pci.msi, 0);
}
break;
@@ -680,6 +678,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
sysbus_init_irq(sbd, &s->pci.irqs[i]);
}
+ sysbus_init_irq(sbd, &s->pci.msi);
memory_region_init_io(&s->mmio,
OBJECT(s),
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 61c593f..9da32fc 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -33,6 +33,7 @@
#include "hw/usb/chipidea.h"
#include "hw/usb/imx-usb-phy.h"
#include "hw/pci-host/designware.h"
+#include "hw/or-irq.h"
#include "exec/memory.h"
#include "cpu.h"
#include "qom/object.h"
@@ -73,6 +74,7 @@ struct FslIMX6State {
ChipideaState usb[FSL_IMX6_NUM_USBS];
IMXFECState eth;
DesignwarePCIEHost pcie;
+ OrIRQState pcie4_msi_irq;
MemoryRegion rom;
MemoryRegion caam;
MemoryRegion ocram;
@@ -457,7 +459,7 @@ struct FslIMX6State {
#define FSL_IMX6_PCIE1_IRQ 120
#define FSL_IMX6_PCIE2_IRQ 121
#define FSL_IMX6_PCIE3_IRQ 122
-#define FSL_IMX6_PCIE4_IRQ 123
+#define FSL_IMX6_PCIE4_MSI_IRQ 123
#define FSL_IMX6_DCIC1_IRQ 124
#define FSL_IMX6_DCIC2_IRQ 125
#define FSL_IMX6_MLB150_HIGH_IRQ 126
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 411fa1c..aa7818c 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -36,6 +36,7 @@
#include "hw/net/imx_fec.h"
#include "hw/pci-host/designware.h"
#include "hw/usb/chipidea.h"
+#include "hw/or-irq.h"
#include "cpu.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -85,6 +86,7 @@ struct FslIMX7State {
IMX7GPRState gpr;
ChipideaState usb[FSL_IMX7_NUM_USBS];
DesignwarePCIEHost pcie;
+ OrIRQState pcie4_msi_irq;
MemoryRegion rom;
MemoryRegion caam;
MemoryRegion ocram;
@@ -428,7 +430,7 @@ enum FslIMX7IRQs {
FSL_IMX7_PCI_INTA_IRQ = 125,
FSL_IMX7_PCI_INTB_IRQ = 124,
FSL_IMX7_PCI_INTC_IRQ = 123,
- FSL_IMX7_PCI_INTD_IRQ = 122,
+ FSL_IMX7_PCI_INTD_MSI_IRQ = 122,
FSL_IMX7_UART7_IRQ = 126,
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index c484e37..bf8b278 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -86,6 +86,7 @@ struct DesignwarePCIEHost {
MemoryRegion io;
qemu_irq irqs[4];
+ qemu_irq msi;
} pci;
MemoryRegion mmio;