qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Yubin Zou <yubinz@google.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Tyrone Ting <kfting@nuvoton.com>,  Hao Wu <wuhaotsh@google.com>,
	qemu-arm@nongnu.org,  Peter Maydell <peter.maydell@linaro.org>,
	Yubin Zou <yubinz@google.com>,
	 Titus Rwantare <titusr@google.com>
Subject: [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port
Date: Tue, 09 Sep 2025 22:10:59 +0000	[thread overview]
Message-ID: <20250909-pcie-root-upstream-v1-4-d85883b2688d@google.com> (raw)
In-Reply-To: <20250909-pcie-root-upstream-v1-0-d85883b2688d@google.com>

From: Titus Rwantare <titusr@google.com>

Signed-off-by: Titus Rwantare <titusr@google.com>
---
 hw/arm/npcm8xx.c                  |   3 +-
 hw/pci-host/npcm_pcierc.c         | 137 ++++++++++++++++++++++++++++++++++++++
 include/hw/pci-host/npcm_pcierc.h |  22 +++++-
 3 files changed, 160 insertions(+), 2 deletions(-)

diff --git a/hw/arm/npcm8xx.c b/hw/arm/npcm8xx.c
index 9b3e648e3fc3ca4352d5c8d310a19ea462e62cc7..f7a5ae2d121ffec99c519b484503e71dc8a43695 100644
--- a/hw/arm/npcm8xx.c
+++ b/hw/arm/npcm8xx.c
@@ -51,6 +51,7 @@
 #define NPCM8XX_MC_BA           0xf0824000
 #define NPCM8XX_RNG_BA          0xf000b000
 #define NPCM8XX_PCIERC_BA       0xe1000000
+#define NPCM8XX_PCIE_ROOT_BA    0xe8000000
 
 /* ADC Module */
 #define NPCM8XX_ADC_BA          0xf000c000
@@ -772,13 +773,13 @@ static void npcm8xx_realize(DeviceState *dev, Error **errp)
     /* PCIe RC */
     sysbus_realize(SYS_BUS_DEVICE(&s->pcierc), &error_abort);
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 0, NPCM8XX_PCIERC_BA);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 1, NPCM8XX_PCIE_ROOT_BA);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcierc), 0,
                        npcm8xx_irq(s, NPCM8XX_PCIE_RC_IRQ));
 
     create_unimplemented_device("npcm8xx.shm",          0xc0001000,   4 * KiB);
     create_unimplemented_device("npcm8xx.gicextra",     0xdfffa000,  24 * KiB);
     create_unimplemented_device("npcm8xx.vdmx",         0xe0800000,   4 * KiB);
-    create_unimplemented_device("npcm8xx.rootc",        0xe8000000, 128 * MiB);
     create_unimplemented_device("npcm8xx.kcs",          0xf0007000,   4 * KiB);
     create_unimplemented_device("npcm8xx.gfxi",         0xf000e000,   4 * KiB);
     create_unimplemented_device("npcm8xx.fsw",          0xf000f000,   4 * KiB);
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
index bffdec71acaba6562856b3bdd8aec07c3c153323..a1767335fe79a30464acf32ae94fc14e417c89eb 100644
--- a/hw/pci-host/npcm_pcierc.c
+++ b/hw/pci-host/npcm_pcierc.c
@@ -203,6 +203,7 @@ static void npcm_pcierc_write_window(NPCMPCIERCState *s, hwaddr addr,
     npcm_pcie_update_window_maps(s);
 }
 
+/* read root complex configuration registers */
 static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr, unsigned size)
 {
     NPCMPCIERCState *s = NPCM_PCIERC(opaque);
@@ -248,6 +249,7 @@ static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr, unsigned size)
     return ret;
 }
 
+/* write root complex configuration registers */
 static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
                                   unsigned size)
 {
@@ -291,6 +293,53 @@ static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
     }
 }
 
