* [PATCH 1/7] hw/pci-host: implement Nuvoton PCIE Root Complex stub
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
@ 2025-09-09 22:10 ` 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
` (7 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:10 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
From: Titus Rwantare <titusr@google.com>
create a basic device to introduce the root complex registers and
respond to its mmio configuration accesses
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/pci-host/Kconfig | 4 +
hw/pci-host/meson.build | 1 +
hw/pci-host/npcm_pcierc.c | 164 ++++++++++++++++++++++++++++++++++++++
hw/pci-host/trace-events | 4 +
include/hw/pci-host/npcm_pcierc.h | 55 +++++++++++++
5 files changed, 228 insertions(+)
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
index 9824fa188d6b8865dcf7b069f2c16f269b211aa0..1d726b6e05c732b69e22aa2883892aaeaed129fa 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -108,3 +108,7 @@ config GT64120
select PCI
select EMPTY_SLOT
select I8259
+
+config NPCM_PCIERC
+ bool
+ select PCI_EXPRESS
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
index 937a0f72acf940f963fc683ab52a5f8b80657ca3..2c0a49cbc5102110f7d92e279df1ad4654570332 100644
--- a/hw/pci-host/meson.build
+++ b/hw/pci-host/meson.build
@@ -30,6 +30,7 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
# ARM devices
pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
+pci_ss.add(when: 'CONFIG_NPCM_PCIERC', if_true: files('npcm_pcierc.c'))
# HPPA devices
specific_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c'))
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
new file mode 100644
index 0000000000000000000000000000000000000000..3afe92e264f6ce4312e94f05b5e908840008df64
--- /dev/null
+++ b/hw/pci-host/npcm_pcierc.c
@@ -0,0 +1,164 @@
+/*
+ * Nuvoton PCIe Root complex
+ *
+ * Copyright 2022 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/pci-host/npcm_pcierc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qom/object.h"
+#include "trace.h"
+
+static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr, unsigned size)
+{
+ NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+ uint32_t ret = -1;
+
+ switch (addr) {
+ case NPCM_PCIERC_RCCFGNUM:
+ ret = s->rccfgnum;
+ break;
+
+ case NPCM_PCIERC_INTEN:
+ ret = s->rcinten;
+ break;
+
+ case NPCM_PCIERC_INTST:
+ ret = s->rcintstat;
+ break;
+
+ case NPCM_PCIERC_IMSI_ADDR:
+ ret = s->rcimsiaddr;
+ break;
+
+ case NPCM_PCIERC_MSISTAT:
+ ret = s->rcmsisstat;
+ break;
+
+ case NPCM_PCIERC_AXI_ERROR_REPORT:
+ ret = s->axierr;
+ break;
+
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: read from unimplemented register 0x%04lx\n",
+ __func__, addr);
+ ret = -1;
+ break;
+ }
+ trace_npcm_pcierc_read(addr, size, ret);
+ return ret;
+}
+
+static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+
+ trace_npcm_pcierc_write(addr, size, data);
+ switch (addr) {
+ case NPCM_PCIERC_RCCFGNUM:
+ s->rccfgnum = data;
+ break;
+
+ case NPCM_PCIERC_INTEN:
+ s->rcinten = data;
+ break;
+
+ case NPCM_PCIERC_INTST:
+ s->rcintstat &= ~data;
+ break;
+
+ case NPCM_PCIERC_IMSI_ADDR:
+ s->rcimsiaddr = data;
+ break;
+
+ case NPCM_PCIERC_MSISTAT:
+ s->rcmsisstat &= ~data;
+ break;
+
+ case NPCM_PCIERC_AXI_ERROR_REPORT:
+ s->axierr = data;
+ break;
+
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: write to unimplemented reg 0x%04lx data: 0x%lx\n",
+ __func__, addr, data);
+ break;
+ }
+}
+
+static void npcm_pcierc_reset(Object *obj, ResetType type)
+{
+ NPCMPCIERCState *s = NPCM_PCIERC(obj);
+
+ s->rccfgnum = 0;
+ s->rcinten = 0;
+ s->rcintstat = 0;
+ s->rcimsiaddr = 0;
+ s->rcmsisstat = 0;
+ s->axierr = 0;
+}
+
+static const char *npcm_pcierc_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+ return "0000:00";
+}
+
+static const MemoryRegionOps npcm_pcierc_cfg_ops = {
+ .read = npcm_pcierc_cfg_read,
+ .write = npcm_pcierc_cfg_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
+{
+ NPCMPCIERCState *s = NPCM_PCIERC(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ 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);
+}
+
+static void npcm_pcierc_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIHostBridgeClass *hbc = PCI_HOST_BRIDGE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ hbc->root_bus_path = npcm_pcierc_root_bus_path;
+ dc->realize = npcm_pcierc_realize;
+ rc->phases.enter = npcm_pcierc_reset;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ dc->fw_name = "pci";
+}
+
+static const TypeInfo npcm_pcierc_type_info = {
+ .name = TYPE_NPCM_PCIERC,
+ .parent = TYPE_PCIE_HOST_BRIDGE,
+ .instance_size = sizeof(NPCMPCIERCState),
+ .class_init = npcm_pcierc_class_init,
+};
+
+static void npcm_pcierc_register_types(void)
+{
+ type_register_static(&npcm_pcierc_type_info);
+}
+
+type_init(npcm_pcierc_register_types)
diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events
index 0a816b9aa129bb0c37d207e2612e09ac4762d51a..e4794f687177ee90fe4d33194b484c83a34dcaf9 100644
--- a/hw/pci-host/trace-events
+++ b/hw/pci-host/trace-events
@@ -69,3 +69,7 @@ elroy_pci_config_data_read(uint64_t addr, int size, uint64_t val) "addr 0x%"PRIx
elroy_pci_config_data_write(uint64_t addr, int size, uint64_t val) "addr 0x%"PRIx64" size %d val 0x%"PRIx64
iosapic_reg_write(uint64_t reg_select, int size, uint64_t val) "reg_select 0x%"PRIx64" size %d val 0x%"PRIx64
iosapic_reg_read(uint64_t reg_select, int size, uint64_t val) "reg_select 0x%"PRIx64" size %d val 0x%"PRIx64
+
+# npmc_pcierc.c
+npcm_pcierc_read(uint64_t offset, uint32_t size, uint64_t data) "offset: 0x%" PRIx64 " size: %d data: 0x%" PRIx64
+npcm_pcierc_write(uint64_t offset, uint32_t size, uint64_t data) "offset: 0x%" PRIx64 " size: %d data: 0x%" PRIx64
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c817147d495fdc1d1fa4b389bad0469fd6a825e
--- /dev/null
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton PCIe Root complex
+ *
+ * Copyright 2022 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * The PCIERC configuration registers must be initialised by the BMC kernel
+ * during boot for PCIe to function
+ * - A single window from the PCIe to the Memory controller
+ * - 4 windows from the BMC to the PCIe.
+ * 1 of these five BMC-to-PCIe windows must be allocated for configuration
+ * transactions, the rest can be used for I/0 or memory transactions
+ * - All BMC-to-PCIe windows are mapped to address range
+ * 0xe800_0000 to 0xefff_ffff (128MB)
+ */
+
+#ifndef NPCM_PCIERC_H
+#define NPCM_PCIERC_H
+
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "qom/object.h"
+
+/* PCIe Root Complex Registers */
+#define LINKSTAT 0x92
+#define NPCM_PCIERC_RCCFGNUM 0x140 /* Configuration Number */
+#define NPCM_PCIERC_INTEN 0x180 /* Interrupt Enable */
+#define NPCM_PCIERC_INTST 0x184 /* Interrupt Status */
+#define NPCM_PCIERC_IMSI_ADDR 0x190
+#define NPCM_PCIERC_MSISTAT 0x194 /* MSI Status Register */
+#define NPCM_PCIERC_AXI_ERROR_REPORT 0x3E0
+
+#define TYPE_NPCM_PCIERC "npcm-pcie-root-complex"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERCState, NPCM_PCIERC)
+
+struct NPCMPCIERCState {
+ PCIExpressHost parent;
+
+ qemu_irq irq;
+
+ /* PCIe RC registers */
+ MemoryRegion mmio;
+ uint32_t rccfgnum;
+ uint32_t rcinten;
+ uint32_t rcintstat;
+ uint32_t rcimsiaddr;
+ uint32_t rcmsisstat;
+ uint32_t axierr;
+};
+
+#endif /* NPCM_PCIERC_H */
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 1/7] hw/pci-host: implement Nuvoton PCIE Root Complex stub
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
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:33 UTC (permalink / raw)
To: Yubin Zou, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org, Peter Maydell,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Yubin Zou <yubinz@google.com>
Sent: Wednesday, September 10, 2025 6:11 AM
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <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 1/7] hw/pci-host: implement Nuvoton PCIE Root Complex stub
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
From: Titus Rwantare <titusr@google.com>
create a basic device to introduce the root complex registers and
respond to its mmio configuration accesses
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/pci-host/Kconfig | 4 +
hw/pci-host/meson.build | 1 +
hw/pci-host/npcm_pcierc.c | 164 ++++++++++++++++++++++++++++++++++++++
hw/pci-host/trace-events | 4 +
include/hw/pci-host/npcm_pcierc.h | 55 +++++++++++++
5 files changed, 228 insertions(+)
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index 9824fa188d6b8865dcf7b069f2c16f269b211aa0..1d726b6e05c732b69e22aa2883892aaeaed129fa 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -108,3 +108,7 @@ config GT64120
select PCI
select EMPTY_SLOT
select I8259
+
+config NPCM_PCIERC
+ bool
+ select PCI_EXPRESS
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index 937a0f72acf940f963fc683ab52a5f8b80657ca3..2c0a49cbc5102110f7d92e279df1ad4654570332 100644
--- a/hw/pci-host/meson.build
+++ b/hw/pci-host/meson.build
@@ -30,6 +30,7 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c')) # ARM devices
pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
+pci_ss.add(when: 'CONFIG_NPCM_PCIERC', if_true: files('npcm_pcierc.c'))
# HPPA devices
specific_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c')) diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c new file mode 100644 index 0000000000000000000000000000000000000000..3afe92e264f6ce4312e94f05b5e908840008df64
--- /dev/null
+++ b/hw/pci-host/npcm_pcierc.c
@@ -0,0 +1,164 @@
+/*
+ * Nuvoton PCIe Root complex
+ *
+ * Copyright 2022 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/pci-host/npcm_pcierc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qom/object.h"
+#include "trace.h"
+
+static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr,
+unsigned size) {
+ NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+ uint32_t ret = -1;
+
+ switch (addr) {
+ case NPCM_PCIERC_RCCFGNUM:
+ ret = s->rccfgnum;
+ break;
+
+ case NPCM_PCIERC_INTEN:
+ ret = s->rcinten;
+ break;
+
+ case NPCM_PCIERC_INTST:
+ ret = s->rcintstat;
+ break;
+
+ case NPCM_PCIERC_IMSI_ADDR:
+ ret = s->rcimsiaddr;
+ break;
+
+ case NPCM_PCIERC_MSISTAT:
+ ret = s->rcmsisstat;
+ break;
+
+ case NPCM_PCIERC_AXI_ERROR_REPORT:
+ ret = s->axierr;
+ break;
+
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: read from unimplemented register 0x%04lx\n",
+ __func__, addr);
+ ret = -1;
+ break;
+ }
+ trace_npcm_pcierc_read(addr, size, ret);
+ return ret;
+}
+
+static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size) {
+ NPCMPCIERCState *s = NPCM_PCIERC(opaque);
+
+ trace_npcm_pcierc_write(addr, size, data);
+ switch (addr) {
+ case NPCM_PCIERC_RCCFGNUM:
+ s->rccfgnum = data;
+ break;
+
+ case NPCM_PCIERC_INTEN:
+ s->rcinten = data;
+ break;
+
+ case NPCM_PCIERC_INTST:
+ s->rcintstat &= ~data;
+ break;
+
+ case NPCM_PCIERC_IMSI_ADDR:
+ s->rcimsiaddr = data;
+ break;
+
+ case NPCM_PCIERC_MSISTAT:
+ s->rcmsisstat &= ~data;
+ break;
+
+ case NPCM_PCIERC_AXI_ERROR_REPORT:
+ s->axierr = data;
+ break;
+
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: write to unimplemented reg 0x%04lx data: 0x%lx\n",
+ __func__, addr, data);
+ break;
+ }
+}
+
+static void npcm_pcierc_reset(Object *obj, ResetType type) {
+ NPCMPCIERCState *s = NPCM_PCIERC(obj);
+
+ s->rccfgnum = 0;
+ s->rcinten = 0;
+ s->rcintstat = 0;
+ s->rcimsiaddr = 0;
+ s->rcmsisstat = 0;
+ s->axierr = 0;
+}
+
+static const char *npcm_pcierc_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus) {
+ return "0000:00";
+}
+
+static const MemoryRegionOps npcm_pcierc_cfg_ops = {
+ .read = npcm_pcierc_cfg_read,
+ .write = npcm_pcierc_cfg_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void npcm_pcierc_realize(DeviceState *dev, Error **errp) {
+ NPCMPCIERCState *s = NPCM_PCIERC(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ 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);
+}
+
+static void npcm_pcierc_class_init(ObjectClass *klass, const void
+*data) {
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIHostBridgeClass *hbc = PCI_HOST_BRIDGE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ hbc->root_bus_path = npcm_pcierc_root_bus_path;
+ dc->realize = npcm_pcierc_realize;
+ rc->phases.enter = npcm_pcierc_reset;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ dc->fw_name = "pci";
+}
+
+static const TypeInfo npcm_pcierc_type_info = {
+ .name = TYPE_NPCM_PCIERC,
+ .parent = TYPE_PCIE_HOST_BRIDGE,
+ .instance_size = sizeof(NPCMPCIERCState),
+ .class_init = npcm_pcierc_class_init, };
+
+static void npcm_pcierc_register_types(void) {
+ type_register_static(&npcm_pcierc_type_info);
+}
+
+type_init(npcm_pcierc_register_types)
diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events index 0a816b9aa129bb0c37d207e2612e09ac4762d51a..e4794f687177ee90fe4d33194b484c83a34dcaf9 100644
--- a/hw/pci-host/trace-events
+++ b/hw/pci-host/trace-events
@@ -69,3 +69,7 @@ elroy_pci_config_data_read(uint64_t addr, int size, uint64_t val) "addr 0x%"PRIx elroy_pci_config_data_write(uint64_t addr, int size, uint64_t val) "addr 0x%"PRIx64" size %d val 0x%"PRIx64 iosapic_reg_write(uint64_t reg_select, int size, uint64_t val) "reg_select 0x%"PRIx64" size %d val 0x%"PRIx64 iosapic_reg_read(uint64_t reg_select, int size, uint64_t val) "reg_select 0x%"PRIx64" size %d val 0x%"PRIx64
+
+# npmc_pcierc.c
+npcm_pcierc_read(uint64_t offset, uint32_t size, uint64_t data)
+"offset: 0x%" PRIx64 " size: %d data: 0x%" PRIx64
+npcm_pcierc_write(uint64_t offset, uint32_t size, uint64_t data)
+"offset: 0x%" PRIx64 " size: %d data: 0x%" PRIx64
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c817147d495fdc1d1fa4b389bad0469fd6a825e
--- /dev/null
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton PCIe Root complex
+ *
+ * Copyright 2022 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * The PCIERC configuration registers must be initialised by the BMC
+kernel
+ * during boot for PCIe to function
+ * - A single window from the PCIe to the Memory controller
+ * - 4 windows from the BMC to the PCIe.
+ * 1 of these five BMC-to-PCIe windows must be allocated for configuration
+ * transactions, the rest can be used for I/0 or memory transactions
+ * - All BMC-to-PCIe windows are mapped to address range
+ * 0xe800_0000 to 0xefff_ffff (128MB)
+ */
+
+#ifndef NPCM_PCIERC_H
+#define NPCM_PCIERC_H
+
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "qom/object.h"
+
+/* PCIe Root Complex Registers */
+#define LINKSTAT 0x92
+#define NPCM_PCIERC_RCCFGNUM 0x140 /* Configuration Number */
+#define NPCM_PCIERC_INTEN 0x180 /* Interrupt Enable */
+#define NPCM_PCIERC_INTST 0x184 /* Interrupt Status */
+#define NPCM_PCIERC_IMSI_ADDR 0x190
+#define NPCM_PCIERC_MSISTAT 0x194 /* MSI Status Register */
+#define NPCM_PCIERC_AXI_ERROR_REPORT 0x3E0
+
+#define TYPE_NPCM_PCIERC "npcm-pcie-root-complex"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERCState, NPCM_PCIERC)
+
+struct NPCMPCIERCState {
+ PCIExpressHost parent;
+
+ qemu_irq irq;
+
+ /* PCIe RC registers */
+ MemoryRegion mmio;
+ uint32_t rccfgnum;
+ uint32_t rcinten;
+ uint32_t rcintstat;
+ uint32_t rcimsiaddr;
+ uint32_t rcmsisstat;
+ uint32_t axierr;
+};
+
+#endif /* NPCM_PCIERC_H */
--
2.51.0.384.g4c02a37b29-goog
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
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-09 22:10 ` Yubin Zou
2025-09-25 16:38 ` Peter Maydell
2025-09-09 22:10 ` [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx Yubin Zou
` (6 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:10 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
From: Titus Rwantare <titusr@google.com>
Adds the windowing registers without address translation
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/pci-host/npcm_pcierc.c | 223 +++++++++++++++++++++++++++++++++++++-
include/hw/pci-host/npcm_pcierc.h | 77 ++++++++++++-
2 files changed, 297 insertions(+), 3 deletions(-)
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
index 3afe92e264f6ce4312e94f05b5e908840008df64..bffdec71acaba6562856b3bdd8aec07c3c153323 100644
--- a/hw/pci-host/npcm_pcierc.c
+++ b/hw/pci-host/npcm_pcierc.c
@@ -16,6 +16,193 @@
#include "qom/object.h"
#include "trace.h"
+/* Map enabled windows to a memory subregion */
+static void npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
+{
+ MemoryRegion *system = get_system_memory();
+ uint32_t size = NPCM_PCIERC_SAL_SIZE(w->sal);
+ hwaddr bar = ((uint64_t)w->sah) << 32 | (w->sal & 0xFFFFF000);
+ char name[26];
+
+ /* check if window is enabled */
+ if (!(w->sal & NPCM_PCIERC_SAL_EN)) {
+ return;
+ }
+
+ if (size > 2 * GiB || size < 4 * KiB) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid PCI window size %d bytes\n",
+ __func__, size);
+ return;
+ }
+
+ if (w->type == AXI2PCIE) {
+ snprintf(name, sizeof(name), "npcm-axi2pcie-window-%d", w->id);
+ } else if (w->type == PCIE2AXI) {
+ snprintf(name, sizeof(name), "npcm-pcie2axi-window-%d", w->id);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: unable to map uninitialized PCIe window",
+ __func__);
+ return;
+ }
+
+ /* TODO: set subregion to target translation address */
+ /* add subregion starting at the window source address */
+ if (!memory_region_is_mapped(&w->mem)) {
+ memory_region_init(&w->mem, OBJECT(s), name, size);
+ memory_region_add_subregion(system, bar, &w->mem);
+ }
+}
+
+/* unmap windows marked as disabled */
+static void npcm_pcierc_unmap_disabled(NPCMPCIEWindow *w)
+{
+ MemoryRegion *system = get_system_memory();
+ /* Bit 0 in the Source address enables the window */
+ if (memory_region_is_mapped(&w->mem) && !(w->sal & NPCM_PCIERC_SAL_EN)) {
+ memory_region_del_subregion(system, &w->mem);
+ }
+}
+
+static void npcm_pcie_update_window_maps(NPCMPCIERCState *s)
+{
+ for (int i = 0; i < NPCM_PCIERC_NUM_PA_WINDOWS; i++) {
+ npcm_pcierc_unmap_disabled(&s->pcie2axi[i]);
+ }
+
+ for (int i = 0; i < NPCM_PCIERC_NUM_AP_WINDOWS; i++) {
+ npcm_pcierc_unmap_disabled(&s->axi2pcie[i]);
+ }
+
+ for (int i = 0; i < NPCM_PCIERC_NUM_AP_WINDOWS; i++) {
+ npcm_pcierc_map_enabled(s, &s->axi2pcie[i]);
+ }
+
+ for (int i = 0; i < NPCM_PCIERC_NUM_PA_WINDOWS; i++) {
+ npcm_pcierc_map_enabled(s, &s->pcie2axi[i]);
+ }
+}
+
+static NPCMPCIEWindow *npcm_pcierc_get_window(NPCMPCIERCState *s, hwaddr addr)
+{
+ NPCMPCIEWindow *window;
+
+ switch (addr) {
+ case NPCM_PCIERC_PAnSAL(0) ... NPCM_PCIERC_PAnTP(1):
+ window = &s->pcie2axi[NPCM_PCIERC_PA_WINDOW(addr)];
+ break;
+
+ case NPCM_PCIERC_APnSAL(0) ... NPCM_PCIERC_APnTP(4):
+ window = &s->axi2pcie[NPCM_PCIERC_AP_WINDOW(addr)];
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: invalid window address 0x%lx\n",
+ __func__, addr);
+ return 0;
+ }
+ return window;
+}
+
+static int npcm_pcierc_get_window_offset(NPCMPCIEWindow *w, hwaddr addr)
+{
+ if (w->type == AXI2PCIE) {
+ return addr & NPCM_PCIERC_AP_OFFSET_MASK;
+ } else if (w->type == PCIE2AXI) {
+ return addr & NPCM_PCIERC_PA_OFFSET_MASK;
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: unable to access uninitialized PCIe window",
+ __func__);
+ return -1;
+ }
+}
+
+static uint32_t npcm_pcierc_read_window(NPCMPCIERCState *s, hwaddr addr)
+{
+ NPCMPCIEWindow *window = npcm_pcierc_get_window(s, addr);
+ int offset;
+
+ if (!window) {
+ return 0;
+ }
+
+ offset = npcm_pcierc_get_window_offset(window, addr);
+ if (offset < 0) {
+ return 0;
+ }
+
+ switch (offset) {
+ case NPCM_PCIERC_SAL_OFFSET:
+ return window->sal;
+
+ case NPCM_PCIERC_SAH_OFFSET:
+ return window->sah;
+
+ case NPCM_PCIERC_TAL_OFFSET:
+ return window->tal;
+
+ case NPCM_PCIERC_TAH_OFFSET:
+ return window->tah;
+
+ case NPCM_PCIERC_PARAM_OFFSET:
+ return window->params;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: invalid window offset 0x%x\n",
+ __func__, offset);
+ return 0;
+ }
+}
+
+static void npcm_pcierc_write_window(NPCMPCIERCState *s, hwaddr addr,
+ uint64_t data)
+{
+ NPCMPCIEWindow *window = npcm_pcierc_get_window(s, addr);
+ int offset;
+
+ if (!window) {
+ return;
+ }
+
+ offset = npcm_pcierc_get_window_offset(window, addr);
+ if (offset < 0) {
+ return;
+ }
+
+ switch (offset) {
+ case NPCM_PCIERC_SAL_OFFSET:
+ window->sal = data;
+ break;
+
+ case NPCM_PCIERC_SAH_OFFSET:
+ window->sah = data;
+ break;
+
+ case NPCM_PCIERC_TAL_OFFSET:
+ window->tal = data;
+ break;
+
+ case NPCM_PCIERC_TAH_OFFSET:
+ window->tah = data;
+ break;
+
+ case NPCM_PCIERC_PARAM_OFFSET:
+ window->params = data;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: invalid window offset 0x%x\n",
+ __func__, offset);
+ }
+
+ npcm_pcie_update_window_maps(s);
+}
+
static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr, unsigned size)
{
NPCMPCIERCState *s = NPCM_PCIERC(opaque);
@@ -46,6 +233,10 @@ static uint64_t npcm_pcierc_cfg_read(void *opaque, hwaddr addr, unsigned size)
ret = s->axierr;
break;
+ case NPCM_PCIERC_PAnSAL(0) ... NPCM_PCIERC_APnTP(4):
+ ret = npcm_pcierc_read_window(s, addr);
+ break;
+
default:
qemu_log_mask(LOG_UNIMP,
"%s: read from unimplemented register 0x%04lx\n",
@@ -88,6 +279,10 @@ static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
s->axierr = data;
break;
+ case NPCM_PCIERC_PAnSAL(0) ... NPCM_PCIERC_APnTP(4):
+ npcm_pcierc_write_window(s, addr, data);
+ break;
+
default:
qemu_log_mask(LOG_UNIMP,
"%s: write to unimplemented reg 0x%04lx data: 0x%lx\n",
@@ -96,6 +291,22 @@ static void npcm_pcierc_cfg_write(void *opaque, hwaddr addr, uint64_t data,
}
}
+static void npcm_pcierc_reset_pcie_windows(NPCMPCIERCState *s)
+{
+ memset(s->axi2pcie, 0, sizeof(s->axi2pcie));
+ memset(s->pcie2axi, 0, sizeof(s->pcie2axi));
+
+ for (int i = 0; i < NPCM_PCIERC_NUM_PA_WINDOWS; i++) {
+ s->pcie2axi[i].id = i;
+ s->pcie2axi[i].type = PCIE2AXI;
+ }
+
+ for (int i = 0; i < NPCM_PCIERC_NUM_AP_WINDOWS; i++) {
+ s->axi2pcie[i].id = i;
+ s->axi2pcie[i].type = AXI2PCIE;
+ }
+}
+
static void npcm_pcierc_reset(Object *obj, ResetType type)
{
NPCMPCIERCState *s = NPCM_PCIERC(obj);
@@ -106,6 +317,8 @@ static void npcm_pcierc_reset(Object *obj, ResetType type)
s->rcimsiaddr = 0;
s->rcmsisstat = 0;
s->axierr = 0;
+
+ npcm_pcierc_reset_pcie_windows(s);
}
static const char *npcm_pcierc_root_bus_path(PCIHostState *host_bridge,
@@ -136,6 +349,13 @@ static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
}
+static void npcm_pcierc_instance_init(Object *obj)
+{
+ NPCMPCIERCState *s = NPCM_PCIERC(obj);
+
+ npcm_pcierc_reset_pcie_windows(s);
+}
+
static void npcm_pcierc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -144,7 +364,7 @@ static void npcm_pcierc_class_init(ObjectClass *klass, const void *data)
hbc->root_bus_path = npcm_pcierc_root_bus_path;
dc->realize = npcm_pcierc_realize;
- rc->phases.enter = npcm_pcierc_reset;
+ rc->phases.exit = npcm_pcierc_reset;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "pci";
}
@@ -153,6 +373,7 @@ static const TypeInfo npcm_pcierc_type_info = {
.name = TYPE_NPCM_PCIERC,
.parent = TYPE_PCIE_HOST_BRIDGE,
.instance_size = sizeof(NPCMPCIERCState),
+ .instance_init = npcm_pcierc_instance_init,
.class_init = npcm_pcierc_class_init,
};
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
index 2c817147d495fdc1d1fa4b389bad0469fd6a825e..410b34d1c1ced0e25f63fc7693d87bb625a80776 100644
--- a/include/hw/pci-host/npcm_pcierc.h
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -9,8 +9,8 @@
/*
* The PCIERC configuration registers must be initialised by the BMC kernel
* during boot for PCIe to function
- * - A single window from the PCIe to the Memory controller
- * - 4 windows from the BMC to the PCIe.
+ * - A single window from PCIe to the Memory controller
+ * - 4 windows from the BMC to PCIe.
* 1 of these five BMC-to-PCIe windows must be allocated for configuration
* transactions, the rest can be used for I/0 or memory transactions
* - All BMC-to-PCIe windows are mapped to address range
@@ -34,9 +34,77 @@
#define NPCM_PCIERC_MSISTAT 0x194 /* MSI Status Register */
#define NPCM_PCIERC_AXI_ERROR_REPORT 0x3E0
+/* PCIe-to-AXI Window 0 and 1 Registers */
+/* Source address low */
+#define NPCM_PCIERC_PAnSAL(n) (0x600 + (0x100 * (n)))
+/* Source address high */
+#define NPCM_PCIERC_PAnSAH(n) (0x604 + (0x100 * (n)))
+/* Translation address low */
+#define NPCM_PCIERC_PAnTAL(n) (0x608 + (0x100 * (n)))
+/* Translation address high */
+#define NPCM_PCIERC_PAnTAH(n) (0x60C + (0x100 * (n)))
+/* Translation parameters */
+#define NPCM_PCIERC_PAnTP(n) (0x610 + (0x100 * (n)))
+/* Get window number from address */
+#define NPCM_PCIERC_PA_WINDOW(addr) (((addr) - 0x600) / 0x100)
+#define NPCM_PCIERC_PA_OFFSET_MASK 0xff
+
+/* AXI-to-PCIe Window 1 to 5 Registers, n in range [0,4] */
+/* Source address low */
+#define NPCM_PCIERC_APnSAL(n) (0x820 + (0x20 * (n)))
+/* Source address high */
+#define NPCM_PCIERC_APnSAH(n) (0x824 + (0x20 * (n)))
+/* Translation address low */
+#define NPCM_PCIERC_APnTAL(n) (0x828 + (0x20 * (n)))
+/* Translation address high */
+#define NPCM_PCIERC_APnTAH(n) (0x82C + (0x20 * (n)))
+/* Translation parameters */
+#define NPCM_PCIERC_APnTP(n) (0x830 + (0x20 * (n)))
+/* Get window number from address */
+#define NPCM_PCIERC_AP_WINDOW(addr) (((addr) - 0x820) / 0x20)
+#define NPCM_PCIERC_AP_OFFSET_MASK 0x1f
+
+/* Translation window parameters */
+#define NPCM_PCIERC_TRSL_ID(p) ((p) & 0x7)
+#define NPCM_PCIERC_TRSL_ID_TX_RX 0
+#define NPCM_PCIERC_TRSL_ID_CONFIG 1
+#define NPCM_PCIERC_TRSF_PARAM(p) (((p) >> 16) & 0xFFF)
+#define NPCM_PCIERC_TRSF_PARAM_MEMORY 0
+#define NPCM_PCIERC_TRSF_PARAM_CONFIG 1
+#define NPCM_PCIERC_TRSF_PARAM_IO 2
+
+#define NPCM_PCIERC_SAL_OFFSET 0x0
+#define NPCM_PCIERC_SAL_EN 1
+#define NPCM_PCIERC_SAL_SIZE(addr) (2ull << (((addr) >> 1) & 0x1F))
+#define NPCM_PCIERC_SAH_OFFSET 0x4
+#define NPCM_PCIERC_TAL_OFFSET 0x8
+#define NPCM_PCIERC_TAH_OFFSET 0xC
+#define NPCM_PCIERC_PARAM_OFFSET 0x10
+
+#define NPCM_PCIERC_NUM_PA_WINDOWS 2
+#define NPCM_PCIERC_NUM_AP_WINDOWS 5
+
#define TYPE_NPCM_PCIERC "npcm-pcie-root-complex"
OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERCState, NPCM_PCIERC)
+typedef enum {
+ AXI2PCIE = 1,
+ PCIE2AXI
+} NPCMPCIEWindowType;
+
+/* Nuvoton PCIe translation Window */
+typedef struct NPCMPCIEWindow {
+ uint32_t sal; /* source address low */
+ uint32_t sah; /* source address high */
+ uint32_t tal; /* translation address low */
+ uint32_t tah; /* translation address high */
+ uint32_t params; /* translation window parameters */
+
+ MemoryRegion mem; /* QEMU memory subregion per window */
+ NPCMPCIEWindowType type; /* translation direction */
+ uint8_t id;
+} NPCMPCIEWindow;
+
struct NPCMPCIERCState {
PCIExpressHost parent;
@@ -50,6 +118,11 @@ struct NPCMPCIERCState {
uint32_t rcimsiaddr;
uint32_t rcmsisstat;
uint32_t axierr;
+ /* PCIe to AXI Windows */
+ NPCMPCIEWindow pcie2axi[NPCM_PCIERC_NUM_PA_WINDOWS];
+
+ /* AXI to PCIe Windows */
+ NPCMPCIEWindow axi2pcie[NPCM_PCIERC_NUM_AP_WINDOWS];
};
#endif /* NPCM_PCIERC_H */
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
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
0 siblings, 1 reply; 22+ messages in thread
From: Peter Maydell @ 2025-09-25 16:38 UTC (permalink / raw)
To: Yubin Zou
Cc: qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm,
Titus Rwantare
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> From: Titus Rwantare <titusr@google.com>
>
> Adds the windowing registers without address translation
>
> Signed-off-by: Titus Rwantare <titusr@google.com>
> ---
> hw/pci-host/npcm_pcierc.c | 223 +++++++++++++++++++++++++++++++++++++-
> include/hw/pci-host/npcm_pcierc.h | 77 ++++++++++++-
> 2 files changed, 297 insertions(+), 3 deletions(-)
>
> diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
> index 3afe92e264f6ce4312e94f05b5e908840008df64..bffdec71acaba6562856b3bdd8aec07c3c153323 100644
> --- a/hw/pci-host/npcm_pcierc.c
> +++ b/hw/pci-host/npcm_pcierc.c
> @@ -16,6 +16,193 @@
> #include "qom/object.h"
> #include "trace.h"
>
> +/* Map enabled windows to a memory subregion */
> +static void npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
> +{
> + MemoryRegion *system = get_system_memory();
> + /* TODO: set subregion to target translation address */
> + /* add subregion starting at the window source address */
> + if (!memory_region_is_mapped(&w->mem)) {
> + memory_region_init(&w->mem, OBJECT(s), name, size);
> + memory_region_add_subregion(system, bar, &w->mem);
> + }
This looks weird. Generally devices should not map themselves
into the system address space, although some of our older
pci-host devices do for historical reasons. Should we
be modelling this some other way?
thanks
-- PMM
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
2025-09-25 16:38 ` Peter Maydell
@ 2025-09-25 19:39 ` Titus Rwantare
2025-09-26 9:07 ` Peter Maydell
0 siblings, 1 reply; 22+ messages in thread
From: Titus Rwantare @ 2025-09-25 19:39 UTC (permalink / raw)
To: Peter Maydell
Cc: Yubin Zou, qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu,
qemu-arm
On Thu, 25 Sept 2025 at 09:38, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
> >
> > From: Titus Rwantare <titusr@google.com>
> >
> > Adds the windowing registers without address translation
> >
> > Signed-off-by: Titus Rwantare <titusr@google.com>
> > ---
> > hw/pci-host/npcm_pcierc.c | 223 +++++++++++++++++++++++++++++++++++++-
> > include/hw/pci-host/npcm_pcierc.h | 77 ++++++++++++-
> > 2 files changed, 297 insertions(+), 3 deletions(-)
> >
> > diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
> > index 3afe92e264f6ce4312e94f05b5e908840008df64..bffdec71acaba6562856b3bdd8aec07c3c153323 100644
> > --- a/hw/pci-host/npcm_pcierc.c
> > +++ b/hw/pci-host/npcm_pcierc.c
> > @@ -16,6 +16,193 @@
> > #include "qom/object.h"
> > #include "trace.h"
> >
> > +/* Map enabled windows to a memory subregion */
> > +static void npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
> > +{
> > + MemoryRegion *system = get_system_memory();
>
> > + /* TODO: set subregion to target translation address */
> > + /* add subregion starting at the window source address */
> > + if (!memory_region_is_mapped(&w->mem)) {
> > + memory_region_init(&w->mem, OBJECT(s), name, size);
> > + memory_region_add_subregion(system, bar, &w->mem);
> > + }
>
> This looks weird. Generally devices should not map themselves
> into the system address space, although some of our older
> pci-host devices do for historical reasons. Should we
> be modelling this some other way?
>
> thanks
> -- PMM
I can update this. What devices are doing it the new way?
-Titus
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
2025-09-25 19:39 ` Titus Rwantare
@ 2025-09-26 9:07 ` Peter Maydell
2025-09-30 1:34 ` KFTING
0 siblings, 1 reply; 22+ messages in thread
From: Peter Maydell @ 2025-09-26 9:07 UTC (permalink / raw)
To: Titus Rwantare
Cc: Yubin Zou, qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu,
qemu-arm
On Thu, 25 Sept 2025 at 20:40, Titus Rwantare <titusr@google.com> wrote:
>
> On Thu, 25 Sept 2025 at 09:38, Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
> > >
> > > From: Titus Rwantare <titusr@google.com>
> > >
> > > Adds the windowing registers without address translation
> > >
> > > Signed-off-by: Titus Rwantare <titusr@google.com>
> > > ---
> > > hw/pci-host/npcm_pcierc.c | 223 +++++++++++++++++++++++++++++++++++++-
> > > include/hw/pci-host/npcm_pcierc.h | 77 ++++++++++++-
> > > 2 files changed, 297 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
> > > index 3afe92e264f6ce4312e94f05b5e908840008df64..bffdec71acaba6562856b3bdd8aec07c3c153323 100644
> > > --- a/hw/pci-host/npcm_pcierc.c
> > > +++ b/hw/pci-host/npcm_pcierc.c
> > > @@ -16,6 +16,193 @@
> > > #include "qom/object.h"
> > > #include "trace.h"
> > >
> > > +/* Map enabled windows to a memory subregion */
> > > +static void npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
> > > +{
> > > + MemoryRegion *system = get_system_memory();
> >
> > > + /* TODO: set subregion to target translation address */
> > > + /* add subregion starting at the window source address */
> > > + if (!memory_region_is_mapped(&w->mem)) {
> > > + memory_region_init(&w->mem, OBJECT(s), name, size);
> > > + memory_region_add_subregion(system, bar, &w->mem);
> > > + }
> >
> > This looks weird. Generally devices should not map themselves
> > into the system address space, although some of our older
> > pci-host devices do for historical reasons. Should we
> > be modelling this some other way?
> I can update this. What devices are doing it the new way?
I'm not sure exactly what your device is doing here in
general, but typically the device exposes sysbus MRs
to the SoC and the SoC maps those where they ought to go.
Is there documentation on what the hardware behaviour is?
thanks
-- PMM
^ permalink raw reply [flat|nested] 22+ messages in thread* RE: [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
2025-09-26 9:07 ` Peter Maydell
@ 2025-09-30 1:34 ` KFTING
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:34 UTC (permalink / raw)
To: Peter Maydell, Titus Rwantare
Cc: Yubin Zou, qemu-devel@nongnu.org, Paolo Bonzini, Hao Wu,
qemu-arm@nongnu.org, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Peter Maydell <peter.maydell@linaro.org>
Sent: Friday, September 26, 2025 5:08 PM
To: Titus Rwantare <titusr@google.com>
Cc: Yubin Zou <yubinz@google.com>; qemu-devel@nongnu.org; Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <KFTING@nuvoton.com>; Hao Wu <wuhaotsh@google.com>; qemu-arm@nongnu.org
Subject: Re: [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
On Thu, 25 Sept 2025 at 20:40, Titus Rwantare <titusr@google.com> wrote:
>
> On Thu, 25 Sept 2025 at 09:38, Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
> > >
> > > From: Titus Rwantare <titusr@google.com>
> > >
> > > Adds the windowing registers without address translation
> > >
> > > Signed-off-by: Titus Rwantare <titusr@google.com>
> > > ---
> > > hw/pci-host/npcm_pcierc.c | 223 +++++++++++++++++++++++++++++++++++++-
> > > include/hw/pci-host/npcm_pcierc.h | 77 ++++++++++++-
> > > 2 files changed, 297 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
> > > index
> > > 3afe92e264f6ce4312e94f05b5e908840008df64..bffdec71acaba6562856b3bd
> > > d8aec07c3c153323 100644
> > > --- a/hw/pci-host/npcm_pcierc.c
> > > +++ b/hw/pci-host/npcm_pcierc.c
> > > @@ -16,6 +16,193 @@
> > > #include "qom/object.h"
> > > #include "trace.h"
> > >
> > > +/* Map enabled windows to a memory subregion */ static void
> > > +npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w) {
> > > + MemoryRegion *system = get_system_memory();
> >
> > > + /* TODO: set subregion to target translation address */
> > > + /* add subregion starting at the window source address */
> > > + if (!memory_region_is_mapped(&w->mem)) {
> > > + memory_region_init(&w->mem, OBJECT(s), name, size);
> > > + memory_region_add_subregion(system, bar, &w->mem);
> > > + }
> >
> > This looks weird. Generally devices should not map themselves into
> > the system address space, although some of our older pci-host
> > devices do for historical reasons. Should we be modelling this some
> > other way?
> I can update this. What devices are doing it the new way?
I'm not sure exactly what your device is doing here in general, but typically the device exposes sysbus MRs to the SoC and the SoC maps those where they ought to go.
Is there documentation on what the hardware behaviour is?
thanks
-- PMM
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx
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-09 22:10 ` [PATCH 2/7] hw/pci-host: add basic Nuvoton PCIe window support Yubin Zou
@ 2025-09-09 22:10 ` Yubin Zou
2025-09-30 1:35 ` KFTING
2025-09-09 22:10 ` [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port Yubin Zou
` (5 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:10 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
From: Titus Rwantare <titusr@google.com>
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/arm/Kconfig | 3 ++-
hw/arm/npcm8xx.c | 10 +++++++++-
include/hw/arm/npcm8xx.h | 2 ++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 2aa4b5d77864ff01e69650711e7d914f351e9966..6ac38d083e4a01e09fc00e63df66046c7c17b356 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -499,7 +499,8 @@ config NPCM8XX
select SERIAL
select SSI
select UNIMP
-
+ select CMIS
+ select NPCM_PCIERC
config FSL_IMX25
bool
diff --git a/hw/arm/npcm8xx.c b/hw/arm/npcm8xx.c
index a276fea6985715cf82ea0ac7bb5aae78d2003ccf..9b3e648e3fc3ca4352d5c8d310a19ea462e62cc7 100644
--- a/hw/arm/npcm8xx.c
+++ b/hw/arm/npcm8xx.c
@@ -50,6 +50,7 @@
#define NPCM8XX_CLK_BA 0xf0801000
#define NPCM8XX_MC_BA 0xf0824000
#define NPCM8XX_RNG_BA 0xf000b000
+#define NPCM8XX_PCIERC_BA 0xe1000000
/* ADC Module */
#define NPCM8XX_ADC_BA 0xf000c000
@@ -136,6 +137,7 @@ enum NPCM8xxInterrupt {
NPCM8XX_GPIO5_IRQ,
NPCM8XX_GPIO6_IRQ,
NPCM8XX_GPIO7_IRQ,
+ NPCM8XX_PCIE_RC_IRQ = 127,
NPCM8XX_SMBUS0_IRQ = 128,
NPCM8XX_SMBUS1_IRQ,
NPCM8XX_SMBUS2_IRQ,
@@ -467,6 +469,7 @@ static void npcm8xx_init(Object *obj)
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
object_initialize_child(obj, "pspi", &s->pspi, TYPE_NPCM_PSPI);
+ object_initialize_child(obj, "pcierc", &s->pcierc, TYPE_NPCM_PCIERC);
}
static void npcm8xx_realize(DeviceState *dev, Error **errp)
@@ -766,10 +769,15 @@ static void npcm8xx_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pspi), 0,
npcm8xx_irq(s, NPCM8XX_PSPI_IRQ));
+ /* PCIe RC */
+ sysbus_realize(SYS_BUS_DEVICE(&s->pcierc), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 0, NPCM8XX_PCIERC_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.pcierc", 0xe1000000, 64 * 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);
diff --git a/include/hw/arm/npcm8xx.h b/include/hw/arm/npcm8xx.h
index a8377db490586636ca4c2e491c91f40de0f17d87..fa968e9c0881adac6a27fb5f2117e2fce163be47 100644
--- a/include/hw/arm/npcm8xx.h
+++ b/include/hw/arm/npcm8xx.h
@@ -31,6 +31,7 @@
#include "hw/net/npcm_gmac.h"
#include "hw/net/npcm_pcs.h"
#include "hw/nvram/npcm7xx_otp.h"
+#include "hw/pci-host/npcm_pcierc.h"
#include "hw/sd/npcm7xx_sdhci.h"
#include "hw/timer/npcm7xx_timer.h"
#include "hw/ssi/npcm7xx_fiu.h"
@@ -104,6 +105,7 @@ struct NPCM8xxState {
NPCMPCSState pcs;
NPCM7xxSDHCIState mmc;
NPCMPSPIState pspi;
+ NPCMPCIERCState pcierc;
};
struct NPCM8xxClass {
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx
2025-09-09 22:10 ` [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx Yubin Zou
@ 2025-09-30 1:35 ` KFTING
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:35 UTC (permalink / raw)
To: Yubin Zou, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org, Peter Maydell,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Yubin Zou <yubinz@google.com>
Sent: Wednesday, September 10, 2025 6:11 AM
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <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 3/7] hw/arm: attach PCIe root complex to npmcm8xx
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
From: Titus Rwantare <titusr@google.com>
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/arm/Kconfig | 3 ++-
hw/arm/npcm8xx.c | 10 +++++++++-
include/hw/arm/npcm8xx.h | 2 ++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 2aa4b5d77864ff01e69650711e7d914f351e9966..6ac38d083e4a01e09fc00e63df66046c7c17b356 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -499,7 +499,8 @@ config NPCM8XX
select SERIAL
select SSI
select UNIMP
-
+ select CMIS
+ select NPCM_PCIERC
config FSL_IMX25
bool
diff --git a/hw/arm/npcm8xx.c b/hw/arm/npcm8xx.c index a276fea6985715cf82ea0ac7bb5aae78d2003ccf..9b3e648e3fc3ca4352d5c8d310a19ea462e62cc7 100644
--- a/hw/arm/npcm8xx.c
+++ b/hw/arm/npcm8xx.c
@@ -50,6 +50,7 @@
#define NPCM8XX_CLK_BA 0xf0801000
#define NPCM8XX_MC_BA 0xf0824000
#define NPCM8XX_RNG_BA 0xf000b000
+#define NPCM8XX_PCIERC_BA 0xe1000000
/* ADC Module */
#define NPCM8XX_ADC_BA 0xf000c000
@@ -136,6 +137,7 @@ enum NPCM8xxInterrupt {
NPCM8XX_GPIO5_IRQ,
NPCM8XX_GPIO6_IRQ,
NPCM8XX_GPIO7_IRQ,
+ NPCM8XX_PCIE_RC_IRQ = 127,
NPCM8XX_SMBUS0_IRQ = 128,
NPCM8XX_SMBUS1_IRQ,
NPCM8XX_SMBUS2_IRQ,
@@ -467,6 +469,7 @@ static void npcm8xx_init(Object *obj)
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
object_initialize_child(obj, "pspi", &s->pspi, TYPE_NPCM_PSPI);
+ object_initialize_child(obj, "pcierc", &s->pcierc,
+ TYPE_NPCM_PCIERC);
}
static void npcm8xx_realize(DeviceState *dev, Error **errp) @@ -766,10 +769,15 @@ static void npcm8xx_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pspi), 0,
npcm8xx_irq(s, NPCM8XX_PSPI_IRQ));
+ /* PCIe RC */
+ sysbus_realize(SYS_BUS_DEVICE(&s->pcierc), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 0, NPCM8XX_PCIERC_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.pcierc", 0xe1000000, 64 * 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);
diff --git a/include/hw/arm/npcm8xx.h b/include/hw/arm/npcm8xx.h index a8377db490586636ca4c2e491c91f40de0f17d87..fa968e9c0881adac6a27fb5f2117e2fce163be47 100644
--- a/include/hw/arm/npcm8xx.h
+++ b/include/hw/arm/npcm8xx.h
@@ -31,6 +31,7 @@
#include "hw/net/npcm_gmac.h"
#include "hw/net/npcm_pcs.h"
#include "hw/nvram/npcm7xx_otp.h"
+#include "hw/pci-host/npcm_pcierc.h"
#include "hw/sd/npcm7xx_sdhci.h"
#include "hw/timer/npcm7xx_timer.h"
#include "hw/ssi/npcm7xx_fiu.h"
@@ -104,6 +105,7 @@ struct NPCM8xxState {
NPCMPCSState pcs;
NPCM7xxSDHCIState mmc;
NPCMPSPIState pspi;
+ NPCMPCIERCState pcierc;
};
struct NPCM8xxClass {
--
2.51.0.384.g4c02a37b29-goog
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (2 preceding siblings ...)
2025-09-09 22:10 ` [PATCH 3/7] hw/arm: attach PCIe root complex to npmcm8xx Yubin Zou
@ 2025-09-09 22:10 ` Yubin Zou
2025-09-25 16:42 ` Peter Maydell
2025-09-09 22:11 ` [PATCH 5/7] hw/pci-host: enable MSI on npcm PCIe root complex Yubin Zou
` (4 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:10 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
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
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port
2025-09-09 22:10 ` [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port Yubin Zou
@ 2025-09-25 16:42 ` Peter Maydell
2025-09-30 1:34 ` KFTING
0 siblings, 1 reply; 22+ messages in thread
From: Peter Maydell @ 2025-09-25 16:42 UTC (permalink / raw)
To: Yubin Zou
Cc: qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm,
Titus Rwantare
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> From: Titus Rwantare <titusr@google.com>
>
> Signed-off-by: Titus Rwantare <titusr@google.com>
> --- 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)
> {
These comments look like they should have been in
a previous patch where the functions were added.
thanks
-- PMM
^ permalink raw reply [flat|nested] 22+ messages in thread* RE: [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port
2025-09-25 16:42 ` Peter Maydell
@ 2025-09-30 1:34 ` KFTING
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:34 UTC (permalink / raw)
To: Peter Maydell, Yubin Zou
Cc: qemu-devel@nongnu.org, Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Peter Maydell <peter.maydell@linaro.org>
Sent: Friday, September 26, 2025 12:42 AM
To: Yubin Zou <yubinz@google.com>
Cc: qemu-devel@nongnu.org; Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <KFTING@nuvoton.com>; Hao Wu <wuhaotsh@google.com>; qemu-arm@nongnu.org; Titus Rwantare <titusr@google.com>
Subject: Re: [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> From: Titus Rwantare <titusr@google.com>
>
> Signed-off-by: Titus Rwantare <titusr@google.com>
> --- 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) {
These comments look like they should have been in a previous patch where the functions were added.
thanks
-- PMM
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 5/7] hw/pci-host: enable MSI on npcm PCIe root complex
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (3 preceding siblings ...)
2025-09-09 22:10 ` [PATCH 4/7] hw/pci-host: add Nuvoton PCIe root port Yubin Zou
@ 2025-09-09 22:11 ` 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
` (3 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:11 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
From: Titus Rwantare <titusr@google.com>
This allows MSI capable qemu devices to attach to the root complex
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/pci-host/npcm_pcierc.c | 5 +++++
include/hw/pci-host/npcm_pcierc.h | 2 ++
2 files changed, 7 insertions(+)
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
index a1767335fe79a30464acf32ae94fc14e417c89eb..0af76d1067a78bdbb169af3e3d5c4a2514cd0ff5 100644
--- a/hw/pci-host/npcm_pcierc.c
+++ b/hw/pci-host/npcm_pcierc.c
@@ -10,6 +10,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/pci-host/npcm_pcierc.h"
+#include "hw/pci/msi.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/units.h"
@@ -442,6 +443,10 @@ static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
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);
+
+ msi_nonbroken = true;
+ msi_init(root, NPCM_PCIERC_MSI_OFFSET, NPCM_PCIERC_MSI_NR,
+ true, true, errp);
}
static void npcm_pcie_root_port_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
index a47eae0084b88ba4388681b24ab97f77a4338594..7d18177510f60d49f7fae7908dd1e3bfbe9ae12b 100644
--- a/include/hw/pci-host/npcm_pcierc.h
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -87,6 +87,8 @@
#define NPCM_PCIERC_NUM_PA_WINDOWS 2
#define NPCM_PCIERC_NUM_AP_WINDOWS 5
+#define NPCM_PCIERC_MSI_NR 32
+#define NPCM_PCIERC_MSI_OFFSET 0x50
/* PCIe extended config space offsets */
#define NPCM_PCIE_HEADER_OFFSET 0x80
#define NPCM_PCIE_AER_OFFSET 0x100
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 5/7] hw/pci-host: enable MSI on npcm PCIe root complex
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
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:36 UTC (permalink / raw)
To: Yubin Zou, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org, Peter Maydell,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Yubin Zou <yubinz@google.com>
Sent: Wednesday, September 10, 2025 6:11 AM
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <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 5/7] hw/pci-host: enable MSI on npcm PCIe root complex
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
From: Titus Rwantare <titusr@google.com>
This allows MSI capable qemu devices to attach to the root complex
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/pci-host/npcm_pcierc.c | 5 +++++
include/hw/pci-host/npcm_pcierc.h | 2 ++
2 files changed, 7 insertions(+)
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c index a1767335fe79a30464acf32ae94fc14e417c89eb..0af76d1067a78bdbb169af3e3d5c4a2514cd0ff5 100644
--- a/hw/pci-host/npcm_pcierc.c
+++ b/hw/pci-host/npcm_pcierc.c
@@ -10,6 +10,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/pci-host/npcm_pcierc.h"
+#include "hw/pci/msi.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/units.h"
@@ -442,6 +443,10 @@ static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
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);
+
+ msi_nonbroken = true;
+ msi_init(root, NPCM_PCIERC_MSI_OFFSET, NPCM_PCIERC_MSI_NR,
+ true, true, errp);
}
static void npcm_pcie_root_port_realize(DeviceState *dev, Error **errp) diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
index a47eae0084b88ba4388681b24ab97f77a4338594..7d18177510f60d49f7fae7908dd1e3bfbe9ae12b 100644
--- a/include/hw/pci-host/npcm_pcierc.h
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -87,6 +87,8 @@
#define NPCM_PCIERC_NUM_PA_WINDOWS 2
#define NPCM_PCIERC_NUM_AP_WINDOWS 5
+#define NPCM_PCIERC_MSI_NR 32
+#define NPCM_PCIERC_MSI_OFFSET 0x50
/* PCIe extended config space offsets */
#define NPCM_PCIE_HEADER_OFFSET 0x80
#define NPCM_PCIE_AER_OFFSET 0x100
--
2.51.0.384.g4c02a37b29-goog
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (4 preceding siblings ...)
2025-09-09 22:11 ` [PATCH 5/7] hw/pci-host: enable MSI on npcm PCIe root complex Yubin Zou
@ 2025-09-09 22:11 ` Yubin Zou
2025-09-25 16:40 ` Peter Maydell
2025-09-09 22:11 ` [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC Yubin Zou
` (2 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:11 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou, Titus Rwantare
From: Titus Rwantare <titusr@google.com>
This switches to a using a fully sized PCI memory region that's
separate from system memory. Accesses to this PCI memory region are
gated by the AXI to PCIe windows whose size and offsets are validated.
- PCIe config space is not necessarily aliased with PCIe mmio space.
Ignore translation addresses for config space windows.
- Make window configuration register writes order independent.
Tested with pci-testdev.
Signed-off-by: Titus Rwantare <titusr@google.com>
---
hw/arm/npcm8xx.c | 1 -
hw/pci-host/npcm_pcierc.c | 156 ++++++++++++++++++++++++++------------
include/hw/pci-host/npcm_pcierc.h | 9 ++-
3 files changed, 115 insertions(+), 51 deletions(-)
diff --git a/hw/arm/npcm8xx.c b/hw/arm/npcm8xx.c
index f7a5ae2d121ffec99c519b484503e71dc8a43695..504874c99e7d12afa92268786239ca946e8e2129 100644
--- a/hw/arm/npcm8xx.c
+++ b/hw/arm/npcm8xx.c
@@ -773,7 +773,6 @@ 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));
diff --git a/hw/pci-host/npcm_pcierc.c b/hw/pci-host/npcm_pcierc.c
index 0af76d1067a78bdbb169af3e3d5c4a2514cd0ff5..3aab7d401a7be8c1b14a476ed934f521b8dfdaa7 100644
--- a/hw/pci-host/npcm_pcierc.c
+++ b/hw/pci-host/npcm_pcierc.c
@@ -17,63 +17,123 @@
#include "qom/object.h"
#include "trace.h"
+
+#define NPCM_SAL BIT(0)
+#define NPCM_SAH BIT(1)
+#define NPCM_TAL BIT(2)
+#define NPCM_TAH BIT(3)
+#define NPCM_PARAMS BIT(4)
+#define NPCM_BITFIELDS_ALL 0x1f
+
+
+static bool npcm_pcierc_valid_window_addr(hwaddr addr, uint32_t size)
+{
+ if ((addr + size) > NPCM_PCIE_HOLE_END) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: window mapping @0x%lx, size: %d is invalid.\n",
+ __func__, addr, size);
+ return false;
+ } else if (addr < NPCM_PCIE_HOLE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: window mapping @0x%lx, is invalid.\n",
+ __func__, addr);
+ return false;
+ } else {
+ return true;
+ }
+};
+
+static bool npcm_pcierc_valid_window_size(hwaddr src, hwaddr dst, uint32_t size)
+{
+ if (size > 2 * GiB || size < 4 * KiB) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid PCI window size %d bytes\n",
+ __func__, size);
+ return false;
+ }
+
+ return true;
+}
+
/* Map enabled windows to a memory subregion */
static void npcm_pcierc_map_enabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
{
MemoryRegion *system = get_system_memory();
uint32_t size = NPCM_PCIERC_SAL_SIZE(w->sal);
- hwaddr bar = ((uint64_t)w->sah) << 32 | (w->sal & 0xFFFFF000);
+ hwaddr src_ba = ((uint64_t)w->sah) << 32 | (w->sal & 0xFFFFF000);
+ hwaddr dest_ba = ((uint64_t)w->tah) << 32 | w->tal;
char name[26];
- /* check if window is enabled */
- if (!(w->sal & NPCM_PCIERC_SAL_EN)) {
+ if (!(w->sal & NPCM_PCIERC_SAL_EN) || /* ignore disabled windows */
+ !npcm_pcierc_valid_window_size(src_ba, dest_ba, size) ||
+ memory_region_is_mapped(&w->mem) /* ignore existing windows */) {
return;
}
- if (size > 2 * GiB || size < 4 * KiB) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Invalid PCI window size %d bytes\n",
- __func__, size);
+ /* bitfield for all 5 registers required to create a PCIe window */
+ if (w->set_fields != NPCM_BITFIELDS_ALL) {
return;
}
+ w->set_fields = 0;
+ /*
+ * This implementation of the Nuvoton root complex uses memory region
+ * aliasing to emulate the behaviour of the windowing system on hardware.
+ * AXI to PCIe windows in QEMU are system_memory subregions aliased to PCI
+ * memory at the respective source and translation addresses
+ * PCIe to AXI windows are done as PCI memory subregions aliased to system
+ * memory. PCIe to AXI windows have no address restrictions.
+ */
if (w->type == AXI2PCIE) {
+ if (!npcm_pcierc_valid_window_addr(src_ba, size)) {
+ return;
+ };
snprintf(name, sizeof(name), "npcm-axi2pcie-window-%d", w->id);
+ if (w->params &
+ (NPCM_PCIERC_TRSF_PARAM_CONFIG | NPCM_PCIERC_TRSL_ID_CONFIG)) {
+ memory_region_init_alias(&w->mem, OBJECT(s), name,
+ &s->rp_config, 0, size);
+ } else {
+ memory_region_init_alias(&w->mem, OBJECT(s), name,
+ &s->pcie_memory, dest_ba, size);
+ }
+ memory_region_add_subregion(system, src_ba, &w->mem);
} else if (w->type == PCIE2AXI) {
snprintf(name, sizeof(name), "npcm-pcie2axi-window-%d", w->id);
+ memory_region_init_alias(&w->mem, OBJECT(s), name,
+ system, src_ba, size);
+ memory_region_add_subregion(&s->pcie_memory, dest_ba, &w->mem);
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: unable to map uninitialized PCIe window",
__func__);
return;
}
-
- /* TODO: set subregion to target translation address */
- /* add subregion starting at the window source address */
- if (!memory_region_is_mapped(&w->mem)) {
- memory_region_init(&w->mem, OBJECT(s), name, size);
- memory_region_add_subregion(system, bar, &w->mem);
- }
}
/* unmap windows marked as disabled */
-static void npcm_pcierc_unmap_disabled(NPCMPCIEWindow *w)
+static void npcm_pcierc_unmap_disabled(NPCMPCIERCState *s, NPCMPCIEWindow *w)
{
MemoryRegion *system = get_system_memory();
+
/* Bit 0 in the Source address enables the window */
if (memory_region_is_mapped(&w->mem) && !(w->sal & NPCM_PCIERC_SAL_EN)) {
- memory_region_del_subregion(system, &w->mem);
+ if (w->type == AXI2PCIE) {
+ memory_region_del_subregion(system, &w->mem);
+ } else {
+ memory_region_del_subregion(&s->pcie_memory, &w->mem);
+ }
}
}
static void npcm_pcie_update_window_maps(NPCMPCIERCState *s)
{
for (int i = 0; i < NPCM_PCIERC_NUM_PA_WINDOWS; i++) {
- npcm_pcierc_unmap_disabled(&s->pcie2axi[i]);
+ npcm_pcierc_unmap_disabled(s, &s->pcie2axi[i]);
}
for (int i = 0; i < NPCM_PCIERC_NUM_AP_WINDOWS; i++) {
- npcm_pcierc_unmap_disabled(&s->axi2pcie[i]);
+ npcm_pcierc_unmap_disabled(s, &s->axi2pcie[i]);
}
for (int i = 0; i < NPCM_PCIERC_NUM_AP_WINDOWS; i++) {
@@ -177,22 +237,27 @@ static void npcm_pcierc_write_window(NPCMPCIERCState *s, hwaddr addr,
switch (offset) {
case NPCM_PCIERC_SAL_OFFSET:
window->sal = data;
+ window->set_fields |= NPCM_SAL;
break;
case NPCM_PCIERC_SAH_OFFSET:
window->sah = data;
+ window->set_fields |= NPCM_SAH;
break;
case NPCM_PCIERC_TAL_OFFSET:
window->tal = data;
+ window->set_fields |= NPCM_TAL;
break;
case NPCM_PCIERC_TAH_OFFSET:
window->tah = data;
+ window->set_fields |= NPCM_TAH;
break;
case NPCM_PCIERC_PARAM_OFFSET:
window->params = data;
+ window->set_fields |= NPCM_PARAMS;
break;
default:
@@ -305,7 +370,7 @@ static uint64_t npcm_pcie_host_config_read(void *opaque, hwaddr addr,
PCIDevice *pcid = pci_find_device(pcih->bus, bus, devfn);
if (pcid) {
- return pci_host_config_read_common(pcid, addr,
+ return pci_host_config_read_common(pcid, (addr & 0x7FF),
pci_config_size(pcid),
size);
}
@@ -323,7 +388,7 @@ static void npcm_pcie_host_config_write(void *opaque, hwaddr addr,
PCIDevice *pcid = pci_find_device(pcih->bus, bus, devfn);
if (pcid) {
- pci_host_config_write_common(pcid, addr,
+ pci_host_config_write_common(pcid, (addr & 0x7FF),
pci_config_size(pcid),
data,
size);
@@ -413,40 +478,43 @@ static void npcm_pcie_set_irq(void *opaque, int irq_num, int level)
static void npcm_pcierc_realize(DeviceState *dev, Error **errp)
{
NPCMPCIERCState *s = NPCM_PCIERC(dev);
+ PCIHostState *phs = PCI_HOST_BRIDGE(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);
+ /* init the underlying memory region for all PCI address space */
+ memory_region_init(&s->pcie_memory, OBJECT(s), "npcm-pcie-mem", UINT64_MAX);
- /* IO memory region is needed to create a PCI bus, but is unused on ARM */
+ /* I/O 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",
+ phs->bus = pci_register_root_bus(dev, "pcie",
npcm_pcie_set_irq,
pci_swizzle_map_irq_fn,
- s, &s->pcie_root, &s->pcie_io,
+ s, &s->pcie_memory, &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);
+ address_space_init(&s->pcie_space, &s->pcie_memory, "pcie-address-space");
+ pci_setup_iommu(phs->bus, &npcm_pcierc_iommu_ops, s);
+ /* init region for root complex registers (not config space) */
+ memory_region_init_io(&s->rc_regs, OBJECT(s), &npcm_pcierc_cfg_ops,
+ s, TYPE_NPCM_PCIERC, 4 * KiB);
+ sysbus_init_mmio(sbd, &s->rc_regs);
+ sysbus_init_irq(sbd, &s->irq);
+
+ /* create and add region for the root port in config space */
+ memory_region_init_io(&s->rp_config, OBJECT(s),
+ &npcm_pcie_cfg_space_ops, s, "npcm-pcie-config",
+ 4 * KiB);
+ /* realize the root port */
+ pci_realize_and_unref(root, phs->bus, &error_fatal);
+ /* enable MSI (non-X) in root port config space */
msi_nonbroken = true;
msi_init(root, NPCM_PCIERC_MSI_OFFSET, NPCM_PCIERC_MSI_NR,
true, true, errp);
+
+ npcm_pcierc_reset_pcie_windows(s);
}
static void npcm_pcie_root_port_realize(DeviceState *dev, Error **errp)
@@ -461,13 +529,6 @@ static void npcm_pcie_root_port_realize(DeviceState *dev, Error **errp)
}
}
-static void npcm_pcierc_instance_init(Object *obj)
-{
- NPCMPCIERCState *s = NPCM_PCIERC(obj);
-
- npcm_pcierc_reset_pcie_windows(s);
-}
-
static void npcm_pcierc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -507,7 +568,6 @@ static const TypeInfo npcm_pcierc_type_info = {
.name = TYPE_NPCM_PCIERC,
.parent = TYPE_PCIE_HOST_BRIDGE,
.instance_size = sizeof(NPCMPCIERCState),
- .instance_init = npcm_pcierc_instance_init,
.class_init = npcm_pcierc_class_init,
};
diff --git a/include/hw/pci-host/npcm_pcierc.h b/include/hw/pci-host/npcm_pcierc.h
index 7d18177510f60d49f7fae7908dd1e3bfbe9ae12b..a986e7666abadd8c0bb97ac5e10853339f0fe815 100644
--- a/include/hw/pci-host/npcm_pcierc.h
+++ b/include/hw/pci-host/npcm_pcierc.h
@@ -96,6 +96,9 @@
#define TYPE_NPCM_PCIERC "npcm-pcie-root-complex"
OBJECT_DECLARE_SIMPLE_TYPE(NPCMPCIERCState, NPCM_PCIERC)
+#define NPCM_PCIE_HOLE (0xe8000000)
+#define NPCM_PCIE_HOLE_END (0xe8000000 + (128 * MiB))
+
typedef enum {
AXI2PCIE = 1,
PCIE2AXI
@@ -111,6 +114,7 @@ typedef struct NPCMPCIEWindow {
MemoryRegion mem; /* QEMU memory subregion per window */
NPCMPCIEWindowType type; /* translation direction */
+ uint8_t set_fields;
uint8_t id;
} NPCMPCIEWindow;
@@ -127,7 +131,7 @@ struct NPCMPCIERCState {
qemu_irq irq;
/* PCIe RC registers */
- MemoryRegion mmio;
+ MemoryRegion rc_regs;
uint32_t rccfgnum;
uint32_t rcinten;
uint32_t rcintstat;
@@ -137,8 +141,9 @@ struct NPCMPCIERCState {
/* Address translation state */
AddressSpace pcie_space;
- MemoryRegion pcie_root;
+ MemoryRegion pcie_memory;
MemoryRegion pcie_io; /* unused - but required for IO space PCI */
+ MemoryRegion rp_config;
NPCMPCIERootPort port;
/* PCIe to AXI Windows */
NPCMPCIEWindow pcie2axi[NPCM_PCIERC_NUM_PA_WINDOWS];
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions
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
0 siblings, 1 reply; 22+ messages in thread
From: Peter Maydell @ 2025-09-25 16:40 UTC (permalink / raw)
To: Yubin Zou
Cc: qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm,
Titus Rwantare
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> From: Titus Rwantare <titusr@google.com>
>
> This switches to a using a fully sized PCI memory region that's
> separate from system memory. Accesses to this PCI memory region are
> gated by the AXI to PCIe windows whose size and offsets are validated.
>
> - PCIe config space is not necessarily aliased with PCIe mmio space.
> Ignore translation addresses for config space windows.
> - Make window configuration register writes order independent.
>
> Tested with pci-testdev.
I'm in general not a fan of introducing something in
one patch and then "reworking" it in a later patch in
the same series. It's usually easier to understand and
review if you implement it the right way the first time.
thanks
-- PMM
^ permalink raw reply [flat|nested] 22+ messages in thread
* RE: [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions
2025-09-25 16:40 ` Peter Maydell
@ 2025-09-30 1:34 ` KFTING
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:34 UTC (permalink / raw)
To: Peter Maydell, Yubin Zou
Cc: qemu-devel@nongnu.org, Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Peter Maydell <peter.maydell@linaro.org>
Sent: Friday, September 26, 2025 12:40 AM
To: Yubin Zou <yubinz@google.com>
Cc: qemu-devel@nongnu.org; Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <KFTING@nuvoton.com>; Hao Wu <wuhaotsh@google.com>; qemu-arm@nongnu.org; Titus Rwantare <titusr@google.com>
Subject: Re: [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> From: Titus Rwantare <titusr@google.com>
>
> This switches to a using a fully sized PCI memory region that's
> separate from system memory. Accesses to this PCI memory region are
> gated by the AXI to PCIe windows whose size and offsets are validated.
>
> - PCIe config space is not necessarily aliased with PCIe mmio space.
> Ignore translation addresses for config space windows.
> - Make window configuration register writes order independent.
>
> Tested with pci-testdev.
I'm in general not a fan of introducing something in one patch and then "reworking" it in a later patch in the same series. It's usually easier to understand and review if you implement it the right way the first time.
thanks
-- PMM
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (5 preceding siblings ...)
2025-09-09 22:11 ` [PATCH 6/7] hw/pci-host: rework Nuvoton PCIe windowing and memory regions Yubin Zou
@ 2025-09-09 22:11 ` 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
8 siblings, 1 reply; 22+ messages in thread
From: Yubin Zou @ 2025-09-09 22:11 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm, Peter Maydell,
Yubin Zou
From: Hao Wu <wuhaotsh@google.com>
GitWatcher: ignore
Google-Bug-Id: 262946103
Google-Bug-Id: 240169286
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Change-Id: I77ce849af30e999ec26aeab62b7db437db28c012
---
hw/arm/Kconfig | 1 +
hw/arm/npcm7xx.c | 10 ++++++++++
include/hw/arm/npcm7xx.h | 4 +++-
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 6ac38d083e4a01e09fc00e63df66046c7c17b356..a3f2041db7920c134a2d9d79ed4836bd35507d7b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -487,6 +487,7 @@ config NPCM7XX
select UNIMP
select PCA954X
select USB_OHCI_SYSBUS
+ select NPCM_PCIERC
config NPCM8XX
bool
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index ecfae328a96a49c82beaa53a5d803469c8f02d91..118470af0694718520b7c3828d3a09ecfafb31ec 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -47,6 +47,8 @@
#define NPCM7XX_CLK_BA (0xf0801000)
#define NPCM7XX_MC_BA (0xf0824000)
#define NPCM7XX_RNG_BA (0xf000b000)
+#define NPCM7XX_PCIERC_BA (0xe1000000)
+#define NPCM7XX_PCIE_ROOT_BA (0xe8000000)
/* USB Host modules */
#define NPCM7XX_EHCI_BA (0xf0806000)
@@ -148,6 +150,7 @@ enum NPCM7xxInterrupt {
NPCM7XX_GPIO5_IRQ,
NPCM7XX_GPIO6_IRQ,
NPCM7XX_GPIO7_IRQ,
+ NPCM7XX_PCIE_RC_IRQ = 127,
};
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -475,6 +478,7 @@ static void npcm7xx_init(Object *obj)
}
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
+ object_initialize_child(obj, "pcierc", &s->pcierc, TYPE_NPCM_PCIERC);
}
static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -781,6 +785,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
}
+ /* PCIe RC */
+ sysbus_realize(SYS_BUS_DEVICE(&s->pcierc), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 0, NPCM7XX_PCIERC_BA);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcierc), 0,
+ npcm7xx_irq(s, NPCM7XX_PCIE_RC_IRQ));
+
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 56536565b748c5fb2f415d85df36bc01cb64dc54..661d4050154a36dc2b90e96915ae59971a8c4a7a 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -31,6 +31,7 @@
#include "hw/net/npcm7xx_emc.h"
#include "hw/net/npcm_gmac.h"
#include "hw/nvram/npcm7xx_otp.h"
+#include "hw/pci-host/npcm_pcierc.h"
#include "hw/timer/npcm7xx_timer.h"
#include "hw/ssi/npcm7xx_fiu.h"
#include "hw/ssi/npcm_pspi.h"
@@ -108,7 +109,8 @@ struct NPCM7xxState {
NPCMGMACState gmac[2];
NPCM7xxSDHCIState mmc;
NPCMPSPIState pspi[2];
-};
+ NPCMPCIERCState pcierc;
+} NPCM7xxState;
#define TYPE_NPCM7XX "npcm7xx"
OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
--
2.51.0.384.g4c02a37b29-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC
2025-09-09 22:11 ` [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC Yubin Zou
@ 2025-09-30 1:36 ` KFTING
0 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:36 UTC (permalink / raw)
To: Yubin Zou, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org, Peter Maydell,
KWLIU@nuvoton.com, CHLI30@nuvoton.com, Avi.Fishman@nuvoton.com,
tomer.maimon@nuvoton.com, tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Yubin Zou <yubinz@google.com>
Sent: Wednesday, September 10, 2025 6:11 AM
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <KFTING@nuvoton.com>; Hao Wu <wuhaotsh@google.com>; qemu-arm@nongnu.org; Peter Maydell <peter.maydell@linaro.org>; Yubin Zou <yubinz@google.com>
Subject: [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
From: Hao Wu <wuhaotsh@google.com>
GitWatcher: ignore
Google-Bug-Id: 262946103
Google-Bug-Id: 240169286
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Change-Id: I77ce849af30e999ec26aeab62b7db437db28c012
---
hw/arm/Kconfig | 1 +
hw/arm/npcm7xx.c | 10 ++++++++++
include/hw/arm/npcm7xx.h | 4 +++-
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 6ac38d083e4a01e09fc00e63df66046c7c17b356..a3f2041db7920c134a2d9d79ed4836bd35507d7b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -487,6 +487,7 @@ config NPCM7XX
select UNIMP
select PCA954X
select USB_OHCI_SYSBUS
+ select NPCM_PCIERC
config NPCM8XX
bool
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index ecfae328a96a49c82beaa53a5d803469c8f02d91..118470af0694718520b7c3828d3a09ecfafb31ec 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -47,6 +47,8 @@
#define NPCM7XX_CLK_BA (0xf0801000)
#define NPCM7XX_MC_BA (0xf0824000)
#define NPCM7XX_RNG_BA (0xf000b000)
+#define NPCM7XX_PCIERC_BA (0xe1000000)
+#define NPCM7XX_PCIE_ROOT_BA (0xe8000000)
/* USB Host modules */
#define NPCM7XX_EHCI_BA (0xf0806000)
@@ -148,6 +150,7 @@ enum NPCM7xxInterrupt {
NPCM7XX_GPIO5_IRQ,
NPCM7XX_GPIO6_IRQ,
NPCM7XX_GPIO7_IRQ,
+ NPCM7XX_PCIE_RC_IRQ = 127,
};
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */ @@ -475,6 +478,7 @@ static void npcm7xx_init(Object *obj)
}
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
+ object_initialize_child(obj, "pcierc", &s->pcierc,
+ TYPE_NPCM_PCIERC);
}
static void npcm7xx_realize(DeviceState *dev, Error **errp) @@ -781,6 +785,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
}
+ /* PCIe RC */
+ sysbus_realize(SYS_BUS_DEVICE(&s->pcierc), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcierc), 0, NPCM7XX_PCIERC_BA);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcierc), 0,
+ npcm7xx_irq(s, NPCM7XX_PCIE_RC_IRQ));
+
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index 56536565b748c5fb2f415d85df36bc01cb64dc54..661d4050154a36dc2b90e96915ae59971a8c4a7a 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -31,6 +31,7 @@
#include "hw/net/npcm7xx_emc.h"
#include "hw/net/npcm_gmac.h"
#include "hw/nvram/npcm7xx_otp.h"
+#include "hw/pci-host/npcm_pcierc.h"
#include "hw/timer/npcm7xx_timer.h"
#include "hw/ssi/npcm7xx_fiu.h"
#include "hw/ssi/npcm_pspi.h"
@@ -108,7 +109,8 @@ struct NPCM7xxState {
NPCMGMACState gmac[2];
NPCM7xxSDHCIState mmc;
NPCMPSPIState pspi[2];
-};
+ NPCMPCIERCState pcierc;
+} NPCM7xxState;
#define TYPE_NPCM7XX "npcm7xx"
OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
--
2.51.0.384.g4c02a37b29-goog
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (6 preceding siblings ...)
2025-09-09 22:11 ` [PATCH 7/7] hw/arm: Add PCIERC to NPCM7xx SoC Yubin Zou
@ 2025-09-25 16:43 ` Peter Maydell
2025-09-30 1:32 ` KFTING
8 siblings, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2025-09-25 16:43 UTC (permalink / raw)
To: Yubin Zou
Cc: qemu-devel, Paolo Bonzini, Tyrone Ting, Hao Wu, qemu-arm,
Titus Rwantare
On Tue, 9 Sept 2025 at 23:11, Yubin Zou <yubinz@google.com> wrote:
>
> Improvement to QEMU:
> These changes enhance QEMU by adding emulation support for a new piece
> of hardware, the Nuvoton PCIe root complex, which is prevalent
> in both NPCM7xx and NPCM8XX Board SoCs.
>
> Impact (Before/After):
> - Before: QEMU lacked a specific model for the Nuvoton PCIe host.
> Emulating platforms using this SoC meant PCIe capabilities were either
> missing or inaccurate.
>
> - After: QEMU can now model the fundamental aspects of the
> PCIe host controller. Virtual PCIe devices can be attached to emulated
> NPCM7xx and NPCM8xx machines, and the guest OS can interact with them
> through a more faithful representation of the on-chip PCIe hardware.
>
> Signed-off-by: Yubin Zou <yubinz@google.com>
I have made a few comments about general patch structure,
but reminder that Nuvoton-interested folks should be reviewing
Nuvoton patches for detailed correctness, not assuming that
I will :-)
thanks
-- PMM
^ permalink raw reply [flat|nested] 22+ messages in thread* RE: [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx
2025-09-09 22:10 [PATCH 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx Yubin Zou
` (7 preceding siblings ...)
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
8 siblings, 0 replies; 22+ messages in thread
From: KFTING @ 2025-09-30 1:32 UTC (permalink / raw)
To: Yubin Zou, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Hao Wu, qemu-arm@nongnu.org, Peter Maydell,
Titus Rwantare, KWLIU@nuvoton.com, CHLI30@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
tali.perry@nuvoton.com
Loop in more Nuvoton folks.
-----Original Message-----
From: Yubin Zou <yubinz@google.com>
Sent: Wednesday, September 10, 2025 6:11 AM
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>; CS20 KFTing <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 0/7] Introduce PCIE Root Complex on Nuvoton npcm8xx and npcm7xx
CAUTION - External Email: Do not click links or open attachments unless you acknowledge the sender and content.
Improvement to QEMU:
These changes enhance QEMU by adding emulation support for a new piece of hardware, the Nuvoton PCIe root complex, which is prevalent in both NPCM7xx and NPCM8XX Board SoCs.
Impact (Before/After):
- Before: QEMU lacked a specific model for the Nuvoton PCIe host.
Emulating platforms using this SoC meant PCIe capabilities were either missing or inaccurate.
- After: QEMU can now model the fundamental aspects of the PCIe host controller. Virtual PCIe devices can be attached to emulated NPCM7xx and NPCM8xx machines, and the guest OS can interact with them through a more faithful representation of the on-chip PCIe hardware.
Signed-off-by: Yubin Zou <yubinz@google.com>
---
Hao Wu (1):
hw/arm: Add PCIERC to NPCM7xx SoC
Titus Rwantare (6):
hw/pci-host: implement Nuvoton PCIE Root Complex stub
hw/pci-host: add basic Nuvoton PCIe window support
hw/arm: attach PCIe root complex to npmcm8xx
hw/pci-host: add Nuvoton PCIe root port
hw/pci-host: enable MSI on npcm PCIe root complex
hw/pci-host: rework Nuvoton PCIe windowing and memory regions
hw/arm/Kconfig | 4 +-
hw/arm/npcm7xx.c | 10 +
hw/arm/npcm8xx.c | 12 +-
hw/pci-host/Kconfig | 4 +
hw/pci-host/meson.build | 1 +
hw/pci-host/npcm_pcierc.c | 587 ++++++++++++++++++++++++++++++++++++++
hw/pci-host/trace-events | 4 +
include/hw/arm/npcm7xx.h | 4 +-
include/hw/arm/npcm8xx.h | 2 +
include/hw/pci-host/npcm_pcierc.h | 155 ++++++++++
10 files changed, 779 insertions(+), 4 deletions(-)
---
base-commit: 6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8
change-id: 20250909-pcie-root-upstream-1eca4ba1c448
Best regards,
--
Yubin Zou <yubinz@google.com>
Thank you.
Regards,
Tyrone
________________________________
________________________________
The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
^ permalink raw reply [flat|nested] 22+ messages in thread