+/* read PCIe configuration space */
+static uint64_t npcm_pcie_host_config_read(void *opaque, hwaddr addr,
+                                           unsigned size)
+{
+    NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+    PCIHostState *pcih = PCI_HOST_BRIDGE(opaque);
+    int bus = NPCM_PCIE_RCCFGNUM_BUS(s->rccfgnum);
+    uint8_t devfn = NPCM_PCIE_RCCFGNUM_DEVFN(s->rccfgnum);
+    PCIDevice *pcid = pci_find_device(pcih->bus, bus, devfn);
+
+    if (pcid) {
+        return pci_host_config_read_common(pcid, addr,
+                                           pci_config_size(pcid),
+                                           size);
+    }
+    return 0;
+}
+
+/* write PCIe configuration space */
+static void npcm_pcie_host_config_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+    PCIHostState *pcih = PCI_HOST_BRIDGE(opaque);
+    int bus = NPCM_PCIE_RCCFGNUM_BUS(s->rccfgnum);
+    uint8_t devfn = NPCM_PCIE_RCCFGNUM_DEVFN(s->rccfgnum);
+    PCIDevice *pcid = pci_find_device(pcih->bus, bus, devfn);
+
+    if (pcid) {
+        pci_host_config_write_common(pcid, addr,
+                                     pci_config_size(pcid),
+                                     data,
+                                     size);
+    }
+}
+
+static AddressSpace *npcm_pcierc_set_iommu(PCIBus *bus, void *opaque, int devfn)
+{
+    NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+
+    return &s->pcie_space;
+}
+
+static const PCIIOMMUOps npcm_pcierc_iommu_ops = {
+    .get_address_space = npcm_pcierc_set_iommu,
+};
+
 static void npcm_pcierc_reset_pcie_windows(NPCMPCIERCState *s)
 {
     memset(s->axi2pcie, 0, sizeof(s->axi2pcie));
@@ -338,15 +387,73 @@ static const MemoryRegionOps npcm_pcierc_cfg_ops = {
     },
 };
 
+static const MemoryRegionOps npcm_pcie_cfg_space_ops = {
+    .read       = npcm_pcie_host_config_read,
+    .write      = npcm_pcie_host_config_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    }
+};
+
+static void npcm_pcie_set_irq(void *opaque, int irq_num, int level)
+{
+    NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+
+    qemu_set_irq(s->irq, level);
+}
+
 static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
 {
     NPCMPCIERCState *s = NPCM_PCIERC(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+    PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_NPCM_PCIE_ROOT_PORT);
 
     memory_region_init_io(&s->mmio, OBJECT(s), &npcm_pcierc_cfg_ops,
                           s, TYPE_NPCM_PCIERC, 4 * KiB);
     sysbus_init_mmio(sbd, &s->mmio);
     sysbus_init_irq(sbd, &s->irq);
+
+    /* IO memory region is needed to create a PCI bus, but is unused on ARM */
+    memory_region_init(&s->pcie_io, OBJECT(s), "npcm-pcie-io", 16);
+
+    /*
+     * pcie_root is a 128 MiB memory region in the BMC physical address space
+     * in which all PCIe windows must have their programmable source or
+     * destination address
+     */
+    memory_region_init_io(&s->pcie_root, OBJECT(s), &npcm_pcie_cfg_space_ops,
+                          s, "npcm-pcie-config", 128 * MiB);
+    sysbus_init_mmio(sbd, &s->pcie_root);
+
+    pci->bus = pci_register_root_bus(dev, "pcie",
+                                     npcm_pcie_set_irq,
+                                     pci_swizzle_map_irq_fn,
+                                     s, &s->pcie_root, &s->pcie_io,
+                                     0, 4, TYPE_PCIE_BUS);
+
+    address_space_init(&s->pcie_space, &s->pcie_root, "pcie-address-space");
+    pci_realize_and_unref(root, pci->bus, &error_fatal);
+    pci_setup_iommu(pci->bus, &npcm_pcierc_iommu_ops, s);
+}
+
+static void npcm_pcie_root_port_realize(DeviceState *dev, Error **errp)
+{
+    PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    rpc->parent_realize(dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
 }
 
 static void npcm_pcierc_instance_init(Object *obj)
@@ -369,6 +476,28 @@ static void npcm_pcierc_class_init(ObjectClass *klass, const void *data)
     dc->fw_name = "pci";
 }
 
+static void npcm_pcie_rp_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *pk = PCI_DEVICE_CLASS(klass);
+    PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
+
+    dc->desc = "Nuvoton PCIe Root Port";
+    dc->user_creatable = false;
+
+    device_class_set_parent_realize(dc,
+                                    npcm_pcie_root_port_realize,
+                                    &rpc->parent_realize);
+
+    /* TODO(b/229132071) replace with real values */
+    pk->vendor_id = PCI_VENDOR_ID_QEMU;
+    pk->device_id = 0;
+    pk->class_id = PCI_CLASS_BRIDGE_PCI;
+
+    rpc->exp_offset = NPCM_PCIE_HEADER_OFFSET; /* Express capabilities offset */
+    rpc->aer_offset = NPCM_PCIE_AER_OFFSET;
+}
+
 static const TypeInfo npcm_pcierc_type_info = {
     .name = TYPE_NPCM_PCIERC,
     .parent = TYPE_PCIE_HOST_BRIDGE,
@@ -377,9 +506,17 @@ static const TypeInfo npcm_pcierc_type_info = {
     .class_init = npcm_pcierc_class_init,
 };
 
+static const TypeInfo npcm_pcie_port_type_info = {
+    .name = TYPE_NPCM_PCIE_ROOT_PORT,
+    .parent = TYPE_PCIE_ROOT_PORT,
+    .instance_size = sizeof(NPCMPCIERootPort),
+    .class_init = npcm_pcie_rp_class_init,
+};
+
 static void npcm_pcierc_register_types(void)
 {
     type_register_static(&npcm_pcierc_type_info);
+    type_register_static(&npcm_pcie_port_type_info);
 }
 
 type_init(npcm_pcierc_register_types)
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
index 410b34d1c1ced0e25f63fc7693d87bb625a80776..a47eae0084b88ba4388681b24ab97f77a4338594 100644
--- a/include/hw/pci-host/npcm_pcierc.h
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -23,11 +23,14 @@
 #include "hw/sysbus.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
 #include "qom/object.h"
 
 /* PCIe Root Complex Registers */
-#define LINKSTAT                        0x92
+#define NPCM_PCIE_LINK_CTRL             0x90
 #define NPCM_PCIERC_RCCFGNUM            0x140 /* Configuration Number */
+#define     NPCM_PCIE_RCCFGNUM_BUS(a)   (((a) >> 8) & 0xFF)
+#define     NPCM_PCIE_RCCFGNUM_DEVFN(a) ((a) & 0xFF)
 #define NPCM_PCIERC_INTEN               0x180 /* Interrupt Enable */
 #define NPCM_PCIERC_INTST               0x184 /* Interrupt Status */
 #define NPCM_PCIERC_IMSI_ADDR           0x190
@@ -84,6 +87,10 @@
 #define NPCM_PCIERC_NUM_PA_WINDOWS          2
 #define NPCM_PCIERC_NUM_AP_WINDOWS          5
 
+/* PCIe extended config space offsets */
+#define NPCM_PCIE_HEADER_OFFSET             0x80
+#define NPCM_PCIE_AER_OFFSET                0x100
+
 #define TYPE_NPCM_PCIERC "npcm-pcie-root-complex"
 OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERCState, NPCM_PCIERC)
 
@@ -105,6 +112,13 @@ typedef struct NPCMPCIEWindow {
     uint8_t id;
 } NPCMPCIEWindow;
 
+#define TYPE_NPCM_PCIE_ROOT_PORT "npcm-pcie-root-port"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERootPort, NPCM_PCIE_ROOT_PORT)
+
+struct NPCMPCIERootPort {
+    PCIESlot parent;
+};
+
 struct NPCMPCIERCState {
     PCIExpressHost parent;
 
@@ -118,6 +132,12 @@ struct NPCMPCIERCState {
     uint32_t rcimsiaddr;
     uint32_t rcmsisstat;
     uint32_t axierr;
+
+    /* Address translation state */
+    AddressSpace pcie_space;
+    MemoryRegion pcie_root;
+    MemoryRegion pcie_io; /* unused - but required for IO space PCI */
+    NPCMPCIERootPort port;
     /* PCIe to AXI Windows */
     NPCMPCIEWindow pcie2axi[NPCM_PCIERC_NUM_PA_WINDOWS];
 

-- 
2.51.0.384.g4c02a37b29-goog



  parent reply	other threads:[~2025-09-09 22:14 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
2025-09-09 22:10 ` [PATCH 1/7] hw/pci-host: implement Nuvoton PCIE Root Complex stub Yubin Zou
2025-09-30  1:33   ` KFTING
2025-09-09 22:10 ` [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support Yubin Zou
2025-09-25 16:38   ` Peter Maydell
2025-09-25 19:39     ` Titus Rwantare
2025-09-26  9:07       ` Peter Maydell
2025-09-30  1:34         ` KFTING
2025-09-09 22:10 ` [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx Yubin Zou
2025-09-30  1:35   ` KFTING
2025-09-09 22:10 ` Yubin Zou [this message]
2025-09-25 16:42   ` [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port Peter Maydell
2025-09-30  1:34     ` KFTING
2025-09-09 22:11 ` [PATCH 5/7] hw/pci-host: enable MSI on npcm PCIe root complex Yubin Zou
2025-09-30  1:36   ` KFTING
2025-09-09 22:11 ` [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions Yubin Zou
2025-09-25 16:40   ` Peter Maydell
2025-09-30  1:34     ` KFTING
2025-09-09 22:11 ` [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC Yubin Zou
2025-09-30  1:36   ` KFTING
2025-09-25 16:43 ` [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Peter Maydell
2025-09-30  1:32 ` KFTING

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250909-pcie-root-upstream-v1-4-d85883b2688d@google.com \
    --to=yubinz@google.com \
    --cc=kfting@nuvoton.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=titusr@google.com \
    --cc=wuhaotsh@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).