qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/48] AMD Versal Gen 2 support
@ 2025-07-16  9:53 Luc Michel
  2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
                   ` (47 more replies)
  0 siblings, 48 replies; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hello,

This series brings support for the AMD Versal Gen 2 (versal2) SoC in
QEMU. This SoC is the next iteration of the existing Versal SoC.

It is organized as follows:
  - The first patch is a fix in the Cadence GEM model. Some registers
    were badly initialized when the device was built with a number of
    priority queues greater than 2. This was confusing the Linux driver.

  - The next and biggest part of the series performs refactoring of the
    existing versal SoC implementation. This consists in:
       - splitting existing device types into base/concrete classes,
       - moving from an in-place to dynamic device creation approach in
         the SoC code for flexibility,
       - describing the SoC using a new structure called VersalMap,
       - moving the DTB creation logic in the SoC code itself alongside
         device creation.
    Patches are split such that each device is individually converted to
    use this new approach. Behaviour changes are minimal and are
    emphasised in the commit messages. This gets the SoC code ready for
    versal2 addition and leverage the fact that Versal family SoCs are
    quite similar in term of architecture.

  - versal2 SoC support is then added by adding the corresponding
    VersalMap description. This allows to reuse the existing code
    without duplication and almost no special case.

  - The amd-versal2-virt machine is finally added, following the same
    idea as amd-versal-virt. The documentation and tests are updated
    accordingly.

Note that the xlnx-versal-virt machine is renamed amd-versal-virt to
follow current branding guidelines and stay coherent with the new
amd-versal2-virt machine. The xlnx-versal-virt name is kept as an alias
to amd-versal-virt for command line backward compatibility.

Thanks

Luc


Francisco Iglesias (1):
  hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property

Luc Michel (47):
  hw/net/cadence_gem: fix register mask initialization
  hw/arm/xlnx-versal: split the xlnx-versal type
  hw/arm/xlnx-versal: prepare for FDT creation
  hw/arm/xlnx-versal: uart: refactor creation
  hw/arm/xlnx-versal: canfd: refactor creation
  hw/arm/xlnx-versal: sdhci: refactor creation
  hw/arm/xlnx-versal: gem: refactor creation
  hw/arm/xlnx-versal: adma: refactor creation
  hw/arm/xlnx-versal: xram: refactor creation
  hw/arm/xlnx-versal: usb: refactor creation
  hw/arm/xlnx-versal: efuse: refactor creation
  hw/arm/xlnx-versal: ospi: refactor creation
  hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation
  hw/arm/xlnx-versal: bbram: refactor creation
  hw/arm/xlnx-versal: trng: refactor creation
  hw/arm/xlnx-versal: rtc: refactor creation
  hw/arm/xlnx-versal: cfu: refactor creation
  hw/arm/xlnx-versal: crl: refactor creation
  hw/arm/xlnx-versal-virt: virtio: refactor creation
  hw/arm/xlnx-versal: refactor CPU cluster creation
  hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping
  hw/arm/xlnx-versal: instantiate the GIC ITS in the APU
  hw/arm/xlnx-versal: add support for multiple GICs
  hw/arm/xlnx-versal: add support for GICv2
  hw/arm/xlnx-versal: rpu: refactor creation
  hw/arm/xlnx-versal: ocm: refactor creation
  hw/arm/xlnx-versal: ddr: refactor creation
  hw/arm/xlnx-versal: add the versal_get_num_cpu accessor
  hw/misc/xlnx-versal-crl: remove unnecessary include directives
  hw/misc/xlnx-versal-crl: split into base/concrete classes
  hw/misc/xlnx-versal-crl: refactor device reset logic
  hw/arm/xlnx-versal: reconnect the CRL to the other devices
  hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices
  hw/arm/xlnx-versal: tidy up
  hw/misc/xlnx-versal-crl: add the versal2 version
  hw/arm/xlnx-versal: add a per_cluster_gic switch to
    VersalCpuClusterMap
  hw/arm/xlnx-versal: add the target field in IRQ descriptor
  target/arm/tcg/cpu64: add the cortex-a78ae CPU
  hw/arm/xlnx-versal: add versal2 SoC
  hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt
  hw/arm/xlnx-versal-virt: split into base/concrete classes
  hw/arm/xlnx-versal-virt: tidy up
  docs/system/arm/xlnx-versal-virt: update supported devices
  docs/system/arm/xlnx-versal-virt: add a note about dumpdtb
  hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine
  tests/functional/test_aarch64_xlnx_versal: test the versal2 machine

 docs/system/arm/xlnx-versal-virt.rst         |   80 +-
 include/hw/arm/xlnx-versal-version.h         |   16 +
 include/hw/arm/xlnx-versal.h                 |  341 +--
 include/hw/intc/arm_gicv3_common.h           |    1 +
 include/hw/misc/xlnx-versal-crl.h            |  378 ++-
 hw/arm/xlnx-versal-virt.c                    |  742 ++----
 hw/arm/xlnx-versal.c                         | 2460 +++++++++++++-----
 hw/intc/arm_gicv3_common.c                   |    3 +-
 hw/intc/arm_gicv3_cpuif.c                    |    2 +-
 hw/misc/xlnx-versal-crl.c                    |  602 ++++-
 hw/net/cadence_gem.c                         |    2 +-
 target/arm/tcg/cpu64.c                       |   75 +
 tests/functional/test_aarch64_xlnx_versal.py |   10 +-
 13 files changed, 3051 insertions(+), 1661 deletions(-)
 create mode 100644 include/hw/arm/xlnx-versal-version.h

-- 
2.50.0



^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-24  8:30   ` Francisco Iglesias
  2025-07-28  8:47   ` Boddu, Sai Pavan
  2025-07-16  9:53 ` [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type Luc Michel
                   ` (46 subsequent siblings)
  47 siblings, 2 replies; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu, Jason Wang

The gem_init_register_masks function was called at init time but it
relies on the num-priority-queues property. Call it at realize time
instead.

Fixes: 4c70e32f05f ("net: cadence_gem: Define access permission for interrupt registers")
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/net/cadence_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 50025d5a6f2..44446666deb 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1754,10 +1754,11 @@ static void gem_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < s->num_priority_queues; ++i) {
         sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
     }
 
+    gem_init_register_masks(s);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
     s->nic = qemu_new_nic(&net_gem_info, &s->conf,
                           object_get_typename(OBJECT(dev)), dev->id,
                           &dev->mem_reentrancy_guard, s);
@@ -1774,11 +1775,10 @@ static void gem_init(Object *obj)
     CadenceGEMState *s = CADENCE_GEM(obj);
     DeviceState *dev = DEVICE(obj);
 
     DB_PRINT("\n");
 
-    gem_init_register_masks(s);
     memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
                           "enet", sizeof(s->regs));
 
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
 }
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
  2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 16:59   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation Luc Michel
                   ` (45 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Split the xlnx-versal device into two classes, a base, abstract class
and the existing concrete one. Introduce a VersalVersion type that will
be used across several device models when versal2 implementation is
added.

This is in preparation for versal2 implementation.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal-version.h | 15 ++++++++++++++
 include/hw/arm/xlnx-versal.h         | 12 ++++++++++-
 hw/arm/xlnx-versal.c                 | 31 +++++++++++++++++++++-------
 3 files changed, 50 insertions(+), 8 deletions(-)
 create mode 100644 include/hw/arm/xlnx-versal-version.h

diff --git a/include/hw/arm/xlnx-versal-version.h b/include/hw/arm/xlnx-versal-version.h
new file mode 100644
index 00000000000..46eb165a2bd
--- /dev/null
+++ b/include/hw/arm/xlnx-versal-version.h
@@ -0,0 +1,15 @@
+/*
+ * AMD Versal versions
+ *
+ * Copyright (c) 2025, Advanced Micro Devices, Inc.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_ARM_XLNX_VERSAL_VERSION_H
+#define HW_ARM_XLNX_VERSAL_VERSION_H
+
+typedef enum VersalVersion {
+    VERSAL_VER_VERSAL,
+} VersalVersion;
+
+#endif
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 05ed641b6b6..1f92e314d6c 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -1,9 +1,10 @@
 /*
  * Model of the Xilinx Versal
  *
  * Copyright (c) 2018 Xilinx Inc.
+ * Copyright (c) 2025 Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or
  * (at your option) any later version.
@@ -33,13 +34,16 @@
 #include "hw/misc/xlnx-versal-trng.h"
 #include "hw/net/xlnx-versal-canfd.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "target/arm/cpu.h"
+#include "hw/arm/xlnx-versal-version.h"
+
+#define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
+OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
-OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
 
 #define XLNX_VERSAL_NR_ACPUS   2
 #define XLNX_VERSAL_NR_RCPUS   2
 #define XLNX_VERSAL_NR_UARTS   2
 #define XLNX_VERSAL_NR_GEMS    2
@@ -135,10 +139,16 @@ struct Versal {
     struct {
         MemoryRegion *mr_ddr;
     } cfg;
 };
 
+struct VersalClass {
+    SysBusDeviceClass parent;
+
+    VersalVersion version;
+};
+
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
 
 #define VERSAL_GIC_MAINT_IRQ        9
 #define VERSAL_TIMER_VIRT_IRQ       11
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index a42b9e7140b..4da656318f6 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -1,9 +1,10 @@
 /*
  * Xilinx Versal SoC model.
  *
  * Copyright (c) 2018 Xilinx Inc.
+ * Copyright (c) 2025 Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or
  * (at your option) any later version.
@@ -918,11 +919,11 @@ static void versal_unimp(Versal *s)
                                 gpio_in);
 }
 
 static void versal_realize(DeviceState *dev, Error **errp)
 {
-    Versal *s = XLNX_VERSAL(dev);
+    Versal *s = XLNX_VERSAL_BASE(dev);
     qemu_irq pic[XLNX_VERSAL_NR_IRQS];
 
     versal_create_apu_cpus(s);
     versal_create_apu_gic(s, pic);
     versal_create_rpu_cpus(s);
@@ -953,13 +954,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
     memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
                                         &s->lpd.rpu.mr_ps_alias, 0);
 }
 
-static void versal_init(Object *obj)
+static void versal_base_init(Object *obj)
 {
-    Versal *s = XLNX_VERSAL(obj);
+    Versal *s = XLNX_VERSAL_BASE(obj);
 
     memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
     memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
     memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
@@ -973,28 +974,44 @@ static const Property versal_properties[] = {
                       TYPE_CAN_BUS, CanBusState *),
     DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
                       TYPE_CAN_BUS, CanBusState *),
 };
 
-static void versal_class_init(ObjectClass *klass, const void *data)
+static void versal_base_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = versal_realize;
     device_class_set_props(dc, versal_properties);
     /* No VMSD since we haven't got any top-level SoC state to save.  */
 }
 
-static const TypeInfo versal_info = {
-    .name = TYPE_XLNX_VERSAL,
+static void versal_class_init(ObjectClass *klass, const void *data)
+{
+    VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
+
+    vc->version = VERSAL_VER_VERSAL;
+}
+
+static const TypeInfo versal_base_info = {
+    .name = TYPE_XLNX_VERSAL_BASE,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Versal),
-    .instance_init = versal_init,
+    .instance_init = versal_base_init,
+    .class_init = versal_base_class_init,
+    .class_size = sizeof(VersalClass),
+    .abstract = true,
+};
+
+static const TypeInfo versal_info = {
+    .name = TYPE_XLNX_VERSAL,
+    .parent = TYPE_XLNX_VERSAL_BASE,
     .class_init = versal_class_init,
 };
 
 static void versal_register_types(void)
 {
+    type_register_static(&versal_base_info);
     type_register_static(&versal_info);
 }
 
 type_init(versal_register_types);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
  2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
  2025-07-16  9:53 ` [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 17:13   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation Luc Michel
                   ` (44 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

The following commits will move FDT creation logic from the
xlnx-versal-virt machine to the xlnx-versal SoC itself. Prepare this by
passing the FDT handle to the SoC before it is realized. If no FDT is
passed, a dummy one is created internally as a stub to the fdt function
calls.

For now the SoC only creates the two clock nodes. The ones from the
xlnx-versal virt machine are renamed with a `old-' prefix and will be
removed once they are not referenced anymore.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h | 12 ++++++++++++
 hw/arm/xlnx-versal-virt.c    | 11 +++++++----
 hw/arm/xlnx-versal.c         | 30 ++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 1f92e314d6c..f2a62b43552 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -134,21 +134,33 @@ struct Versal {
         XlnxVersalCFrameBcastReg cframe_bcast;
 
         OrIRQState apb_irq_orgate;
     } pmc;
 
+    struct {
+        uint32_t clk_25mhz;
+        uint32_t clk_125mhz;
+    } phandle;
+
     struct {
         MemoryRegion *mr_ddr;
+        void *fdt;
     } cfg;
 };
 
 struct VersalClass {
     SysBusDeviceClass parent;
 
     VersalVersion version;
 };
 
+static inline void versal_set_fdt(Versal *s, void *fdt)
+{
+    g_assert(!qdev_is_realized(DEVICE(s)));
+    s->cfg.fdt = fdt;
+}
+
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
 
 #define VERSAL_GIC_MAINT_IRQ        9
 #define VERSAL_TIMER_VIRT_IRQ       11
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index adadbb72902..c30dcca424c 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -1,9 +1,10 @@
 /*
  * Xilinx Versal Virtual board.
  *
  * Copyright (c) 2018 Xilinx Inc.
+ * Copyright (c) 2025, Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or
  * (at your option) any later version.
@@ -695,14 +696,13 @@ static void versal_virt_init(MachineState *machine)
                              &error_abort);
     object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
                              &error_abort);
     object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
                              &error_abort);
-    sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
 
     fdt_create(s);
-    create_virtio_regions(s);
+    versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gem_nodes(s);
     fdt_add_uart_nodes(s);
     fdt_add_canfd_nodes(s);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
@@ -712,12 +712,15 @@ static void versal_virt_init(MachineState *machine)
     fdt_add_rtc_node(s);
     fdt_add_bbram_node(s);
     fdt_add_efuse_ctrl_node(s);
     fdt_add_efuse_cache_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
-    fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
-    fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
+    fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
+    fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
+
+    sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
+    create_virtio_regions(s);
 
     /* Make the APU cpu address space visible to virtio and other
      * modules unaware of multiple address-spaces.  */
     memory_region_add_subregion_overlap(get_system_memory(),
                                         0, &s->soc.fpd.apu.mr, 0);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 4da656318f6..7bb55751e5c 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -22,10 +22,12 @@
 #include "hw/misc/unimp.h"
 #include "hw/arm/xlnx-versal.h"
 #include "qemu/log.h"
 #include "target/arm/cpu-qom.h"
 #include "target/arm/gtimer.h"
+#include "system/device_tree.h"
+#include "hw/arm/fdt.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -917,14 +919,42 @@ static void versal_unimp(Versal *s)
     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
                                 SYSBUS_DEVICE_GPIO_IRQ, 0,
                                 gpio_in);
 }
 
+static uint32_t fdt_add_clk_node(Versal *s, const char *name,
+                                 unsigned int freq_hz)
+{
+    uint32_t phandle;
+
+    phandle = qemu_fdt_alloc_phandle(s->cfg.fdt);
+
+    qemu_fdt_add_subnode(s->cfg.fdt, name);
+    qemu_fdt_setprop_cell(s->cfg.fdt, name, "phandle", phandle);
+    qemu_fdt_setprop_cell(s->cfg.fdt, name, "clock-frequency", freq_hz);
+    qemu_fdt_setprop_cell(s->cfg.fdt, name, "#clock-cells", 0x0);
+    qemu_fdt_setprop_string(s->cfg.fdt, name, "compatible", "fixed-clock");
+    qemu_fdt_setprop(s->cfg.fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
+
+    return phandle;
+}
+
 static void versal_realize(DeviceState *dev, Error **errp)
 {
     Versal *s = XLNX_VERSAL_BASE(dev);
     qemu_irq pic[XLNX_VERSAL_NR_IRQS];
+    const VersalMap *map = versal_get_map(s);
+    size_t i;
+
+    if (s->cfg.fdt == NULL) {
+        int fdt_size;
+
+        s->cfg.fdt = create_device_tree(&fdt_size);
+    }
+
+    s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
+    s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
 
     versal_create_apu_cpus(s);
     versal_create_apu_gic(s, pic);
     versal_create_rpu_cpus(s);
     versal_create_uarts(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (2 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 17:29   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 05/48] hw/arm/xlnx-versal: canfd: " Luc Michel
                   ` (43 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the UARTs creations. The VersalMap struct is now used to
describe the SoC and its peripherals. For now it contains the two UARTs
mapping information. The creation function now embeds the FDT creation
logic as well. The devices are now created dynamically using qdev_new
and (qdev|sysbus)_realize_and_unref.

This will allow to rely entirely on the VersalMap structure to create
the SoC and allow easy addition of new SoCs of the same family (like
versal2 coming with next commits).

Note that the connection to the CRL is removed for now and will be
re-added by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |   2 -
 hw/arm/xlnx-versal-virt.c    |  36 +--------
 hw/arm/xlnx-versal.c         | 142 ++++++++++++++++++++++++++++-------
 3 files changed, 117 insertions(+), 63 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index f2a62b43552..b01ddeb1423 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -16,11 +16,10 @@
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/sd/sdhci.h"
 #include "hw/intc/arm_gicv3.h"
-#include "hw/char/pl011.h"
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
@@ -78,11 +77,10 @@ struct Versal {
 
     struct {
         MemoryRegion mr_ocm;
 
         struct {
-            PL011State uart[XLNX_VERSAL_NR_UARTS];
             CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
             OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
             XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
             VersalUsb2 usb;
             CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index c30dcca424c..7213ead466d 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -75,10 +75,11 @@ static void fdt_create(VersalVirt *s)
 
     s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
     /* Create /chosen node for load_dtb.  */
     qemu_fdt_add_subnode(s->fdt, "/chosen");
+    qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
     qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
     qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
     qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
@@ -206,44 +207,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
     qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
     g_free(name);
 }
 
-static void fdt_add_uart_nodes(VersalVirt *s)
-{
-    uint64_t addrs[] = { MM_UART1, MM_UART0 };
-    unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
-    const char compat[] = "arm,pl011\0arm,sbsa-uart";
-    const char clocknames[] = "uartclk\0apb_pclk";
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
-        char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
-        qemu_fdt_add_subnode(s->fdt, name);
-        qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
-        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
-        qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                     2, addrs[i], 2, 0x1000);
-        qemu_fdt_setprop(s->fdt, name, "compatible",
-                         compat, sizeof(compat));
-        qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
-
-        if (addrs[i] == MM_UART0) {
-            /* Select UART0.  */
-            qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
-        }
-        g_free(name);
-    }
-}
-
 static void fdt_add_canfd_nodes(VersalVirt *s)
 {
     uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
     uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
     unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
@@ -700,11 +667,10 @@ static void versal_virt_init(MachineState *machine)
                              &error_abort);
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gem_nodes(s);
-    fdt_add_uart_nodes(s);
     fdt_add_canfd_nodes(s);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_zdma_nodes(s);
     fdt_add_usb_xhci_nodes(s);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 7bb55751e5c..87468cbc291 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -24,18 +24,96 @@
 #include "qemu/log.h"
 #include "target/arm/cpu-qom.h"
 #include "target/arm/gtimer.h"
 #include "system/device_tree.h"
 #include "hw/arm/fdt.h"
+#include "hw/char/pl011.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
 #define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
+typedef struct VersalSimplePeriphMap {
+    uint64_t addr;
+    int irq;
+} VersalSimplePeriphMap;
+
+typedef struct VersalMap {
+    VersalSimplePeriphMap uart[2];
+    size_t num_uart;
+} VersalMap;
+
+static const VersalMap VERSAL_MAP = {
+    .uart[0] = { 0xff000000, 18 },
+    .uart[1] = { 0xff010000, 19 },
+    .num_uart = 2,
+};
+
+static const VersalMap *VERSION_TO_MAP[] = {
+    [VERSAL_VER_VERSAL] = &VERSAL_MAP,
+};
+
+static inline VersalVersion versal_get_version(Versal *s)
+{
+    return XLNX_VERSAL_BASE_GET_CLASS(s)->version;
+}
+
+static inline const VersalMap *versal_get_map(Versal *s)
+{
+    return VERSION_TO_MAP[versal_get_version(s)];
+}
+
+
+static qemu_irq versal_get_irq(Versal *s, int irq_idx)
+{
+    return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
+}
+
+static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
+                                      int sbd_idx, int irq_idx)
+{
+    qemu_irq irq = versal_get_irq(s, irq_idx);
+
+    if (irq == NULL) {
+        return;
+    }
+
+    sysbus_connect_irq(sbd, sbd_idx, irq);
+}
+
+static inline char *versal_fdt_add_subnode(Versal *s, const char *path,
+                                           uint64_t at, const char *compat,
+                                           size_t compat_sz)
+{
+    char *p;
+
+    p = g_strdup_printf("%s@%" PRIx64, path, at);
+    qemu_fdt_add_subnode(s->cfg.fdt, p);
+
+    if (!strncmp(compat, "memory", compat_sz)) {
+        qemu_fdt_setprop(s->cfg.fdt, p, "device_type", compat, compat_sz);
+    } else {
+        qemu_fdt_setprop(s->cfg.fdt, p, "compatible", compat, compat_sz);
+    }
+
+    return p;
+}
+
+static inline char *versal_fdt_add_simple_subnode(Versal *s, const char *path,
+                                                  uint64_t addr, uint64_t len,
+                                                  const char *compat,
+                                                  size_t compat_sz)
+{
+    char *p = versal_fdt_add_subnode(s, path, addr, compat, compat_sz);
+
+    qemu_fdt_setprop_sized_cells(s->cfg.fdt, p, "reg", 2, addr, 2, len);
+    return p;
+}
+
 static void versal_create_apu_cpus(Versal *s)
 {
     int i;
 
     object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
@@ -165,32 +243,48 @@ static void versal_create_rpu_cpus(Versal *s)
     }
 
     qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
 }
 
-static void versal_create_uarts(Versal *s, qemu_irq *pic)
+static void versal_create_uart(Versal *s,
+                               const VersalSimplePeriphMap *map,
+                               int chardev_idx)
 {
-    int i;
+    DeviceState *dev;
+    MemoryRegion *mr;
+    g_autofree char *node;
+    g_autofree char *alias;
+    const char compatible[] = "arm,pl011\0arm,sbsa-uart";
+    const char clocknames[] = "uartclk\0apb_pclk";
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
-        static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
-        static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
-        char *name = g_strdup_printf("uart%d", i);
-        DeviceState *dev;
-        MemoryRegion *mr;
+    dev = qdev_new(TYPE_PL011);
+    object_property_add_child(OBJECT(s), "uart[*]", OBJECT(dev));
+    qdev_prop_set_chr(dev, "chardev", serial_hd(chardev_idx));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 
-        object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i],
-                                TYPE_PL011);
-        dev = DEVICE(&s->lpd.iou.uart[i]);
-        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
-        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
 
-        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
-        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
+    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
 
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
-        g_free(name);
+    node = versal_fdt_add_simple_subnode(s, "/uart", map->addr, 0x1000,
+                                         compatible, sizeof(compatible));
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "current-speed", 115200);
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                           s->phandle.clk_125mhz, s->phandle.clk_125mhz);
+    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names", clocknames,
+                     sizeof(clocknames));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop(s->cfg.fdt, node, "u-boot,dm-pre-reloc", NULL, 0);
+
+    alias = g_strdup_printf("serial%d", chardev_idx);
+    qemu_fdt_setprop_string(s->cfg.fdt, "/aliases", alias, node);
+
+    if (chardev_idx == 0) {
+        qemu_fdt_setprop_string(s->cfg.fdt, "/chosen", "stdout-path", node);
     }
 }
 
 static void versal_create_canfds(Versal *s, qemu_irq *pic)
 {
@@ -781,18 +875,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
         object_property_set_link(OBJECT(&s->lpd.crl),
                                  name, OBJECT(&s->lpd.iou.adma[i]),
                                  &error_abort);
     }
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
-        g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
-
-        object_property_set_link(OBJECT(&s->lpd.crl),
-                                 name, OBJECT(&s->lpd.iou.uart[i]),
-                                 &error_abort);
-    }
-
     object_property_set_link(OBJECT(&s->lpd.crl),
                              "usb", OBJECT(&s->lpd.iou.usb),
                              &error_abort);
 
     sysbus_realize(sbd, &error_fatal);
@@ -955,11 +1041,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
     s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
 
     versal_create_apu_cpus(s);
     versal_create_apu_gic(s, pic);
     versal_create_rpu_cpus(s);
-    versal_create_uarts(s, pic);
+
+    for (i = 0; i < map->num_uart; i++) {
+        versal_create_uart(s, &map->uart[i], i);
+    }
+
     versal_create_canfds(s, pic);
     versal_create_usbs(s, pic);
     versal_create_gems(s, pic);
     versal_create_admas(s, pic);
     versal_create_sds(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 05/48] hw/arm/xlnx-versal: canfd: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (3 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 20:44   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 06/48] hw/arm/xlnx-versal: sdhci: " Luc Michel
                   ` (42 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the CAN controllers creation using the VersalMap structure.

Note that the connection to the CRL is removed for now and will be
re-added by next commits.

The xlnx-versal-virt machine now dynamically creates the correct amount
of CAN bus link properties based on the number of CAN controller
advertised by the SoC.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  7 +--
 hw/arm/xlnx-versal-virt.c    | 73 ++++++++++--------------------
 hw/arm/xlnx-versal.c         | 86 +++++++++++++++++++++++++-----------
 3 files changed, 87 insertions(+), 79 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index b01ddeb1423..007c91b596e 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -29,11 +29,11 @@
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/misc/xlnx-versal-trng.h"
-#include "hw/net/xlnx-versal-canfd.h"
+#include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
 
@@ -81,12 +81,10 @@ struct Versal {
         struct {
             CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
             OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
             XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
             VersalUsb2 usb;
-            CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
-            XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
         } iou;
 
         /* Real-time Processing Unit.  */
         struct {
             MemoryRegion mr;
@@ -139,10 +137,11 @@ struct Versal {
         uint32_t clk_125mhz;
     } phandle;
 
     struct {
         MemoryRegion *mr_ddr;
+        CanBusState **canbus;
         void *fdt;
     } cfg;
 };
 
 struct VersalClass {
@@ -155,10 +154,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
 {
     g_assert(!qdev_is_realized(DEVICE(s)));
     s->cfg.fdt = fdt;
 }
 
+int versal_get_num_can(VersalVersion version);
+
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
 
 #define VERSAL_GIC_MAINT_IRQ        9
 #define VERSAL_TIMER_VIRT_IRQ       11
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 7213ead466d..18a3ea169d0 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -41,15 +41,15 @@ struct VersalVirt {
         uint32_t ethernet_phy[2];
         uint32_t clk_125Mhz;
         uint32_t clk_25Mhz;
         uint32_t usb;
         uint32_t dwc;
-        uint32_t canfd[2];
     } phandle;
     struct arm_boot_info binfo;
 
-    CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
+    CanBusState **canbus;
+
     struct {
         bool secure;
     } cfg;
     char *ospi_model;
 };
@@ -207,42 +207,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
     qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
     g_free(name);
 }
 
-static void fdt_add_canfd_nodes(VersalVirt *s)
-{
-    uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
-    uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
-    unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
-    const char clocknames[] = "can_clk\0s_axi_aclk";
-    int i;
-
-    /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
-    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
-        char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
-        qemu_fdt_add_subnode(s->fdt, name);
-
-        qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
-        qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
-
-        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
-        qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                     2, addrs[i], 2, size[i]);
-        qemu_fdt_setprop_string(s->fdt, name, "compatible",
-                                "xlnx,canfd-2.0");
-
-        g_free(name);
-    }
-}
-
 static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
                                      uint32_t phandle)
 {
     char *name = g_strdup_printf("%s/fixed-link", gemname);
 
@@ -659,19 +627,22 @@ static void versal_virt_init(MachineState *machine)
 
     object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
                             TYPE_XLNX_VERSAL);
     object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
                              &error_abort);
-    object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
-                             &error_abort);
-    object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
-                             &error_abort);
+
+    for (i = 0; i < versal_get_num_can(VERSAL_VER_VERSAL); i++) {
+        g_autofree char *prop_name = g_strdup_printf("canbus%d", i);
+
+        object_property_set_link(OBJECT(&s->soc), prop_name,
+                                 OBJECT(s->canbus[i]),
+                                 &error_abort);
+    }
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gem_nodes(s);
-    fdt_add_canfd_nodes(s);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_zdma_nodes(s);
     fdt_add_usb_xhci_nodes(s);
     fdt_add_sd_nodes(s);
@@ -753,30 +724,34 @@ static void versal_virt_init(MachineState *machine)
 }
 
 static void versal_virt_machine_instance_init(Object *obj)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
+    size_t i, num_can;
+
+    num_can = versal_get_num_can(VERSAL_VER_VERSAL);
+    s->canbus = g_new0(CanBusState *, num_can);
 
     /*
-     * User can set canbus0 and canbus1 properties to can-bus object and connect
-     * to socketcan(optional) interface via command line.
+     * User can set canbusx properties to can-bus object and optionally connect
+     * to socketcan interface via command line.
      */
-    object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
-                             (Object **)&s->canbus[0],
-                             object_property_allow_set_link,
-                             0);
-    object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
-                             (Object **)&s->canbus[1],
-                             object_property_allow_set_link,
-                             0);
+    for (i = 0; i < num_can; i++) {
+        g_autofree char *prop_name = g_strdup_printf("canbus%zu", i);
+
+        object_property_add_link(obj, prop_name, TYPE_CAN_BUS,
+                                 (Object **) &s->canbus[i],
+                                 object_property_allow_set_link, 0);
+    }
 }
 
 static void versal_virt_machine_finalize(Object *obj)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
 
     g_free(s->ospi_model);
+    g_free(s->canbus);
 }
 
 static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 87468cbc291..5dccf231942 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -25,10 +25,11 @@
 #include "target/arm/cpu-qom.h"
 #include "target/arm/gtimer.h"
 #include "system/device_tree.h"
 #include "hw/arm/fdt.h"
 #include "hw/char/pl011.h"
+#include "hw/net/xlnx-versal-canfd.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -41,16 +42,23 @@ typedef struct VersalSimplePeriphMap {
 } VersalSimplePeriphMap;
 
 typedef struct VersalMap {
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
+
+    VersalSimplePeriphMap canfd[4];
+    size_t num_canfd;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
     .num_uart = 2,
+
+    .canfd[0] = { 0xff060000, 20 },
+    .canfd[1] = { 0xff070000, 21 },
+    .num_canfd = 2,
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -284,40 +292,46 @@ static void versal_create_uart(Versal *s,
     if (chardev_idx == 0) {
         qemu_fdt_setprop_string(s->cfg.fdt, "/chosen", "stdout-path", node);
     }
 }
 
-static void versal_create_canfds(Versal *s, qemu_irq *pic)
+static void versal_create_canfd(Versal *s, const VersalSimplePeriphMap *map,
+                                CanBusState *bus)
 {
-    int i;
-    uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
-    uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
+    SysBusDevice *sbd;
+    MemoryRegion *mr;
+    g_autofree char *node;
+    const char compatible[] = "xlnx,canfd-2.0";
+    const char clocknames[] = "can_clk\0s_axi_aclk";
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
-        char *name = g_strdup_printf("canfd%d", i);
-        SysBusDevice *sbd;
-        MemoryRegion *mr;
+    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XILINX_CANFD));
+    object_property_add_child(OBJECT(s), "canfd[*]", OBJECT(sbd));
 
-        object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
-                                TYPE_XILINX_CANFD);
-        sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);
+    object_property_set_int(OBJECT(sbd), "ext_clk_freq",
+                            25 * 1000 * 1000 , &error_abort);
 
-        object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
-                                XLNX_VERSAL_CANFD_REF_CLK , &error_abort);
+    object_property_set_link(OBJECT(sbd), "canfdbus", OBJECT(bus),
+                             &error_abort);
 
-        object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
-                                 OBJECT(s->lpd.iou.canbus[i]),
-                                 &error_abort);
+    sysbus_realize_and_unref(sbd, &error_fatal);
 
-        sysbus_realize(sbd, &error_fatal);
+    mr = sysbus_mmio_get_region(sbd, 0);
+    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
 
-        mr = sysbus_mmio_get_region(sbd, 0);
-        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
+    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
 
-        sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
-        g_free(name);
-    }
+    node = versal_fdt_add_simple_subnode(s, "/canfd", map->addr, 0x10000,
+                                         compatible, sizeof(compatible));
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "rx-fifo-depth", 0x40);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "tx-mailbox-count", 0x20);
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                           s->phandle.clk_25mhz, s->phandle.clk_25mhz);
+    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
+                     clocknames, sizeof(clocknames));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 }
 
 static void versal_create_usbs(Versal *s, qemu_irq *pic)
 {
     DeviceState *dev;
@@ -1046,11 +1060,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_uart; i++) {
         versal_create_uart(s, &map->uart[i], i);
     }
 
-    versal_create_canfds(s, pic);
+    for (i = 0; i < map->num_canfd; i++) {
+        versal_create_canfd(s, &map->canfd[i], s->cfg.canbus[i]);
+    }
+
     versal_create_usbs(s, pic);
     versal_create_gems(s, pic);
     versal_create_admas(s, pic);
     versal_create_sds(s, pic);
     versal_create_pmc_apb_irq_orgate(s, pic);
@@ -1074,28 +1091,43 @@ static void versal_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
     memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
                                         &s->lpd.rpu.mr_ps_alias, 0);
 }
 
+int versal_get_num_can(VersalVersion version)
+{
+    const VersalMap *map = VERSION_TO_MAP[version];
+
+    return map->num_canfd;
+}
+
 static void versal_base_init(Object *obj)
 {
     Versal *s = XLNX_VERSAL_BASE(obj);
+    size_t i, num_can;
 
     memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
     memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
     memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
                              "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
+
+    num_can = versal_get_map(s)->num_canfd;
+    s->cfg.canbus = g_new0(CanBusState *, num_can);
+
+    for (i = 0; i < num_can; i++) {
+        g_autofree char *prop_name = g_strdup_printf("canbus%zu", i);
+
+        object_property_add_link(obj, prop_name, TYPE_CAN_BUS,
+                                 (Object **) &s->cfg.canbus[i],
+                                 object_property_allow_set_link, 0);
+    }
 }
 
 static const Property versal_properties[] = {
     DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
                      MemoryRegion *),
-    DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
-                      TYPE_CAN_BUS, CanBusState *),
-    DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
-                      TYPE_CAN_BUS, CanBusState *),
 };
 
 static void versal_base_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 06/48] hw/arm/xlnx-versal: sdhci: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (4 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 05/48] hw/arm/xlnx-versal: canfd: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 20:50   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 07/48] hw/arm/xlnx-versal: gem: " Luc Michel
                   ` (41 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the SDHCI controllers creation using the VersalMap structure.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  5 +-
 hw/arm/xlnx-versal-virt.c    | 43 ++--------------
 hw/arm/xlnx-versal.c         | 96 ++++++++++++++++++++++++++++--------
 3 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 007c91b596e..4a7a2d85aac 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -14,11 +14,10 @@
 #define XLNX_VERSAL_H
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
-#include "hw/sd/sdhci.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
@@ -103,11 +102,10 @@ struct Versal {
     } lpd;
 
     /* The Platform Management Controller subsystem.  */
     struct {
         struct {
-            SDHCIState sd[XLNX_VERSAL_NR_SDS];
             XlnxVersalPmcIouSlcr slcr;
 
             struct {
                 XlnxVersalOspi ospi;
                 XlnxCSUDMA dma_src;
@@ -154,11 +152,14 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
 {
     g_assert(!qdev_is_realized(DEVICE(s)));
     s->cfg.fdt = fdt;
 }
 
+void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
+
 int versal_get_num_can(VersalVersion version);
+int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
 
 #define VERSAL_GIC_MAINT_IRQ        9
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 18a3ea169d0..99ce84d5a46 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -282,36 +282,10 @@ static void fdt_add_zdma_nodes(VersalVirt *s)
         qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
         g_free(name);
     }
 }
 
-static void fdt_add_sd_nodes(VersalVirt *s)
-{
-    const char clocknames[] = "clk_xin\0clk_ahb";
-    const char compat[] = "arasan,sdhci-8.9a";
-    int i;
-
-    for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
-        uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i;
-        char *name = g_strdup_printf("/sdhci@%" PRIx64, addr);
-
-        qemu_fdt_add_subnode(s->fdt, name);
-
-        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
-        qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2,
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                     2, addr, 2, MM_PMC_SD0_SIZE);
-        qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-        g_free(name);
-    }
-}
-
 static void fdt_add_rtc_node(VersalVirt *s)
 {
     const char compat[] = "xlnx,zynqmp-rtc";
     const char interrupt_names[] = "alarm\0sec";
     char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
@@ -562,20 +536,15 @@ static void efuse_attach_drive(XlnxEFuse *dev)
     if (blk) {
         qdev_prop_set_drive(DEVICE(dev), "drive", blk);
     }
 }
 
-static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
+static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
 {
     BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
-    DeviceState *card;
 
-    card = qdev_new(TYPE_SD_CARD);
-    object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
-    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
-    qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"),
-                           &error_fatal);
+    versal_sdhci_plug_card(&s->soc, idx, blk);
 }
 
 static char *versal_get_ospi_model(Object *obj, Error **errp)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
@@ -643,11 +612,10 @@ static void versal_virt_init(MachineState *machine)
     fdt_add_gem_nodes(s);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_zdma_nodes(s);
     fdt_add_usb_xhci_nodes(s);
-    fdt_add_sd_nodes(s);
     fdt_add_rtc_node(s);
     fdt_add_bbram_node(s);
     fdt_add_efuse_ctrl_node(s);
     fdt_add_efuse_cache_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
@@ -666,14 +634,13 @@ static void versal_virt_init(MachineState *machine)
     bbram_attach_drive(&s->soc.pmc.bbram);
 
     /* Attach efuse backend, if given */
     efuse_attach_drive(&s->soc.pmc.efuse);
 
-    /* Plugin SD cards.  */
-    for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
-        sd_plugin_card(&s->soc.pmc.iou.sd[i],
-                       drive_get(IF_SD, 0, i));
+    /* Plug SD cards */
+    for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
+        sd_plug_card(s, i, drive_get(IF_SD, 0, i));
     }
 
     s->binfo.ram_size = machine->ram_size;
     s->binfo.loader_start = 0x0;
     s->binfo.get_dtb = versal_virt_get_dtb;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 5dccf231942..b963a05935b 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -26,10 +26,11 @@
 #include "target/arm/gtimer.h"
 #include "system/device_tree.h"
 #include "hw/arm/fdt.h"
 #include "hw/char/pl011.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/sd/sdhci.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -45,20 +46,27 @@ typedef struct VersalMap {
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
 
     VersalSimplePeriphMap canfd[4];
     size_t num_canfd;
+
+    VersalSimplePeriphMap sdhci[2];
+    size_t num_sdhci;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
     .num_uart = 2,
 
     .canfd[0] = { 0xff060000, 20 },
     .canfd[1] = { 0xff070000, 21 },
     .num_canfd = 2,
+
+    .sdhci[0] = { 0xf1040000, 126 },
+    .sdhci[1] = { 0xf1050000, 128 },
+    .num_sdhci = 2,
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -71,10 +79,22 @@ static inline VersalVersion versal_get_version(Versal *s)
 static inline const VersalMap *versal_get_map(Versal *s)
 {
     return VERSION_TO_MAP[versal_get_version(s)];
 }
 
+static inline Object *versal_get_child(Versal *s, const char *child)
+{
+    return object_resolve_path_at(OBJECT(s), child);
+}
+
+static inline Object *versal_get_child_idx(Versal *s, const char *child,
+                                           size_t idx)
+{
+    g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
+
+    return versal_get_child(s, n);
+}
 
 static qemu_irq versal_get_irq(Versal *s, int irq_idx)
 {
     return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
 }
@@ -422,36 +442,43 @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
         g_free(name);
     }
 }
 
 #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
-static void versal_create_sds(Versal *s, qemu_irq *pic)
+static void versal_create_sdhci(Versal *s,
+                                const VersalSimplePeriphMap *map)
 {
-    int i;
+    DeviceState *dev;
+    MemoryRegion *mr;
+    g_autofree char *node;
+    const char compatible[] = "arasan,sdhci-8.9a";
+    const char clocknames[] = "clk_xin\0clk_ahb";
 
-    for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
-        DeviceState *dev;
-        MemoryRegion *mr;
+    dev = qdev_new(TYPE_SYSBUS_SDHCI);
+    object_property_add_child(OBJECT(s), "sdhci[*]", OBJECT(dev));
 
-        object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i],
-                                TYPE_SYSBUS_SDHCI);
-        dev = DEVICE(&s->pmc.iou.sd[i]);
+    object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
+                             &error_fatal);
+    object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
+                             &error_fatal);
+    object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 
-        object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
-                                 &error_fatal);
-        object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
-                                 &error_fatal);
-        object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
-        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
 
-        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
-        memory_region_add_subregion(&s->mr_ps,
-                                    MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
+    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
 
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
-                           pic[VERSAL_SD0_IRQ_0 + i * 2]);
-    }
+    node = versal_fdt_add_simple_subnode(s, "/sdhci", map->addr, 0x10000,
+                                         compatible, sizeof(compatible));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                           s->phandle.clk_25mhz, s->phandle.clk_25mhz);
+    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
+                     clocknames, sizeof(clocknames));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 }
 
 static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
 {
     DeviceState *orgate;
@@ -1064,14 +1091,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_canfd; i++) {
         versal_create_canfd(s, &map->canfd[i], s->cfg.canbus[i]);
     }
 
+    for (i = 0; i < map->num_sdhci; i++) {
+        versal_create_sdhci(s, &map->sdhci[i]);
+    }
+
     versal_create_usbs(s, pic);
     versal_create_gems(s, pic);
     versal_create_admas(s, pic);
-    versal_create_sds(s, pic);
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_xrams(s, pic);
     versal_create_bbram(s, pic);
@@ -1091,17 +1121,41 @@ static void versal_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
     memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
                                         &s->lpd.rpu.mr_ps_alias, 0);
 }
 
+void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
+{
+    DeviceState *sdhci, *card;
+
+    sdhci = DEVICE(versal_get_child_idx(s, "sdhci", sd_idx));
+
+    if (sdhci == NULL) {
+        return;
+    }
+
+    card = qdev_new(TYPE_SD_CARD);
+    object_property_add_child(OBJECT(sdhci), "card[*]", OBJECT(card));
+    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
+    qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
+                           &error_fatal);
+}
+
 int versal_get_num_can(VersalVersion version)
 {
     const VersalMap *map = VERSION_TO_MAP[version];
 
     return map->num_canfd;
 }
 
+int versal_get_num_sdhci(VersalVersion version)
+{
+    const VersalMap *map = VERSION_TO_MAP[version];
+
+    return map->num_sdhci;
+}
+
 static void versal_base_init(Object *obj)
 {
     Versal *s = XLNX_VERSAL_BASE(obj);
     size_t i, num_can;
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 07/48] hw/arm/xlnx-versal: gem: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (5 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 06/48] hw/arm/xlnx-versal: sdhci: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 20:56   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 08/48] hw/arm/xlnx-versal: adma: " Luc Michel
                   ` (40 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the GEM ethernet controllers creation using the VersalMap
structure.

Note that the connection to the CRL is removed for now and will be
re-added by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |   3 -
 hw/arm/xlnx-versal-virt.c    |  54 -------------
 hw/arm/xlnx-versal.c         | 151 +++++++++++++++++++++++++----------
 3 files changed, 108 insertions(+), 100 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 4a7a2d85aac..1fcc2b623da 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -16,11 +16,10 @@
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/dma/xlnx-zdma.h"
-#include "hw/net/cadence_gem.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/nvram/xlnx-bbram.h"
@@ -76,12 +75,10 @@ struct Versal {
 
     struct {
         MemoryRegion mr_ocm;
 
         struct {
-            CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
-            OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
             XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
             VersalUsb2 usb;
         } iou;
 
         /* Real-time Processing Unit.  */
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 99ce84d5a46..09f87dc76dd 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -36,11 +36,10 @@ struct VersalVirt {
 
     void *fdt;
     int fdt_size;
     struct {
         uint32_t gic;
-        uint32_t ethernet_phy[2];
         uint32_t clk_125Mhz;
         uint32_t clk_25Mhz;
         uint32_t usb;
         uint32_t dwc;
     } phandle;
@@ -55,23 +54,19 @@ struct VersalVirt {
 };
 
 static void fdt_create(VersalVirt *s)
 {
     MachineClass *mc = MACHINE_GET_CLASS(s);
-    int i;
 
     s->fdt = create_device_tree(&s->fdt_size);
     if (!s->fdt) {
         error_report("create_device_tree() failed");
         exit(1);
     }
 
     /* Allocate all phandles.  */
     s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
-    for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
-        s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
-    }
     s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
 
     s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
@@ -207,58 +202,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
     qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
     g_free(name);
 }
 
-static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
-                                     uint32_t phandle)
-{
-    char *name = g_strdup_printf("%s/fixed-link", gemname);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-    qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
-    qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
-    qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
-    g_free(name);
-}
-
-static void fdt_add_gem_nodes(VersalVirt *s)
-{
-    uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
-    unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
-    const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
-    const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
-        char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
-        qemu_fdt_add_subnode(s->fdt, name);
-
-        fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
-        qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
-        qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
-                              s->phandle.ethernet_phy[i]);
-        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
-                               s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
-        qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
-                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                     2, addrs[i], 2, 0x1000);
-        qemu_fdt_setprop(s->fdt, name, "compatible",
-                         compat_gem, sizeof(compat_gem));
-        qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
-        qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
-        g_free(name);
-    }
-}
-
 static void fdt_add_zdma_nodes(VersalVirt *s)
 {
     const char clocknames[] = "clk_main\0clk_apb";
     const char compat[] = "xlnx,zynqmp-dma-1.0";
     int i;
@@ -607,11 +554,10 @@ static void versal_virt_init(MachineState *machine)
                                  &error_abort);
     }
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
-    fdt_add_gem_nodes(s);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_zdma_nodes(s);
     fdt_add_usb_xhci_nodes(s);
     fdt_add_rtc_node(s);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index b963a05935b..062f9a91a6c 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,10 +27,11 @@
 #include "system/device_tree.h"
 #include "hw/arm/fdt.h"
 #include "hw/char/pl011.h"
 #include "hw/net/xlnx-versal-canfd.h"
 #include "hw/sd/sdhci.h"
+#include "hw/net/cadence_gem.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -49,10 +50,18 @@ typedef struct VersalMap {
     VersalSimplePeriphMap canfd[4];
     size_t num_canfd;
 
     VersalSimplePeriphMap sdhci[2];
     size_t num_sdhci;
+
+    struct VersalGemMap {
+        VersalSimplePeriphMap map;
+        size_t num_prio_queue;
+        const char *phy_mode;
+        const uint32_t speed;
+    } gem[3];
+    size_t num_gem;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -63,10 +72,14 @@ static const VersalMap VERSAL_MAP = {
     .num_canfd = 2,
 
     .sdhci[0] = { 0xf1040000, 126 },
     .sdhci[1] = { 0xf1050000, 128 },
     .num_sdhci = 2,
+
+    .gem[0] = { { 0xff0c0000, 56 }, 2, "rgmii-id", 1000 },
+    .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
+    .num_gem = 2,
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -109,10 +122,22 @@ static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
     }
 
     sysbus_connect_irq(sbd, sbd_idx, irq);
 }
 
+static void versal_qdev_connect_gpio_out(Versal *s, DeviceState *dev,
+                                         int dev_idx, int irq_idx)
+{
+    qemu_irq irq = versal_get_irq(s, irq_idx);
+
+    if (irq == NULL) {
+        return;
+    }
+
+    qdev_connect_gpio_out(dev, dev_idx, irq);
+}
+
 static inline char *versal_fdt_add_subnode(Versal *s, const char *path,
                                            uint64_t at, const char *compat,
                                            size_t compat_sz)
 {
     char *p;
@@ -138,10 +163,25 @@ static inline char *versal_fdt_add_simple_subnode(Versal *s, const char *path,
 
     qemu_fdt_setprop_sized_cells(s->cfg.fdt, p, "reg", 2, addr, 2, len);
     return p;
 }
 
+static inline DeviceState *create_or_gate(Versal *s, Object *parent,
+                                          const char *name, uint16_t num_lines,
+                                          int irq_idx)
+{
+    DeviceState *or;
+
+    or = qdev_new(TYPE_OR_IRQ);
+    qdev_prop_set_uint16(or, "num-lines", num_lines);
+    object_property_add_child(parent, name, OBJECT(or));
+    qdev_realize_and_unref(or, NULL, &error_abort);
+    versal_qdev_connect_gpio_out(s, or, 0, irq_idx);
+
+    return or;
+}
+
 static void versal_create_apu_cpus(Versal *s)
 {
     int i;
 
     object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
@@ -375,50 +415,80 @@ static void versal_create_usbs(Versal *s, qemu_irq *pic)
 
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
     memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
 }
 
-static void versal_create_gems(Versal *s, qemu_irq *pic)
+static void versal_create_gem(Versal *s,
+                              const struct VersalGemMap *map)
 {
+    DeviceState *dev;
+    MemoryRegion *mr;
+    DeviceState *or;
     int i;
+    g_autofree char *node;
+    g_autofree char *phy_node;
+    int phy_phandle;
+    const char compatible[] = "cdns,zynqmp-gem\0cdns,gem";
+    const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
+    g_autofree uint32_t *irq_prop;
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
-        static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
-        static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
-        char *name = g_strdup_printf("gem%d", i);
-        DeviceState *dev;
-        MemoryRegion *mr;
-        OrIRQState *or_irq;
-
-        object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
-                                TYPE_CADENCE_GEM);
-        or_irq = &s->lpd.iou.gem_irq_orgate[i];
-        object_initialize_child(OBJECT(s), "gem-irq-orgate[*]",
-                                or_irq, TYPE_OR_IRQ);
-        dev = DEVICE(&s->lpd.iou.gem[i]);
-        qemu_configure_nic_device(dev, true, NULL);
-        object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
-        object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
-                                &error_abort);
-        object_property_set_int(OBJECT(or_irq),
-                                "num-lines", 2, &error_fatal);
-        qdev_realize(DEVICE(or_irq), NULL, &error_fatal);
-        qdev_connect_gpio_out(DEVICE(or_irq), 0, pic[irqs[i]]);
-
-        object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
-                                 &error_abort);
-        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
-
-        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
-        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
-
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(or_irq), 0));
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(or_irq), 1));
-        g_free(name);
+    dev = qdev_new(TYPE_CADENCE_GEM);
+    object_property_add_child(OBJECT(s), "gem[*]", OBJECT(dev));
+
+    qemu_configure_nic_device(dev, true, NULL);
+    object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
+    object_property_set_int(OBJECT(dev), "num-priority-queues",
+                            map->num_prio_queue, &error_abort);
+
+    object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
+                             &error_abort);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_add_subregion(&s->mr_ps, map->map.addr, mr);
+
+    /*
+     * The GEM controller exposes one IRQ line per priority queue. In Versal
+     * family devices, those are OR'ed together.
+     */
+    or = create_or_gate(s, OBJECT(dev), "irq-orgate",
+                        map->num_prio_queue, map->map.irq);
+
+    for (i = 0; i < map->num_prio_queue; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, qdev_get_gpio_in(or, i));
+    }
+
+    node = versal_fdt_add_simple_subnode(s, "/ethernet", map->map.addr, 0x1000,
+                                         compatible, sizeof(compatible));
+    phy_node = g_strdup_printf("%s/fixed-link", node);
+    phy_phandle = qemu_fdt_alloc_phandle(s->cfg.fdt);
+
+    /* Fixed link PHY node */
+    qemu_fdt_add_subnode(s->cfg.fdt, phy_node);
+    qemu_fdt_setprop_cell(s->cfg.fdt, phy_node, "phandle", phy_phandle);
+    qemu_fdt_setprop(s->cfg.fdt, phy_node, "full-duplex", NULL, 0);
+    qemu_fdt_setprop_cell(s->cfg.fdt, phy_node, "speed", map->speed);
+
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "phy-mode", map->phy_mode);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "phy-handle", phy_phandle);
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                           s->phandle.clk_25mhz, s->phandle.clk_25mhz,
+                           s->phandle.clk_125mhz, s->phandle.clk_125mhz);
+    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
+                     clocknames, sizeof(clocknames));
+
+    irq_prop = g_new(uint32_t, map->num_prio_queue * 3);
+    for (i = 0; i < map->num_prio_queue; i++) {
+        irq_prop[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
+        irq_prop[3 * i + 1] = cpu_to_be32(map->map.irq);
+        irq_prop[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
     }
+    qemu_fdt_setprop(s->cfg.fdt, node, "interrupts", irq_prop,
+                     sizeof(uint32_t) * map->num_prio_queue * 3);
 }
 
+
 static void versal_create_admas(Versal *s, qemu_irq *pic)
 {
     int i;
 
     for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
@@ -900,18 +970,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
         object_property_set_link(OBJECT(&s->lpd.crl),
                                  name, OBJECT(&s->lpd.rpu.cpu[i]),
                                  &error_abort);
     }
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
-        g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
-
-        object_property_set_link(OBJECT(&s->lpd.crl),
-                                 name, OBJECT(&s->lpd.iou.gem[i]),
-                                 &error_abort);
-    }
-
     for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
         g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
 
         object_property_set_link(OBJECT(&s->lpd.crl),
                                  name, OBJECT(&s->lpd.iou.adma[i]),
@@ -1095,12 +1157,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_sdhci; i++) {
         versal_create_sdhci(s, &map->sdhci[i]);
     }
 
+    for (i = 0; i < map->num_gem; i++) {
+        versal_create_gem(s, &map->gem[i]);
+    }
+
     versal_create_usbs(s, pic);
-    versal_create_gems(s, pic);
     versal_create_admas(s, pic);
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_xrams(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 08/48] hw/arm/xlnx-versal: adma: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (6 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 07/48] hw/arm/xlnx-versal: gem: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 21:02   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 09/48] hw/arm/xlnx-versal: xram: " Luc Michel
                   ` (39 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the ADMA creation using the VersalMap structure.

Note that the connection to the CRL is removed for now and will be
re-added by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  2 -
 hw/arm/xlnx-versal-virt.c    | 28 --------------
 hw/arm/xlnx-versal.c         | 72 ++++++++++++++++++++++++------------
 3 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 1fcc2b623da..4eeea98ff34 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -15,11 +15,10 @@
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
-#include "hw/dma/xlnx-zdma.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/nvram/xlnx-bbram.h"
@@ -75,11 +74,10 @@ struct Versal {
 
     struct {
         MemoryRegion mr_ocm;
 
         struct {
-            XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
             VersalUsb2 usb;
         } iou;
 
         /* Real-time Processing Unit.  */
         struct {
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 09f87dc76dd..1922a90019c 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -202,37 +202,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
     qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
     g_free(name);
 }
 
-static void fdt_add_zdma_nodes(VersalVirt *s)
-{
-    const char clocknames[] = "clk_main\0clk_apb";
-    const char compat[] = "xlnx,zynqmp-dma-1.0";
-    int i;
-
-    for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
-        uint64_t addr = MM_ADMA_CH0 + MM_ADMA_CH0_SIZE * i;
-        char *name = g_strdup_printf("/dma@%" PRIx64, addr);
-
-        qemu_fdt_add_subnode(s->fdt, name);
-
-        qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
-        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
-        qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                     2, addr, 2, 0x1000);
-        qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-        g_free(name);
-    }
-}
-
 static void fdt_add_rtc_node(VersalVirt *s)
 {
     const char compat[] = "xlnx,zynqmp-rtc";
     const char interrupt_names[] = "alarm\0sec";
     char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
@@ -556,11 +529,10 @@ static void versal_virt_init(MachineState *machine)
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
-    fdt_add_zdma_nodes(s);
     fdt_add_usb_xhci_nodes(s);
     fdt_add_rtc_node(s);
     fdt_add_bbram_node(s);
     fdt_add_efuse_ctrl_node(s);
     fdt_add_efuse_cache_node(s);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 062f9a91a6c..97cd991be10 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -28,10 +28,11 @@
 #include "hw/arm/fdt.h"
 #include "hw/char/pl011.h"
 #include "hw/net/xlnx-versal-canfd.h"
 #include "hw/sd/sdhci.h"
 #include "hw/net/cadence_gem.h"
+#include "hw/dma/xlnx-zdma.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -58,10 +59,20 @@ typedef struct VersalMap {
         size_t num_prio_queue;
         const char *phy_mode;
         const uint32_t speed;
     } gem[3];
     size_t num_gem;
+
+    struct VersalZDMAMap {
+        const char *name;
+        VersalSimplePeriphMap map;
+        size_t num_chan;
+        uint64_t chan_stride;
+        int irq_stride;
+    } zdma[2];
+    size_t num_zdma;
+
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -76,10 +87,13 @@ static const VersalMap VERSAL_MAP = {
     .num_sdhci = 2,
 
     .gem[0] = { { 0xff0c0000, 56 }, 2, "rgmii-id", 1000 },
     .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
     .num_gem = 2,
+
+    .zdma[0] = { "adma", { 0xffa80000, 60 }, 8, 0x10000, 1 },
+    .num_zdma = 1,
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -484,34 +498,49 @@ static void versal_create_gem(Versal *s,
     }
     qemu_fdt_setprop(s->cfg.fdt, node, "interrupts", irq_prop,
                      sizeof(uint32_t) * map->num_prio_queue * 3);
 }
 
-
-static void versal_create_admas(Versal *s, qemu_irq *pic)
+static void versal_create_zdma(Versal *s,
+                               const struct VersalZDMAMap *map)
 {
-    int i;
+    DeviceState *dev;
+    MemoryRegion *mr;
+    g_autofree char *name;
+    const char compatible[] = "xlnx,zynqmp-dma-1.0";
+    const char clocknames[] = "clk_main\0clk_apb";
+    size_t i;
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
-        char *name = g_strdup_printf("adma%d", i);
-        DeviceState *dev;
-        MemoryRegion *mr;
+    name = g_strdup_printf("%s[*]", map->name);
 
-        object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i],
-                                TYPE_XLNX_ZDMA);
-        dev = DEVICE(&s->lpd.iou.adma[i]);
+    for (i = 0; i < map->num_chan; i++) {
+        uint64_t addr = map->map.addr + map->chan_stride * i;
+        int irq = map->map.irq + map->irq_stride * i;
+        g_autofree char *node;
+
+        dev = qdev_new(TYPE_XLNX_ZDMA);
+        object_property_add_child(OBJECT(s), name, OBJECT(dev));
         object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
         object_property_set_link(OBJECT(dev), "dma",
                                  OBJECT(get_system_memory()), &error_fatal);
-        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 
         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
-        memory_region_add_subregion(&s->mr_ps,
-                                    MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
+        memory_region_add_subregion(&s->mr_ps, addr, mr);
 
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
-        g_free(name);
+        versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, irq);
+
+        node = versal_fdt_add_simple_subnode(s, "/dma", addr, 0x1000,
+                                             compatible, sizeof(compatible));
+        qemu_fdt_setprop_cell(s->cfg.fdt, node, "xlnx,bus-width", 64);
+        qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                               s->phandle.clk_25mhz, s->phandle.clk_25mhz);
+        qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
+                         clocknames, sizeof(clocknames));
+        qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, irq,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
     }
 }
 
 #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
 static void versal_create_sdhci(Versal *s,
@@ -970,18 +999,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
         object_property_set_link(OBJECT(&s->lpd.crl),
                                  name, OBJECT(&s->lpd.rpu.cpu[i]),
                                  &error_abort);
     }
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
-        g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
-
-        object_property_set_link(OBJECT(&s->lpd.crl),
-                                 name, OBJECT(&s->lpd.iou.adma[i]),
-                                 &error_abort);
-    }
-
     object_property_set_link(OBJECT(&s->lpd.crl),
                              "usb", OBJECT(&s->lpd.iou.usb),
                              &error_abort);
 
     sysbus_realize(sbd, &error_fatal);
@@ -1161,12 +1182,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_gem; i++) {
         versal_create_gem(s, &map->gem[i]);
     }
 
+    for (i = 0; i < map->num_zdma; i++) {
+        versal_create_zdma(s, &map->zdma[i]);
+    }
+
     versal_create_usbs(s, pic);
-    versal_create_admas(s, pic);
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_xrams(s, pic);
     versal_create_bbram(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 09/48] hw/arm/xlnx-versal: xram: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (7 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 08/48] hw/arm/xlnx-versal: adma: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 21:05   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 10/48] hw/arm/xlnx-versal: usb: " Luc Michel
                   ` (38 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the XRAM devices creation using the VersalMap structure.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  6 ----
 hw/arm/xlnx-versal.c         | 59 +++++++++++++++++++++---------------
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 4eeea98ff34..71c3314b8b4 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -18,11 +18,10 @@
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
-#include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/nvram/xlnx-bbram.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
@@ -86,15 +85,10 @@ struct Versal {
 
             CPUClusterState cluster;
             ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
         } rpu;
 
-        struct {
-            OrIRQState irq_orgate;
-            XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
-        } xram;
-
         XlnxVersalCRL crl;
     } lpd;
 
     /* The Platform Management Controller subsystem.  */
     struct {
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 97cd991be10..6c5eb6d3fd5 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -29,10 +29,11 @@
 #include "hw/char/pl011.h"
 #include "hw/net/xlnx-versal-canfd.h"
 #include "hw/sd/sdhci.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/dma/xlnx-zdma.h"
+#include "hw/misc/xlnx-versal-xramc.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -69,10 +70,18 @@ typedef struct VersalMap {
         uint64_t chan_stride;
         int irq_stride;
     } zdma[2];
     size_t num_zdma;
 
+    struct VersalXramMap {
+        uint64_t mem;
+        uint64_t mem_stride;
+        uint64_t ctrl;
+        uint64_t ctrl_stride;
+        int irq;
+        size_t num;
+    } xram;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -90,10 +99,17 @@ static const VersalMap VERSAL_MAP = {
     .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
     .num_gem = 2,
 
     .zdma[0] = { "adma", { 0xffa80000, 60 }, 8, 0x10000, 1 },
     .num_zdma = 1,
+
+    .xram = {
+        .num = 4,
+        .mem = 0xfe800000, .mem_stride = 1 * MiB,
+        .ctrl = 0xff8e0000, .ctrl_stride = 0x10000,
+        .irq = 79,
+    },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -633,41 +649,35 @@ static void versal_create_trng(Versal *s, qemu_irq *pic)
     mr = sysbus_mmio_get_region(sbd, 0);
     memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr);
     sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
 }
 
-static void versal_create_xrams(Versal *s, qemu_irq *pic)
+static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
 {
-    int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
-    DeviceState *orgate;
-    int i;
+    SysBusDevice *sbd;
+    MemoryRegion *mr;
+    DeviceState *or;
+    size_t i;
 
-    /* XRAM IRQs get ORed into a single line.  */
-    object_initialize_child(OBJECT(s), "xram-irq-orgate",
-                            &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
-    orgate = DEVICE(&s->lpd.xram.irq_orgate);
-    object_property_set_int(OBJECT(orgate),
-                            "num-lines", nr_xrams, &error_fatal);
-    qdev_realize(orgate, NULL, &error_fatal);
-    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
+    or = create_or_gate(s, OBJECT(s), "xram-orgate", map->num, map->irq);
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
-        SysBusDevice *sbd;
-        MemoryRegion *mr;
+    for (i = 0; i < map->num; i++) {
+        hwaddr ctrl, mem;
 
-        object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
-                                TYPE_XLNX_XRAM_CTRL);
-        sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
-        sysbus_realize(sbd, &error_fatal);
+        sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_XRAM_CTRL));
+        object_property_add_child(OBJECT(s), "xram[*]", OBJECT(sbd));
+        sysbus_realize_and_unref(sbd, &error_fatal);
+
+        ctrl = map->ctrl + map->ctrl_stride * i;
+        mem = map->mem + map->mem_stride * i;
 
         mr = sysbus_mmio_get_region(sbd, 0);
-        memory_region_add_subregion(&s->mr_ps,
-                                    MM_XRAMC + i * MM_XRAMC_SIZE, mr);
+        memory_region_add_subregion(&s->mr_ps, ctrl, mr);
         mr = sysbus_mmio_get_region(sbd, 1);
-        memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
+        memory_region_add_subregion(&s->mr_ps, mem, mr);
 
-        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
+        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(or, i));
     }
 }
 
 static void versal_create_bbram(Versal *s, qemu_irq *pic)
 {
@@ -1186,15 +1196,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_zdma; i++) {
         versal_create_zdma(s, &map->zdma[i]);
     }
 
+    versal_create_xrams(s, &map->xram);
+
     versal_create_usbs(s, pic);
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
-    versal_create_xrams(s, pic);
     versal_create_bbram(s, pic);
     versal_create_efuse(s, pic);
     versal_create_pmc_iou_slcr(s, pic);
     versal_create_ospi(s, pic);
     versal_create_crl(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 10/48] hw/arm/xlnx-versal: usb: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (8 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 09/48] hw/arm/xlnx-versal: xram: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-28 21:13   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 11/48] hw/arm/xlnx-versal: efuse: " Luc Michel
                   ` (37 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the USB controller creation using the VersalMap structure.

Note that the connection to the CRL is removed for now and will be
re-added by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  5 ---
 hw/arm/xlnx-versal-virt.c    | 56 +--------------------------
 hw/arm/xlnx-versal.c         | 74 +++++++++++++++++++++++++++++-------
 3 files changed, 62 insertions(+), 73 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 71c3314b8b4..5d4b30f0ff9 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -17,11 +17,10 @@
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
-#include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/nvram/xlnx-bbram.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
@@ -72,14 +71,10 @@ struct Versal {
     } noc;
 
     struct {
         MemoryRegion mr_ocm;
 
-        struct {
-            VersalUsb2 usb;
-        } iou;
-
         /* Real-time Processing Unit.  */
         struct {
             MemoryRegion mr;
             MemoryRegion mr_ps_alias;
 
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 1922a90019c..36341b825eb 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -12,10 +12,11 @@
 
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "system/device_tree.h"
+#include "system/address-spaces.h"
 #include "hw/block/flash.h"
 #include "hw/boards.h"
 #include "hw/sysbus.h"
 #include "hw/arm/fdt.h"
 #include "hw/qdev-properties.h"
@@ -38,12 +39,10 @@ struct VersalVirt {
     int fdt_size;
     struct {
         uint32_t gic;
         uint32_t clk_125Mhz;
         uint32_t clk_25Mhz;
-        uint32_t usb;
-        uint32_t dwc;
     } phandle;
     struct arm_boot_info binfo;
 
     CanBusState **canbus;
 
@@ -66,12 +65,10 @@ static void fdt_create(VersalVirt *s)
     /* Allocate all phandles.  */
     s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
 
-    s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
-    s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
     /* Create /chosen node for load_dtb.  */
     qemu_fdt_add_subnode(s->fdt, "/chosen");
     qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
@@ -152,60 +149,10 @@ static void fdt_add_timer_nodes(VersalVirt *s)
             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
     qemu_fdt_setprop(s->fdt, "/timer", "compatible",
                      compat, sizeof(compat));
 }
 
-static void fdt_add_usb_xhci_nodes(VersalVirt *s)
-{
-    const char clocknames[] = "bus_clk\0ref_clk";
-    const char irq_name[] = "dwc_usb3";
-    const char compatVersalDWC3[] = "xlnx,versal-dwc3";
-    const char compatDWC3[] = "snps,dwc3";
-    char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-    qemu_fdt_setprop(s->fdt, name, "compatible",
-                         compatVersalDWC3, sizeof(compatVersalDWC3));
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_USB2_CTRL_REGS,
-                                 2, MM_USB2_CTRL_REGS_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "clock-names",
-                         clocknames, sizeof(clocknames));
-    qemu_fdt_setprop_cells(s->fdt, name, "clocks",
-                               s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
-    qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
-    qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
-    qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
-    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
-    g_free(name);
-
-    name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
-                           MM_USB2_CTRL_REGS, MM_USB_0);
-    qemu_fdt_add_subnode(s->fdt, name);
-    qemu_fdt_setprop(s->fdt, name, "compatible",
-                     compatDWC3, sizeof(compatDWC3));
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_USB_0, 2, MM_USB_0_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
-                     irq_name, sizeof(irq_name));
-    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(s->fdt, name,
-                          "snps,quirk-frame-length-adjustment", 0x20);
-    qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
-    qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
-    qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
-    qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
-    qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
-    qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
-    qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
-    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
-    qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
-    g_free(name);
-}
-
 static void fdt_add_rtc_node(VersalVirt *s)
 {
     const char compat[] = "xlnx,zynqmp-rtc";
     const char interrupt_names[] = "alarm\0sec";
     char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
@@ -529,11 +476,10 @@ static void versal_virt_init(MachineState *machine)
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
-    fdt_add_usb_xhci_nodes(s);
     fdt_add_rtc_node(s);
     fdt_add_bbram_node(s);
     fdt_add_efuse_ctrl_node(s);
     fdt_add_efuse_cache_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 6c5eb6d3fd5..4e4df0851e8 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -30,10 +30,11 @@
 #include "hw/net/xlnx-versal-canfd.h"
 #include "hw/sd/sdhci.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/misc/xlnx-versal-xramc.h"
+#include "hw/usb/xlnx-usb-subsystem.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -78,10 +79,17 @@ typedef struct VersalMap {
         uint64_t ctrl;
         uint64_t ctrl_stride;
         int irq;
         size_t num;
     } xram;
+
+    struct VersalUsbMap {
+        uint64_t xhci;
+        uint64_t ctrl;
+        int irq;
+    } usb[2];
+    size_t num_usb;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -106,10 +114,13 @@ static const VersalMap VERSAL_MAP = {
         .num = 4,
         .mem = 0xfe800000, .mem_stride = 1 * MiB,
         .ctrl = 0xff8e0000, .ctrl_stride = 0x10000,
         .irq = 79,
     },
+
+    .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
+    .num_usb = 1,
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -420,33 +431,71 @@ static void versal_create_canfd(Versal *s, const VersalSimplePeriphMap *map,
     qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, map->irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 }
 
-static void versal_create_usbs(Versal *s, qemu_irq *pic)
+static void versal_create_usb(Versal *s,
+                              const struct VersalUsbMap *map)
 {
     DeviceState *dev;
     MemoryRegion *mr;
+    g_autofree char *node, *subnode;
+    const char clocknames[] = "bus_clk\0ref_clk";
+    const char irq_name[] = "dwc_usb3";
+    const char compat_versal_dwc3[] = "xlnx,versal-dwc3";
+    const char compat_dwc3[] = "snps,dwc3";
 
-    object_initialize_child(OBJECT(s), "usb2", &s->lpd.iou.usb,
-                            TYPE_XILINX_VERSAL_USB2);
-    dev = DEVICE(&s->lpd.iou.usb);
+    dev = qdev_new(TYPE_XILINX_VERSAL_USB2);
+    object_property_add_child(OBJECT(s), "usb[*]", OBJECT(dev));
 
     object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
                              &error_abort);
     qdev_prop_set_uint32(dev, "intrs", 1);
     qdev_prop_set_uint32(dev, "slots", 2);
 
-    sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
-    memory_region_add_subregion(&s->mr_ps, MM_USB_0, mr);
+    memory_region_add_subregion(&s->mr_ps, map->xhci, mr);
 
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_USB0_IRQ_0]);
+    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
 
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
-    memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
+    memory_region_add_subregion(&s->mr_ps, map->ctrl, mr);
+
+    node = versal_fdt_add_simple_subnode(s, "/usb", map->ctrl, 0x10000,
+                                         compat_versal_dwc3,
+                                         sizeof(compat_versal_dwc3));
+    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
+                         clocknames, sizeof(clocknames));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
+                               s->phandle.clk_25mhz, s->phandle.clk_125mhz);
+    qemu_fdt_setprop(s->cfg.fdt, node, "ranges", NULL, 0);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#address-cells", 2);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#size-cells", 2);
+
+    subnode = g_strdup_printf("/%s/dwc3", node);
+    g_free(node);
+
+    node = versal_fdt_add_simple_subnode(s, subnode, map->xhci, 0x10000,
+                                         compat_dwc3,
+                                         sizeof(compat_dwc3));
+    qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-names",
+                     irq_name, sizeof(irq_name));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, map->irq,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node,
+                          "snps,quirk-frame-length-adjustment", 0x20);
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "#stream-id-cells", 1);
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "dr_mode", "host");
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "phy-names", "usb3-phy");
+    qemu_fdt_setprop(s->cfg.fdt, node, "snps,dis_u2_susphy_quirk", NULL, 0);
+    qemu_fdt_setprop(s->cfg.fdt, node, "snps,dis_u3_susphy_quirk", NULL, 0);
+    qemu_fdt_setprop(s->cfg.fdt, node, "snps,refclk_fladj", NULL, 0);
+    qemu_fdt_setprop(s->cfg.fdt, node, "snps,mask_phy_reset", NULL, 0);
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "maximum-speed", "high-speed");
 }
 
 static void versal_create_gem(Versal *s,
                               const struct VersalGemMap *map)
 {
@@ -1009,14 +1058,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
         object_property_set_link(OBJECT(&s->lpd.crl),
                                  name, OBJECT(&s->lpd.rpu.cpu[i]),
                                  &error_abort);
     }
 
-    object_property_set_link(OBJECT(&s->lpd.crl),
-                             "usb", OBJECT(&s->lpd.iou.usb),
-                             &error_abort);
-
     sysbus_realize(sbd, &error_fatal);
     memory_region_add_subregion(&s->mr_ps, MM_CRL,
                                 sysbus_mmio_get_region(sbd, 0));
     sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
 }
@@ -1198,11 +1243,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
         versal_create_zdma(s, &map->zdma[i]);
     }
 
     versal_create_xrams(s, &map->xram);
 
-    versal_create_usbs(s, pic);
+    for (i = 0; i < map->num_usb; i++) {
+        versal_create_usb(s, &map->usb[i]);
+    }
+
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_bbram(s, pic);
     versal_create_efuse(s, pic);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 11/48] hw/arm/xlnx-versal: efuse: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (9 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 10/48] hw/arm/xlnx-versal: usb: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 13:25   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 12/48] hw/arm/xlnx-versal: ospi: " Luc Michel
                   ` (36 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactore the eFuse devices creation using the VersalMap structure.

Note that the corresponding FDT nodes are removed. They do not
correspond to any real node in standard Versal DTBs. No matching drivers
exist for them.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  5 +--
 hw/arm/xlnx-versal-virt.c    | 43 ++------------------
 hw/arm/xlnx-versal.c         | 78 +++++++++++++++++++++++-------------
 3 files changed, 54 insertions(+), 72 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 5d4b30f0ff9..79ca9b13321 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -18,11 +18,10 @@
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/nvram/xlnx-bbram.h"
-#include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/misc/xlnx-versal-trng.h"
@@ -100,13 +99,10 @@ struct Versal {
         } iou;
 
         XlnxZynqMPRTC rtc;
         XlnxVersalTRng trng;
         XlnxBBRam bbram;
-        XlnxEFuse efuse;
-        XlnxVersalEFuseCtrl efuse_ctrl;
-        XlnxVersalEFuseCache efuse_cache;
         XlnxVersalCFUAPB cfu_apb;
         XlnxVersalCFUFDRO cfu_fdro;
         XlnxVersalCFUSFR cfu_sfr;
         XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
         XlnxVersalCFrameBcastReg cframe_bcast;
@@ -137,10 +133,11 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
     g_assert(!qdev_is_realized(DEVICE(s)));
     s->cfg.fdt = fdt;
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
+void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
 
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 36341b825eb..d3c84d1955a 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -190,45 +190,10 @@ static void fdt_add_bbram_node(VersalVirt *s)
                                  2, MM_PMC_BBRAM_CTRL_SIZE);
     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
     g_free(name);
 }
 
-static void fdt_add_efuse_ctrl_node(VersalVirt *s)
-{
-    const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
-    const char interrupt_names[] = "pmc_efuse";
-    char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-
-    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
-                     interrupt_names, sizeof(interrupt_names));
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_PMC_EFUSE_CTRL,
-                                 2, MM_PMC_EFUSE_CTRL_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-    g_free(name);
-}
-
-static void fdt_add_efuse_cache_node(VersalVirt *s)
-{
-    const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
-    char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
-                                 MM_PMC_EFUSE_CACHE);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_PMC_EFUSE_CACHE,
-                                 2, MM_PMC_EFUSE_CACHE_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-    g_free(name);
-}
-
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
     char **node_path;
     int n = 0;
@@ -391,19 +356,19 @@ static void bbram_attach_drive(XlnxBBRam *dev)
     if (blk) {
         qdev_prop_set_drive(DEVICE(dev), "drive", blk);
     }
 }
 
-static void efuse_attach_drive(XlnxEFuse *dev)
+static void efuse_attach_drive(VersalVirt *s)
 {
     DriveInfo *dinfo;
     BlockBackend *blk;
 
     dinfo = drive_get_by_index(IF_PFLASH, 1);
     blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
     if (blk) {
-        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+        versal_efuse_attach_drive(&s->soc, blk);
     }
 }
 
 static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
 {
@@ -478,12 +443,10 @@ static void versal_virt_init(MachineState *machine)
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_rtc_node(s);
     fdt_add_bbram_node(s);
-    fdt_add_efuse_ctrl_node(s);
-    fdt_add_efuse_cache_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
     fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
     fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
 
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
@@ -496,11 +459,11 @@ static void versal_virt_init(MachineState *machine)
 
     /* Attach bbram backend, if given */
     bbram_attach_drive(&s->soc.pmc.bbram);
 
     /* Attach efuse backend, if given */
-    efuse_attach_drive(&s->soc.pmc.efuse);
+    efuse_attach_drive(s);
 
     /* Plug SD cards */
     for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
         sd_plug_card(s, i, drive_get(IF_SD, 0, i));
     }
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 4e4df0851e8..ed202b0fcda 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -31,10 +31,11 @@
 #include "hw/sd/sdhci.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
+#include "hw/nvram/xlnx-versal-efuse.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -86,10 +87,16 @@ typedef struct VersalMap {
         uint64_t xhci;
         uint64_t ctrl;
         int irq;
     } usb[2];
     size_t num_usb;
+
+    struct VersalEfuseMap {
+        uint64_t ctrl;
+        uint64_t cache;
+        int irq;
+    } efuse;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -117,10 +124,12 @@ static const VersalMap VERSAL_MAP = {
         .irq = 79,
     },
 
     .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
     .num_usb = 1,
+
+    .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -744,46 +753,45 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic)
                                 sysbus_mmio_get_region(sbd, 0));
     sysbus_connect_irq(sbd, 0,
                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1));
 }
 
-static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base)
+static void versal_create_efuse(Versal *s,
+                                const struct VersalEfuseMap *map)
 {
-    SysBusDevice *part = SYS_BUS_DEVICE(dev);
+    DeviceState *bits;
+    DeviceState *ctrl;
+    DeviceState *cache;
 
-    object_property_set_link(OBJECT(part), "efuse",
-                             OBJECT(&s->pmc.efuse), &error_abort);
+    ctrl = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CTRL);
+    cache = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CACHE);
+    bits = qdev_new(TYPE_XLNX_EFUSE);
 
-    sysbus_realize(part, &error_abort);
-    memory_region_add_subregion(&s->mr_ps, base,
-                                sysbus_mmio_get_region(part, 0));
-}
+    qdev_prop_set_uint32(bits, "efuse-nr", 3);
+    qdev_prop_set_uint32(bits, "efuse-size", 8192);
 
-static void versal_create_efuse(Versal *s, qemu_irq *pic)
-{
-    Object *bits = OBJECT(&s->pmc.efuse);
-    Object *ctrl = OBJECT(&s->pmc.efuse_ctrl);
-    Object *cache = OBJECT(&s->pmc.efuse_cache);
+    object_property_add_child(OBJECT(s), "efuse", OBJECT(bits));
+    qdev_realize_and_unref(bits, NULL, &error_abort);
 
-    object_initialize_child(OBJECT(s), "efuse-ctrl", &s->pmc.efuse_ctrl,
-                            TYPE_XLNX_VERSAL_EFUSE_CTRL);
+    object_property_set_link(OBJECT(ctrl), "efuse", OBJECT(bits), &error_abort);
 
-    object_initialize_child(OBJECT(s), "efuse-cache", &s->pmc.efuse_cache,
-                            TYPE_XLNX_VERSAL_EFUSE_CACHE);
+    object_property_set_link(OBJECT(cache), "efuse", OBJECT(bits),
+                             &error_abort);
 
-    object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
-                                       sizeof(s->pmc.efuse),
-                                       TYPE_XLNX_EFUSE, &error_abort,
-                                       "efuse-nr", "3",
-                                       "efuse-size", "8192",
-                                       NULL);
+    object_property_add_child(OBJECT(s), "efuse-cache", OBJECT(cache));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(cache), &error_abort);
 
-    qdev_realize(DEVICE(bits), NULL, &error_abort);
-    versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL);
-    versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE);
+    object_property_add_child(OBJECT(s), "efuse-ctrl", OBJECT(ctrl));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(ctrl), &error_abort);
 
-    sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]);
+    memory_region_add_subregion(&s->mr_ps, map->ctrl,
+                                sysbus_mmio_get_region(SYS_BUS_DEVICE(ctrl),
+                                                       0));
+    memory_region_add_subregion(&s->mr_ps, map->cache,
+                                sysbus_mmio_get_region(SYS_BUS_DEVICE(cache),
+                                                       0));
+    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(ctrl), 0, map->irq);
 }
 
 static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
 {
     SysBusDevice *sbd;
@@ -1247,15 +1255,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < map->num_usb; i++) {
         versal_create_usb(s, &map->usb[i]);
     }
 
+    versal_create_efuse(s, &map->efuse);
+
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_bbram(s, pic);
-    versal_create_efuse(s, pic);
     versal_create_pmc_iou_slcr(s, pic);
     versal_create_ospi(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
@@ -1286,10 +1295,23 @@ void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
     qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
     qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
                            &error_fatal);
 }
 
+void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
+{
+    DeviceState *efuse;
+
+    efuse = DEVICE(versal_get_child(s, "efuse"));
+
+    if (efuse == NULL) {
+        return;
+    }
+
+    qdev_prop_set_drive(efuse, "drive", blk);
+}
+
 int versal_get_num_can(VersalVersion version)
 {
     const VersalMap *map = VERSION_TO_MAP[version];
 
     return map->num_canfd;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 12/48] hw/arm/xlnx-versal: ospi: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (10 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 11/48] hw/arm/xlnx-versal: efuse: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 13:34   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs Luc Michel
                   ` (35 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the OSPI controller creation using the VersalMap structure.

Note that the connection to the PMC IOU SLCR is removed for now and will
be re-added by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  12 +--
 hw/arm/xlnx-versal-virt.c    |  41 ++++------
 hw/arm/xlnx-versal.c         | 142 ++++++++++++++++++++---------------
 3 files changed, 98 insertions(+), 97 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 79ca9b13321..b7ef255d6fd 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -18,12 +18,10 @@
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/nvram/xlnx-bbram.h"
-#include "hw/ssi/xlnx-versal-ospi.h"
-#include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/misc/xlnx-versal-trng.h"
 #include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
@@ -86,18 +84,10 @@ struct Versal {
 
     /* The Platform Management Controller subsystem.  */
     struct {
         struct {
             XlnxVersalPmcIouSlcr slcr;
-
-            struct {
-                XlnxVersalOspi ospi;
-                XlnxCSUDMA dma_src;
-                XlnxCSUDMA dma_dst;
-                MemoryRegion linear_mr;
-                OrIRQState irq_orgate;
-            } ospi;
         } iou;
 
         XlnxZynqMPRTC rtc;
         XlnxVersalTRng trng;
         XlnxBBRam bbram;
@@ -134,10 +124,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
     s->cfg.fdt = fdt;
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
 void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
+void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
+                              BlockBackend *blk);
 
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index d3c84d1955a..43f3c3d0be9 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -46,12 +46,12 @@ struct VersalVirt {
 
     CanBusState **canbus;
 
     struct {
         bool secure;
+        char *ospi_model;
     } cfg;
-    char *ospi_model;
 };
 
 static void fdt_create(VersalVirt *s)
 {
     MachineClass *mc = MACHINE_GET_CLASS(s);
@@ -379,19 +379,19 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
 
 static char *versal_get_ospi_model(Object *obj, Error **errp)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
 
-    return g_strdup(s->ospi_model);
+    return g_strdup(s->cfg.ospi_model);
 }
 
 static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
 
-    g_free(s->ospi_model);
-    s->ospi_model = g_strdup(value);
+    g_free(s->cfg.ospi_model);
+    s->cfg.ospi_model = g_strdup(value);
 }
 
 
 static void versal_virt_init(MachineState *machine)
 {
@@ -480,42 +480,31 @@ static void versal_virt_init(MachineState *machine)
         s->binfo.dtb_limit = 0x1000000;
     }
     arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
 
     for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
-        BusState *spi_bus;
-        DeviceState *flash_dev;
         ObjectClass *flash_klass;
-        qemu_irq cs_line;
         DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
+        BlockBackend *blk;
+        const char *mdl;
 
-        spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
-
-        if (s->ospi_model) {
-            flash_klass = object_class_by_name(s->ospi_model);
+        if (s->cfg.ospi_model) {
+            flash_klass = object_class_by_name(s->cfg.ospi_model);
             if (!flash_klass ||
                 object_class_is_abstract(flash_klass) ||
                 !object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
                 error_report("'%s' is either abstract or"
-                       " not a subtype of m25p80", s->ospi_model);
+                       " not a subtype of m25p80", s->cfg.ospi_model);
                 exit(1);
             }
+            mdl = s->cfg.ospi_model;
+        } else {
+            mdl = "mt35xu01g";
         }
 
-        flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
-
-        if (dinfo) {
-            qdev_prop_set_drive_err(flash_dev, "drive",
-                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
-        }
-        qdev_prop_set_uint8(flash_dev, "cs", i);
-        qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
-
-        cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
-
-        sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
-                           i + 1, cs_line);
+        blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+        versal_ospi_create_flash(&s->soc, i, mdl, blk);
     }
 }
 
 static void versal_virt_machine_instance_init(Object *obj)
 {
@@ -540,11 +529,11 @@ static void versal_virt_machine_instance_init(Object *obj)
 
 static void versal_virt_machine_finalize(Object *obj)
 {
     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
 
-    g_free(s->ospi_model);
+    g_free(s->cfg.ospi_model);
     g_free(s->canbus);
 }
 
 static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
 {
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index ed202b0fcda..58176fa11e5 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -32,10 +32,11 @@
 #include "hw/net/cadence_gem.h"
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
+#include "hw/ssi/xlnx-versal-ospi.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -93,10 +94,19 @@ typedef struct VersalMap {
     struct VersalEfuseMap {
         uint64_t ctrl;
         uint64_t cache;
         int irq;
     } efuse;
+
+    struct VersalOspiMap {
+        uint64_t ctrl;
+        uint64_t dac;
+        uint64_t dac_sz;
+        uint64_t dma_src;
+        uint64_t dma_dst;
+        int irq;
+    } ospi;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -126,10 +136,17 @@ static const VersalMap VERSAL_MAP = {
 
     .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
     .num_usb = 1,
 
     .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
+
+    .ospi = {
+        .ctrl = 0xf1010000,
+        .dac = 0xc0000000, .dac_sz = 0x20000000,
+        .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
+        .irq = 124,
+    },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -807,99 +824,78 @@ static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
 
     sysbus_connect_irq(sbd, 0,
                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
 }
 
-static void versal_create_ospi(Versal *s, qemu_irq *pic)
+static DeviceState *versal_create_ospi(Versal *s,
+                                       const struct VersalOspiMap *map)
 {
     SysBusDevice *sbd;
     MemoryRegion *mr_dac;
-    qemu_irq ospi_mux_sel;
-    DeviceState *orgate;
+    DeviceState *dev, *dma_dst, *dma_src, *orgate;
+    MemoryRegion *linear_mr = g_new(MemoryRegion, 1);
 
-    memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s),
-                       "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE);
+    dev = qdev_new(TYPE_XILINX_VERSAL_OSPI);
+    object_property_add_child(OBJECT(s), "ospi", OBJECT(dev));
 
-    object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi,
-                            TYPE_XILINX_VERSAL_OSPI);
+    memory_region_init(linear_mr, OBJECT(dev), "linear-mr", map->dac_sz);
 
-    mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1);
-    memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac);
+    mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+    memory_region_add_subregion(linear_mr, 0x0, mr_dac);
 
     /* Create the OSPI destination DMA */
-    object_initialize_child(OBJECT(s), "versal-ospi-dma-dst",
-                            &s->pmc.iou.ospi.dma_dst,
-                            TYPE_XLNX_CSU_DMA);
+    dma_dst = qdev_new(TYPE_XLNX_CSU_DMA);
+    object_property_add_child(OBJECT(dev), "dma-dst-dev", OBJECT(dma_dst));
+    object_property_set_link(OBJECT(dma_dst), "dma",
+                             OBJECT(get_system_memory()), &error_abort);
 
-    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst),
-                            "dma", OBJECT(get_system_memory()),
-                             &error_abort);
+    sbd = SYS_BUS_DEVICE(dma_dst);
+    sysbus_realize_and_unref(sbd, &error_fatal);
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst);
-    sysbus_realize(sbd, &error_fatal);
-
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST,
+    memory_region_add_subregion(&s->mr_ps, map->dma_dst,
                                 sysbus_mmio_get_region(sbd, 0));
 
     /* Create the OSPI source DMA */
-    object_initialize_child(OBJECT(s), "versal-ospi-dma-src",
-                            &s->pmc.iou.ospi.dma_src,
-                            TYPE_XLNX_CSU_DMA);
+    dma_src = qdev_new(TYPE_XLNX_CSU_DMA);
+    object_property_add_child(OBJECT(dev), "dma-src-dev", OBJECT(dma_src));
 
-    object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst",
-                             false, &error_abort);
+    object_property_set_bool(OBJECT(dma_src), "is-dst", false, &error_abort);
 
-    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
-                            "dma", OBJECT(mr_dac), &error_abort);
-
-    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
-                            "stream-connected-dma",
-                             OBJECT(&s->pmc.iou.ospi.dma_dst),
+    object_property_set_link(OBJECT(dma_src), "dma", OBJECT(mr_dac),
                              &error_abort);
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src);
-    sysbus_realize(sbd, &error_fatal);
+    object_property_set_link(OBJECT(dma_src), "stream-connected-dma",
+                             OBJECT(dma_dst), &error_abort);
 
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC,
+    sbd = SYS_BUS_DEVICE(dma_src);
+    sysbus_realize_and_unref(sbd, &error_fatal);
+
+    memory_region_add_subregion(&s->mr_ps, map->dma_src,
                                 sysbus_mmio_get_region(sbd, 0));
 
     /* Realize the OSPI */
-    object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src",
-                             OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort);
+    object_property_set_link(OBJECT(dev), "dma-src",
+                             OBJECT(dma_src), &error_abort);
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi);
-    sysbus_realize(sbd, &error_fatal);
+    sbd = SYS_BUS_DEVICE(dev);
+    sysbus_realize_and_unref(sbd, &error_fatal);
 
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI,
+    memory_region_add_subregion(&s->mr_ps, map->ctrl,
                                 sysbus_mmio_get_region(sbd, 0));
 
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC,
-                                &s->pmc.iou.ospi.linear_mr);
-
-    /* ospi_mux_sel */
-    ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi),
-                                          "ospi-mux-sel", 0);
-    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0,
-                                ospi_mux_sel);
+    memory_region_add_subregion(&s->mr_ps, map->dac,
+                                linear_mr);
 
     /* OSPI irq */
-    object_initialize_child(OBJECT(s), "ospi-irq-orgate",
-                            &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ);
-    object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate),
-                            "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal);
+    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
+                            map->irq);
 
-    orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate);
-    qdev_realize(orgate, NULL, &error_fatal);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
 
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0,
-                       qdev_get_gpio_in(orgate, 0));
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0,
-                       qdev_get_gpio_in(orgate, 1));
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0,
-                       qdev_get_gpio_in(orgate, 2));
-
-    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
+    return dev;
 }
 
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
     SysBusDevice *sbd;
@@ -1256,17 +1252,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < map->num_usb; i++) {
         versal_create_usb(s, &map->usb[i]);
     }
 
     versal_create_efuse(s, &map->efuse);
+    versal_create_ospi(s, &map->ospi);
 
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_bbram(s, pic);
     versal_create_pmc_iou_slcr(s, pic);
-    versal_create_ospi(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
@@ -1308,10 +1304,34 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
     }
 
     qdev_prop_set_drive(efuse, "drive", blk);
 }
 
+void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
+                              BlockBackend *blk)
+{
+    BusState *spi_bus;
+    DeviceState *flash, *ospi;
+    qemu_irq cs_line;
+
+    ospi = DEVICE(versal_get_child(s, "ospi"));
+    spi_bus = qdev_get_child_bus(ospi, "spi0");
+
+    flash = qdev_new(flash_mdl);
+
+    if (blk) {
+        qdev_prop_set_drive_err(flash, "drive", blk, &error_fatal);
+    }
+    qdev_prop_set_uint8(flash, "cs", flash_idx);
+    qdev_realize_and_unref(flash, spi_bus, &error_fatal);
+
+    cs_line = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
+
+    sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
+                       flash_idx + 1, cs_line);
+}
+
 int versal_get_num_can(VersalVersion version)
 {
     const VersalMap *map = VERSION_TO_MAP[version];
 
     return map->num_canfd;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (11 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 12/48] hw/arm/xlnx-versal: ospi: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 13:42   ` Francisco Iglesias
  2025-08-04 12:24   ` Peter Maydell
  2025-07-16  9:53 ` [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation Luc Michel
                   ` (34 subsequent siblings)
  47 siblings, 2 replies; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Improve the IRQ index in the VersalMap structure to turn it into a
descriptor:
   - the lower 16 bits still represent the IRQ index
   - bit 18 is used to indicate a shared IRQ connected to a OR gate
   - bits 19 to 22 indicate the index on the OR gate.

This allows to share an IRQ among multiple devices. An OR gate is
created to connect the devices to the actual IRQ pin.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 62 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 58176fa11e5..89c93278336 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -41,10 +41,21 @@
 #define GEM_REVISION        0x40070106
 
 #define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
+/*
+ * IRQ descriptor to catch the following cases:
+ *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
+ */
+FIELD(VERSAL_IRQ, IRQ, 0, 16)
+FIELD(VERSAL_IRQ, ORED, 18, 1)
+FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
+
+#define OR_IRQ(irq, or_idx) \
+    (R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
+
 typedef struct VersalSimplePeriphMap {
     uint64_t addr;
     int irq;
 } VersalSimplePeriphMap;
 
@@ -172,13 +183,56 @@ static inline Object *versal_get_child_idx(Versal *s, const char *child,
     g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
 
     return versal_get_child(s, n);
 }
 
+/*
+ * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
+ * used to return the corresponding or gate input IRQ. The or gate is created if
+ * not already existant.
+ *
+ * Or gates are placed under the /soc/irq-or-gates QOM container.
+ */
+static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
+                                          qemu_irq target_irq)
+{
+    Object *container = versal_get_child(s, "irq-or-gates");
+    DeviceState *dev;
+    g_autofree char *name;
+    int idx, or_idx;
+
+    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
+    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
+
+    name = g_strdup_printf("irq[%d]", idx);
+    dev = DEVICE(object_resolve_path_at(container, name));
+
+    if (dev == NULL) {
+        dev = qdev_new(TYPE_OR_IRQ);
+        object_property_add_child(container, name, OBJECT(dev));
+        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
+        qdev_realize_and_unref(dev, NULL, &error_abort);
+        qdev_connect_gpio_out(dev, 0, target_irq);
+    }
+
+    return qdev_get_gpio_in(dev, or_idx);
+}
+
 static qemu_irq versal_get_irq(Versal *s, int irq_idx)
 {
-    return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
+    qemu_irq irq;
+    bool ored;
+
+    ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
+
+    irq = qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
+
+    if (ored) {
+        irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
+    }
+
+    return irq;
 }
 
 static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
                                       int sbd_idx, int irq_idx)
 {
@@ -1209,10 +1263,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
 
 static void versal_realize(DeviceState *dev, Error **errp)
 {
     Versal *s = XLNX_VERSAL_BASE(dev);
     qemu_irq pic[XLNX_VERSAL_NR_IRQS];
+    Object *container;
     const VersalMap *map = versal_get_map(s);
     size_t i;
 
     if (s->cfg.fdt == NULL) {
         int fdt_size;
@@ -1223,10 +1278,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
     s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
     s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
 
     versal_create_apu_cpus(s);
     versal_create_apu_gic(s, pic);
+
+    container = object_new(TYPE_CONTAINER);
+    object_property_add_child(OBJECT(s), "irq-or-gates", container);
+    object_unref(container);
+
     versal_create_rpu_cpus(s);
 
     for (i = 0; i < map->num_uart; i++) {
         versal_create_uart(s, &map->uart[i], i);
     }
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (12 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 19:41   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 15/48] hw/arm/xlnx-versal: bbram: " Luc Michel
                   ` (33 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the PMC IOU SLCR device creation using the VersalMap structure.
This is the first user of a shared IRQ using an OR gate. The OSPI
controller is reconnected to the SLCR.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  5 ----
 hw/arm/xlnx-versal.c         | 48 +++++++++++++++++++++---------------
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index b7ef255d6fd..78442e6c2c5 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -19,11 +19,10 @@
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/nvram/xlnx-bbram.h"
 #include "hw/misc/xlnx-versal-crl.h"
-#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/misc/xlnx-versal-trng.h"
 #include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "target/arm/cpu.h"
@@ -82,14 +81,10 @@ struct Versal {
         XlnxVersalCRL crl;
     } lpd;
 
     /* The Platform Management Controller subsystem.  */
     struct {
-        struct {
-            XlnxVersalPmcIouSlcr slcr;
-        } iou;
-
         XlnxZynqMPRTC rtc;
         XlnxVersalTRng trng;
         XlnxBBRam bbram;
         XlnxVersalCFUAPB cfu_apb;
         XlnxVersalCFUFDRO cfu_fdro;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 89c93278336..d34a36e18aa 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -33,10 +33,11 @@
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
+#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -114,10 +115,12 @@ typedef struct VersalMap {
         uint64_t dac_sz;
         uint64_t dma_src;
         uint64_t dma_dst;
         int irq;
     } ospi;
+
+    VersalSimplePeriphMap pmc_iou_slcr;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -154,10 +157,12 @@ static const VersalMap VERSAL_MAP = {
         .ctrl = 0xf1010000,
         .dac = 0xc0000000, .dac_sz = 0x20000000,
         .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
         .irq = 124,
     },
+
+    .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -861,25 +866,28 @@ static void versal_create_efuse(Versal *s,
                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(cache),
                                                        0));
     versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(ctrl), 0, map->irq);
 }
 
-static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
+static DeviceState *versal_create_pmc_iou_slcr(Versal *s,
+                                               const VersalSimplePeriphMap *map)
 {
     SysBusDevice *sbd;
+    DeviceState *dev;
 
-    object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr,
-                            TYPE_XILINX_VERSAL_PMC_IOU_SLCR);
+    dev = qdev_new(TYPE_XILINX_VERSAL_PMC_IOU_SLCR);
+    object_property_add_child(OBJECT(s), "pmc-iou-slcr", OBJECT(dev));
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr);
-    sysbus_realize(sbd, &error_fatal);
+    sbd = SYS_BUS_DEVICE(dev);
+    sysbus_realize_and_unref(sbd, &error_fatal);
 
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR,
+    memory_region_add_subregion(&s->mr_ps, map->addr,
                                 sysbus_mmio_get_region(sbd, 0));
 
-    sysbus_connect_irq(sbd, 0,
-                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
+    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
+
+    return dev;
 }
 
 static DeviceState *versal_create_ospi(Versal *s,
                                        const struct VersalOspiMap *map)
 {
@@ -1201,10 +1209,11 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
                   "is not yet implemented\n");
 }
 
 static void versal_unimp(Versal *s)
 {
+    DeviceState *slcr;
     qemu_irq gpio_in;
 
     versal_unimp_area(s, "psm", &s->mr_ps,
                         MM_PSM_START, MM_PSM_END - MM_PSM_START);
     versal_unimp_area(s, "crf", &s->mr_ps,
@@ -1223,27 +1232,22 @@ static void versal_unimp(Versal *s)
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
                             "qspi-ospi-mux-sel-dummy", 1);
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr,
                             "irq-parity-imr-dummy", 1);
 
+    slcr = DEVICE(versal_get_child(s, "pmc-iou-slcr"));
     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0);
-    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0,
-                                gpio_in);
+    qdev_connect_gpio_out_named(slcr, "sd-emmc-sel", 0, gpio_in);
 
     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1);
-    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1,
-                                gpio_in);
+    qdev_connect_gpio_out_named(slcr, "sd-emmc-sel", 1, gpio_in);
 
     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0);
-    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
-                                "qspi-ospi-mux-sel", 0,
-                                gpio_in);
+    qdev_connect_gpio_out_named(slcr, "qspi-ospi-mux-sel", 0, gpio_in);
 
     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0);
-    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
-                                SYSBUS_DEVICE_GPIO_IRQ, 0,
-                                gpio_in);
+    qdev_connect_gpio_out_named(slcr, SYSBUS_DEVICE_GPIO_IRQ, 0, gpio_in);
 }
 
 static uint32_t fdt_add_clk_node(Versal *s, const char *name,
                                  unsigned int freq_hz)
 {
@@ -1262,10 +1266,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
 }
 
 static void versal_realize(DeviceState *dev, Error **errp)
 {
     Versal *s = XLNX_VERSAL_BASE(dev);
+    DeviceState *slcr, *ospi;
     qemu_irq pic[XLNX_VERSAL_NR_IRQS];
     Object *container;
     const VersalMap *map = versal_get_map(s);
     size_t i;
 
@@ -1312,17 +1317,20 @@ static void versal_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < map->num_usb; i++) {
         versal_create_usb(s, &map->usb[i]);
     }
 
     versal_create_efuse(s, &map->efuse);
-    versal_create_ospi(s, &map->ospi);
+    ospi = versal_create_ospi(s, &map->ospi);
+    slcr = versal_create_pmc_iou_slcr(s, &map->pmc_iou_slcr);
 
+    qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
+                                qdev_get_gpio_in_named(ospi,
+                                                       "ospi-mux-sel", 0));
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
     versal_create_bbram(s, pic);
-    versal_create_pmc_iou_slcr(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 15/48] hw/arm/xlnx-versal: bbram: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (13 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 19:48   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 16/48] hw/arm/xlnx-versal: trng: " Luc Michel
                   ` (32 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the BBRAM device creation using the VersalMap structure.

Note that the corresponding FDT node is removed. It does not correspond
to any real node in standard Versal DTBs. No matching drivers exist for
it.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  3 +--
 hw/arm/xlnx-versal-virt.c    | 27 +++---------------------
 hw/arm/xlnx-versal.c         | 41 +++++++++++++++++++++++++-----------
 3 files changed, 33 insertions(+), 38 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 78442e6c2c5..9adce02f8a9 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -17,11 +17,10 @@
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
-#include "hw/nvram/xlnx-bbram.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-trng.h"
 #include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
@@ -83,11 +82,10 @@ struct Versal {
 
     /* The Platform Management Controller subsystem.  */
     struct {
         XlnxZynqMPRTC rtc;
         XlnxVersalTRng trng;
-        XlnxBBRam bbram;
         XlnxVersalCFUAPB cfu_apb;
         XlnxVersalCFUFDRO cfu_fdro;
         XlnxVersalCFUSFR cfu_sfr;
         XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
         XlnxVersalCFrameBcastReg cframe_bcast;
@@ -119,10 +117,11 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
     s->cfg.fdt = fdt;
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
 void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
+void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
 void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
                               BlockBackend *blk);
 
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 43f3c3d0be9..2d7e8a5955a 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -170,30 +170,10 @@ static void fdt_add_rtc_node(VersalVirt *s)
                                  2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
     g_free(name);
 }
 
-static void fdt_add_bbram_node(VersalVirt *s)
-{
-    const char compat[] = TYPE_XLNX_BBRAM;
-    const char interrupt_names[] = "bbram-error";
-    char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-
-    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
-                     interrupt_names, sizeof(interrupt_names));
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_PMC_BBRAM_CTRL,
-                                 2, MM_PMC_BBRAM_CTRL_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-    g_free(name);
-}
-
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
     char **node_path;
     int n = 0;
@@ -344,19 +324,19 @@ static void create_virtio_regions(VersalVirt *s)
         qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
         g_free(name);
     }
 }
 
-static void bbram_attach_drive(XlnxBBRam *dev)
+static void bbram_attach_drive(VersalVirt *s)
 {
     DriveInfo *dinfo;
     BlockBackend *blk;
 
     dinfo = drive_get_by_index(IF_PFLASH, 0);
     blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
     if (blk) {
-        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+        versal_bbram_attach_drive(&s->soc, blk);
     }
 }
 
 static void efuse_attach_drive(VersalVirt *s)
 {
@@ -442,11 +422,10 @@ static void versal_virt_init(MachineState *machine)
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
     fdt_add_rtc_node(s);
-    fdt_add_bbram_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
     fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
     fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
 
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
@@ -456,11 +435,11 @@ static void versal_virt_init(MachineState *machine)
      * modules unaware of multiple address-spaces.  */
     memory_region_add_subregion_overlap(get_system_memory(),
                                         0, &s->soc.fpd.apu.mr, 0);
 
     /* Attach bbram backend, if given */
-    bbram_attach_drive(&s->soc.pmc.bbram);
+    bbram_attach_drive(s);
 
     /* Attach efuse backend, if given */
     efuse_attach_drive(s);
 
     /* Plug SD cards */
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index d34a36e18aa..615eea54372 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -34,10 +34,11 @@
 #include "hw/misc/xlnx-versal-xramc.h"
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
+#include "hw/nvram/xlnx-bbram.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -117,10 +118,11 @@ typedef struct VersalMap {
         uint64_t dma_dst;
         int irq;
     } ospi;
 
     VersalSimplePeriphMap pmc_iou_slcr;
+    VersalSimplePeriphMap bbram;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -159,10 +161,11 @@ static const VersalMap VERSAL_MAP = {
         .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
         .irq = 124,
     },
 
     .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
+    .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -811,26 +814,25 @@ static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
 
         sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(or, i));
     }
 }
 
-static void versal_create_bbram(Versal *s, qemu_irq *pic)
+static void versal_create_bbram(Versal *s,
+                                const VersalSimplePeriphMap *map)
 {
+    DeviceState *dev;
     SysBusDevice *sbd;
 
-    object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram,
-                                       sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM,
-                                       &error_fatal,
-                                       "crc-zpads", "0",
-                                       NULL);
-    sbd = SYS_BUS_DEVICE(&s->pmc.bbram);
+    dev = qdev_new(TYPE_XLNX_BBRAM);
+    sbd = SYS_BUS_DEVICE(dev);
 
-    sysbus_realize(sbd, &error_fatal);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL,
+    object_property_add_child(OBJECT(s), "bbram", OBJECT(dev));
+    qdev_prop_set_uint32(dev, "crc-zpads", 0);
+    sysbus_realize_and_unref(sbd, &error_abort);
+    memory_region_add_subregion(&s->mr_ps, map->addr,
                                 sysbus_mmio_get_region(sbd, 0));
-    sysbus_connect_irq(sbd, 0,
-                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1));
+    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
 }
 
 static void versal_create_efuse(Versal *s,
                                 const struct VersalEfuseMap *map)
 {
@@ -1323,14 +1325,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
     slcr = versal_create_pmc_iou_slcr(s, &map->pmc_iou_slcr);
 
     qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
                                 qdev_get_gpio_in_named(ospi,
                                                        "ospi-mux-sel", 0));
+
+    versal_create_bbram(s, &map->bbram);
+
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
     versal_create_trng(s, pic);
-    versal_create_bbram(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
@@ -1372,10 +1376,23 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
     }
 
     qdev_prop_set_drive(efuse, "drive", blk);
 }
 
+void versal_bbram_attach_drive(Versal *s, BlockBackend *blk)
+{
+    DeviceState *bbram;
+
+    bbram = DEVICE(versal_get_child(s, "bbram"));
+
+    if (bbram == NULL) {
+        return;
+    }
+
+    qdev_prop_set_drive(bbram, "drive", blk);
+}
+
 void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
                               BlockBackend *blk)
 {
     BusState *spi_bus;
     DeviceState *flash, *ospi;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 16/48] hw/arm/xlnx-versal: trng: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (14 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 15/48] hw/arm/xlnx-versal: bbram: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 19:50   ` Francisco Iglesias
  2025-07-16  9:53 ` [PATCH 17/48] hw/arm/xlnx-versal: rtc: " Luc Michel
                   ` (31 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the TRNG device creation using the VersalMap structure.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  2 --
 hw/arm/xlnx-versal.c         | 18 ++++++++++--------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9adce02f8a9..bba96201d37 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -18,11 +18,10 @@
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/misc/xlnx-versal-crl.h"
-#include "hw/misc/xlnx-versal-trng.h"
 #include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
@@ -81,11 +80,10 @@ struct Versal {
     } lpd;
 
     /* The Platform Management Controller subsystem.  */
     struct {
         XlnxZynqMPRTC rtc;
-        XlnxVersalTRng trng;
         XlnxVersalCFUAPB cfu_apb;
         XlnxVersalCFUFDRO cfu_fdro;
         XlnxVersalCFUSFR cfu_sfr;
         XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
         XlnxVersalCFrameBcastReg cframe_bcast;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 615eea54372..45d9fc1e282 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -35,10 +35,11 @@
 #include "hw/usb/xlnx-usb-subsystem.h"
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/nvram/xlnx-bbram.h"
+#include "hw/misc/xlnx-versal-trng.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -119,10 +120,11 @@ typedef struct VersalMap {
         int irq;
     } ospi;
 
     VersalSimplePeriphMap pmc_iou_slcr;
     VersalSimplePeriphMap bbram;
+    VersalSimplePeriphMap trng;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -162,10 +164,11 @@ static const VersalMap VERSAL_MAP = {
         .irq = 124,
     },
 
     .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
     .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
+    .trng = { 0xf1230000, 141 },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -771,23 +774,22 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
      */
     sysbus_connect_irq(sbd, 1,
                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0));
 }
 
-static void versal_create_trng(Versal *s, qemu_irq *pic)
+static void versal_create_trng(Versal *s, const VersalSimplePeriphMap *map)
 {
     SysBusDevice *sbd;
     MemoryRegion *mr;
 
-    object_initialize_child(OBJECT(s), "trng", &s->pmc.trng,
-                            TYPE_XLNX_VERSAL_TRNG);
-    sbd = SYS_BUS_DEVICE(&s->pmc.trng);
-    sysbus_realize(sbd, &error_fatal);
+    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_VERSAL_TRNG));
+    object_property_add_child(OBJECT(s), "trng", OBJECT(sbd));
+    sysbus_realize_and_unref(sbd, &error_abort);
 
     mr = sysbus_mmio_get_region(sbd, 0);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr);
-    sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
+    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
+    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
 }
 
 static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
 {
     SysBusDevice *sbd;
@@ -1327,14 +1329,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
                                 qdev_get_gpio_in_named(ospi,
                                                        "ospi-mux-sel", 0));
 
     versal_create_bbram(s, &map->bbram);
+    versal_create_trng(s, &map->trng);
 
     versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_rtc(s, pic);
-    versal_create_trng(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 17/48] hw/arm/xlnx-versal: rtc: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (15 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 16/48] hw/arm/xlnx-versal: trng: " Luc Michel
@ 2025-07-16  9:53 ` Luc Michel
  2025-07-29 19:54   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 18/48] hw/arm/xlnx-versal: cfu: " Luc Michel
                   ` (30 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:53 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the RTC device creation using the VersalMap structure.

The sysbus IRQ output 0 (APB IRQ) is connected instead of the output 1
(addr error IRQ). This does not change the current behaviour since the
RTC model does not implement those IRQs anyway.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  2 --
 hw/arm/xlnx-versal-virt.c    | 22 --------------------
 hw/arm/xlnx-versal.c         | 40 ++++++++++++++++++++++++++++--------
 3 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index bba96201d37..abdbed15689 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -15,11 +15,10 @@
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
-#include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "qom/object.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "net/can_emu.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
@@ -79,11 +78,10 @@ struct Versal {
         XlnxVersalCRL crl;
     } lpd;
 
     /* The Platform Management Controller subsystem.  */
     struct {
-        XlnxZynqMPRTC rtc;
         XlnxVersalCFUAPB cfu_apb;
         XlnxVersalCFUFDRO cfu_fdro;
         XlnxVersalCFUSFR cfu_sfr;
         XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
         XlnxVersalCFrameBcastReg cframe_bcast;
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 2d7e8a5955a..01c230491df 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -149,31 +149,10 @@ static void fdt_add_timer_nodes(VersalVirt *s)
             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
     qemu_fdt_setprop(s->fdt, "/timer", "compatible",
                      compat, sizeof(compat));
 }
 
-static void fdt_add_rtc_node(VersalVirt *s)
-{
-    const char compat[] = "xlnx,zynqmp-rtc";
-    const char interrupt_names[] = "alarm\0sec";
-    char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
-
-    qemu_fdt_add_subnode(s->fdt, name);
-
-    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI,
-                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
-                     interrupt_names, sizeof(interrupt_names));
-    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
-                                 2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
-    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
-    g_free(name);
-}
-
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
     char **node_path;
     int n = 0;
@@ -421,11 +400,10 @@ static void versal_virt_init(MachineState *machine)
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
     fdt_add_gic_nodes(s);
     fdt_add_timer_nodes(s);
-    fdt_add_rtc_node(s);
     fdt_add_cpu_nodes(s, psci_conduit);
     fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
     fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
 
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 45d9fc1e282..41965531f8d 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -36,10 +36,11 @@
 #include "hw/nvram/xlnx-versal-efuse.h"
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/nvram/xlnx-bbram.h"
 #include "hw/misc/xlnx-versal-trng.h"
+#include "hw/rtc/xlnx-zynqmp-rtc.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -121,10 +122,16 @@ typedef struct VersalMap {
     } ospi;
 
     VersalSimplePeriphMap pmc_iou_slcr;
     VersalSimplePeriphMap bbram;
     VersalSimplePeriphMap trng;
+
+    struct VersalRtcMap {
+        VersalSimplePeriphMap map;
+        int alarm_irq;
+        int second_irq;
+    } rtc;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -165,10 +172,14 @@ static const VersalMap VERSAL_MAP = {
     },
 
     .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
     .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
     .trng = { 0xf1230000, 141 },
+    .rtc = {
+        { 0xf12a0000, OR_IRQ(121, 2) },
+        .alarm_irq = 142, .second_irq = 143
+    },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -753,29 +764,40 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
                             "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal);
     qdev_realize(orgate, NULL, &error_fatal);
     qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]);
 }
 
-static void versal_create_rtc(Versal *s, qemu_irq *pic)
+static void versal_create_rtc(Versal *s, const struct VersalRtcMap *map)
 {
     SysBusDevice *sbd;
     MemoryRegion *mr;
+    g_autofree char *node;
+    const char compatible[] = "xlnx,zynqmp-rtc";
+    const char interrupt_names[] = "alarm\0sec";
 
-    object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
-                            TYPE_XLNX_ZYNQMP_RTC);
-    sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
-    sysbus_realize(sbd, &error_fatal);
+    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_ZYNQMP_RTC));
+    object_property_add_child(OBJECT(s), "rtc", OBJECT(sbd));
+    sysbus_realize_and_unref(sbd, &error_abort);
 
     mr = sysbus_mmio_get_region(sbd, 0);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
+    memory_region_add_subregion(&s->mr_ps, map->map.addr, mr);
 
     /*
      * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
      * supports them.
      */
-    sysbus_connect_irq(sbd, 1,
-                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0));
+    versal_sysbus_connect_irq(s, sbd, 0, map->map.irq);
+
+    node = versal_fdt_add_simple_subnode(s, "/rtc", map->map.addr, 0x10000,
+                                         compatible, sizeof(compatible));
+    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, map->alarm_irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI,
+                           GIC_FDT_IRQ_TYPE_SPI, map->second_irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-names",
+                     interrupt_names, sizeof(interrupt_names));
 }
 
 static void versal_create_trng(Versal *s, const VersalSimplePeriphMap *map)
 {
     SysBusDevice *sbd;
@@ -1330,13 +1352,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
                                 qdev_get_gpio_in_named(ospi,
                                                        "ospi-mux-sel", 0));
 
     versal_create_bbram(s, &map->bbram);
     versal_create_trng(s, &map->trng);
+    versal_create_rtc(s, &map->rtc);
 
     versal_create_pmc_apb_irq_orgate(s, pic);
-    versal_create_rtc(s, pic);
     versal_create_crl(s, pic);
     versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 18/48] hw/arm/xlnx-versal: cfu: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (16 preceding siblings ...)
  2025-07-16  9:53 ` [PATCH 17/48] hw/arm/xlnx-versal: rtc: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 19:58   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 19/48] hw/arm/xlnx-versal: crl: " Luc Michel
                   ` (29 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the CFU device creation using the VersalMap structure. All
users of the APB IRQ OR gate have now been converted. The OR gate device
can be dropped.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  14 --
 hw/arm/xlnx-versal.c         | 258 ++++++++++++++++-------------------
 2 files changed, 115 insertions(+), 157 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index abdbed15689..5a685aea6d4 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -13,17 +13,14 @@
 #ifndef XLNX_VERSAL_H
 #define XLNX_VERSAL_H
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
-#include "hw/or-irq.h"
 #include "hw/intc/arm_gicv3.h"
 #include "qom/object.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "net/can_emu.h"
-#include "hw/misc/xlnx-versal-cfu.h"
-#include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
 
 #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
 OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
@@ -76,21 +73,10 @@ struct Versal {
         } rpu;
 
         XlnxVersalCRL crl;
     } lpd;
 
-    /* The Platform Management Controller subsystem.  */
-    struct {
-        XlnxVersalCFUAPB cfu_apb;
-        XlnxVersalCFUFDRO cfu_fdro;
-        XlnxVersalCFUSFR cfu_sfr;
-        XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
-        XlnxVersalCFrameBcastReg cframe_bcast;
-
-        OrIRQState apb_irq_orgate;
-    } pmc;
-
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
     } phandle;
 
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 41965531f8d..2128dbbad92 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -37,10 +37,13 @@
 #include "hw/ssi/xlnx-versal-ospi.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/nvram/xlnx-bbram.h"
 #include "hw/misc/xlnx-versal-trng.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+#include "hw/or-irq.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -128,10 +131,28 @@ typedef struct VersalMap {
     struct VersalRtcMap {
         VersalSimplePeriphMap map;
         int alarm_irq;
         int second_irq;
     } rtc;
+
+    struct VersalCfuMap {
+        uint64_t cframe_base;
+        uint64_t cframe_stride;
+        uint64_t cfu_fdro;
+        uint64_t cframe_bcast_reg;
+        uint64_t cframe_bcast_fdri;
+        uint64_t cfu_apb;
+        uint64_t cfu_stream;
+        uint64_t cfu_stream_2;
+        uint64_t cfu_sfr;
+        int cfu_apb_irq;
+        int cframe_irq;
+        size_t num_cframe;
+        struct VersalCfuCframeCfg {
+            uint32_t blktype_frames[7];
+        } cframe_cfg[15];
+    } cfu;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -176,10 +197,26 @@ static const VersalMap VERSAL_MAP = {
     .trng = { 0xf1230000, 141 },
     .rtc = {
         { 0xf12a0000, OR_IRQ(121, 2) },
         .alarm_irq = 142, .second_irq = 143
     },
+
+    .cfu = {
+        .cframe_base = 0xf12d0000, .cframe_stride = 0x1000,
+        .cframe_bcast_reg = 0xf12ee000, .cframe_bcast_fdri = 0xf12ef000,
+        .cfu_apb = 0xf12b0000, .cfu_sfr = 0xf12c1000,
+        .cfu_stream = 0xf12c0000, .cfu_stream_2 = 0xf1f80000,
+        .cfu_fdro = 0xf12c2000,
+        .cfu_apb_irq = 120, .cframe_irq = OR_IRQ(121, 3),
+        .num_cframe = 15,
+        .cframe_cfg = {
+            { { 34111, 3528, 12800, 11, 5, 1, 1 } },
+            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
+            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
+            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
+        },
+    },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -743,31 +780,10 @@ static void versal_create_sdhci(Versal *s,
     qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, map->irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 }
 
-static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
-{
-    DeviceState *orgate;
-
-    /*
-     * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following
-     * models:
-     *  - RTC
-     *  - BBRAM
-     *  - PMC SLCR
-     *  - CFRAME regs (input 3 - 17 to the orgate)
-     */
-    object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
-                            &s->pmc.apb_irq_orgate, TYPE_OR_IRQ);
-    orgate = DEVICE(&s->pmc.apb_irq_orgate);
-    object_property_set_int(OBJECT(orgate),
-                            "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal);
-    qdev_realize(orgate, NULL, &error_fatal);
-    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]);
-}
-
 static void versal_create_rtc(Versal *s, const struct VersalRtcMap *map)
 {
     SysBusDevice *sbd;
     MemoryRegion *mr;
     g_autofree char *node;
@@ -982,158 +998,115 @@ static DeviceState *versal_create_ospi(Versal *s,
     sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
 
     return dev;
 }
 
-static void versal_create_cfu(Versal *s, qemu_irq *pic)
+static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
 {
     SysBusDevice *sbd;
-    DeviceState *dev;
+    Object *container;
+    DeviceState *cfu_fdro, *cfu_apb, *cfu_sfr, *cframe_bcast;
+    DeviceState *cframe_irq_or;
     int i;
-    const struct {
+
+    container = object_new(TYPE_CONTAINER);
+    object_property_add_child(OBJECT(s), "cfu", container);
+    object_unref(container);
+
+    /* CFU FDRO */
+    cfu_fdro = qdev_new(TYPE_XLNX_VERSAL_CFU_FDRO);
+    object_property_add_child(container, "cfu-fdro", OBJECT(cfu_fdro));
+    sbd = SYS_BUS_DEVICE(cfu_fdro);
+
+    sysbus_realize_and_unref(sbd, &error_fatal);
+    memory_region_add_subregion(&s->mr_ps, map->cfu_fdro,
+                                sysbus_mmio_get_region(sbd, 0));
+
+    /* cframe bcast */
+    cframe_bcast = qdev_new(TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
+    object_property_add_child(container, "cframe-bcast", OBJECT(cframe_bcast));
+
+    /* CFU APB */
+    cfu_apb = qdev_new(TYPE_XLNX_VERSAL_CFU_APB);
+    object_property_add_child(container, "cfu-apb", OBJECT(cfu_apb));
+
+    /* IRQ or gate for cframes */
+    cframe_irq_or = qdev_new(TYPE_OR_IRQ);
+    object_property_add_child(container, "cframe-irq-or-gate",
+                              OBJECT(cframe_irq_or));
+    qdev_prop_set_uint16(cframe_irq_or, "num-lines", map->num_cframe);
+    qdev_realize_and_unref(cframe_irq_or, NULL, &error_abort);
+    versal_qdev_connect_gpio_out(s, cframe_irq_or, 0, map->cframe_irq);
+
+    /* cframe reg */
+    for (i = 0; i < map->num_cframe; i++) {
         uint64_t reg_base;
         uint64_t fdri_base;
-    } cframe_addr[] = {
-        { MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
-        { MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
-        { MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
-        { MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
-        { MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
-        { MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
-        { MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
-        { MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
-        { MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
-        { MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
-        { MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
-        { MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
-        { MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
-        { MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
-        { MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
-    };
-    const struct {
-        uint32_t blktype0_frames;
-        uint32_t blktype1_frames;
-        uint32_t blktype2_frames;
-        uint32_t blktype3_frames;
-        uint32_t blktype4_frames;
-        uint32_t blktype5_frames;
-        uint32_t blktype6_frames;
-    } cframe_cfg[] = {
-        [0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
-        [1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
-        [2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
-        [3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
-    };
+        DeviceState *dev;
+        g_autofree char *prop_name;
+        size_t j;
 
-    /* CFU FDRO */
-    object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
-                            TYPE_XLNX_VERSAL_CFU_FDRO);
-    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_fdro);
+        dev = qdev_new(TYPE_XLNX_VERSAL_CFRAME_REG);
+        object_property_add_child(container, "cframe[*]", OBJECT(dev));
 
-    sysbus_realize(sbd, &error_fatal);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
-                                sysbus_mmio_get_region(sbd, 0));
+        sbd = SYS_BUS_DEVICE(dev);
 
-    /* CFRAME REG */
-    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
-        g_autofree char *name = g_strdup_printf("cframe%d", i);
+        for (j = 0; j < ARRAY_SIZE(map->cframe_cfg[i].blktype_frames); j++) {
+            g_autofree char *blktype_prop_name;
 
-        object_initialize_child(OBJECT(s), name, &s->pmc.cframe[i],
-                                TYPE_XLNX_VERSAL_CFRAME_REG);
-
-        sbd = SYS_BUS_DEVICE(&s->pmc.cframe[i]);
-        dev = DEVICE(&s->pmc.cframe[i]);
-
-        if (i < ARRAY_SIZE(cframe_cfg)) {
-            object_property_set_int(OBJECT(dev), "blktype0-frames",
-                                    cframe_cfg[i].blktype0_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype1-frames",
-                                    cframe_cfg[i].blktype1_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype2-frames",
-                                    cframe_cfg[i].blktype2_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype3-frames",
-                                    cframe_cfg[i].blktype3_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype4-frames",
-                                    cframe_cfg[i].blktype4_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype5-frames",
-                                    cframe_cfg[i].blktype5_frames,
-                                    &error_abort);
-            object_property_set_int(OBJECT(dev), "blktype6-frames",
-                                    cframe_cfg[i].blktype6_frames,
+            blktype_prop_name = g_strdup_printf("blktype%zu-frames", j);
+            object_property_set_int(OBJECT(dev), blktype_prop_name,
+                                    map->cframe_cfg[i].blktype_frames[j],
                                     &error_abort);
         }
+
         object_property_set_link(OBJECT(dev), "cfu-fdro",
-                                 OBJECT(&s->pmc.cfu_fdro), &error_fatal);
+                                 OBJECT(cfu_fdro), &error_abort);
 
-        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
 
-        memory_region_add_subregion(&s->mr_ps, cframe_addr[i].reg_base,
+        reg_base = map->cframe_base + i * map->cframe_stride * 2;
+        fdri_base = reg_base + map->cframe_stride;
+        memory_region_add_subregion(&s->mr_ps, reg_base,
                                     sysbus_mmio_get_region(sbd, 0));
-        memory_region_add_subregion(&s->mr_ps, cframe_addr[i].fdri_base,
+        memory_region_add_subregion(&s->mr_ps, fdri_base,
                                     sysbus_mmio_get_region(sbd, 1));
-        sysbus_connect_irq(sbd, 0,
-                           qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate),
-                                            3 + i));
-    }
-
-    /* CFRAME BCAST */
-    object_initialize_child(OBJECT(s), "cframe_bcast", &s->pmc.cframe_bcast,
-                            TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
+        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(cframe_irq_or, i));
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.cframe_bcast);
-    dev = DEVICE(&s->pmc.cframe_bcast);
-
-    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
-        g_autofree char *propname = g_strdup_printf("cframe%d", i);
-        object_property_set_link(OBJECT(dev), propname,
-                                 OBJECT(&s->pmc.cframe[i]), &error_fatal);
+        prop_name = g_strdup_printf("cframe%d", i);
+        object_property_set_link(OBJECT(cframe_bcast), prop_name,
+                                 OBJECT(dev), &error_abort);
+        object_property_set_link(OBJECT(cfu_apb), prop_name,
+                                 OBJECT(dev), &error_abort);
     }
 
-    sysbus_realize(sbd, &error_fatal);
-
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_REG,
+    sbd = SYS_BUS_DEVICE(cframe_bcast);
+    sysbus_realize_and_unref(sbd, &error_abort);
+    memory_region_add_subregion(&s->mr_ps, map->cframe_bcast_reg,
                                 sysbus_mmio_get_region(sbd, 0));
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_FDRI,
+    memory_region_add_subregion(&s->mr_ps, map->cframe_bcast_fdri,
                                 sysbus_mmio_get_region(sbd, 1));
 
-    /* CFU APB */
-    object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
-                            TYPE_XLNX_VERSAL_CFU_APB);
-    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
-    dev = DEVICE(&s->pmc.cfu_apb);
-
-    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
-        g_autofree char *propname = g_strdup_printf("cframe%d", i);
-        object_property_set_link(OBJECT(dev), propname,
-                                 OBJECT(&s->pmc.cframe[i]), &error_fatal);
-    }
-
-    sysbus_realize(sbd, &error_fatal);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
+    sbd = SYS_BUS_DEVICE(cfu_apb);
+    sysbus_realize_and_unref(sbd, &error_fatal);
+    memory_region_add_subregion(&s->mr_ps, map->cfu_apb,
                                 sysbus_mmio_get_region(sbd, 0));
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM,
+    memory_region_add_subregion(&s->mr_ps, map->cfu_stream,
                                 sysbus_mmio_get_region(sbd, 1));
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM_2,
+    memory_region_add_subregion(&s->mr_ps, map->cfu_stream_2,
                                 sysbus_mmio_get_region(sbd, 2));
-    sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+    versal_sysbus_connect_irq(s, sbd, 0, map->cfu_apb_irq);
 
     /* CFU SFR */
-    object_initialize_child(OBJECT(s), "cfu-sfr", &s->pmc.cfu_sfr,
-                            TYPE_XLNX_VERSAL_CFU_SFR);
+    cfu_sfr = qdev_new(TYPE_XLNX_VERSAL_CFU_SFR);
+    object_property_add_child(container, "cfu-sfr", OBJECT(cfu_sfr));
+    sbd = SYS_BUS_DEVICE(cfu_sfr);
 
-    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_sfr);
-
-    object_property_set_link(OBJECT(&s->pmc.cfu_sfr),
-                            "cfu", OBJECT(&s->pmc.cfu_apb), &error_abort);
-
-    sysbus_realize(sbd, &error_fatal);
-    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_SFR,
+    object_property_set_link(OBJECT(cfu_sfr),
+                            "cfu", OBJECT(cfu_apb), &error_abort);
+    sysbus_realize_and_unref(sbd, &error_fatal);
+    memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
                                 sysbus_mmio_get_region(sbd, 0));
 }
 
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
@@ -1353,14 +1326,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
                                                        "ospi-mux-sel", 0));
 
     versal_create_bbram(s, &map->bbram);
     versal_create_trng(s, &map->trng);
     versal_create_rtc(s, &map->rtc);
+    versal_create_cfu(s, &map->cfu);
 
-    versal_create_pmc_apb_irq_orgate(s, pic);
     versal_create_crl(s, pic);
-    versal_create_cfu(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
     /* Create the On Chip Memory (OCM).  */
     memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 19/48] hw/arm/xlnx-versal: crl: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (17 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 18/48] hw/arm/xlnx-versal: cfu: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 20:00   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: " Luc Michel
                   ` (28 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the CRL device creation using the VersalMap structure. The
connections to the RPU CPUs are temporarily removed and will be
reintroduced with next refactoring commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  3 ---
 hw/arm/xlnx-versal.c         | 36 +++++++++++++++++++-----------------
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 5a685aea6d4..d3ce13e69de 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -15,11 +15,10 @@
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
 #include "hw/intc/arm_gicv3.h"
 #include "qom/object.h"
-#include "hw/misc/xlnx-versal-crl.h"
 #include "net/can_emu.h"
 #include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
 
 #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
@@ -69,12 +68,10 @@ struct Versal {
             MemoryRegion mr_ps_alias;
 
             CPUClusterState cluster;
             ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
         } rpu;
-
-        XlnxVersalCRL crl;
     } lpd;
 
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 2128dbbad92..ff55ec62301 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -40,10 +40,11 @@
 #include "hw/misc/xlnx-versal-trng.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "hw/or-irq.h"
+#include "hw/misc/xlnx-versal-crl.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -149,10 +150,12 @@ typedef struct VersalMap {
         size_t num_cframe;
         struct VersalCfuCframeCfg {
             uint32_t blktype_frames[7];
         } cframe_cfg[15];
     } cfu;
+
+    VersalSimplePeriphMap crl;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -213,10 +216,12 @@ static const VersalMap VERSAL_MAP = {
             { { 38498, 3841, 15361, 13, 7, 3, 1 } },
             { { 38498, 3841, 15361, 13, 7, 3, 1 } },
             { { 38498, 3841, 15361, 13, 7, 3, 1 } },
         },
     },
+
+    .crl = { 0xff5e0000, 10 },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -1106,31 +1111,28 @@ static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
     sysbus_realize_and_unref(sbd, &error_fatal);
     memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
                                 sysbus_mmio_get_region(sbd, 0));
 }
 
-static void versal_create_crl(Versal *s, qemu_irq *pic)
+static inline void versal_create_crl(Versal *s)
 {
-    SysBusDevice *sbd;
-    int i;
+    const VersalMap *map;
+    const char *crl_class;
+    DeviceState *dev;
 
-    object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
-                            TYPE_XLNX_VERSAL_CRL);
-    sbd = SYS_BUS_DEVICE(&s->lpd.crl);
+    map = versal_get_map(s);
 
-    for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
-        g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
+    crl_class = TYPE_XLNX_VERSAL_CRL;
+    dev = qdev_new(crl_class);
+    object_property_add_child(OBJECT(s), "crl", OBJECT(dev));
 
-        object_property_set_link(OBJECT(&s->lpd.crl),
-                                 name, OBJECT(&s->lpd.rpu.cpu[i]),
-                                 &error_abort);
-    }
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
 
-    sysbus_realize(sbd, &error_fatal);
-    memory_region_add_subregion(&s->mr_ps, MM_CRL,
-                                sysbus_mmio_get_region(sbd, 0));
-    sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
+    memory_region_add_subregion(&s->mr_ps, map->crl.addr,
+                                sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
+
+    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
 }
 
 /* This takes the board allocated linear DDR memory and creates aliases
  * for each split DDR range/aperture on the Versal address map.
  */
@@ -1327,12 +1329,12 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     versal_create_bbram(s, &map->bbram);
     versal_create_trng(s, &map->trng);
     versal_create_rtc(s, &map->rtc);
     versal_create_cfu(s, &map->cfu);
+    versal_create_crl(s);
 
-    versal_create_crl(s, pic);
     versal_map_ddr(s);
     versal_unimp(s);
 
     /* Create the On Chip Memory (OCM).  */
     memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (18 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 19/48] hw/arm/xlnx-versal: crl: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 20:04   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation Luc Michel
                   ` (27 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the creation of virtio devices. Use the accessors provided by
the Versal SoC to retrieve the reserved MMIO and IRQ space. Those are
defined in the VersalMap structure.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  3 +++
 hw/arm/xlnx-versal-virt.c    | 31 ++++++++++++-------------------
 hw/arm/xlnx-versal.c         | 26 ++++++++++++++++++++++++++
 3 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index d3ce13e69de..af47acb288f 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -100,10 +100,13 @@ void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
 void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
 void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
 void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
                               BlockBackend *blk);
 
+qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx);
+hwaddr versal_get_reserved_mmio_addr(Versal *s);
+
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 01c230491df..a776ee87088 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -269,41 +269,34 @@ static void create_virtio_regions(VersalVirt *s)
 {
     int virtio_mmio_size = 0x200;
     int i;
 
     for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
-        char *name = g_strdup_printf("virtio%d", i);
-        hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
-        int irq = VERSAL_RSVD_IRQ_FIRST + i;
+        hwaddr base = versal_get_reserved_mmio_addr(&s->soc)
+            + i * virtio_mmio_size;
+        g_autofree char *node = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+        int dtb_irq;
         MemoryRegion *mr;
         DeviceState *dev;
         qemu_irq pic_irq;
 
-        pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
+        pic_irq = versal_get_reserved_irq(&s->soc, i, &dtb_irq);
         dev = qdev_new("virtio-mmio");
-        object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev));
+        object_property_add_child(OBJECT(s), "virtio-mmio[*]", OBJECT(dev));
         sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
         memory_region_add_subregion(&s->soc.mr_ps, base, mr);
-        g_free(name);
-    }
 
-    for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
-        hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
-        int irq = VERSAL_RSVD_IRQ_FIRST + i;
-        char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
-
-        qemu_fdt_add_subnode(s->fdt, name);
-        qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
-        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irq,
+        qemu_fdt_add_subnode(s->fdt, node);
+        qemu_fdt_setprop(s->fdt, node, "dma-coherent", NULL, 0);
+        qemu_fdt_setprop_cells(s->fdt, node, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, dtb_irq,
                                GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
-        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+        qemu_fdt_setprop_sized_cells(s->fdt, node, "reg",
                                      2, base, 2, virtio_mmio_size);
-        qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
-        g_free(name);
+        qemu_fdt_setprop_string(s->fdt, node, "compatible", "virtio,mmio");
     }
 }
 
 static void bbram_attach_drive(VersalVirt *s)
 {
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index ff55ec62301..fe2c789a557 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -152,10 +152,17 @@ typedef struct VersalMap {
             uint32_t blktype_frames[7];
         } cframe_cfg[15];
     } cfu;
 
     VersalSimplePeriphMap crl;
+
+    /* reserved MMIO/IRQ space that can safely be used for virtio devices */
+    struct VersalReserved {
+        uint64_t mmio_start;
+        int irq_start;
+        int irq_num;
+    } reserved;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -218,10 +225,12 @@ static const VersalMap VERSAL_MAP = {
             { { 38498, 3841, 15361, 13, 7, 3, 1 } },
         },
     },
 
     .crl = { 0xff5e0000, 10 },
+
+    .reserved = { 0xa0000000, 111, 8 },
 };
 
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
 };
@@ -1411,10 +1420,27 @@ void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
 
     sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
                        flash_idx + 1, cs_line);
 }
 
+qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx)
+{
+    const VersalMap *map = versal_get_map(s);
+
+    g_assert(idx < map->reserved.irq_num);
+
+    *dtb_idx = map->reserved.irq_start + idx;
+    return versal_get_irq(s, *dtb_idx);
+}
+
+hwaddr versal_get_reserved_mmio_addr(Versal *s)
+{
+    const VersalMap *map = versal_get_map(s);
+
+    return map->reserved.mmio_start;
+}
+
 int versal_get_num_can(VersalVersion version)
 {
     const VersalMap *map = VERSION_TO_MAP[version];
 
     return map->num_canfd;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (19 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 20:13   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping Luc Michel
                   ` (26 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the CPU cluster creation using the VersalMap structure. There
is no functional change. The clusters properties are now described in
the VersalMap structure. For now only the APU is converted. The RPU will
be taken care of by next commits.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  11 +-
 hw/arm/xlnx-versal-virt.c    |  80 +-------
 hw/arm/xlnx-versal.c         | 346 ++++++++++++++++++++++++++---------
 3 files changed, 269 insertions(+), 168 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index af47acb288f..ba5719d80f5 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -13,11 +13,10 @@
 #ifndef XLNX_VERSAL_H
 #define XLNX_VERSAL_H
 
 #include "hw/sysbus.h"
 #include "hw/cpu/cluster.h"
-#include "hw/intc/arm_gicv3.h"
 #include "qom/object.h"
 #include "net/can_emu.h"
 #include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
 
@@ -41,19 +40,10 @@ OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 struct Versal {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
-    struct {
-        struct {
-            MemoryRegion mr;
-            CPUClusterState cluster;
-            ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
-            GICv3State gic;
-        } apu;
-    } fpd;
-
     MemoryRegion mr_ps;
 
     struct {
         /* 4 ranges to access DDR.  */
         MemoryRegion mr_ddr_ranges[4];
@@ -73,10 +63,11 @@ struct Versal {
     } lpd;
 
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
+        uint32_t gic;
     } phandle;
 
     struct {
         MemoryRegion *mr_ddr;
         CanBusState **canbus;
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index a776ee87088..55159536ceb 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -36,11 +36,10 @@ struct VersalVirt {
     Versal soc;
 
     void *fdt;
     int fdt_size;
     struct {
-        uint32_t gic;
         uint32_t clk_125Mhz;
         uint32_t clk_25Mhz;
     } phandle;
     struct arm_boot_info binfo;
 
@@ -61,22 +60,18 @@ static void fdt_create(VersalVirt *s)
         error_report("create_device_tree() failed");
         exit(1);
     }
 
     /* Allocate all phandles.  */
-    s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
     s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
 
     /* Create /chosen node for load_dtb.  */
     qemu_fdt_add_subnode(s->fdt, "/chosen");
     qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
-    qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
-    qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
-    qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
     qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
     qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
 }
 
 static void fdt_add_clk_node(VersalVirt *s, const char *name,
@@ -88,71 +83,10 @@ static void fdt_add_clk_node(VersalVirt *s, const char *name,
     qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
     qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
     qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
 }
 
-static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
-{
-    int i;
-
-    qemu_fdt_add_subnode(s->fdt, "/cpus");
-    qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
-    qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
-
-    for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
-        char *name = g_strdup_printf("/cpus/cpu@%d", i);
-        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
-
-        qemu_fdt_add_subnode(s->fdt, name);
-        qemu_fdt_setprop_cell(s->fdt, name, "reg",
-                              arm_cpu_mp_affinity(armcpu));
-        if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
-            qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
-        }
-        qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
-        qemu_fdt_setprop_string(s->fdt, name, "compatible",
-                                armcpu->dtb_compatible);
-        g_free(name);
-    }
-}
-
-static void fdt_add_gic_nodes(VersalVirt *s)
-{
-    char *nodename;
-
-    nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
-    qemu_fdt_add_subnode(s->fdt, nodename);
-    qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
-    qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
-                           GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
-    qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
-                                 2, MM_GIC_APU_DIST_MAIN,
-                                 2, MM_GIC_APU_DIST_MAIN_SIZE,
-                                 2, MM_GIC_APU_REDIST_0,
-                                 2, MM_GIC_APU_REDIST_0_SIZE);
-    qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
-    qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
-    g_free(nodename);
-}
-
-static void fdt_add_timer_nodes(VersalVirt *s)
-{
-    const char compat[] = "arm,armv8-timer";
-    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
-
-    qemu_fdt_add_subnode(s->fdt, "/timer");
-    qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
-            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
-            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
-            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
-            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
-    qemu_fdt_setprop(s->fdt, "/timer", "compatible",
-                     compat, sizeof(compat));
-}
-
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
     char **node_path;
     int n = 0;
@@ -391,23 +325,21 @@ static void versal_virt_init(MachineState *machine)
                                  &error_abort);
     }
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
-    fdt_add_gic_nodes(s);
-    fdt_add_timer_nodes(s);
-    fdt_add_cpu_nodes(s, psci_conduit);
     fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
     fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
 
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
     create_virtio_regions(s);
 
-    /* Make the APU cpu address space visible to virtio and other
-     * modules unaware of multiple address-spaces.  */
-    memory_region_add_subregion_overlap(get_system_memory(),
-                                        0, &s->soc.fpd.apu.mr, 0);
+    /*
+     * Map the SoC address space onto system memory. This will allow virtio and
+     * other modules unaware of multiple address-spaces to work.
+     */
+    memory_region_add_subregion(get_system_memory(), 0, &s->soc.mr_ps);
 
     /* Attach bbram backend, if given */
     bbram_attach_drive(s);
 
     /* Attach efuse backend, if given */
@@ -427,11 +359,11 @@ static void versal_virt_init(MachineState *machine)
         /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
          * Offset things by 4K.  */
         s->binfo.loader_start = 0x1000;
         s->binfo.dtb_limit = 0x1000000;
     }
-    arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
+    arm_load_kernel(ARM_CPU(qemu_get_cpu(0)), machine, &s->binfo);
 
     for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
         ObjectClass *flash_klass;
         DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
         BlockBackend *blk;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index fe2c789a557..5a08ad07b28 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -41,10 +41,11 @@
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "hw/or-irq.h"
 #include "hw/misc/xlnx-versal-crl.h"
+#include "hw/intc/arm_gicv3_common.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -65,11 +66,38 @@ FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
 typedef struct VersalSimplePeriphMap {
     uint64_t addr;
     int irq;
 } VersalSimplePeriphMap;
 
+typedef struct VersalGicMap {
+    int version;
+    uint64_t dist;
+    uint64_t redist;
+    size_t num_irq;
+} VersalGicMap;
+
+enum StartPoweredOffMode {
+    SPO_SECONDARIES,
+    SPO_ALL,
+};
+
+typedef struct VersalCpuClusterMap {
+    VersalGicMap gic;
+
+    const char *name;
+    const char *cpu_model;
+    size_t num_core;
+    size_t num_cluster;
+    uint32_t qemu_cluster_id;
+    bool dtb_expose;
+
+    enum StartPoweredOffMode start_powered_off;
+} VersalCpuClusterMap;
+
 typedef struct VersalMap {
+    VersalCpuClusterMap apu;
+
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
 
     VersalSimplePeriphMap canfd[4];
     size_t num_canfd;
@@ -162,10 +190,26 @@ typedef struct VersalMap {
         int irq_num;
     } reserved;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
+    .apu = {
+        .name = "apu",
+        .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
+        .num_cluster = 1,
+        .num_core = 2,
+        .qemu_cluster_id = 0,
+        .start_powered_off = SPO_SECONDARIES,
+        .dtb_expose = true,
+        .gic = {
+            .version = 3,
+            .dist = 0xf9000000,
+            .redist = 0xf9080000,
+            .num_irq = 192,
+        },
+    },
+
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
     .num_uart = 2,
 
     .canfd[0] = { 0xff060000, 20 },
@@ -292,14 +336,16 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
 
 static qemu_irq versal_get_irq(Versal *s, int irq_idx)
 {
     qemu_irq irq;
     bool ored;
+    DeviceState *gic;
 
     ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
 
-    irq = qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
+    gic = DEVICE(versal_get_child_idx(s, "apu-gic", 0));
+    irq = qdev_get_gpio_in(gic, irq_idx);
 
     if (ored) {
         irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
     }
 
@@ -372,111 +418,243 @@ static inline DeviceState *create_or_gate(Versal *s, Object *parent,
     versal_qdev_connect_gpio_out(s, or, 0, irq_idx);
 
     return or;
 }
 
-static void versal_create_apu_cpus(Versal *s)
+static MemoryRegion *create_cpu_mr(Versal *s, DeviceState *cluster,
+                                   const VersalCpuClusterMap *map)
 {
-    int i;
+    MemoryRegion *mr, *root_alias;
+    char *name;
 
-    object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
-                            TYPE_CPU_CLUSTER);
-    qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
+    mr = g_new(MemoryRegion, 1);
+    name = g_strdup_printf("%s-mr", map->name);
+    memory_region_init(mr, OBJECT(cluster), name, UINT64_MAX);
+    g_free(name);
 
-    for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
-        Object *obj;
+    root_alias = g_new(MemoryRegion, 1);
+    name = g_strdup_printf("ps-alias-for-%s", map->name);
+    memory_region_init_alias(root_alias, OBJECT(cluster), name,
+                             &s->mr_ps, 0, UINT64_MAX);
+    g_free(name);
+    memory_region_add_subregion(mr, 0, root_alias);
 
-        object_initialize_child(OBJECT(&s->fpd.apu.cluster),
-                                "apu-cpu[*]", &s->fpd.apu.cpu[i],
-                                XLNX_VERSAL_ACPU_TYPE);
-        obj = OBJECT(&s->fpd.apu.cpu[i]);
-        if (i) {
-            /* Secondary CPUs start in powered-down state */
-            object_property_set_bool(obj, "start-powered-off", true,
-                                     &error_abort);
-        }
-
-        object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu),
-                                &error_abort);
-        object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr),
-                                 &error_abort);
-        qdev_realize(DEVICE(obj), NULL, &error_fatal);
-    }
-
-    qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
+    return mr;
 }
 
-static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
+static DeviceState *versal_create_gic(Versal *s,
+                                      const VersalCpuClusterMap *map,
+                                      MemoryRegion *mr,
+                                      size_t num_cpu)
 {
-    static const uint64_t addrs[] = {
-        MM_GIC_APU_DIST_MAIN,
-        MM_GIC_APU_REDIST_0
-    };
-    SysBusDevice *gicbusdev;
-    DeviceState *gicdev;
+    DeviceState *dev;
+    SysBusDevice *sbd;
     QList *redist_region_count;
-    int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
-    int i;
+    g_autofree char *node = NULL;
+    g_autofree char *name = NULL;
+    const char compatible[] = "arm,gic-v3";
 
-    object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic,
-                            gicv3_class_name());
-    gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
-    gicdev = DEVICE(&s->fpd.apu.gic);
-    qdev_prop_set_uint32(gicdev, "revision", 3);
-    qdev_prop_set_uint32(gicdev, "num-cpu", nr_apu_cpus);
-    qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
+    dev = qdev_new(gicv3_class_name());
+    name = g_strdup_printf("%s-gic[*]", map->name);
+    object_property_add_child(OBJECT(s), name, OBJECT(dev));
+    sbd = SYS_BUS_DEVICE(dev);
+    qdev_prop_set_uint32(dev, "revision", 3);
+    qdev_prop_set_uint32(dev, "num-cpu", num_cpu);
+    qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32);
 
     redist_region_count = qlist_new();
-    qlist_append_int(redist_region_count, nr_apu_cpus);
-    qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
+    qlist_append_int(redist_region_count, num_cpu);
+    qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
 
-    qdev_prop_set_bit(gicdev, "has-security-extensions", true);
+    qdev_prop_set_bit(dev, "has-security-extensions", true);
+    object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
 
-    sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal);
+    sysbus_realize_and_unref(sbd, &error_fatal);
 
-    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
-        MemoryRegion *mr;
+    memory_region_add_subregion(mr, map->gic.dist,
+                                sysbus_mmio_get_region(sbd, 0));
+    memory_region_add_subregion(mr, map->gic.redist,
+                                sysbus_mmio_get_region(sbd, 1));
 
-        mr = sysbus_mmio_get_region(gicbusdev, i);
-        memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
+    if (map->dtb_expose) {
+        node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible,
+                                      sizeof(compatible));
+        qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
+        qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
+        qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
+                                     2, map->gic.dist,
+                                     2, 0x10000,
+                                     2, map->gic.redist,
+                                     2, GICV3_REDIST_SIZE * num_cpu);
+        qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
+                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+        qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
     }
 
-    for (i = 0; i < nr_apu_cpus; i++) {
-        DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
-        int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
-        qemu_irq maint_irq;
-        int ti;
-        /* Mapping from the output timer irq lines from the CPU to the
-         * GIC PPI inputs.
-         */
-        const int timer_irq[] = {
-            [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
-            [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
-            [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
-            [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
-        };
+    return dev;
+}
 
+static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
+                               DeviceState *gic, DeviceState *cpu, size_t idx,
+                               size_t num_cpu)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(gic);
+    int ppibase = map->gic.num_irq + idx * GIC_INTERNAL + GIC_NR_SGIS;
+    int ti;
+    bool has_gtimer;
+    /*
+     * Mapping from the output timer irq lines from the CPU to the
+     * GIC PPI inputs.
+     */
+    const int timer_irq[] = {
+        [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
+        [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
+        [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
+        [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
+    };
+
+    has_gtimer = arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_GENERIC_TIMER);
+
+    if (has_gtimer) {
         for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
-            qdev_connect_gpio_out(cpudev, ti,
-                                  qdev_get_gpio_in(gicdev,
+            qdev_connect_gpio_out(cpu, ti,
+                                  qdev_get_gpio_in(gic,
                                                    ppibase + timer_irq[ti]));
         }
-        maint_irq = qdev_get_gpio_in(gicdev,
-                                        ppibase + VERSAL_GIC_MAINT_IRQ);
-        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+    }
+
+    if (map->gic.version == 3) {
+        qemu_irq maint_irq;
+
+        maint_irq = qdev_get_gpio_in(gic,
+                                     ppibase + VERSAL_GIC_MAINT_IRQ);
+        qdev_connect_gpio_out_named(cpu, "gicv3-maintenance-interrupt",
                                     0, maint_irq);
-        sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
-        sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
-        sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
-        sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
     }
 
-    for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
-        pic[i] = qdev_get_gpio_in(gicdev, i);
+    sysbus_connect_irq(sbd, idx, qdev_get_gpio_in(cpu, ARM_CPU_IRQ));
+    sysbus_connect_irq(sbd, idx + num_cpu,
+                       qdev_get_gpio_in(cpu, ARM_CPU_FIQ));
+    sysbus_connect_irq(sbd, idx + 2 * num_cpu,
+                       qdev_get_gpio_in(cpu, ARM_CPU_VIRQ));
+    sysbus_connect_irq(sbd, idx + 3 * num_cpu,
+                       qdev_get_gpio_in(cpu, ARM_CPU_VFIQ));
+}
+
+static inline void versal_create_and_connect_gic(Versal *s,
+                                                 const VersalCpuClusterMap *map,
+                                                 MemoryRegion *mr,
+                                                 DeviceState **cpus,
+                                                 size_t num_cpu)
+{
+    DeviceState *gic;
+    size_t i;
+
+    gic = versal_create_gic(s, map, mr, num_cpu);
+
+    for (i = 0; i < num_cpu; i++) {
+        connect_gic_to_cpu(map, gic, cpus[i], i, num_cpu);
+    }
+}
+
+static DeviceState *versal_create_cpu(Versal *s,
+                                      const VersalCpuClusterMap *map,
+                                      DeviceState *qemu_cluster,
+                                      MemoryRegion *cpu_mr,
+                                      size_t cluster_idx,
+                                      size_t core_idx)
+{
+    DeviceState *cpu = qdev_new(map->cpu_model);
+    ARMCPU *arm_cpu = ARM_CPU(cpu);
+    Object *obj = OBJECT(cpu);
+    bool start_off;
+    size_t idx = cluster_idx * map->num_core + core_idx;
+    g_autofree char *name;
+    g_autofree char *node = NULL;
+
+    start_off = map->start_powered_off == SPO_ALL
+        || ((map->start_powered_off == SPO_SECONDARIES)
+            && (cluster_idx || core_idx));
+
+    name = g_strdup_printf("%s[*]", map->name);
+    object_property_add_child(OBJECT(qemu_cluster), name, obj);
+    object_property_set_bool(obj, "start-powered-off", start_off,
+                             &error_abort);
+    qdev_prop_set_int32(cpu, "core-count",  map->num_core);
+    object_property_set_link(obj, "memory", OBJECT(cpu_mr), &error_abort);
+    qdev_realize_and_unref(cpu, NULL, &error_fatal);
+
+    if (!map->dtb_expose) {
+        return cpu;
+    }
+
+    node = versal_fdt_add_subnode(s, "/cpus/cpu", idx,
+                                  arm_cpu->dtb_compatible,
+                                  strlen(arm_cpu->dtb_compatible) + 1);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "reg",
+                          arm_cpu_mp_affinity(arm_cpu) & ARM64_AFFINITY_MASK);
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "device_type", "cpu");
+    qemu_fdt_setprop_string(s->cfg.fdt, node, "enable-method", "psci");
+
+    return cpu;
+}
+
+static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
+{
+    size_t i, j;
+    DeviceState *cluster;
+    MemoryRegion *mr;
+    char *name;
+    g_autofree DeviceState **cpus;
+    const char compatible[] = "arm,armv8-timer";
+    bool has_gtimer;
+
+    cluster = qdev_new(TYPE_CPU_CLUSTER);
+    name = g_strdup_printf("%s-cluster", map->name);
+    object_property_add_child(OBJECT(s), name, OBJECT(cluster));
+    g_free(name);
+    qdev_prop_set_uint32(cluster, "cluster-id", map->qemu_cluster_id);
+
+    mr = create_cpu_mr(s, cluster, map);
+
+    cpus = g_new(DeviceState *, map->num_cluster * map->num_core);
+
+    if (map->dtb_expose) {
+        qemu_fdt_add_subnode(s->cfg.fdt, "/cpus");
+        qemu_fdt_setprop_cell(s->cfg.fdt, "/cpus", "#size-cells", 0);
+        qemu_fdt_setprop_cell(s->cfg.fdt, "/cpus", "#address-cells", 1);
+    }
+
+    for (i = 0; i < map->num_cluster; i++) {
+        for (j = 0; j < map->num_core; j++) {
+            DeviceState *cpu = versal_create_cpu(s, map, cluster, mr, i, j);
+
+            cpus[i * map->num_core + j] = cpu;
+        }
+
+    }
+
+    qdev_realize_and_unref(cluster, NULL, &error_fatal);
+
+    versal_create_and_connect_gic(s, map, mr, cpus,
+                                  map->num_cluster * map->num_core);
+
+    has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
+    if (map->dtb_expose && has_gtimer) {
+        qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
+        qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
+                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
+                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
+                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
+                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+        qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
+                         compatible, sizeof(compatible));
     }
 }
 
 static void versal_create_rpu_cpus(Versal *s)
 {
@@ -1277,11 +1455,10 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
 
 static void versal_realize(DeviceState *dev, Error **errp)
 {
     Versal *s = XLNX_VERSAL_BASE(dev);
     DeviceState *slcr, *ospi;
-    qemu_irq pic[XLNX_VERSAL_NR_IRQS];
     Object *container;
     const VersalMap *map = versal_get_map(s);
     size_t i;
 
     if (s->cfg.fdt == NULL) {
@@ -1290,18 +1467,21 @@ static void versal_realize(DeviceState *dev, Error **errp)
         s->cfg.fdt = create_device_tree(&fdt_size);
     }
 
     s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
     s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
-
-    versal_create_apu_cpus(s);
-    versal_create_apu_gic(s, pic);
+    s->phandle.gic = qemu_fdt_alloc_phandle(s->cfg.fdt);
 
     container = object_new(TYPE_CONTAINER);
     object_property_add_child(OBJECT(s), "irq-or-gates", container);
     object_unref(container);
 
+    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
+    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#size-cells", 0x2);
+    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#address-cells", 0x2);
+
+    versal_create_cpu_cluster(s, &map->apu);
     versal_create_rpu_cpus(s);
 
     for (i = 0; i < map->num_uart; i++) {
         versal_create_uart(s, &map->uart[i], i);
     }
@@ -1348,11 +1528,10 @@ static void versal_realize(DeviceState *dev, Error **errp)
     /* Create the On Chip Memory (OCM).  */
     memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
                            MM_OCM_SIZE, &error_fatal);
 
     memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
-    memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
     memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
                                         &s->lpd.rpu.mr_ps_alias, 0);
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
@@ -1456,11 +1635,10 @@ int versal_get_num_sdhci(VersalVersion version)
 static void versal_base_init(Object *obj)
 {
     Versal *s = XLNX_VERSAL_BASE(obj);
     size_t i, num_can;
 
-    memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
     memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
     memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
                              "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (20 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 20:15   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU Luc Michel
                   ` (25 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add a way to configure the MP affinity value of the CPUs given their
core and cluster IDs. For the Versal APU CPUs, the MP affinity value is
directly given by the core ID.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 5a08ad07b28..35c32de0159 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -88,10 +88,18 @@ typedef struct VersalCpuClusterMap {
     size_t num_core;
     size_t num_cluster;
     uint32_t qemu_cluster_id;
     bool dtb_expose;
 
+    struct {
+        uint64_t base;
+        uint64_t core_mask;
+        uint64_t core_shift;
+        uint64_t cluster_mask;
+        uint64_t cluster_shift;
+    } mp_affinity;
+
     enum StartPoweredOffMode start_powered_off;
 } VersalCpuClusterMap;
 
 typedef struct VersalMap {
     VersalCpuClusterMap apu;
@@ -196,10 +204,15 @@ static const VersalMap VERSAL_MAP = {
         .name = "apu",
         .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
         .num_cluster = 1,
         .num_core = 2,
         .qemu_cluster_id = 0,
+        .mp_affinity = {
+            .base = 0x0,
+            .core_mask = 0xff,
+            .core_shift = 0,
+        },
         .start_powered_off = SPO_SECONDARIES,
         .dtb_expose = true,
         .gic = {
             .version = 3,
             .dist = 0xf9000000,
@@ -565,23 +578,31 @@ static DeviceState *versal_create_cpu(Versal *s,
                                       size_t core_idx)
 {
     DeviceState *cpu = qdev_new(map->cpu_model);
     ARMCPU *arm_cpu = ARM_CPU(cpu);
     Object *obj = OBJECT(cpu);
+    uint64_t affinity;
     bool start_off;
     size_t idx = cluster_idx * map->num_core + core_idx;
     g_autofree char *name;
     g_autofree char *node = NULL;
 
+    affinity = map->mp_affinity.base;
+    affinity |= (cluster_idx & map->mp_affinity.cluster_mask)
+        << map->mp_affinity.cluster_shift;
+    affinity |= (core_idx & map->mp_affinity.core_mask)
+        << map->mp_affinity.core_shift;
+
     start_off = map->start_powered_off == SPO_ALL
         || ((map->start_powered_off == SPO_SECONDARIES)
             && (cluster_idx || core_idx));
 
     name = g_strdup_printf("%s[*]", map->name);
     object_property_add_child(OBJECT(qemu_cluster), name, obj);
     object_property_set_bool(obj, "start-powered-off", start_off,
                              &error_abort);
+    qdev_prop_set_uint64(cpu, "mp-affinity", affinity);
     qdev_prop_set_int32(cpu, "core-count",  map->num_core);
     object_property_set_link(obj, "memory", OBJECT(cpu_mr), &error_abort);
     qdev_realize_and_unref(cpu, NULL, &error_fatal);
 
     if (!map->dtb_expose) {
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (21 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-29 20:16   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property Luc Michel
                   ` (24 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the instance of the GIC ITS in the APU.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 35c32de0159..ba8c69bd435 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -42,10 +42,11 @@
 #include "hw/misc/xlnx-versal-cfu.h"
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "hw/or-irq.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "hw/intc/arm_gicv3_its_common.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -70,11 +71,13 @@ typedef struct VersalSimplePeriphMap {
 
 typedef struct VersalGicMap {
     int version;
     uint64_t dist;
     uint64_t redist;
+    uint64_t its;
     size_t num_irq;
+    bool has_its;
 } VersalGicMap;
 
 enum StartPoweredOffMode {
     SPO_SECONDARIES,
     SPO_ALL,
@@ -216,10 +219,12 @@ static const VersalMap VERSAL_MAP = {
         .gic = {
             .version = 3,
             .dist = 0xf9000000,
             .redist = 0xf9080000,
             .num_irq = 192,
+            .has_its = true,
+            .its = 0xf9020000,
         },
     },
 
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
@@ -452,10 +457,52 @@ static MemoryRegion *create_cpu_mr(Versal *s, DeviceState *cluster,
     memory_region_add_subregion(mr, 0, root_alias);
 
     return mr;
 }
 
+static void versal_create_gic_its(Versal *s,
+                                  const VersalCpuClusterMap *map,
+                                  DeviceState *gic,
+                                  MemoryRegion *mr,
+                                  char *gic_node)
+{
+    DeviceState *dev;
+    SysBusDevice *sbd;
+    g_autofree char *node_pat = NULL, *node = NULL;
+    const char compatible[] = "arm,gic-v3-its";
+
+    if (!map->gic.has_its) {
+        return;
+    }
+
+    dev = qdev_new(TYPE_ARM_GICV3_ITS);
+    sbd = SYS_BUS_DEVICE(dev);
+
+    object_property_add_child(OBJECT(gic), "its", OBJECT(dev));
+    object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(gic),
+                             &error_abort);
+
+    sysbus_realize_and_unref(sbd, &error_abort);
+
+    memory_region_add_subregion(mr, map->gic.its,
+                                sysbus_mmio_get_region(sbd, 0));
+
+    if (!map->dtb_expose) {
+        return;
+    }
+
+    qemu_fdt_setprop(s->cfg.fdt, gic_node, "ranges", NULL, 0);
+    qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#address-cells", 2);
+    qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#size-cells", 2);
+
+    node_pat = g_strdup_printf("%s/its", gic_node);
+    node = versal_fdt_add_simple_subnode(s, node_pat, map->gic.its, 0x20000,
+                                         compatible, sizeof(compatible));
+    qemu_fdt_setprop(s->cfg.fdt, node, "msi-controller", NULL, 0);
+    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#msi-cells", 1);
+}
+
 static DeviceState *versal_create_gic(Versal *s,
                                       const VersalCpuClusterMap *map,
                                       MemoryRegion *mr,
                                       size_t num_cpu)
 {
@@ -477,10 +524,11 @@ static DeviceState *versal_create_gic(Versal *s,
     redist_region_count = qlist_new();
     qlist_append_int(redist_region_count, num_cpu);
     qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
 
     qdev_prop_set_bit(dev, "has-security-extensions", true);
+    qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
     object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
 
     sysbus_realize_and_unref(sbd, &error_fatal);
 
     memory_region_add_subregion(mr, map->gic.dist,
@@ -502,10 +550,12 @@ static DeviceState *versal_create_gic(Versal *s,
                                GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
     }
 
+    versal_create_gic_its(s, map, dev, mr, node);
+
     return dev;
 }
 
 static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
                                DeviceState *gic, DeviceState *cpu, size_t idx,
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (22 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-08-04 12:33   ` Peter Maydell
  2025-07-16  9:54 ` [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs Luc Michel
                   ` (23 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Francisco Iglesias, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis,
	Frederic Konrad, Sai Pavan Boddu, Edgar E. Iglesias

From: Francisco Iglesias <francisco.iglesias@xilinx.com>

Introduce a 'first-cpu-index' property for specifying the first QEMU CPU
connected to the GICv3. This makes it possible to have multiple instances
of the GICv3 connected to different CPU clusters.

Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 include/hw/intc/arm_gicv3_common.h | 1 +
 hw/intc/arm_gicv3_common.c         | 3 ++-
 hw/intc/arm_gicv3_cpuif.c          | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index c18503869f9..3c2ed30de71 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -226,10 +226,11 @@ struct GICv3State {
     MemoryRegion iomem_dist; /* Distributor */
     GICv3RedistRegion *redist_regions; /* Redistributor Regions */
     uint32_t *redist_region_count; /* redistributor count within each region */
     uint32_t nb_redist_regions; /* number of redist regions */
 
+    uint32_t first_cpu_idx;
     uint32_t num_cpu;
     uint32_t num_irq;
     uint32_t revision;
     uint32_t maint_irq;
     bool lpi_enable;
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index e438d8c042d..2d0df6da86c 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -434,11 +434,11 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
     }
 
     s->cpu = g_new0(GICv3CPUState, s->num_cpu);
 
     for (i = 0; i < s->num_cpu; i++) {
-        CPUState *cpu = qemu_get_cpu(i);
+        CPUState *cpu = qemu_get_cpu(s->first_cpu_idx + i);
         uint64_t cpu_affid;
 
         s->cpu[i].cpu = cpu;
         s->cpu[i].gic = s;
         /* Store GICv3CPUState in CPUARMState gicv3state pointer */
@@ -620,10 +620,11 @@ static const Property arm_gicv3_common_properties[] = {
     DEFINE_PROP_BOOL("force-8-bit-prio", GICv3State, force_8bit_prio, 0),
     DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
                       redist_region_count, qdev_prop_uint32, uint32_t),
     DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
                      MemoryRegion *),
+    DEFINE_PROP_UINT32("first-cpu-index", GICv3State, first_cpu_idx, 0),
 };
 
 static void arm_gicv3_common_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 4b4cf091570..1af7690b958 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -3022,11 +3022,11 @@ void gicv3_init_cpuif(GICv3State *s)
      * registers with the CPU
      */
     int i;
 
     for (i = 0; i < s->num_cpu; i++) {
-        ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
+        ARMCPU *cpu = ARM_CPU(qemu_get_cpu(s->first_cpu_idx + i));
         GICv3CPUState *cs = &s->cpu[i];
 
         /*
          * If the CPU doesn't define a GICv3 configuration, probably because
          * in real hardware it doesn't have one, then we use default values
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (23 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 14:26   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2 Luc Michel
                   ` (22 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

The Versal SoC contains two GICs: one GICv3 in the APU and one GICv2 in
the RPU (currently not instantiated). To prepare for the GICv2
instantiation, add support for multiple GICs when connecting interrupts.

When a GIC is created, the first-cpu-index property is set on it, and a
pointer to the GIC is stored in the intc array. When connecting an IRQ,
a TYPE_SPLIT_IRQ device is created with its num-lines property set to
the number of GICs in the SoC. The split device is used to fan out the
IRQ to all the GICs.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  1 +
 hw/arm/xlnx-versal.c         | 55 +++++++++++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index ba5719d80f5..9b11ffb845d 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -40,10 +40,11 @@ OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 struct Versal {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
+    GArray *intc;
     MemoryRegion mr_ps;
 
     struct {
         /* 4 ranges to access DDR.  */
         MemoryRegion mr_ddr_ranges[4];
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index ba8c69bd435..58cd874f81f 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -43,10 +43,11 @@
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "hw/or-irq.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/intc/arm_gicv3_its_common.h"
+#include "hw/core/split-irq.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -318,10 +319,47 @@ static inline Object *versal_get_child_idx(Versal *s, const char *child,
     g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
 
     return versal_get_child(s, n);
 }
 
+/*
+ * The SoC embeds multiple GICs. They all receives the same IRQ lines at the
+ * same index. This function creates a TYPE_SPLIT_IRQ device to fan out the
+ * given IRQ input to all the GICs.
+ *
+ * The TYPE_SPLIT_IRQ devices lie in the /soc/irq-splits QOM container
+ */
+static qemu_irq versal_get_gic_irq(Versal *s, int irq_idx)
+{
+    DeviceState *split;
+    Object *container = versal_get_child(s, "irq-splits");
+    int idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
+    g_autofree char *name = g_strdup_printf("irq[%d]", idx);
+
+    split = DEVICE(object_resolve_path_at(container, name));
+
+    if (split == NULL) {
+        size_t i;
+
+        split = qdev_new(TYPE_SPLIT_IRQ);
+        qdev_prop_set_uint16(split, "num-lines", s->intc->len);
+        object_property_add_child(container, name, OBJECT(split));
+        qdev_realize_and_unref(split, NULL, &error_abort);
+
+        for (i = 0; i < s->intc->len; i++) {
+            DeviceState *gic;
+
+            gic = g_array_index(s->intc, DeviceState *, i);
+            qdev_connect_gpio_out(split, i, qdev_get_gpio_in(gic, idx));
+        }
+    } else {
+        g_assert(FIELD_EX32(irq_idx, VERSAL_IRQ, ORED));
+    }
+
+    return qdev_get_gpio_in(split, 0);
+}
+
 /*
  * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
  * used to return the corresponding or gate input IRQ. The or gate is created if
  * not already existant.
  *
@@ -354,16 +392,14 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
 
 static qemu_irq versal_get_irq(Versal *s, int irq_idx)
 {
     qemu_irq irq;
     bool ored;
-    DeviceState *gic;
 
     ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
 
-    gic = DEVICE(versal_get_child_idx(s, "apu-gic", 0));
-    irq = qdev_get_gpio_in(gic, irq_idx);
+    irq = versal_get_gic_irq(s, irq_idx);
 
     if (ored) {
         irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
     }
 
@@ -502,10 +538,11 @@ static void versal_create_gic_its(Versal *s,
 }
 
 static DeviceState *versal_create_gic(Versal *s,
                                       const VersalCpuClusterMap *map,
                                       MemoryRegion *mr,
+                                      int first_cpu_idx,
                                       size_t num_cpu)
 {
     DeviceState *dev;
     SysBusDevice *sbd;
     QList *redist_region_count;
@@ -526,10 +563,11 @@ static DeviceState *versal_create_gic(Versal *s,
     qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
 
     qdev_prop_set_bit(dev, "has-security-extensions", true);
     qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
     object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
+    qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx);
 
     sysbus_realize_and_unref(sbd, &error_fatal);
 
     memory_region_add_subregion(mr, map->gic.dist,
                                 sysbus_mmio_get_region(sbd, 0));
@@ -552,10 +590,12 @@ static DeviceState *versal_create_gic(Versal *s,
         qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
     }
 
     versal_create_gic_its(s, map, dev, mr, node);
 
+    g_array_append_val(s->intc, dev);
+
     return dev;
 }
 
 static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
                                DeviceState *gic, DeviceState *cpu, size_t idx,
@@ -609,13 +649,15 @@ static inline void versal_create_and_connect_gic(Versal *s,
                                                  MemoryRegion *mr,
                                                  DeviceState **cpus,
                                                  size_t num_cpu)
 {
     DeviceState *gic;
+    int first_cpu_idx;
     size_t i;
 
-    gic = versal_create_gic(s, map, mr, num_cpu);
+    first_cpu_idx = CPU(cpus[0])->cpu_index;
+    gic = versal_create_gic(s, map, mr, first_cpu_idx, num_cpu);
 
     for (i = 0; i < num_cpu; i++) {
         connect_gic_to_cpu(map, gic, cpus[i], i, num_cpu);
     }
 }
@@ -1540,10 +1582,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
     s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
     s->phandle.gic = qemu_fdt_alloc_phandle(s->cfg.fdt);
 
+    container = object_new(TYPE_CONTAINER);
+    object_property_add_child(OBJECT(s), "irq-splits", container);
+    object_unref(container);
+
     container = object_new(TYPE_CONTAINER);
     object_property_add_child(OBJECT(s), "irq-or-gates", container);
     object_unref(container);
 
     qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
@@ -1710,10 +1756,11 @@ static void versal_base_init(Object *obj)
 
     memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
     memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
                              "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
+    s->intc = g_array_new(false, false, sizeof(DeviceState *));
 
     num_can = versal_get_map(s)->num_canfd;
     s->cfg.canbus = g_new0(CanBusState *, num_can);
 
     for (i = 0; i < num_can; i++) {
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (24 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 14:29   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation Luc Michel
                   ` (21 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add support for GICv2 instantiation in the Versal SoC. This is in
preparation for the RPU refactoring.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 82 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 62 insertions(+), 20 deletions(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 58cd874f81f..771f6108558 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -43,10 +43,11 @@
 #include "hw/misc/xlnx-versal-cframe-reg.h"
 #include "hw/or-irq.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/intc/arm_gicv3_its_common.h"
+#include "hw/intc/arm_gic.h"
 #include "hw/core/split-irq.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
@@ -72,10 +73,11 @@ typedef struct VersalSimplePeriphMap {
 
 typedef struct VersalGicMap {
     int version;
     uint64_t dist;
     uint64_t redist;
+    uint64_t cpu_iface;
     uint64_t its;
     size_t num_irq;
     bool has_its;
 } VersalGicMap;
 
@@ -504,10 +506,14 @@ static void versal_create_gic_its(Versal *s,
     DeviceState *dev;
     SysBusDevice *sbd;
     g_autofree char *node_pat = NULL, *node = NULL;
     const char compatible[] = "arm,gic-v3-its";
 
+    if (map->gic.version != 3) {
+        return;
+    }
+
     if (!map->gic.has_its) {
         return;
     }
 
     dev = qdev_new(TYPE_ARM_GICV3_ITS);
@@ -543,49 +549,85 @@ static DeviceState *versal_create_gic(Versal *s,
                                       int first_cpu_idx,
                                       size_t num_cpu)
 {
     DeviceState *dev;
     SysBusDevice *sbd;
-    QList *redist_region_count;
     g_autofree char *node = NULL;
     g_autofree char *name = NULL;
-    const char compatible[] = "arm,gic-v3";
+    const char gicv3_compat[] = "arm,gic-v3";
+    const char gicv2_compat[] = "arm,cortex-a15-gic";
+
+    switch (map->gic.version) {
+    case 2:
+        dev = qdev_new(gic_class_name());
+        break;
+
+    case 3:
+        dev = qdev_new(gicv3_class_name());
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
 
-    dev = qdev_new(gicv3_class_name());
     name = g_strdup_printf("%s-gic[*]", map->name);
     object_property_add_child(OBJECT(s), name, OBJECT(dev));
     sbd = SYS_BUS_DEVICE(dev);
-    qdev_prop_set_uint32(dev, "revision", 3);
+    qdev_prop_set_uint32(dev, "revision", map->gic.version);
     qdev_prop_set_uint32(dev, "num-cpu", num_cpu);
     qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32);
-
-    redist_region_count = qlist_new();
-    qlist_append_int(redist_region_count, num_cpu);
-    qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
-
     qdev_prop_set_bit(dev, "has-security-extensions", true);
-    qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
-    object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
     qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx);
 
+    if (map->gic.version == 3) {
+        QList *redist_region_count;
+
+        redist_region_count = qlist_new();
+        qlist_append_int(redist_region_count, num_cpu);
+        qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
+        qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
+        object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr),
+                                 &error_abort);
+
+    }
+
     sysbus_realize_and_unref(sbd, &error_fatal);
 
     memory_region_add_subregion(mr, map->gic.dist,
                                 sysbus_mmio_get_region(sbd, 0));
-    memory_region_add_subregion(mr, map->gic.redist,
-                                sysbus_mmio_get_region(sbd, 1));
+
+    if (map->gic.version == 3) {
+        memory_region_add_subregion(mr, map->gic.redist,
+                                    sysbus_mmio_get_region(sbd, 1));
+    } else {
+        memory_region_add_subregion(mr, map->gic.cpu_iface,
+                                    sysbus_mmio_get_region(sbd, 1));
+    }
 
     if (map->dtb_expose) {
-        node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible,
-                                      sizeof(compatible));
+        if (map->gic.version == 3) {
+            node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
+                                          gicv3_compat,
+                                          sizeof(gicv3_compat));
+            qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
+                                         2, map->gic.dist,
+                                         2, 0x10000,
+                                         2, map->gic.redist,
+                                         2, GICV3_REDIST_SIZE * num_cpu);
+        } else {
+            node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
+                                          gicv2_compat,
+                                          sizeof(gicv2_compat));
+            qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
+                                         2, map->gic.dist,
+                                         2, 0x1000,
+                                         2, map->gic.cpu_iface,
+                                         2, 0x1000);
+        }
+
         qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
         qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
-        qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
-                                     2, map->gic.dist,
-                                     2, 0x10000,
-                                     2, map->gic.redist,
-                                     2, GICV3_REDIST_SIZE * num_cpu);
         qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
                                GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
     }
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (25 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2 Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:03   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 28/48] hw/arm/xlnx-versal: ocm: " Luc Michel
                   ` (20 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the RPU cluster creation using the VersalMap structure. This
effectively instantiate the RPU GICv2 which was not instantiated before.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h | 11 -------
 hw/arm/xlnx-versal-virt.c    |  1 +
 hw/arm/xlnx-versal.c         | 60 +++++++++++++++---------------------
 3 files changed, 26 insertions(+), 46 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9b11ffb845d..62b8d234ecb 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -12,14 +12,12 @@
 
 #ifndef XLNX_VERSAL_H
 #define XLNX_VERSAL_H
 
 #include "hw/sysbus.h"
-#include "hw/cpu/cluster.h"
 #include "qom/object.h"
 #include "net/can_emu.h"
-#include "target/arm/cpu.h"
 #include "hw/arm/xlnx-versal-version.h"
 
 #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
 OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 
@@ -50,19 +48,10 @@ struct Versal {
         MemoryRegion mr_ddr_ranges[4];
     } noc;
 
     struct {
         MemoryRegion mr_ocm;
-
-        /* Real-time Processing Unit.  */
-        struct {
-            MemoryRegion mr;
-            MemoryRegion mr_ps_alias;
-
-            CPUClusterState cluster;
-            ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
-        } rpu;
     } lpd;
 
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 55159536ceb..cad345b98e0 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -22,10 +22,11 @@
 #include "hw/qdev-properties.h"
 #include "hw/arm/xlnx-versal.h"
 #include "hw/arm/boot.h"
 #include "target/arm/multiprocessing.h"
 #include "qom/object.h"
+#include "target/arm/cpu.h"
 
 #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
 OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
 
 #define XLNX_VERSAL_NUM_OSPI_FLASH 4
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 771f6108558..3905549b32e 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -45,10 +45,12 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/intc/arm_gicv3_common.h"
 #include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/core/split-irq.h"
+#include "target/arm/cpu.h"
+#include "hw/cpu/cluster.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -107,10 +109,11 @@ typedef struct VersalCpuClusterMap {
     enum StartPoweredOffMode start_powered_off;
 } VersalCpuClusterMap;
 
 typedef struct VersalMap {
     VersalCpuClusterMap apu;
+    VersalCpuClusterMap rpu;
 
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
 
     VersalSimplePeriphMap canfd[4];
@@ -227,10 +230,31 @@ static const VersalMap VERSAL_MAP = {
             .has_its = true,
             .its = 0xf9020000,
         },
     },
 
+    .rpu = {
+        .name = "rpu",
+        .cpu_model = ARM_CPU_TYPE_NAME("cortex-r5f"),
+        .num_cluster = 1,
+        .num_core = 2,
+        .qemu_cluster_id = 1,
+        .mp_affinity = {
+            .base = 0x100,
+            .core_mask = 0xff,
+            .core_shift = 0,
+        },
+        .start_powered_off = SPO_ALL,
+        .dtb_expose = false,
+        .gic = {
+            .version = 2,
+            .dist = 0xf9000000,
+            .cpu_iface = 0xf9001000,
+            .num_irq = 192,
+        },
+    },
+
     .uart[0] = { 0xff000000, 18 },
     .uart[1] = { 0xff010000, 19 },
     .num_uart = 2,
 
     .canfd[0] = { 0xff060000, 20 },
@@ -809,39 +833,10 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
         qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
                          compatible, sizeof(compatible));
     }
 }
 
-static void versal_create_rpu_cpus(Versal *s)
-{
-    int i;
-
-    object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
-                            TYPE_CPU_CLUSTER);
-    qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
-
-    for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
-        Object *obj;
-
-        object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
-                                "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
-                                XLNX_VERSAL_RCPU_TYPE);
-        obj = OBJECT(&s->lpd.rpu.cpu[i]);
-        object_property_set_bool(obj, "start-powered-off", true,
-                                 &error_abort);
-
-        object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
-        object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
-                                &error_abort);
-        object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
-                                 &error_abort);
-        qdev_realize(DEVICE(obj), NULL, &error_fatal);
-    }
-
-    qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
-}
-
 static void versal_create_uart(Versal *s,
                                const VersalSimplePeriphMap *map,
                                int chardev_idx)
 {
     DeviceState *dev;
@@ -1637,11 +1632,11 @@ static void versal_realize(DeviceState *dev, Error **errp)
     qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
     qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#size-cells", 0x2);
     qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#address-cells", 0x2);
 
     versal_create_cpu_cluster(s, &map->apu);
-    versal_create_rpu_cpus(s);
+    versal_create_cpu_cluster(s, &map->rpu);
 
     for (i = 0; i < map->num_uart; i++) {
         versal_create_uart(s, &map->uart[i], i);
     }
 
@@ -1687,12 +1682,10 @@ static void versal_realize(DeviceState *dev, Error **errp)
     /* Create the On Chip Memory (OCM).  */
     memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
                            MM_OCM_SIZE, &error_fatal);
 
     memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
-    memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
-                                        &s->lpd.rpu.mr_ps_alias, 0);
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
 {
     DeviceState *sdhci, *card;
@@ -1794,14 +1787,11 @@ int versal_get_num_sdhci(VersalVersion version)
 static void versal_base_init(Object *obj)
 {
     Versal *s = XLNX_VERSAL_BASE(obj);
     size_t i, num_can;
 
-    memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
-    memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
-                             "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
     s->intc = g_array_new(false, false, sizeof(DeviceState *));
 
     num_can = versal_get_map(s)->num_canfd;
     s->cfg.canbus = g_new0(CanBusState *, num_can);
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 28/48] hw/arm/xlnx-versal: ocm: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (26 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:04   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 29/48] hw/arm/xlnx-versal: ddr: " Luc Michel
                   ` (19 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the OCM creation using the VersalMap structure.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  4 ----
 hw/arm/xlnx-versal.c         | 20 ++++++++++++++++----
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 62b8d234ecb..7be5a6ccf4d 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -46,14 +46,10 @@ struct Versal {
     struct {
         /* 4 ranges to access DDR.  */
         MemoryRegion mr_ddr_ranges[4];
     } noc;
 
-    struct {
-        MemoryRegion mr_ocm;
-    } lpd;
-
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
         uint32_t gic;
     } phandle;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3905549b32e..f46c73ac8e7 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -71,10 +71,15 @@ FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
 typedef struct VersalSimplePeriphMap {
     uint64_t addr;
     int irq;
 } VersalSimplePeriphMap;
 
+typedef struct VersalMemMap {
+    uint64_t addr;
+    uint64_t size;
+} VersalMemMap;
+
 typedef struct VersalGicMap {
     int version;
     uint64_t dist;
     uint64_t redist;
     uint64_t cpu_iface;
@@ -108,10 +113,12 @@ typedef struct VersalCpuClusterMap {
 
     enum StartPoweredOffMode start_powered_off;
 } VersalCpuClusterMap;
 
 typedef struct VersalMap {
+    VersalMemMap ocm;
+
     VersalCpuClusterMap apu;
     VersalCpuClusterMap rpu;
 
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
@@ -207,10 +214,15 @@ typedef struct VersalMap {
         int irq_num;
     } reserved;
 } VersalMap;
 
 static const VersalMap VERSAL_MAP = {
+    .ocm = {
+        .addr = 0xfffc0000,
+        .size = 0x40000,
+    },
+
     .apu = {
         .name = "apu",
         .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
         .num_cluster = 1,
         .num_core = 2,
@@ -1605,10 +1617,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
 
 static void versal_realize(DeviceState *dev, Error **errp)
 {
     Versal *s = XLNX_VERSAL_BASE(dev);
     DeviceState *slcr, *ospi;
+    MemoryRegion *ocm;
     Object *container;
     const VersalMap *map = versal_get_map(s);
     size_t i;
 
     if (s->cfg.fdt == NULL) {
@@ -1678,14 +1691,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
 
     versal_map_ddr(s);
     versal_unimp(s);
 
     /* Create the On Chip Memory (OCM).  */
-    memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
-                           MM_OCM_SIZE, &error_fatal);
-
-    memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
+    ocm = g_new(MemoryRegion, 1);
+    memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
+    memory_region_add_subregion_overlap(&s->mr_ps, map->ocm.addr, ocm, 0);
 }
 
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
 {
     DeviceState *sdhci, *card;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 29/48] hw/arm/xlnx-versal: ddr: refactor creation
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (27 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 28/48] hw/arm/xlnx-versal: ocm: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:12   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor Luc Michel
                   ` (18 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the DDR aperture regions creation using the VersalMap
structure. Device creation and FDT node creation are split into two
functions because the later must happen during ARM virtual bootloader
modify_dtb callback.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  7 +---
 hw/arm/xlnx-versal-virt.c    | 79 +-----------------------------------
 hw/arm/xlnx-versal.c         | 73 ++++++++++++++++++++++-----------
 3 files changed, 53 insertions(+), 106 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 7be5a6ccf4d..a3bc967c352 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -41,15 +41,10 @@ struct Versal {
 
     /*< public >*/
     GArray *intc;
     MemoryRegion mr_ps;
 
-    struct {
-        /* 4 ranges to access DDR.  */
-        MemoryRegion mr_ddr_ranges[4];
-    } noc;
-
     struct {
         uint32_t clk_25mhz;
         uint32_t clk_125mhz;
         uint32_t gic;
     } phandle;
@@ -71,10 +66,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
 {
     g_assert(!qdev_is_realized(DEVICE(s)));
     s->cfg.fdt = fdt;
 }
 
+void versal_fdt_add_memory_nodes(Versal *s, uint64_t ram_size);
+
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
 void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
 void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
 void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
                               BlockBackend *blk);
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index cad345b98e0..7f40c197072 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -104,92 +104,17 @@ static void fdt_nop_memory_nodes(void *fdt, Error **errp)
         n++;
     }
     g_strfreev(node_path);
 }
 
-static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
-{
-    /* Describes the various split DDR access regions.  */
-    static const struct {
-        uint64_t base;
-        uint64_t size;
-    } addr_ranges[] = {
-        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
-        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
-        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
-        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
-    };
-    uint64_t mem_reg_prop[8] = {0};
-    uint64_t size = ram_size;
-    Error *err = NULL;
-    char *name;
-    int i;
-
-    fdt_nop_memory_nodes(fdt, &err);
-    if (err) {
-        error_report_err(err);
-        return;
-    }
-
-    name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
-    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
-        uint64_t mapsize;
-
-        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
-
-        mem_reg_prop[i * 2] = addr_ranges[i].base;
-        mem_reg_prop[i * 2 + 1] = mapsize;
-        size -= mapsize;
-    }
-    qemu_fdt_add_subnode(fdt, name);
-    qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
-
-    switch (i) {
-    case 1:
-        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
-                                     2, mem_reg_prop[0],
-                                     2, mem_reg_prop[1]);
-        break;
-    case 2:
-        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
-                                     2, mem_reg_prop[0],
-                                     2, mem_reg_prop[1],
-                                     2, mem_reg_prop[2],
-                                     2, mem_reg_prop[3]);
-        break;
-    case 3:
-        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
-                                     2, mem_reg_prop[0],
-                                     2, mem_reg_prop[1],
-                                     2, mem_reg_prop[2],
-                                     2, mem_reg_prop[3],
-                                     2, mem_reg_prop[4],
-                                     2, mem_reg_prop[5]);
-        break;
-    case 4:
-        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
-                                     2, mem_reg_prop[0],
-                                     2, mem_reg_prop[1],
-                                     2, mem_reg_prop[2],
-                                     2, mem_reg_prop[3],
-                                     2, mem_reg_prop[4],
-                                     2, mem_reg_prop[5],
-                                     2, mem_reg_prop[6],
-                                     2, mem_reg_prop[7]);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    g_free(name);
-}
-
 static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
                                     void *fdt)
 {
     VersalVirt *s = container_of(binfo, VersalVirt, binfo);
 
-    fdt_add_memory_nodes(s, fdt, binfo->ram_size);
+    fdt_nop_memory_nodes(s->fdt, &error_abort);
+    versal_fdt_add_memory_nodes(&s->soc, binfo->ram_size);
 }
 
 static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
                                   int *fdt_size)
 {
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index f46c73ac8e7..bf680077e48 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -115,10 +115,15 @@ typedef struct VersalCpuClusterMap {
 } VersalCpuClusterMap;
 
 typedef struct VersalMap {
     VersalMemMap ocm;
 
+    struct VersalDDRMap {
+        VersalMemMap chan[4];
+        size_t num_chan;
+    } ddr;
+
     VersalCpuClusterMap apu;
     VersalCpuClusterMap rpu;
 
     VersalSimplePeriphMap uart[2];
     size_t num_uart;
@@ -219,10 +224,18 @@ static const VersalMap VERSAL_MAP = {
     .ocm = {
         .addr = 0xfffc0000,
         .size = 0x40000,
     },
 
+    .ddr = {
+        .chan[0] = { .addr = 0x0, .size = 2 * GiB },
+        .chan[1] = { .addr = 0x800000000ull, .size = 32 * GiB },
+        .chan[2] = { .addr = 0xc00000000ull, .size = 256 * GiB },
+        .chan[3] = { .addr = 0x10000000000ull, .size = 734 * GiB },
+        .num_chan = 4,
+    },
+
     .apu = {
         .name = "apu",
         .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
         .num_cluster = 1,
         .num_core = 2,
@@ -1480,50 +1493,62 @@ static inline void versal_create_crl(Versal *s)
                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
 
     versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
 }
 
-/* This takes the board allocated linear DDR memory and creates aliases
+/*
+ * This takes the board allocated linear DDR memory and creates aliases
  * for each split DDR range/aperture on the Versal address map.
  */
-static void versal_map_ddr(Versal *s)
+static void versal_map_ddr(Versal *s, const struct VersalDDRMap *map)
 {
     uint64_t size = memory_region_size(s->cfg.mr_ddr);
-    /* Describes the various split DDR access regions.  */
-    static const struct {
-        uint64_t base;
-        uint64_t size;
-    } addr_ranges[] = {
-        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
-        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
-        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
-        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
-    };
     uint64_t offset = 0;
     int i;
 
-    assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
-    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
-        char *name;
+    for (i = 0; i < map->num_chan && size; i++) {
         uint64_t mapsize;
+        MemoryRegion *alias;
+
+        mapsize = MIN(size, map->chan[i].size);
 
-        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
-        name = g_strdup_printf("noc-ddr-range%d", i);
         /* Create the MR alias.  */
-        memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
-                                 name, s->cfg.mr_ddr,
-                                 offset, mapsize);
+        alias = g_new(MemoryRegion, 1);
+        memory_region_init_alias(alias, OBJECT(s), "noc-ddr-range",
+                                 s->cfg.mr_ddr, offset, mapsize);
 
         /* Map it onto the NoC MR.  */
-        memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
-                                    &s->noc.mr_ddr_ranges[i]);
+        memory_region_add_subregion(&s->mr_ps, map->chan[i].addr, alias);
         offset += mapsize;
         size -= mapsize;
-        g_free(name);
     }
 }
 
+void versal_fdt_add_memory_nodes(Versal *s, uint64_t size)
+{
+    const struct VersalDDRMap *map = &versal_get_map(s)->ddr;
+    g_autofree char *node;
+    g_autofree uint64_t *reg;
+    int i;
+
+    reg = g_new(uint64_t, map->num_chan * 2);
+
+    for (i = 0; i < map->num_chan && size; i++) {
+        uint64_t mapsize;
+
+        mapsize = MIN(size, map->chan[i].size);
+
+        reg[i * 2] = cpu_to_be64(map->chan[i].addr);
+        reg[i * 2 + 1] = cpu_to_be64(mapsize);
+
+        size -= mapsize;
+    }
+
+    node = versal_fdt_add_subnode(s, "/memory", 0, "memory", sizeof("memory"));
+    qemu_fdt_setprop(s->cfg.fdt, node, "reg", reg, sizeof(uint64_t) * i * 2);
+}
+
 static void versal_unimp_area(Versal *s, const char *name,
                                 MemoryRegion *mr,
                                 hwaddr base, hwaddr size)
 {
     DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
@@ -1687,11 +1712,11 @@ static void versal_realize(DeviceState *dev, Error **errp)
     versal_create_trng(s, &map->trng);
     versal_create_rtc(s, &map->rtc);
     versal_create_cfu(s, &map->cfu);
     versal_create_crl(s);
 
-    versal_map_ddr(s);
+    versal_map_ddr(s, &map->ddr);
     versal_unimp(s);
 
     /* Create the On Chip Memory (OCM).  */
     ocm = g_new(MemoryRegion, 1);
     memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (28 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 29/48] hw/arm/xlnx-versal: ddr: " Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:13   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives Luc Michel
                   ` (17 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the versal_get_num_cpu accessor to the Versal SoC to retrieve the
number of CPUs in the SoC. Use it in the xlnx-versal-virt machine.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h | 1 +
 hw/arm/xlnx-versal-virt.c    | 7 ++++---
 hw/arm/xlnx-versal.c         | 8 ++++++++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index a3bc967c352..ffa7801b30f 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -77,10 +77,11 @@ void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
                               BlockBackend *blk);
 
 qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx);
 hwaddr versal_get_reserved_mmio_addr(Versal *s);
 
+int versal_get_num_cpu(VersalVersion version);
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 7f40c197072..5e47a20922a 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -344,16 +344,17 @@ static void versal_virt_machine_finalize(Object *obj)
 }
 
 static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
+    int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
 
     mc->desc = "Xilinx Versal Virtual development board";
     mc->init = versal_virt_init;
-    mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
-    mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
-    mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
+    mc->min_cpus = num_cpu;
+    mc->max_cpus = num_cpu;
+    mc->default_cpus = num_cpu;
     mc->no_cdrom = true;
     mc->auto_create_sdcard = true;
     mc->default_ram_id = "ddr";
     object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
                                    versal_set_ospi_model);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index bf680077e48..5151822ad56 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -1805,10 +1805,18 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s)
     const VersalMap *map = versal_get_map(s);
 
     return map->reserved.mmio_start;
 }
 
+int versal_get_num_cpu(VersalVersion version)
+{
+    const VersalMap *map = VERSION_TO_MAP[version];
+
+    return map->apu.num_cluster * map->apu.num_core
+        + map->rpu.num_cluster * map->rpu.num_core;
+}
+
 int versal_get_num_can(VersalVersion version)
 {
     const VersalMap *map = VERSION_TO_MAP[version];
 
     return map->num_canfd;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (29 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:14   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes Luc Michel
                   ` (16 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Drop unused include directives from xlnx-versal-crl.c

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/misc/xlnx-versal-crl.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index 08ff2fcc24f..f288545967a 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -1,18 +1,15 @@
 /*
  * QEMU model of the Clock-Reset-LPD (CRL).
  *
- * Copyright (c) 2022 Advanced Micro Devices, Inc.
+ * Copyright (c) 2022-2025 Advanced Micro Devices, Inc.
  * SPDX-License-Identifier: GPL-2.0-or-later
  *
  * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
  */
 
 #include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu/log.h"
-#include "qemu/bitops.h"
 #include "migration/vmstate.h"
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
 #include "hw/register.h"
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (30 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-30 19:23   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic Luc Michel
                   ` (15 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Split the TYPE_XLNX_VERSAL_CRL type into base and concrete classes. This
is in preparation for the versal2 version of the CRL.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/misc/xlnx-versal-crl.h | 31 ++++++++++++++++++--
 hw/misc/xlnx-versal-crl.c         | 48 +++++++++++++++++++------------
 2 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
index dba6d3585d1..2b39d203a67 100644
--- a/include/hw/misc/xlnx-versal-crl.h
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -1,21 +1,27 @@
 /*
  * QEMU model of the Clock-Reset-LPD (CRL).
  *
  * Copyright (c) 2022 Xilinx Inc.
+ * Copyright (c) 2025 Advanced Micro Devices, Inc.
  * SPDX-License-Identifier: GPL-2.0-or-later
  *
  * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
  */
 #ifndef HW_MISC_XLNX_VERSAL_CRL_H
 #define HW_MISC_XLNX_VERSAL_CRL_H
 
 #include "hw/sysbus.h"
 #include "hw/register.h"
 #include "target/arm/cpu-qom.h"
+#include "hw/arm/xlnx-versal-version.h"
 
+#define TYPE_XLNX_VERSAL_CRL_BASE "xlnx-versal-crl-base"
 #define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
+
+OBJECT_DECLARE_TYPE(XlnxVersalCRLBase, XlnxVersalCRLBaseClass,
+                    XLNX_VERSAL_CRL_BASE)
 OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
 
 REG32(ERR_CTRL, 0x0)
     FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
 REG32(IR_STATUS, 0x4)
@@ -214,22 +220,43 @@ REG32(PSM_RST_MODE, 0x370)
 
 #define CRL_R_MAX (R_PSM_RST_MODE + 1)
 
 #define RPU_MAX_CPU 2
 
-struct XlnxVersalCRL {
+struct XlnxVersalCRLBase {
     SysBusDevice parent_obj;
+
+    RegisterInfoArray *reg_array;
+    uint32_t *regs;
+};
+
+struct XlnxVersalCRLBaseClass {
+    SysBusDeviceClass parent_class;
+};
+
+struct XlnxVersalCRL {
+    XlnxVersalCRLBase parent_obj;
     qemu_irq irq;
 
     struct {
         ARMCPU *cpu_r5[RPU_MAX_CPU];
         DeviceState *adma[8];
         DeviceState *uart[2];
         DeviceState *gem[2];
         DeviceState *usb;
     } cfg;
 
-    RegisterInfoArray *reg_array;
     uint32_t regs[CRL_R_MAX];
     RegisterInfo regs_info[CRL_R_MAX];
 };
+
+static inline const char *xlnx_versal_crl_class_name(VersalVersion ver)
+{
+    switch (ver) {
+    case VERSAL_VER_VERSAL:
+        return TYPE_XLNX_VERSAL_CRL;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 #endif
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index f288545967a..be89e0da40d 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -296,21 +296,21 @@ static const RegisterAccessInfo crl_regs_info[] = {
         .reset = 0x1,
         .rsvd = 0xf8,
     }
 };
 
-static void crl_reset_enter(Object *obj, ResetType type)
+static void versal_crl_reset_enter(Object *obj, ResetType type)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
     unsigned int i;
 
     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
         register_reset(&s->regs_info[i]);
     }
 }
 
-static void crl_reset_hold(Object *obj, ResetType type)
+static void versal_crl_reset_hold(Object *obj, ResetType type)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
 
     crl_update_irq(s);
 }
@@ -323,24 +323,26 @@ static const MemoryRegionOps crl_ops = {
         .min_access_size = 4,
         .max_access_size = 4,
     },
 };
 
-static void crl_init(Object *obj)
+static void versal_crl_init(Object *obj)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
+    XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     int i;
 
-    s->reg_array =
+    xvcb->reg_array =
         register_init_block32(DEVICE(obj), crl_regs_info,
                               ARRAY_SIZE(crl_regs_info),
                               s->regs_info, s->regs,
                               &crl_ops,
                               XLNX_VERSAL_CRL_ERR_DEBUG,
                               CRL_R_MAX * 4);
-    sysbus_init_mmio(sbd, &s->reg_array->mem);
+    xvcb->regs = s->regs;
+    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
     sysbus_init_irq(sbd, &s->irq);
 
     for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
         object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
                                  (Object **)&s->cfg.cpu_r5[i],
@@ -375,45 +377,53 @@ static void crl_init(Object *obj)
                              OBJ_PROP_LINK_STRONG);
 }
 
 static void crl_finalize(Object *obj)
 {
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
+    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
     register_finalize_block(s->reg_array);
 }
 
-static const VMStateDescription vmstate_crl = {
+static const VMStateDescription vmstate_versal_crl = {
     .name = TYPE_XLNX_VERSAL_CRL,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
         VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
         VMSTATE_END_OF_LIST(),
     }
 };
 
-static void crl_class_init(ObjectClass *klass, const void *data)
+static void versal_crl_class_init(ObjectClass *klass, const void *data)
 {
-    ResettableClass *rc = RESETTABLE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
 
-    dc->vmsd = &vmstate_crl;
-
-    rc->phases.enter = crl_reset_enter;
-    rc->phases.hold = crl_reset_hold;
+    dc->vmsd = &vmstate_versal_crl;
+    rc->phases.enter = versal_crl_reset_enter;
+    rc->phases.hold = versal_crl_reset_hold;
 }
 
-static const TypeInfo crl_info = {
-    .name          = TYPE_XLNX_VERSAL_CRL,
+static const TypeInfo crl_base_info = {
+    .name          = TYPE_XLNX_VERSAL_CRL_BASE,
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(XlnxVersalCRL),
-    .class_init    = crl_class_init,
-    .instance_init = crl_init,
+    .instance_size = sizeof(XlnxVersalCRLBase),
+    .class_size    = sizeof(XlnxVersalCRLBaseClass),
     .instance_finalize = crl_finalize,
+    .abstract      = true,
+};
+
+static const TypeInfo versal_crl_info = {
+    .name          = TYPE_XLNX_VERSAL_CRL,
+    .parent        = TYPE_XLNX_VERSAL_CRL_BASE,
+    .instance_size = sizeof(XlnxVersalCRL),
+    .instance_init = versal_crl_init,
+    .class_init    = versal_crl_class_init,
 };
 
 static void crl_register_types(void)
 {
-    type_register_static(&crl_info);
+    type_register_static(&crl_base_info);
+    type_register_static(&versal_crl_info);
 }
 
 type_init(crl_register_types)
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (31 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 13:23   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices Luc Michel
                   ` (14 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Refactor the device reset logic to have a common register write callback
for all the devices. This uses a decode function to map the register
address to the actual peripheral to reset. This refactoring changes the
CPU property name from cpu_r5[*] to rpu[*] to ease with the connections
in the Versal SoC. It also fixes a bug where the gem device pointer
was mapped to the usb link property.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/misc/xlnx-versal-crl.h |   8 +-
 hw/misc/xlnx-versal-crl.c         | 163 ++++++++++++++++--------------
 2 files changed, 92 insertions(+), 79 deletions(-)

diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
index 2b39d203a67..7e50a95ad3c 100644
--- a/include/hw/misc/xlnx-versal-crl.h
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -218,33 +218,33 @@ REG32(PSM_RST_MODE, 0x370)
     FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
     FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
 
 #define CRL_R_MAX (R_PSM_RST_MODE + 1)
 
-#define RPU_MAX_CPU 2
-
 struct XlnxVersalCRLBase {
     SysBusDevice parent_obj;
 
     RegisterInfoArray *reg_array;
     uint32_t *regs;
 };
 
 struct XlnxVersalCRLBaseClass {
     SysBusDeviceClass parent_class;
+
+    DeviceState ** (*decode_periph_rst)(XlnxVersalCRLBase *s, hwaddr, size_t *);
 };
 
 struct XlnxVersalCRL {
     XlnxVersalCRLBase parent_obj;
     qemu_irq irq;
 
     struct {
-        ARMCPU *cpu_r5[RPU_MAX_CPU];
+        DeviceState *rpu[2];
         DeviceState *adma[8];
         DeviceState *uart[2];
         DeviceState *gem[2];
-        DeviceState *usb;
+        DeviceState *usb[1];
     } cfg;
 
     uint32_t regs[CRL_R_MAX];
     RegisterInfo regs_info[CRL_R_MAX];
 };
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index be89e0da40d..115327cfcf4 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -53,94 +53,103 @@ static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
     s->regs[R_IR_MASK] |= val;
     crl_update_irq(s);
     return 0;
 }
 
-static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
-                          bool rst_old, bool rst_new)
+static DeviceState **versal_decode_periph_rst(XlnxVersalCRLBase *s,
+                                             hwaddr addr, size_t *count)
 {
-    device_cold_reset(dev);
-}
+    size_t idx;
+    XlnxVersalCRL *xvc = XLNX_VERSAL_CRL(s);
 
-static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
-                          bool rst_old, bool rst_new)
-{
-    if (rst_new) {
-        arm_set_cpu_off(arm_cpu_mp_affinity(armcpu));
-    } else {
-        arm_set_cpu_on_and_reset(arm_cpu_mp_affinity(armcpu));
-    }
-}
+    *count = 1;
 
-#define REGFIELD_RESET(type, s, reg, f, new_val, dev) {     \
-    bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f);       \
-    bool new_f = FIELD_EX32(new_val, reg, f);               \
-                                                            \
-    /* Detect edges.  */                                    \
-    if (dev && old_f != new_f) {                            \
-        crl_reset_ ## type(s, dev, old_f, new_f);           \
-    }                                                       \
-}
+    switch (addr) {
+    case A_RST_CPU_R5:
+        return xvc->cfg.rpu;
 
-static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+    case A_RST_ADMA:
+        /* A single register fans out to all DMA reset inputs */
+        *count = ARRAY_SIZE(xvc->cfg.adma);
+        return xvc->cfg.adma;
 
-    REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
-    REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
-    return val64;
-}
+    case A_RST_UART0 ... A_RST_UART1:
+        idx = (addr - A_RST_UART0) / sizeof(uint32_t);
+        return xvc->cfg.uart + idx;
 
-static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
-    int i;
+    case A_RST_GEM0 ... A_RST_GEM1:
+        idx = (addr - A_RST_GEM0) / sizeof(uint32_t);
+        return xvc->cfg.gem + idx;
+
+    case A_RST_USB0:
+        return xvc->cfg.usb;
 
-    /* A single register fans out to all ADMA reset inputs.  */
-    for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
-        REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
+    default:
+        /* invalid or unimplemented */
+        return NULL;
     }
-    return val64;
 }
 
-static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
+static uint64_t crl_rst_cpu_prew(RegisterInfo *reg, uint64_t val64)
 {
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
+    XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
+    DeviceState **dev;
+    size_t i, count;
 
-    REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
-    return val64;
-}
+    dev = xvcbc->decode_periph_rst(s, reg->access->addr, &count);
 
-static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+    for (i = 0; i < 2; i++) {
+        bool prev, new;
+        uint64_t aff;
 
-    REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
-    return val64;
-}
+        prev = extract32(s->regs[reg->access->addr / 4], i, 1);
+        new = extract32(val64, i, 1);
 
-static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+        if (prev == new) {
+            continue;
+        }
 
-    REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
-    return val64;
-}
+        aff = arm_cpu_mp_affinity(ARM_CPU(dev[i]));
 
-static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+        if (new) {
+            arm_set_cpu_off(aff);
+        } else {
+            arm_set_cpu_on_and_reset(aff);
+        }
+    }
 
-    REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
     return val64;
 }
 
-static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
+static uint64_t crl_rst_dev_prew(RegisterInfo *reg, uint64_t val64)
 {
-    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
+    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
+    XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
+    DeviceState **dev;
+    bool prev, new;
+    size_t i, count;
+
+    dev = xvcbc->decode_periph_rst(s, reg->access->addr, &count);
+
+    if (dev == NULL) {
+        return val64;
+    }
+
+    prev = s->regs[reg->access->addr / 4] & 0x1;
+    new = val64 & 0x1;
+
+    if (prev == new) {
+        return val64;
+    }
+
+    for (i = 0; i < count; i++) {
+        if (dev[i]) {
+            device_cold_reset(dev[i]);
+        }
+    }
 
-    REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
     return val64;
 }
 
 static const RegisterAccessInfo crl_regs_info[] = {
     {   .name = "ERR_CTRL",  .addr = A_ERR_CTRL,
@@ -242,31 +251,31 @@ static const RegisterAccessInfo crl_regs_info[] = {
         .reset = 0x3c00,
         .rsvd = 0xfdfc00f8,
     },{ .name = "RST_CPU_R5",  .addr = A_RST_CPU_R5,
         .reset = 0x17,
         .rsvd = 0x8,
-        .pre_write = crl_rst_r5_prew,
+        .pre_write = crl_rst_cpu_prew,
     },{ .name = "RST_ADMA",  .addr = A_RST_ADMA,
         .reset = 0x1,
-        .pre_write = crl_rst_adma_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_GEM0",  .addr = A_RST_GEM0,
         .reset = 0x1,
-        .pre_write = crl_rst_gem0_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_GEM1",  .addr = A_RST_GEM1,
         .reset = 0x1,
-        .pre_write = crl_rst_gem1_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_SPARE",  .addr = A_RST_SPARE,
         .reset = 0x1,
     },{ .name = "RST_USB0",  .addr = A_RST_USB0,
         .reset = 0x1,
-        .pre_write = crl_rst_usb_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_UART0",  .addr = A_RST_UART0,
         .reset = 0x1,
-        .pre_write = crl_rst_uart0_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_UART1",  .addr = A_RST_UART1,
         .reset = 0x1,
-        .pre_write = crl_rst_uart1_prew,
+        .pre_write = crl_rst_dev_prew,
     },{ .name = "RST_SPI0",  .addr = A_RST_SPI0,
         .reset = 0x1,
     },{ .name = "RST_SPI1",  .addr = A_RST_SPI1,
         .reset = 0x1,
     },{ .name = "RST_CAN0",  .addr = A_RST_CAN0,
@@ -341,13 +350,13 @@ static void versal_crl_init(Object *obj)
                               CRL_R_MAX * 4);
     xvcb->regs = s->regs;
     sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
     sysbus_init_irq(sbd, &s->irq);
 
-    for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
-        object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
-                                 (Object **)&s->cfg.cpu_r5[i],
+    for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
+        object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
+                                 (Object **)&s->cfg.rpu[i],
                                  qdev_prop_allow_set_link_before_realize,
                                  OBJ_PROP_LINK_STRONG);
     }
 
     for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
@@ -369,14 +378,16 @@ static void versal_crl_init(Object *obj)
                                  (Object **)&s->cfg.gem[i],
                                  qdev_prop_allow_set_link_before_realize,
                                  OBJ_PROP_LINK_STRONG);
     }
 
-    object_property_add_link(obj, "usb", TYPE_DEVICE,
-                             (Object **)&s->cfg.gem[i],
-                             qdev_prop_allow_set_link_before_realize,
-                             OBJ_PROP_LINK_STRONG);
+    for (i = 0; i < ARRAY_SIZE(s->cfg.usb); ++i) {
+        object_property_add_link(obj, "usb[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.usb[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
 }
 
 static void crl_finalize(Object *obj)
 {
     XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
@@ -394,15 +405,17 @@ static const VMStateDescription vmstate_versal_crl = {
 };
 
 static void versal_crl_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
     ResettableClass *rc = RESETTABLE_CLASS(klass);
 
     dc->vmsd = &vmstate_versal_crl;
     rc->phases.enter = versal_crl_reset_enter;
     rc->phases.hold = versal_crl_reset_hold;
+    xvcc->decode_periph_rst = versal_decode_periph_rst;
 }
 
 static const TypeInfo crl_base_info = {
     .name          = TYPE_XLNX_VERSAL_CRL_BASE,
     .parent        = TYPE_SYS_BUS_DEVICE,
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (32 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 13:26   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices Luc Michel
                   ` (13 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

The CRL connects to various devices through link properties to be able
to reset them. The connections were dropped during the SoC refactoring.
Reintroduce them now.

Rely on the QOM tree to retrieve the devices to connect. The component
parts of the device names are chosen to match the properties on the CRL.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 5151822ad56..796b4911a02 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -1473,21 +1473,50 @@ static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
     sysbus_realize_and_unref(sbd, &error_fatal);
     memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
                                 sysbus_mmio_get_region(sbd, 0));
 }
 
+static inline void crl_connect_dev(Object *crl, Object *dev)
+{
+    const char *prop = object_get_canonical_path_component(dev);
+
+    /* The component part of the device path matches the CRL property name */
+    object_property_set_link(crl, prop, dev, &error_abort);
+}
+
+static inline void crl_connect_dev_by_name(Versal *s, Object *crl,
+                                           const char *name, size_t num)
+{
+    size_t i;
+
+    for (i = 0; i < num; i++) {
+        Object *dev = versal_get_child_idx(s, name, i);
+
+        crl_connect_dev(crl, dev);
+    }
+}
+
 static inline void versal_create_crl(Versal *s)
 {
     const VersalMap *map;
     const char *crl_class;
     DeviceState *dev;
+    Object *obj;
 
     map = versal_get_map(s);
 
     crl_class = TYPE_XLNX_VERSAL_CRL;
     dev = qdev_new(crl_class);
-    object_property_add_child(OBJECT(s), "crl", OBJECT(dev));
+    obj = OBJECT(dev);
+    object_property_add_child(OBJECT(s), "crl", obj);
+
+    crl_connect_dev_by_name(s, obj, "rpu-cluster/rpu",
+                            map->rpu.num_cluster * map->rpu.num_core);
+    crl_connect_dev_by_name(s, obj, map->zdma[0].name, map->zdma[0].num_chan);
+    crl_connect_dev_by_name(s, obj, "uart", map->num_uart);
+    crl_connect_dev_by_name(s, obj, "gem", map->num_gem);
+    crl_connect_dev_by_name(s, obj, "usb", map->num_usb);
 
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
 
     memory_region_add_subregion(&s->mr_ps, map->crl.addr,
                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (33 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 13:29   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 36/48] hw/arm/xlnx-versal: tidy up Luc Michel
                   ` (12 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Use the bsa.h header for ARM timer and maintainance IRQ indices instead
of redefining our owns.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  6 ------
 hw/arm/xlnx-versal.c         | 28 +++++++++++++++++-----------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index ffa7801b30f..3be9f0a5550 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -84,16 +84,10 @@ int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
 
-#define VERSAL_GIC_MAINT_IRQ        9
-#define VERSAL_TIMER_VIRT_IRQ       11
-#define VERSAL_TIMER_S_EL1_IRQ      13
-#define VERSAL_TIMER_NS_EL1_IRQ     14
-#define VERSAL_TIMER_NS_EL2_IRQ     10
-
 #define VERSAL_CRL_IRQ             10
 #define VERSAL_UART0_IRQ_0         18
 #define VERSAL_UART1_IRQ_0         19
 #define VERSAL_CANFD0_IRQ_0        20
 #define VERSAL_CANFD1_IRQ_0        21
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 796b4911a02..c513d28c8d4 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -47,10 +47,11 @@
 #include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/core/split-irq.h"
 #include "target/arm/cpu.h"
 #include "hw/cpu/cluster.h"
+#include "hw/arm/bsa.h"
 
 #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION        0x40070106
 
@@ -674,11 +675,12 @@ static DeviceState *versal_create_gic(Versal *s,
         }
 
         qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
         qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
         qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
-                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
+                               GIC_FDT_IRQ_TYPE_PPI,
+                               INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
     }
 
     versal_create_gic_its(s, map, dev, mr, node);
@@ -699,14 +701,14 @@ static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
     /*
      * Mapping from the output timer irq lines from the CPU to the
      * GIC PPI inputs.
      */
     const int timer_irq[] = {
-        [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
-        [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
-        [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
-        [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
+        [GTIMER_PHYS] = INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ),
+        [GTIMER_VIRT] = INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ),
+        [GTIMER_HYP]  = INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ),
+        [GTIMER_SEC]  = INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ),
     };
 
     has_gtimer = arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_GENERIC_TIMER);
 
     if (has_gtimer) {
@@ -717,13 +719,13 @@ static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
         }
     }
 
     if (map->gic.version == 3) {
         qemu_irq maint_irq;
+        int maint_idx = ppibase + INTID_TO_PPI(ARCH_GIC_MAINT_IRQ);
 
-        maint_irq = qdev_get_gpio_in(gic,
-                                     ppibase + VERSAL_GIC_MAINT_IRQ);
+        maint_irq = qdev_get_gpio_in(gic, maint_idx);
         qdev_connect_gpio_out_named(cpu, "gicv3-maintenance-interrupt",
                                     0, maint_irq);
     }
 
     sysbus_connect_irq(sbd, idx, qdev_get_gpio_in(cpu, ARM_CPU_IRQ));
@@ -845,17 +847,21 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
 
     has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
     if (map->dtb_expose && has_gtimer) {
         qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
         qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
-                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ,
+                               GIC_FDT_IRQ_TYPE_PPI,
+                               INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ),
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI,
-                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ,
+                               GIC_FDT_IRQ_TYPE_PPI,
+                               INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ),
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI,
-                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ,
+                               GIC_FDT_IRQ_TYPE_PPI,
+                               INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ),
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI,
-                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ,
+                               GIC_FDT_IRQ_TYPE_PPI,
+                               INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ),
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
                          compatible, sizeof(compatible));
     }
 }
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 36/48] hw/arm/xlnx-versal: tidy up
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (34 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:14   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version Luc Michel
                   ` (11 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Remove now unused macros in xlnx-versal.[ch]. Those macros have been
replaced by the VersalMap structure that serves as a central description
for the SoC. The ones still in use in the versal_unimp function are
inlined.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h | 204 -----------------------------------
 hw/arm/xlnx-versal.c         |  28 ++---
 2 files changed, 7 insertions(+), 225 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 3be9f0a5550..bdfab2a5426 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -21,22 +21,10 @@
 #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
 OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 
-#define XLNX_VERSAL_NR_ACPUS   2
-#define XLNX_VERSAL_NR_RCPUS   2
-#define XLNX_VERSAL_NR_UARTS   2
-#define XLNX_VERSAL_NR_GEMS    2
-#define XLNX_VERSAL_NR_ADMAS   8
-#define XLNX_VERSAL_NR_SDS     2
-#define XLNX_VERSAL_NR_XRAM    4
-#define XLNX_VERSAL_NR_IRQS    192
-#define XLNX_VERSAL_NR_CANFD   2
-#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
-#define XLNX_VERSAL_NR_CFRAME  15
-
 struct Versal {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
@@ -81,198 +69,6 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s);
 
 int versal_get_num_cpu(VersalVersion version);
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
-/* Memory-map and IRQ definitions. Copied a subset from
- * auto-generated files.  */
-
-#define VERSAL_CRL_IRQ             10
-#define VERSAL_UART0_IRQ_0         18
-#define VERSAL_UART1_IRQ_0         19
-#define VERSAL_CANFD0_IRQ_0        20
-#define VERSAL_CANFD1_IRQ_0        21
-#define VERSAL_USB0_IRQ_0          22
-#define VERSAL_GEM0_IRQ_0          56
-#define VERSAL_GEM0_WAKE_IRQ_0     57
-#define VERSAL_GEM1_IRQ_0          58
-#define VERSAL_GEM1_WAKE_IRQ_0     59
-#define VERSAL_ADMA_IRQ_0          60
-#define VERSAL_XRAM_IRQ_0          79
-#define VERSAL_CFU_IRQ_0           120
-#define VERSAL_PMC_APB_IRQ         121
-#define VERSAL_OSPI_IRQ            124
-#define VERSAL_SD0_IRQ_0           126
-#define VERSAL_EFUSE_IRQ           139
-#define VERSAL_TRNG_IRQ            141
-#define VERSAL_RTC_ALARM_IRQ       142
-#define VERSAL_RTC_SECONDS_IRQ     143
-
-/* Architecturally reserved IRQs suitable for virtualization.  */
-#define VERSAL_RSVD_IRQ_FIRST 111
-#define VERSAL_RSVD_IRQ_LAST  118
-
-#define MM_TOP_RSVD                 0xa0000000U
-#define MM_TOP_RSVD_SIZE            0x4000000
-#define MM_GIC_APU_DIST_MAIN        0xf9000000U
-#define MM_GIC_APU_DIST_MAIN_SIZE   0x10000
-#define MM_GIC_APU_REDIST_0         0xf9080000U
-#define MM_GIC_APU_REDIST_0_SIZE    0x80000
-
-#define MM_UART0                    0xff000000U
-#define MM_UART0_SIZE               0x10000
-#define MM_UART1                    0xff010000U
-#define MM_UART1_SIZE               0x10000
-
-#define MM_CANFD0                   0xff060000U
-#define MM_CANFD0_SIZE              0x10000
-#define MM_CANFD1                   0xff070000U
-#define MM_CANFD1_SIZE              0x10000
-
-#define MM_GEM0                     0xff0c0000U
-#define MM_GEM0_SIZE                0x10000
-#define MM_GEM1                     0xff0d0000U
-#define MM_GEM1_SIZE                0x10000
-
-#define MM_ADMA_CH0                 0xffa80000U
-#define MM_ADMA_CH0_SIZE            0x10000
-
-#define MM_OCM                      0xfffc0000U
-#define MM_OCM_SIZE                 0x40000
-
-#define MM_XRAM                     0xfe800000
-#define MM_XRAMC                    0xff8e0000
-#define MM_XRAMC_SIZE               0x10000
-
-#define MM_USB2_CTRL_REGS           0xFF9D0000
-#define MM_USB2_CTRL_REGS_SIZE      0x10000
-
-#define MM_USB_0                    0xFE200000
-#define MM_USB_0_SIZE               0x10000
-
-#define MM_TOP_DDR                  0x0
-#define MM_TOP_DDR_SIZE             0x80000000U
-#define MM_TOP_DDR_2                0x800000000ULL
-#define MM_TOP_DDR_2_SIZE           0x800000000ULL
-#define MM_TOP_DDR_3                0xc000000000ULL
-#define MM_TOP_DDR_3_SIZE           0x4000000000ULL
-#define MM_TOP_DDR_4                0x10000000000ULL
-#define MM_TOP_DDR_4_SIZE           0xb780000000ULL
-
-#define MM_PSM_START                0xffc80000U
-#define MM_PSM_END                  0xffcf0000U
-
-#define MM_CRL                      0xff5e0000U
-#define MM_CRL_SIZE                 0x300000
-#define MM_IOU_SCNTR                0xff130000U
-#define MM_IOU_SCNTR_SIZE           0x10000
-#define MM_IOU_SCNTRS               0xff140000U
-#define MM_IOU_SCNTRS_SIZE          0x10000
-#define MM_FPD_CRF                  0xfd1a0000U
-#define MM_FPD_CRF_SIZE             0x140000
-#define MM_FPD_FPD_APU              0xfd5c0000
-#define MM_FPD_FPD_APU_SIZE         0x100
-
-#define MM_PMC_PMC_IOU_SLCR         0xf1060000
-#define MM_PMC_PMC_IOU_SLCR_SIZE    0x10000
-
-#define MM_PMC_OSPI                 0xf1010000
-#define MM_PMC_OSPI_SIZE            0x10000
-
-#define MM_PMC_OSPI_DAC             0xc0000000
-#define MM_PMC_OSPI_DAC_SIZE        0x20000000
-
-#define MM_PMC_OSPI_DMA_DST         0xf1011800
-#define MM_PMC_OSPI_DMA_SRC         0xf1011000
-
-#define MM_PMC_SD0                  0xf1040000U
-#define MM_PMC_SD0_SIZE             0x10000
-#define MM_PMC_BBRAM_CTRL           0xf11f0000
-#define MM_PMC_BBRAM_CTRL_SIZE      0x00050
-#define MM_PMC_EFUSE_CTRL           0xf1240000
-#define MM_PMC_EFUSE_CTRL_SIZE      0x00104
-#define MM_PMC_EFUSE_CACHE          0xf1250000
-#define MM_PMC_EFUSE_CACHE_SIZE     0x00C00
-
-#define MM_PMC_CFU_APB              0xf12b0000
-#define MM_PMC_CFU_APB_SIZE         0x10000
-#define MM_PMC_CFU_STREAM           0xf12c0000
-#define MM_PMC_CFU_STREAM_SIZE      0x1000
-#define MM_PMC_CFU_SFR              0xf12c1000
-#define MM_PMC_CFU_SFR_SIZE         0x1000
-#define MM_PMC_CFU_FDRO             0xf12c2000
-#define MM_PMC_CFU_FDRO_SIZE        0x1000
-#define MM_PMC_CFU_STREAM_2         0xf1f80000
-#define MM_PMC_CFU_STREAM_2_SIZE    0x40000
-
-#define MM_PMC_CFRAME0_REG          0xf12d0000
-#define MM_PMC_CFRAME0_REG_SIZE     0x1000
-#define MM_PMC_CFRAME0_FDRI         0xf12d1000
-#define MM_PMC_CFRAME0_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME1_REG          0xf12d2000
-#define MM_PMC_CFRAME1_REG_SIZE     0x1000
-#define MM_PMC_CFRAME1_FDRI         0xf12d3000
-#define MM_PMC_CFRAME1_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME2_REG          0xf12d4000
-#define MM_PMC_CFRAME2_REG_SIZE     0x1000
-#define MM_PMC_CFRAME2_FDRI         0xf12d5000
-#define MM_PMC_CFRAME2_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME3_REG          0xf12d6000
-#define MM_PMC_CFRAME3_REG_SIZE     0x1000
-#define MM_PMC_CFRAME3_FDRI         0xf12d7000
-#define MM_PMC_CFRAME3_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME4_REG          0xf12d8000
-#define MM_PMC_CFRAME4_REG_SIZE     0x1000
-#define MM_PMC_CFRAME4_FDRI         0xf12d9000
-#define MM_PMC_CFRAME4_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME5_REG          0xf12da000
-#define MM_PMC_CFRAME5_REG_SIZE     0x1000
-#define MM_PMC_CFRAME5_FDRI         0xf12db000
-#define MM_PMC_CFRAME5_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME6_REG          0xf12dc000
-#define MM_PMC_CFRAME6_REG_SIZE     0x1000
-#define MM_PMC_CFRAME6_FDRI         0xf12dd000
-#define MM_PMC_CFRAME6_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME7_REG          0xf12de000
-#define MM_PMC_CFRAME7_REG_SIZE     0x1000
-#define MM_PMC_CFRAME7_FDRI         0xf12df000
-#define MM_PMC_CFRAME7_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME8_REG          0xf12e0000
-#define MM_PMC_CFRAME8_REG_SIZE     0x1000
-#define MM_PMC_CFRAME8_FDRI         0xf12e1000
-#define MM_PMC_CFRAME8_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME9_REG          0xf12e2000
-#define MM_PMC_CFRAME9_REG_SIZE     0x1000
-#define MM_PMC_CFRAME9_FDRI         0xf12e3000
-#define MM_PMC_CFRAME9_FDRI_SIZE    0x1000
-#define MM_PMC_CFRAME10_REG         0xf12e4000
-#define MM_PMC_CFRAME10_REG_SIZE    0x1000
-#define MM_PMC_CFRAME10_FDRI        0xf12e5000
-#define MM_PMC_CFRAME10_FDRI_SIZE   0x1000
-#define MM_PMC_CFRAME11_REG         0xf12e6000
-#define MM_PMC_CFRAME11_REG_SIZE    0x1000
-#define MM_PMC_CFRAME11_FDRI        0xf12e7000
-#define MM_PMC_CFRAME11_FDRI_SIZE   0x1000
-#define MM_PMC_CFRAME12_REG         0xf12e8000
-#define MM_PMC_CFRAME12_REG_SIZE    0x1000
-#define MM_PMC_CFRAME12_FDRI        0xf12e9000
-#define MM_PMC_CFRAME12_FDRI_SIZE   0x1000
-#define MM_PMC_CFRAME13_REG         0xf12ea000
-#define MM_PMC_CFRAME13_REG_SIZE    0x1000
-#define MM_PMC_CFRAME13_FDRI        0xf12eb000
-#define MM_PMC_CFRAME13_FDRI_SIZE   0x1000
-#define MM_PMC_CFRAME14_REG         0xf12ec000
-#define MM_PMC_CFRAME14_REG_SIZE    0x1000
-#define MM_PMC_CFRAME14_FDRI        0xf12ed000
-#define MM_PMC_CFRAME14_FDRI_SIZE   0x1000
-#define MM_PMC_CFRAME_BCAST_REG       0xf12ee000
-#define MM_PMC_CFRAME_BCAST_REG_SIZE  0x1000
-#define MM_PMC_CFRAME_BCAST_FDRI      0xf12ef000
-#define MM_PMC_CFRAME_BCAST_FDRI_SIZE 0x1000
-
-#define MM_PMC_CRP                  0xf1260000U
-#define MM_PMC_CRP_SIZE             0x10000
-#define MM_PMC_RTC                  0xf12a0000
-#define MM_PMC_RTC_SIZE             0x10000
-#define MM_PMC_TRNG                 0xf1230000
-#define MM_PMC_TRNG_SIZE            0x10000
 #endif
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index c513d28c8d4..aef53876f26 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -16,11 +16,10 @@
 #include "qobject/qlist.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "net/net.h"
 #include "system/system.h"
-#include "hw/arm/boot.h"
 #include "hw/misc/unimp.h"
 #include "hw/arm/xlnx-versal.h"
 #include "qemu/log.h"
 #include "target/arm/cpu-qom.h"
 #include "target/arm/gtimer.h"
@@ -49,17 +48,10 @@
 #include "hw/core/split-irq.h"
 #include "target/arm/cpu.h"
 #include "hw/cpu/cluster.h"
 #include "hw/arm/bsa.h"
 
-#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
-#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
-#define GEM_REVISION        0x40070106
-
-#define VERSAL_NUM_PMC_APB_IRQS 18
-#define NUM_OSPI_IRQ_LINES 3
-
 /*
  * IRQ descriptor to catch the following cases:
  *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
  */
 FIELD(VERSAL_IRQ, IRQ, 0, 16)
@@ -1361,11 +1353,11 @@ static DeviceState *versal_create_ospi(Versal *s,
 
     memory_region_add_subregion(&s->mr_ps, map->dac,
                                 linear_mr);
 
     /* OSPI irq */
-    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
+    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", 3,
                             map->irq);
 
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
     sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
     sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
@@ -1622,22 +1614,16 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
 static void versal_unimp(Versal *s)
 {
     DeviceState *slcr;
     qemu_irq gpio_in;
 
-    versal_unimp_area(s, "psm", &s->mr_ps,
-                        MM_PSM_START, MM_PSM_END - MM_PSM_START);
-    versal_unimp_area(s, "crf", &s->mr_ps,
-                        MM_FPD_CRF, MM_FPD_CRF_SIZE);
-    versal_unimp_area(s, "apu", &s->mr_ps,
-                        MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE);
-    versal_unimp_area(s, "crp", &s->mr_ps,
-                        MM_PMC_CRP, MM_PMC_CRP_SIZE);
-    versal_unimp_area(s, "iou-scntr", &s->mr_ps,
-                        MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
-    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
-                        MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
+    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
+    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
+    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
+    versal_unimp_area(s, "crp", &s->mr_ps, 0xf1260000, 0x10000);
+    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
+    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, 0xff140000, 0x10000);
 
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel,
                             "sd-emmc-sel-dummy", 2);
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
                             "qspi-ospi-mux-sel-dummy", 1);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (35 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 36/48] hw/arm/xlnx-versal: tidy up Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:19   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap Luc Michel
                   ` (10 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the versal2 version of the CRL device. For the implemented part, it
is similar to the versal version but drives reset line of more devices.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal-version.h |   1 +
 include/hw/misc/xlnx-versal-crl.h    | 329 ++++++++++++++++++++++
 hw/misc/xlnx-versal-crl.c            | 392 +++++++++++++++++++++++++++
 3 files changed, 722 insertions(+)

diff --git a/include/hw/arm/xlnx-versal-version.h b/include/hw/arm/xlnx-versal-version.h
index 46eb165a2bd..1e8d31b3248 100644
--- a/include/hw/arm/xlnx-versal-version.h
+++ b/include/hw/arm/xlnx-versal-version.h
@@ -8,8 +8,9 @@
 #ifndef HW_ARM_XLNX_VERSAL_VERSION_H
 #define HW_ARM_XLNX_VERSAL_VERSION_H
 
 typedef enum VersalVersion {
     VERSAL_VER_VERSAL,
+    VERSAL_VER_VERSAL2,
 } VersalVersion;
 
 #endif
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
index 7e50a95ad3c..f6b8694ebea 100644
--- a/include/hw/misc/xlnx-versal-crl.h
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -15,14 +15,16 @@
 #include "target/arm/cpu-qom.h"
 #include "hw/arm/xlnx-versal-version.h"
 
 #define TYPE_XLNX_VERSAL_CRL_BASE "xlnx-versal-crl-base"
 #define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
+#define TYPE_XLNX_VERSAL2_CRL "xlnx-versal2-crl"
 
 OBJECT_DECLARE_TYPE(XlnxVersalCRLBase, XlnxVersalCRLBaseClass,
                     XLNX_VERSAL_CRL_BASE)
 OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersal2CRL, XLNX_VERSAL2_CRL)
 
 REG32(ERR_CTRL, 0x0)
     FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
 REG32(IR_STATUS, 0x4)
     FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
@@ -218,10 +220,318 @@ REG32(PSM_RST_MODE, 0x370)
     FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
     FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
 
 #define CRL_R_MAX (R_PSM_RST_MODE + 1)
 
+REG32(VERSAL2_ERR_CTRL, 0x0)
+REG32(VERSAL2_WPROT, 0x1c)
+    FIELD(VERSAL2_WPROT, ACTIVE, 0, 1)
+REG32(VERSAL2_RPLL_CTRL, 0x40)
+    FIELD(VERSAL2_RPLL_CTRL, POST_SRC, 24, 3)
+    FIELD(VERSAL2_RPLL_CTRL, PRE_SRC, 20, 3)
+    FIELD(VERSAL2_RPLL_CTRL, CLKOUTDIV, 16, 2)
+    FIELD(VERSAL2_RPLL_CTRL, FBDIV, 8, 8)
+    FIELD(VERSAL2_RPLL_CTRL, BYPASS, 3, 1)
+    FIELD(VERSAL2_RPLL_CTRL, RESET, 0, 1)
+REG32(VERSAL2_RPLL_CFG, 0x44)
+    FIELD(VERSAL2_RPLL_CFG, LOCK_DLY, 25, 7)
+    FIELD(VERSAL2_RPLL_CFG, LOCK_CNT, 13, 10)
+    FIELD(VERSAL2_RPLL_CFG, LFHF, 10, 2)
+    FIELD(VERSAL2_RPLL_CFG, CP, 5, 4)
+    FIELD(VERSAL2_RPLL_CFG, RES, 0, 4)
+REG32(VERSAL2_FLXPLL_CTRL, 0x50)
+    FIELD(VERSAL2_FLXPLL_CTRL, POST_SRC, 24, 3)
+    FIELD(VERSAL2_FLXPLL_CTRL, PRE_SRC, 20, 3)
+    FIELD(VERSAL2_FLXPLL_CTRL, CLKOUTDIV, 16, 2)
+    FIELD(VERSAL2_FLXPLL_CTRL, FBDIV, 8, 8)
+    FIELD(VERSAL2_FLXPLL_CTRL, BYPASS, 3, 1)
+    FIELD(VERSAL2_FLXPLL_CTRL, RESET, 0, 1)
+REG32(VERSAL2_FLXPLL_CFG, 0x54)
+    FIELD(VERSAL2_FLXPLL_CFG, LOCK_DLY, 25, 7)
+    FIELD(VERSAL2_FLXPLL_CFG, LOCK_CNT, 13, 10)
+    FIELD(VERSAL2_FLXPLL_CFG, LFHF, 10, 2)
+    FIELD(VERSAL2_FLXPLL_CFG, CP, 5, 4)
+    FIELD(VERSAL2_FLXPLL_CFG, RES, 0, 4)
+REG32(VERSAL2_PLL_STATUS, 0x60)
+    FIELD(VERSAL2_PLL_STATUS, FLXPLL_STABLE, 3, 1)
+    FIELD(VERSAL2_PLL_STATUS, RPLL_STABLE, 2, 1)
+    FIELD(VERSAL2_PLL_STATUS, FLXPLL_LOCK, 1, 1)
+    FIELD(VERSAL2_PLL_STATUS, RPLL_LOCK, 0, 1)
+REG32(VERSAL2_RPLL_TO_XPD_CTRL, 0x100)
+    FIELD(VERSAL2_RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
+REG32(VERSAL2_LPX_TOP_SWITCH_CTRL, 0x104)
+    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
+    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_LPX_LSBUS_CLK_CTRL, 0x108)
+    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_RPU_CLK_CTRL, 0x10c)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERE, 24, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERD, 23, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERC, 22, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERB, 21, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERA, 20, 1)
+    FIELD(VERSAL2_RPU_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_RPU_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_OCM_CLK_CTRL, 0x120)
+    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM3, 24, 1)
+    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM2, 23, 1)
+    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM1, 22, 1)
+    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM0, 21, 1)
+REG32(VERSAL2_IOU_SWITCH_CLK_CTRL, 0x124)
+    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_GEM0_REF_CTRL, 0x128)
+    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_RX, 27, 1)
+    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_TX, 26, 1)
+    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_GEM0_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_GEM0_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_GEM1_REF_CTRL, 0x12c)
+    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_RX, 27, 1)
+    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_TX, 26, 1)
+    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_GEM1_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_GEM1_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_GEM_TSU_REF_CLK_CTRL, 0x130)
+    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_USB0_BUS_REF_CLK_CTRL, 0x134)
+    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_USB1_BUS_REF_CLK_CTRL, 0x138)
+    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_UART0_REF_CLK_CTRL, 0x13c)
+    FIELD(VERSAL2_UART0_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_UART0_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_UART0_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_UART1_REF_CLK_CTRL, 0x140)
+    FIELD(VERSAL2_UART1_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_UART1_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_UART1_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_SPI0_REF_CLK_CTRL, 0x144)
+    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_SPI1_REF_CLK_CTRL, 0x148)
+    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_CAN0_REF_2X_CTRL, 0x14c)
+    FIELD(VERSAL2_CAN0_REF_2X_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_CAN0_REF_2X_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_CAN0_REF_2X_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_CAN1_REF_2X_CTRL, 0x150)
+    FIELD(VERSAL2_CAN1_REF_2X_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_CAN1_REF_2X_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_CAN1_REF_2X_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_CAN2_REF_2X_CTRL, 0x154)
+    FIELD(VERSAL2_CAN2_REF_2X_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_CAN2_REF_2X_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_CAN2_REF_2X_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_CAN3_REF_2X_CTRL, 0x158)
+    FIELD(VERSAL2_CAN3_REF_2X_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_CAN3_REF_2X_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_CAN3_REF_2X_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C0_REF_CTRL, 0x15c)
+    FIELD(VERSAL2_I3C0_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C0_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C0_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C1_REF_CTRL, 0x160)
+    FIELD(VERSAL2_I3C1_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C1_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C1_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C2_REF_CTRL, 0x164)
+    FIELD(VERSAL2_I3C2_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C2_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C2_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C3_REF_CTRL, 0x168)
+    FIELD(VERSAL2_I3C3_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C3_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C3_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C4_REF_CTRL, 0x16c)
+    FIELD(VERSAL2_I3C4_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C4_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C4_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C5_REF_CTRL, 0x170)
+    FIELD(VERSAL2_I3C5_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C5_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C5_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C6_REF_CTRL, 0x174)
+    FIELD(VERSAL2_I3C6_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C6_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C6_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_I3C7_REF_CTRL, 0x178)
+    FIELD(VERSAL2_I3C7_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_I3C7_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_I3C7_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_DBG_LPX_CTRL, 0x17c)
+    FIELD(VERSAL2_DBG_LPX_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_DBG_LPX_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_DBG_LPX_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_TIMESTAMP_REF_CTRL, 0x180)
+    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_SAFETY_CHK, 0x184)
+REG32(VERSAL2_ASU_CLK_CTRL, 0x188)
+    FIELD(VERSAL2_ASU_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_ASU_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_DBG_TSTMP_CLK_CTRL, 0x18c)
+    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_MMI_TOPSW_CLK_CTRL, 0x190)
+    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, CLKACT, 25, 1)
+    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_WWDT_PLL_CLK_CTRL, 0x194)
+    FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, DIVISOR0, 8, 10)
+    FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, SRCSEL, 0, 3)
+REG32(VERSAL2_RCLK_CTRL, 0x1a0)
+    FIELD(VERSAL2_RCLK_CTRL, CLKACT, 8, 6)
+    FIELD(VERSAL2_RCLK_CTRL, SELECT, 0, 6)
+REG32(VERSAL2_RST_RPU_A, 0x310)
+    FIELD(VERSAL2_RST_RPU_A, TOPRESET, 16, 1)
+    FIELD(VERSAL2_RST_RPU_A, CORE1_POR, 9, 1)
+    FIELD(VERSAL2_RST_RPU_A, CORE0_POR, 8, 1)
+    FIELD(VERSAL2_RST_RPU_A, CORE1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_A, CORE0_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_B, 0x314)
+    FIELD(VERSAL2_RST_RPU_B, TOPRESET, 16, 1)
+    FIELD(VERSAL2_RST_RPU_B, CORE1_POR, 9, 1)
+    FIELD(VERSAL2_RST_RPU_B, CORE0_POR, 8, 1)
+    FIELD(VERSAL2_RST_RPU_B, CORE1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_B, CORE0_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_C, 0x318)
+    FIELD(VERSAL2_RST_RPU_C, TOPRESET, 16, 1)
+    FIELD(VERSAL2_RST_RPU_C, CORE1_POR, 9, 1)
+    FIELD(VERSAL2_RST_RPU_C, CORE0_POR, 8, 1)
+    FIELD(VERSAL2_RST_RPU_C, CORE1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_C, CORE0_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_D, 0x31c)
+    FIELD(VERSAL2_RST_RPU_D, TOPRESET, 16, 1)
+    FIELD(VERSAL2_RST_RPU_D, CORE1_POR, 9, 1)
+    FIELD(VERSAL2_RST_RPU_D, CORE0_POR, 8, 1)
+    FIELD(VERSAL2_RST_RPU_D, CORE1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_D, CORE0_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_E, 0x320)
+    FIELD(VERSAL2_RST_RPU_E, TOPRESET, 16, 1)
+    FIELD(VERSAL2_RST_RPU_E, CORE1_POR, 9, 1)
+    FIELD(VERSAL2_RST_RPU_E, CORE0_POR, 8, 1)
+    FIELD(VERSAL2_RST_RPU_E, CORE1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_E, CORE0_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_GD_0, 0x324)
+    FIELD(VERSAL2_RST_RPU_GD_0, RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_GD_0, TOP_RESET, 0, 1)
+REG32(VERSAL2_RST_RPU_GD_1, 0x328)
+    FIELD(VERSAL2_RST_RPU_GD_1, RESET, 1, 1)
+    FIELD(VERSAL2_RST_RPU_GD_1, TOP_RESET, 0, 1)
+REG32(VERSAL2_RST_ASU_GD, 0x32c)
+    FIELD(VERSAL2_RST_ASU_GD, RESET, 1, 1)
+    FIELD(VERSAL2_RST_ASU_GD, TOP_RESET, 0, 1)
+REG32(VERSAL2_RST_ADMA, 0x334)
+    FIELD(VERSAL2_RST_ADMA, RESET, 0, 1)
+REG32(VERSAL2_RST_SDMA, 0x338)
+    FIELD(VERSAL2_RST_SDMA, RESET, 0, 1)
+REG32(VERSAL2_RST_GEM0, 0x33c)
+    FIELD(VERSAL2_RST_GEM0, RESET, 0, 1)
+REG32(VERSAL2_RST_GEM1, 0x340)
+    FIELD(VERSAL2_RST_GEM1, RESET, 0, 1)
+REG32(VERSAL2_RST_USB0, 0x348)
+    FIELD(VERSAL2_RST_USB0, RESET, 0, 1)
+REG32(VERSAL2_RST_USB1, 0x34c)
+    FIELD(VERSAL2_RST_USB1, RESET, 0, 1)
+REG32(VERSAL2_RST_UART0, 0x350)
+    FIELD(VERSAL2_RST_UART0, RESET, 0, 1)
+REG32(VERSAL2_RST_UART1, 0x354)
+    FIELD(VERSAL2_RST_UART1, RESET, 0, 1)
+REG32(VERSAL2_RST_SPI0, 0x358)
+    FIELD(VERSAL2_RST_SPI0, RESET, 0, 1)
+REG32(VERSAL2_RST_SPI1, 0x35c)
+    FIELD(VERSAL2_RST_SPI1, RESET, 0, 1)
+REG32(VERSAL2_RST_CAN0, 0x360)
+    FIELD(VERSAL2_RST_CAN0, RESET, 0, 1)
+REG32(VERSAL2_RST_CAN1, 0x364)
+    FIELD(VERSAL2_RST_CAN1, RESET, 0, 1)
+REG32(VERSAL2_RST_CAN2, 0x368)
+    FIELD(VERSAL2_RST_CAN2, RESET, 0, 1)
+REG32(VERSAL2_RST_CAN3, 0x36c)
+    FIELD(VERSAL2_RST_CAN3, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C0, 0x374)
+    FIELD(VERSAL2_RST_I3C0, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C1, 0x378)
+    FIELD(VERSAL2_RST_I3C1, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C2, 0x37c)
+    FIELD(VERSAL2_RST_I3C2, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C3, 0x380)
+    FIELD(VERSAL2_RST_I3C3, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C4, 0x384)
+    FIELD(VERSAL2_RST_I3C4, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C5, 0x388)
+    FIELD(VERSAL2_RST_I3C5, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C6, 0x38c)
+    FIELD(VERSAL2_RST_I3C6, RESET, 0, 1)
+REG32(VERSAL2_RST_I3C7, 0x390)
+    FIELD(VERSAL2_RST_I3C7, RESET, 0, 1)
+REG32(VERSAL2_RST_DBG_LPX, 0x398)
+    FIELD(VERSAL2_RST_DBG_LPX, RESET_HSDP, 1, 1)
+    FIELD(VERSAL2_RST_DBG_LPX, RESET, 0, 1)
+REG32(VERSAL2_RST_GPIO, 0x39c)
+    FIELD(VERSAL2_RST_GPIO, RESET, 0, 1)
+REG32(VERSAL2_RST_TTC, 0x3a0)
+    FIELD(VERSAL2_RST_TTC, TTC7_RESET, 7, 1)
+    FIELD(VERSAL2_RST_TTC, TTC6_RESET, 6, 1)
+    FIELD(VERSAL2_RST_TTC, TTC5_RESET, 5, 1)
+    FIELD(VERSAL2_RST_TTC, TTC4_RESET, 4, 1)
+    FIELD(VERSAL2_RST_TTC, TTC3_RESET, 3, 1)
+    FIELD(VERSAL2_RST_TTC, TTC2_RESET, 2, 1)
+    FIELD(VERSAL2_RST_TTC, TTC1_RESET, 1, 1)
+    FIELD(VERSAL2_RST_TTC, TTC0_RESET, 0, 1)
+REG32(VERSAL2_RST_TIMESTAMP, 0x3a4)
+    FIELD(VERSAL2_RST_TIMESTAMP, RESET, 0, 1)
+REG32(VERSAL2_RST_SWDT0, 0x3a8)
+    FIELD(VERSAL2_RST_SWDT0, RESET, 0, 1)
+REG32(VERSAL2_RST_SWDT1, 0x3ac)
+    FIELD(VERSAL2_RST_SWDT1, RESET, 0, 1)
+REG32(VERSAL2_RST_SWDT2, 0x3b0)
+    FIELD(VERSAL2_RST_SWDT2, RESET, 0, 1)
+REG32(VERSAL2_RST_SWDT3, 0x3b4)
+    FIELD(VERSAL2_RST_SWDT3, RESET, 0, 1)
+REG32(VERSAL2_RST_SWDT4, 0x3b8)
+    FIELD(VERSAL2_RST_SWDT4, RESET, 0, 1)
+REG32(VERSAL2_RST_IPI, 0x3bc)
+    FIELD(VERSAL2_RST_IPI, RESET, 0, 1)
+REG32(VERSAL2_RST_SYSMON, 0x3c0)
+    FIELD(VERSAL2_RST_SYSMON, CFG_RST, 0, 1)
+REG32(VERSAL2_ASU_MB_RST_MODE, 0x3c4)
+    FIELD(VERSAL2_ASU_MB_RST_MODE, WAKEUP, 2, 1)
+    FIELD(VERSAL2_ASU_MB_RST_MODE, RST_MODE, 0, 2)
+REG32(VERSAL2_FPX_TOPSW_MUX_CTRL, 0x3c8)
+    FIELD(VERSAL2_FPX_TOPSW_MUX_CTRL, SELECT, 0, 1)
+REG32(VERSAL2_RST_FPX, 0x3d0)
+    FIELD(VERSAL2_RST_FPX, SRST, 1, 1)
+    FIELD(VERSAL2_RST_FPX, POR, 0, 1)
+REG32(VERSAL2_RST_MMI, 0x3d4)
+    FIELD(VERSAL2_RST_MMI, POR, 0, 1)
+REG32(VERSAL2_RST_OCM, 0x3d8)
+    FIELD(VERSAL2_RST_OCM, RESET_OCM3, 3, 1)
+    FIELD(VERSAL2_RST_OCM, RESET_OCM2, 2, 1)
+    FIELD(VERSAL2_RST_OCM, RESET_OCM1, 1, 1)
+    FIELD(VERSAL2_RST_OCM, RESET_OCM0, 0, 1)
+
+#define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1)
+
 struct XlnxVersalCRLBase {
     SysBusDevice parent_obj;
 
     RegisterInfoArray *reg_array;
     uint32_t *regs;
@@ -247,15 +557,34 @@ struct XlnxVersalCRL {
 
     uint32_t regs[CRL_R_MAX];
     RegisterInfo regs_info[CRL_R_MAX];
 };
 
+struct XlnxVersal2CRL {
+    XlnxVersalCRLBase parent_obj;
+
+    struct {
+        DeviceState *rpu[10];
+        DeviceState *adma[8];
+        DeviceState *sdma[8];
+        DeviceState *uart[2];
+        DeviceState *gem[2];
+        DeviceState *usb[2];
+        DeviceState *can[4];
+    } cfg;
+
+    RegisterInfo regs_info[VERSAL2_CRL_R_MAX];
+    uint32_t regs[VERSAL2_CRL_R_MAX];
+};
+
 static inline const char *xlnx_versal_crl_class_name(VersalVersion ver)
 {
     switch (ver) {
     case VERSAL_VER_VERSAL:
         return TYPE_XLNX_VERSAL_CRL;
+    case VERSAL_VER_VERSAL2:
+        return TYPE_XLNX_VERSAL2_CRL;
     default:
         g_assert_not_reached();
     }
 }
 
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index 115327cfcf4..367e42a30d3 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -87,10 +87,55 @@ static DeviceState **versal_decode_periph_rst(XlnxVersalCRLBase *s,
         /* invalid or unimplemented */
         return NULL;
     }
 }
 
+static DeviceState **versal2_decode_periph_rst(XlnxVersalCRLBase *s,
+                                               hwaddr addr, size_t *count)
+{
+    size_t idx;
+    XlnxVersal2CRL *xvc = XLNX_VERSAL2_CRL(s);
+
+    *count = 1;
+
+    switch (addr) {
+    case A_VERSAL2_RST_RPU_A ... A_VERSAL2_RST_RPU_E:
+        idx = (addr - A_VERSAL2_RST_RPU_A) / sizeof(uint32_t);
+        idx *= 2; /* two RPUs per RST_RPU_x registers */
+        return xvc->cfg.rpu + idx;
+
+    case A_VERSAL2_RST_ADMA:
+        /* A single register fans out to all DMA reset inputs */
+        *count = ARRAY_SIZE(xvc->cfg.adma);
+        return xvc->cfg.adma;
+
+    case A_VERSAL2_RST_SDMA:
+        *count = ARRAY_SIZE(xvc->cfg.sdma);
+        return xvc->cfg.sdma;
+
+    case A_VERSAL2_RST_UART0 ... A_VERSAL2_RST_UART1:
+        idx = (addr - A_VERSAL2_RST_UART0) / sizeof(uint32_t);
+        return xvc->cfg.uart + idx;
+
+    case A_VERSAL2_RST_GEM0 ... A_VERSAL2_RST_GEM1:
+        idx = (addr - A_VERSAL2_RST_GEM0) / sizeof(uint32_t);
+        return xvc->cfg.gem + idx;
+
+    case A_VERSAL2_RST_USB0 ... A_VERSAL2_RST_USB1:
+        idx = (addr - A_VERSAL2_RST_USB0) / sizeof(uint32_t);
+        return xvc->cfg.usb + idx;
+
+    case A_VERSAL2_RST_CAN0 ... A_VERSAL2_RST_CAN3:
+        idx = (addr - A_VERSAL2_RST_CAN0) / sizeof(uint32_t);
+        return xvc->cfg.can + idx;
+
+    default:
+        /* invalid or unimplemented */
+        return NULL;
+    }
+}
+
 static uint64_t crl_rst_cpu_prew(RegisterInfo *reg, uint64_t val64)
 {
     XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
     XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
     DeviceState **dev;
@@ -305,20 +350,270 @@ static const RegisterAccessInfo crl_regs_info[] = {
         .reset = 0x1,
         .rsvd = 0xf8,
     }
 };
 
+static const RegisterAccessInfo versal2_crl_regs_info[] = {
+    {   .name = "ERR_CTRL",  .addr = A_VERSAL2_ERR_CTRL,
+        .reset = 0x1,
+    },{ .name = "WPROT",  .addr = A_VERSAL2_WPROT,
+    },{ .name = "RPLL_CTRL",  .addr = A_VERSAL2_RPLL_CTRL,
+        .reset = 0x24809,
+        .rsvd = 0xf88c00f6,
+    },{ .name = "RPLL_CFG",  .addr = A_VERSAL2_RPLL_CFG,
+        .reset = 0x7e5dcc6c,
+        .rsvd = 0x1801210,
+    },{ .name = "FLXPLL_CTRL",  .addr = A_VERSAL2_FLXPLL_CTRL,
+        .reset = 0x24809,
+        .rsvd = 0xf88c00f6,
+    },{ .name = "FLXPLL_CFG",  .addr = A_VERSAL2_FLXPLL_CFG,
+        .reset = 0x7e5dcc6c,
+        .rsvd = 0x1801210,
+    },{ .name = "PLL_STATUS",  .addr = A_VERSAL2_PLL_STATUS,
+        .reset = 0xf,
+        .rsvd = 0xf0,
+        .ro = 0xf,
+    },{ .name = "RPLL_TO_XPD_CTRL",  .addr = A_VERSAL2_RPLL_TO_XPD_CTRL,
+        .reset = 0x2000100,
+        .rsvd = 0xfdfc00ff,
+    },{ .name = "LPX_TOP_SWITCH_CTRL",  .addr = A_VERSAL2_LPX_TOP_SWITCH_CTRL,
+        .reset = 0xe000300,
+        .rsvd = 0xf1fc00f8,
+    },{ .name = "LPX_LSBUS_CLK_CTRL",  .addr = A_VERSAL2_LPX_LSBUS_CLK_CTRL,
+        .reset = 0x2000800,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "RPU_CLK_CTRL",  .addr = A_VERSAL2_RPU_CLK_CTRL,
+        .reset = 0x3f00300,
+        .rsvd = 0xfc0c00f8,
+    },{ .name = "OCM_CLK_CTRL",  .addr = A_VERSAL2_OCM_CLK_CTRL,
+        .reset = 0x1e00000,
+        .rsvd = 0xfe1fffff,
+    },{ .name = "IOU_SWITCH_CLK_CTRL",  .addr = A_VERSAL2_IOU_SWITCH_CLK_CTRL,
+        .reset = 0x2000500,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "GEM0_REF_CTRL",  .addr = A_VERSAL2_GEM0_REF_CTRL,
+        .reset = 0xe000a00,
+        .rsvd = 0xf1fc00f8,
+    },{ .name = "GEM1_REF_CTRL",  .addr = A_VERSAL2_GEM1_REF_CTRL,
+        .reset = 0xe000a00,
+        .rsvd = 0xf1fc00f8,
+    },{ .name = "GEM_TSU_REF_CLK_CTRL",  .addr = A_VERSAL2_GEM_TSU_REF_CLK_CTRL,
+        .reset = 0x300,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "USB0_BUS_REF_CLK_CTRL",
+        .addr = A_VERSAL2_USB0_BUS_REF_CLK_CTRL,
+        .reset = 0x2001900,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "USB1_BUS_REF_CLK_CTRL",
+        .addr = A_VERSAL2_USB1_BUS_REF_CLK_CTRL,
+        .reset = 0x2001900,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "UART0_REF_CLK_CTRL",  .addr = A_VERSAL2_UART0_REF_CLK_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "UART1_REF_CLK_CTRL",  .addr = A_VERSAL2_UART1_REF_CLK_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "SPI0_REF_CLK_CTRL",  .addr = A_VERSAL2_SPI0_REF_CLK_CTRL,
+        .reset = 0x600,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "SPI1_REF_CLK_CTRL",  .addr = A_VERSAL2_SPI1_REF_CLK_CTRL,
+        .reset = 0x600,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "CAN0_REF_2X_CTRL",  .addr = A_VERSAL2_CAN0_REF_2X_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "CAN1_REF_2X_CTRL",  .addr = A_VERSAL2_CAN1_REF_2X_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "CAN2_REF_2X_CTRL",  .addr = A_VERSAL2_CAN2_REF_2X_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "CAN3_REF_2X_CTRL",  .addr = A_VERSAL2_CAN3_REF_2X_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C0_REF_CTRL",  .addr = A_VERSAL2_I3C0_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C1_REF_CTRL",  .addr = A_VERSAL2_I3C1_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C2_REF_CTRL",  .addr = A_VERSAL2_I3C2_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C3_REF_CTRL",  .addr = A_VERSAL2_I3C3_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C4_REF_CTRL",  .addr = A_VERSAL2_I3C4_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C5_REF_CTRL",  .addr = A_VERSAL2_I3C5_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C6_REF_CTRL",  .addr = A_VERSAL2_I3C6_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "I3C7_REF_CTRL",  .addr = A_VERSAL2_I3C7_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "DBG_LPX_CTRL",  .addr = A_VERSAL2_DBG_LPX_CTRL,
+        .reset = 0x300,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "TIMESTAMP_REF_CTRL",  .addr = A_VERSAL2_TIMESTAMP_REF_CTRL,
+        .reset = 0x2000c00,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "SAFETY_CHK",  .addr = A_VERSAL2_SAFETY_CHK,
+    },{ .name = "ASU_CLK_CTRL",  .addr = A_VERSAL2_ASU_CLK_CTRL,
+        .reset = 0x2000f04,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "DBG_TSTMP_CLK_CTRL",  .addr = A_VERSAL2_DBG_TSTMP_CLK_CTRL,
+        .reset = 0x300,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "MMI_TOPSW_CLK_CTRL",  .addr = A_VERSAL2_MMI_TOPSW_CLK_CTRL,
+        .reset = 0x2000300,
+        .rsvd = 0xfdfc00f8,
+    },{ .name = "WWDT_PLL_CLK_CTRL",  .addr = A_VERSAL2_WWDT_PLL_CLK_CTRL,
+        .reset = 0xc00,
+        .rsvd = 0xfffc00f8,
+    },{ .name = "RCLK_CTRL",  .addr = A_VERSAL2_RCLK_CTRL,
+        .rsvd = 0xc040,
+    },{ .name = "RST_RPU_A",  .addr = A_VERSAL2_RST_RPU_A,
+        .reset = 0x10303,
+        .rsvd = 0xfffefcfc,
+        .pre_write = crl_rst_cpu_prew,
+    },{ .name = "RST_RPU_B",  .addr = A_VERSAL2_RST_RPU_B,
+        .reset = 0x10303,
+        .rsvd = 0xfffefcfc,
+        .pre_write = crl_rst_cpu_prew,
+    },{ .name = "RST_RPU_C",  .addr = A_VERSAL2_RST_RPU_C,
+        .reset = 0x10303,
+        .rsvd = 0xfffefcfc,
+        .pre_write = crl_rst_cpu_prew,
+    },{ .name = "RST_RPU_D",  .addr = A_VERSAL2_RST_RPU_D,
+        .reset = 0x10303,
+        .rsvd = 0xfffefcfc,
+        .pre_write = crl_rst_cpu_prew,
+    },{ .name = "RST_RPU_E",  .addr = A_VERSAL2_RST_RPU_E,
+        .reset = 0x10303,
+        .rsvd = 0xfffefcfc,
+        .pre_write = crl_rst_cpu_prew,
+    },{ .name = "RST_RPU_GD_0",  .addr = A_VERSAL2_RST_RPU_GD_0,
+        .reset = 0x3,
+    },{ .name = "RST_RPU_GD_1",  .addr = A_VERSAL2_RST_RPU_GD_1,
+        .reset = 0x3,
+    },{ .name = "RST_ASU_GD",  .addr = A_VERSAL2_RST_ASU_GD,
+        .reset = 0x3,
+    },{ .name = "RST_ADMA",  .addr = A_VERSAL2_RST_ADMA,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_SDMA",  .addr = A_VERSAL2_RST_SDMA,
+        .pre_write = crl_rst_dev_prew,
+        .reset = 0x1,
+    },{ .name = "RST_GEM0",  .addr = A_VERSAL2_RST_GEM0,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_GEM1",  .addr = A_VERSAL2_RST_GEM1,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_USB0",  .addr = A_VERSAL2_RST_USB0,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_USB1",  .addr = A_VERSAL2_RST_USB1,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_UART0",  .addr = A_VERSAL2_RST_UART0,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_UART1",  .addr = A_VERSAL2_RST_UART1,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_SPI0",  .addr = A_VERSAL2_RST_SPI0,
+        .reset = 0x1,
+    },{ .name = "RST_SPI1",  .addr = A_VERSAL2_RST_SPI1,
+        .reset = 0x1,
+    },{ .name = "RST_CAN0",  .addr = A_VERSAL2_RST_CAN0,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_CAN1",  .addr = A_VERSAL2_RST_CAN1,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_CAN2",  .addr = A_VERSAL2_RST_CAN2,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_CAN3",  .addr = A_VERSAL2_RST_CAN3,
+        .reset = 0x1,
+        .pre_write = crl_rst_dev_prew,
+    },{ .name = "RST_I3C0",  .addr = A_VERSAL2_RST_I3C0,
+        .reset = 0x1,
+    },{ .name = "RST_I3C1",  .addr = A_VERSAL2_RST_I3C1,
+        .reset = 0x1,
+    },{ .name = "RST_I3C2",  .addr = A_VERSAL2_RST_I3C2,
+        .reset = 0x1,
+    },{ .name = "RST_I3C3",  .addr = A_VERSAL2_RST_I3C3,
+        .reset = 0x1,
+    },{ .name = "RST_I3C4",  .addr = A_VERSAL2_RST_I3C4,
+        .reset = 0x1,
+    },{ .name = "RST_I3C5",  .addr = A_VERSAL2_RST_I3C5,
+        .reset = 0x1,
+    },{ .name = "RST_I3C6",  .addr = A_VERSAL2_RST_I3C6,
+        .reset = 0x1,
+    },{ .name = "RST_I3C7",  .addr = A_VERSAL2_RST_I3C7,
+        .reset = 0x1,
+    },{ .name = "RST_DBG_LPX",  .addr = A_VERSAL2_RST_DBG_LPX,
+        .reset = 0x3,
+        .rsvd = 0xfc,
+    },{ .name = "RST_GPIO",  .addr = A_VERSAL2_RST_GPIO,
+        .reset = 0x1,
+    },{ .name = "RST_TTC",  .addr = A_VERSAL2_RST_TTC,
+        .reset = 0xff,
+    },{ .name = "RST_TIMESTAMP",  .addr = A_VERSAL2_RST_TIMESTAMP,
+        .reset = 0x1,
+    },{ .name = "RST_SWDT0",  .addr = A_VERSAL2_RST_SWDT0,
+        .reset = 0x1,
+    },{ .name = "RST_SWDT1",  .addr = A_VERSAL2_RST_SWDT1,
+        .reset = 0x1,
+    },{ .name = "RST_SWDT2",  .addr = A_VERSAL2_RST_SWDT2,
+        .reset = 0x1,
+    },{ .name = "RST_SWDT3",  .addr = A_VERSAL2_RST_SWDT3,
+        .reset = 0x1,
+    },{ .name = "RST_SWDT4",  .addr = A_VERSAL2_RST_SWDT4,
+        .reset = 0x1,
+    },{ .name = "RST_IPI",  .addr = A_VERSAL2_RST_IPI,
+    },{ .name = "RST_SYSMON",  .addr = A_VERSAL2_RST_SYSMON,
+    },{ .name = "ASU_MB_RST_MODE",  .addr = A_VERSAL2_ASU_MB_RST_MODE,
+        .reset = 0x1,
+        .rsvd = 0xf8,
+    },{ .name = "FPX_TOPSW_MUX_CTRL",  .addr = A_VERSAL2_FPX_TOPSW_MUX_CTRL,
+        .reset = 0x1,
+    },{ .name = "RST_FPX",  .addr = A_VERSAL2_RST_FPX,
+        .reset = 0x3,
+    },{ .name = "RST_MMI",  .addr = A_VERSAL2_RST_MMI,
+        .reset = 0x1,
+    },{ .name = "RST_OCM",  .addr = A_VERSAL2_RST_OCM,
+    }
+};
+
 static void versal_crl_reset_enter(Object *obj, ResetType type)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
     unsigned int i;
 
     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
         register_reset(&s->regs_info[i]);
     }
 }
 
+static void versal2_crl_reset_enter(Object *obj, ResetType type)
+{
+    XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
+    size_t i;
+
+    for (i = 0; i < VERSAL2_CRL_R_MAX; ++i) {
+        register_reset(&s->regs_info[i]);
+    }
+}
+
 static void versal_crl_reset_hold(Object *obj, ResetType type)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
 
     crl_update_irq(s);
@@ -386,10 +681,77 @@ static void versal_crl_init(Object *obj)
                                  qdev_prop_allow_set_link_before_realize,
                                  OBJ_PROP_LINK_STRONG);
     }
 }
 
+static void versal2_crl_init(Object *obj)
+{
+    XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
+    XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    size_t i;
+
+    xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
+                                            ARRAY_SIZE(versal2_crl_regs_info),
+                                            s->regs_info, s->regs,
+                                            &crl_ops,
+                                            XLNX_VERSAL_CRL_ERR_DEBUG,
+                                            VERSAL2_CRL_R_MAX * 4);
+    xvcb->regs = s->regs;
+
+    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
+        object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
+                                 (Object **)&s->cfg.rpu[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
+        object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.adma[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.sdma); ++i) {
+        object_property_add_link(obj, "sdma[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.sdma[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
+        object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.uart[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
+        object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.gem[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.usb); ++i) {
+        object_property_add_link(obj, "usb[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.usb[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(s->cfg.can); ++i) {
+        object_property_add_link(obj, "can[*]", TYPE_DEVICE,
+                                 (Object **)&s->cfg.can[i],
+                                 qdev_prop_allow_set_link_before_realize,
+                                 OBJ_PROP_LINK_STRONG);
+    }
+}
+
 static void crl_finalize(Object *obj)
 {
     XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
     register_finalize_block(s->reg_array);
 }
@@ -402,10 +764,20 @@ static const VMStateDescription vmstate_versal_crl = {
         VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
         VMSTATE_END_OF_LIST(),
     }
 };
 
+static const VMStateDescription vmstate_versal2_crl = {
+    .name = TYPE_XLNX_VERSAL2_CRL,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, XlnxVersal2CRL, VERSAL2_CRL_R_MAX),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
 static void versal_crl_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
     ResettableClass *rc = RESETTABLE_CLASS(klass);
@@ -414,10 +786,21 @@ static void versal_crl_class_init(ObjectClass *klass, const void *data)
     rc->phases.enter = versal_crl_reset_enter;
     rc->phases.hold = versal_crl_reset_hold;
     xvcc->decode_periph_rst = versal_decode_periph_rst;
 }
 
+static void versal2_crl_class_init(ObjectClass *klass, const void *data)
+{
+    XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->vmsd = &vmstate_versal2_crl;
+    rc->phases.enter = versal2_crl_reset_enter;
+    xvcc->decode_periph_rst = versal2_decode_periph_rst;
+}
+
 static const TypeInfo crl_base_info = {
     .name          = TYPE_XLNX_VERSAL_CRL_BASE,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XlnxVersalCRLBase),
     .class_size    = sizeof(XlnxVersalCRLBaseClass),
@@ -431,12 +814,21 @@ static const TypeInfo versal_crl_info = {
     .instance_size = sizeof(XlnxVersalCRL),
     .instance_init = versal_crl_init,
     .class_init    = versal_crl_class_init,
 };
 
+static const TypeInfo versal2_crl_info = {
+    .name          = TYPE_XLNX_VERSAL2_CRL,
+    .parent        = TYPE_XLNX_VERSAL_CRL_BASE,
+    .instance_size = sizeof(XlnxVersal2CRL),
+    .instance_init = versal2_crl_init,
+    .class_init    = versal2_crl_class_init,
+};
+
 static void crl_register_types(void)
 {
     type_register_static(&crl_base_info);
     type_register_static(&versal_crl_info);
+    type_register_static(&versal2_crl_info);
 }
 
 type_init(crl_register_types)
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (36 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:27   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor Luc Michel
                   ` (9 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the per_cluster_gic switch to the VersalCpuClusterMap structure.
When set, this indicates that a GIC instance should by created
per-cluster instead of globaly for the whole RPU or APU. This is in
preparation for versal2.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index aef53876f26..9d900fe3127 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -86,10 +86,15 @@ enum StartPoweredOffMode {
     SPO_ALL,
 };
 
 typedef struct VersalCpuClusterMap {
     VersalGicMap gic;
+    /*
+     * true: one GIC per cluster.
+     * false: one GIC for all CPUs
+     */
+    bool per_cluster_gic;
 
     const char *name;
     const char *cpu_model;
     size_t num_core;
     size_t num_cluster;
@@ -828,16 +833,22 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
             DeviceState *cpu = versal_create_cpu(s, map, cluster, mr, i, j);
 
             cpus[i * map->num_core + j] = cpu;
         }
 
+        if (map->per_cluster_gic) {
+            versal_create_and_connect_gic(s, map, mr, &cpus[i * map->num_core],
+                                          map->num_core);
+        }
     }
 
     qdev_realize_and_unref(cluster, NULL, &error_fatal);
 
-    versal_create_and_connect_gic(s, map, mr, cpus,
-                                  map->num_cluster * map->num_core);
+    if (!map->per_cluster_gic) {
+        versal_create_and_connect_gic(s, map, mr, cpus,
+                                      map->num_cluster * map->num_core);
+    }
 
     has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
     if (map->dtb_expose && has_gtimer) {
         qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
         qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (37 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:31   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU Luc Michel
                   ` (8 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the target field in the IRQ descriptor. This allows to target an IRQ
to another IRQ controller than the GIC(s). Other supported targets are
the PMC PPU1 CPU interrupt controller and the EAM (Error management)
device. Those two devices are currently not implemented so IRQs
targeting those will be left unconnected. This is in preparation for
versal2.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal.c | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 9d900fe3127..551671af425 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -50,18 +50,30 @@
 #include "hw/cpu/cluster.h"
 #include "hw/arm/bsa.h"
 
 /*
  * IRQ descriptor to catch the following cases:
+ *   - An IRQ can either connect to the GICs, to the PPU1 intc, or the the EAM
  *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
  */
 FIELD(VERSAL_IRQ, IRQ, 0, 16)
+FIELD(VERSAL_IRQ, TARGET, 16, 2)
 FIELD(VERSAL_IRQ, ORED, 18, 1)
 FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
 
+typedef enum VersalIrqTarget {
+    IRQ_TARGET_GIC,
+    IRQ_TARGET_PPU1,
+    IRQ_TARGET_EAM,
+} VersalIrqTarget;
+
+#define PPU1_IRQ(irq) ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
+#define EAM_IRQ(irq) ((IRQ_TARGET_EAM << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
 #define OR_IRQ(irq, or_idx) \
     (R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
+#define PPU1_OR_IRQ(irq, or_idx) \
+    ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | OR_IRQ(irq, or_idx))
 
 typedef struct VersalSimplePeriphMap {
     uint64_t addr;
     int irq;
 } VersalSimplePeriphMap;
@@ -415,19 +427,27 @@ static qemu_irq versal_get_gic_irq(Versal *s, int irq_idx)
  * Or gates are placed under the /soc/irq-or-gates QOM container.
  */
 static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
                                           qemu_irq target_irq)
 {
+    static const char *TARGET_STR[] = {
+        [IRQ_TARGET_GIC] = "gic",
+        [IRQ_TARGET_PPU1] = "ppu1",
+        [IRQ_TARGET_EAM] = "eam",
+    };
+
+    VersalIrqTarget target;
     Object *container = versal_get_child(s, "irq-or-gates");
     DeviceState *dev;
     g_autofree char *name;
     int idx, or_idx;
 
     idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
     or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
+    target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
 
-    name = g_strdup_printf("irq[%d]", idx);
+    name = g_strdup_printf("%s-irq[%d]", TARGET_STR[target], idx);
     dev = DEVICE(object_resolve_path_at(container, name));
 
     if (dev == NULL) {
         dev = qdev_new(TYPE_OR_IRQ);
         object_property_add_child(container, name, OBJECT(dev));
@@ -439,16 +459,33 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
     return qdev_get_gpio_in(dev, or_idx);
 }
 
 static qemu_irq versal_get_irq(Versal *s, int irq_idx)
 {
+    VersalIrqTarget target;
     qemu_irq irq;
     bool ored;
 
+    target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
     ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
 
-    irq = versal_get_gic_irq(s, irq_idx);
+    switch (target) {
+    case IRQ_TARGET_EAM:
+        /* EAM not implemented */
+        return NULL;
+
+    case IRQ_TARGET_PPU1:
+        /* PPU1 CPU not implemented */
+        return NULL;
+
+    case IRQ_TARGET_GIC:
+        irq = versal_get_gic_irq(s, irq_idx);
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
 
     if (ored) {
         irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
     }
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (38 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-08-04 12:44   ` Peter Maydell
  2025-07-16  9:54 ` [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC Luc Michel
                   ` (7 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add support for the ARM Cortex-A78AE CPU.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 target/arm/tcg/cpu64.c | 75 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 35cddbafa4c..337f8cf0c8d 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -404,10 +404,84 @@ static void aarch64_a76_initfn(Object *obj)
 
     /* From D5.1 AArch64 PMU register summary */
     cpu->isar.reset_pmcr_el0 = 0x410b3000;
 }
 
+static void aarch64_a78ae_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    ARMISARegisters *isar = &cpu->isar;
+
+    cpu->dtb_compatible = "arm,cortex-a78ae";
+    set_feature(&cpu->env, ARM_FEATURE_V8);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+    set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
+    set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+    set_feature(&cpu->env, ARM_FEATURE_EL2);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
+    set_feature(&cpu->env, ARM_FEATURE_PMU);
+
+    /* Ordered by B2.4 AArch64 registers by functional group */
+    SET_IDREG(isar, CLIDR, 0x82000023);
+    cpu->ctr = 0x9444c004;
+    cpu->dcz_blocksize = 4;
+    SET_IDREG(isar, ID_AA64DFR0, 0x0000000110305408ull);
+    SET_IDREG(isar, ID_AA64ISAR0, 0x0010100010211120ull);
+    SET_IDREG(isar, ID_AA64ISAR1, 0x0000000001200031ull);
+    SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101125ull);
+    SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(isar, ID_AA64MMFR2, 0x0000000100001011ull);
+    SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
+    SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull);
+    SET_IDREG(isar, ID_AFR0, 0x00000000);
+    SET_IDREG(isar, ID_DFR0, 0x04010088);
+    SET_IDREG(isar, ID_ISAR0, 0x02101110);
+    SET_IDREG(isar, ID_ISAR1, 0x13112111);
+    SET_IDREG(isar, ID_ISAR2, 0x21232042);
+    SET_IDREG(isar, ID_ISAR3, 0x01112131);
+    SET_IDREG(isar, ID_ISAR4, 0x00010142);
+    SET_IDREG(isar, ID_ISAR5, 0x01011121);
+    SET_IDREG(isar, ID_ISAR6, 0x00000010);
+    SET_IDREG(isar, ID_MMFR0, 0x10201105);
+    SET_IDREG(isar, ID_MMFR1, 0x40000000);
+    SET_IDREG(isar, ID_MMFR2, 0x01260000);
+    SET_IDREG(isar, ID_MMFR3, 0x02122211);
+    SET_IDREG(isar, ID_MMFR4, 0x00021110);
+    SET_IDREG(isar, ID_PFR0, 0x10010131);
+    SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */
+    SET_IDREG(isar, ID_PFR2, 0x00000011);
+    cpu->midr = 0x410fd421;          /* r0p1 */
+    cpu->revidr = 0;
+
+    /* From B2.18 CCSIDR_EL1 */
+    /* 64KB L1 dcache */
+    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
+    /* 64KB L1 icache */
+    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
+    /* 512KB L2 cache */
+    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7);
+
+    /* From B2.93 SCTLR_EL3 */
+    cpu->reset_sctlr = 0x30c50838;
+
+    /* From B4.23 ICH_VTR_EL2 */
+    cpu->gic_num_lrs = 4;
+    cpu->gic_vpribits = 5;
+    cpu->gic_vprebits = 5;
+    cpu->gic_pribits = 5;
+
+    /* From B5.1 AdvSIMD AArch64 register summary */
+    cpu->isar.mvfr0 = 0x10110222;
+    cpu->isar.mvfr1 = 0x13211111;
+    cpu->isar.mvfr2 = 0x00000043;
+
+    /* From D5.1 AArch64 PMU register summary */
+    cpu->isar.reset_pmcr_el0 = 0x41223000;
+}
+
 static void aarch64_a64fx_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
     ARMISARegisters *isar = &cpu->isar;
 
@@ -1313,10 +1387,11 @@ void aarch64_max_tcg_initfn(Object *obj)
 static const ARMCPUInfo aarch64_cpus[] = {
     { .name = "cortex-a35",         .initfn = aarch64_a35_initfn },
     { .name = "cortex-a55",         .initfn = aarch64_a55_initfn },
     { .name = "cortex-a72",         .initfn = aarch64_a72_initfn },
     { .name = "cortex-a76",         .initfn = aarch64_a76_initfn },
+    { .name = "cortex-a78ae",       .initfn = aarch64_a78ae_initfn },
     { .name = "cortex-a710",        .initfn = aarch64_a710_initfn },
     { .name = "a64fx",              .initfn = aarch64_a64fx_initfn },
     { .name = "neoverse-n1",        .initfn = aarch64_neoverse_n1_initfn },
     { .name = "neoverse-v1",        .initfn = aarch64_neoverse_v1_initfn },
     { .name = "neoverse-n2",        .initfn = aarch64_neoverse_n2_initfn },
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (39 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:40   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt Luc Michel
                   ` (6 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the Versal Gen 2 (versal2) version of the Versal SoC family.
This version embeds up to 8 Cortex-A78AE cores (split into 4 clusters)
and 10 Cortex-R52 cores (split into 5 clusters). The similarities
between versal and versal2 in term of architecture allow to reuse the
VersalMap structure to almost fully describe the implemented parts of
versal2.

The versal2 eFuse device differs quite a lot from the versal one and is
left as future work.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/arm/xlnx-versal.h |  17 ++-
 hw/arm/xlnx-versal.c         | 212 ++++++++++++++++++++++++++++++++---
 2 files changed, 214 insertions(+), 15 deletions(-)

diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index bdfab2a5426..1d216b5dbf1 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -1,7 +1,7 @@
 /*
- * Model of the Xilinx Versal
+ * AMD/Xilinx Versal family SoC model.
  *
  * Copyright (c) 2018 Xilinx Inc.
  * Copyright (c) 2025 Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
@@ -20,10 +20,11 @@
 
 #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
 OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
+#define TYPE_XLNX_VERSAL2 "xlnx-versal2"
 
 struct Versal {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -69,6 +70,20 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s);
 
 int versal_get_num_cpu(VersalVersion version);
 int versal_get_num_can(VersalVersion version);
 int versal_get_num_sdhci(VersalVersion version);
 
+static inline const char *versal_get_class(VersalVersion version)
+{
+    switch (version) {
+    case VERSAL_VER_VERSAL:
+        return TYPE_XLNX_VERSAL;
+
+    case VERSAL_VER_VERSAL2:
+        return TYPE_XLNX_VERSAL2;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
 #endif
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 551671af425..52a68e356b0 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -1,7 +1,7 @@
 /*
- * Xilinx Versal SoC model.
+ * AMD/Xilinx Versal family SoC model.
  *
  * Copyright (c) 2018 Xilinx Inc.
  * Copyright (c) 2025 Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
@@ -353,12 +353,133 @@ static const VersalMap VERSAL_MAP = {
     .crl = { 0xff5e0000, 10 },
 
     .reserved = { 0xa0000000, 111, 8 },
 };
 
+static const VersalMap VERSAL2_MAP = {
+    .ocm = {
+        .addr = 0xbbe00000,
+        .size = 2 * MiB,
+    },
+
+    .ddr = {
+        .chan[0] = { .addr = 0x0, .size = 2046 * MiB },
+        .chan[1] = { .addr = 0x800000000ull, .size = 32 * GiB },
+        .chan[2] = { .addr = 0xc00000000ull, .size = 256 * GiB },
+        .chan[3] = { .addr = 0x10000000000ull, .size = 734 * GiB },
+        .num_chan = 4,
+    },
+
+    .apu = {
+        .name = "apu",
+        .cpu_model = ARM_CPU_TYPE_NAME("cortex-a78ae"),
+        .num_cluster = 4,
+        .num_core = 2,
+        .qemu_cluster_id = 0,
+        .mp_affinity = {
+            .base = 0x0, /* TODO: the MT bit should be set */
+            .core_mask = 0xff,
+            .core_shift = 8,
+            .cluster_mask = 0xff,
+            .cluster_shift = 16,
+        },
+        .start_powered_off = SPO_SECONDARIES,
+        .dtb_expose = true,
+        .gic = {
+            .version = 3,
+            .dist = 0xe2000000,
+            .redist = 0xe2060000,
+            .num_irq = 544,
+            .has_its = true,
+            .its = 0xe2040000,
+        },
+    },
+
+    .rpu = {
+        .name = "rpu",
+        .cpu_model = ARM_CPU_TYPE_NAME("cortex-r52"),
+        .num_cluster = 5,
+        .num_core = 2,
+        .qemu_cluster_id = 1,
+        .mp_affinity = {
+            .base = 0x0,
+            .core_mask = 0xff,
+            .core_shift = 0,
+            .cluster_mask = 0xff,
+            .cluster_shift = 8,
+        },
+        .start_powered_off = SPO_ALL,
+        .dtb_expose = false,
+        .per_cluster_gic = true,
+        .gic = {
+            .version = 3,
+            .dist = 0x0,
+            .redist = 0x100000,
+            .num_irq = 288,
+        },
+    },
+
+    .uart[0] = { 0xf1920000, 25 },
+    .uart[1] = { 0xf1930000, 26 },
+    .num_uart = 2,
+
+    .canfd[0] = { 0xf19e0000, 27 },
+    .canfd[1] = { 0xf19f0000, 28 },
+    .canfd[2] = { 0xf1a00000, 95 },
+    .canfd[3] = { 0xf1a10000, 96 },
+    .num_canfd = 4,
+
+    .gem[0] = { { 0xf1a60000, 39 }, 2, "rgmii-id", 1000 },
+    .gem[1] = { { 0xf1a70000, 41 }, 2, "rgmii-id", 1000 },
+    .gem[2] = { { 0xed920000, 164 }, 4, "usxgmii", 10000 }, /* MMI 10Gb GEM */
+    .num_gem = 3,
+
+    .zdma[0] = { "adma", { 0xebd00000, 72 }, 8, 0x10000, 1 },
+    .zdma[1] = { "sdma", { 0xebd80000, 112 }, 8, 0x10000, 1 },
+    .num_zdma = 2,
+
+    .usb[0] = { .xhci = 0xf1b00000, .ctrl = 0xf1ee0000, .irq = 29 },
+    .usb[1] = { .xhci = 0xf1c00000, .ctrl = 0xf1ef0000, .irq = 34 },
+    .num_usb = 2,
+
+    .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 230 },
+
+    .ospi = {
+        .ctrl = 0xf1010000,
+        .dac = 0xc0000000, .dac_sz = 0x20000000,
+        .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
+        .irq = 216,
+    },
+
+    .sdhci[0] = { 0xf1040000, 218 },
+    .sdhci[1] = { 0xf1050000, 220 }, /* eMMC */
+    .num_sdhci = 2,
+
+    .pmc_iou_slcr = { 0xf1060000, 222 },
+    .bbram = { 0xf11f0000, PPU1_OR_IRQ(18, 0) },
+    .crl = { 0xeb5e0000 },
+    .trng = { 0xf1230000, 233 },
+    .rtc = {
+        { 0xf12a0000, PPU1_OR_IRQ(18, 1) },
+        .alarm_irq = 200, .second_irq = 201
+    },
+
+    .cfu = {
+        .cframe_base = 0xf12d0000, .cframe_stride = 0x1000,
+        .cframe_bcast_reg = 0xf12ee000, .cframe_bcast_fdri = 0xf12ef000,
+        .cfu_apb = 0xf12b0000, .cfu_sfr = 0xf12c1000,
+        .cfu_stream = 0xf12c0000, .cfu_stream_2 = 0xf1f80000,
+        .cfu_fdro = 0xf12c2000,
+        .cfu_apb_irq = 235, .cframe_irq = EAM_IRQ(7),
+    },
+
+    .reserved = { 0xf5e00000, 270, 8 },
+};
+
 static const VersalMap *VERSION_TO_MAP[] = {
     [VERSAL_VER_VERSAL] = &VERSAL_MAP,
+    [VERSAL_VER_VERSAL2] = &VERSAL2_MAP,
 };
 
 static inline VersalVersion versal_get_version(Versal *s)
 {
     return XLNX_VERSAL_BASE_GET_CLASS(s)->version;
@@ -1291,10 +1412,15 @@ static void versal_create_efuse(Versal *s,
 {
     DeviceState *bits;
     DeviceState *ctrl;
     DeviceState *cache;
 
+    if (versal_get_version(s) != VERSAL_VER_VERSAL) {
+        /* TODO for versal2 */
+        return;
+    }
+
     ctrl = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CTRL);
     cache = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CACHE);
     bits = qdev_new(TYPE_XLNX_EFUSE);
 
     qdev_prop_set_uint32(bits, "efuse-nr", 3);
@@ -1542,34 +1668,47 @@ static inline void crl_connect_dev_by_name(Versal *s, Object *crl,
 }
 
 static inline void versal_create_crl(Versal *s)
 {
     const VersalMap *map;
+    VersalVersion ver;
     const char *crl_class;
     DeviceState *dev;
+    size_t num_gem;
     Object *obj;
 
     map = versal_get_map(s);
+    ver = versal_get_version(s);
 
-    crl_class = TYPE_XLNX_VERSAL_CRL;
+    crl_class = xlnx_versal_crl_class_name(ver);
     dev = qdev_new(crl_class);
     obj = OBJECT(dev);
     object_property_add_child(OBJECT(s), "crl", obj);
 
+    /*
+     * The 3rd GEM controller on versal2 is in the MMI subsystem.
+     * Its reset line is not connected to the CRL. Consider only the first two
+     * ones.
+     */
+    num_gem = ver == VERSAL_VER_VERSAL2 ? 2 : map->num_gem;
+
     crl_connect_dev_by_name(s, obj, "rpu-cluster/rpu",
                             map->rpu.num_cluster * map->rpu.num_core);
     crl_connect_dev_by_name(s, obj, map->zdma[0].name, map->zdma[0].num_chan);
     crl_connect_dev_by_name(s, obj, "uart", map->num_uart);
-    crl_connect_dev_by_name(s, obj, "gem", map->num_gem);
+    crl_connect_dev_by_name(s, obj, "gem", num_gem);
     crl_connect_dev_by_name(s, obj, "usb", map->num_usb);
 
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
 
     memory_region_add_subregion(&s->mr_ps, map->crl.addr,
                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
 
-    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
+    if (ver == VERSAL_VER_VERSAL) {
+        /* CRL IRQ line has been removed in versal2 */
+        versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
+    }
 }
 
 /*
  * This takes the board allocated linear DDR memory and creates aliases
  * for each split DDR range/aperture on the Versal address map.
@@ -1657,21 +1796,16 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
     qemu_log_mask(LOG_UNIMP,
                   "PMC SLCR parity interrupt behaviour "
                   "is not yet implemented\n");
 }
 
-static void versal_unimp(Versal *s)
+static void versal_unimp_common(Versal *s)
 {
     DeviceState *slcr;
     qemu_irq gpio_in;
 
-    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
-    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
-    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
     versal_unimp_area(s, "crp", &s->mr_ps, 0xf1260000, 0x10000);
-    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
-    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, 0xff140000, 0x10000);
 
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel,
                             "sd-emmc-sel-dummy", 2);
     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
                             "qspi-ospi-mux-sel-dummy", 1);
@@ -1690,10 +1824,29 @@ static void versal_unimp(Versal *s)
 
     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0);
     qdev_connect_gpio_out_named(slcr, SYSBUS_DEVICE_GPIO_IRQ, 0, gpio_in);
 }
 
+static void versal_unimp(Versal *s)
+{
+    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
+    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
+    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
+    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
+    versal_unimp_area(s, "iou-scntr-secure", &s->mr_ps, 0xff140000, 0x10000);
+
+    versal_unimp_common(s);
+}
+
+static void versal2_unimp(Versal *s)
+{
+    versal_unimp_area(s, "fpd-systmr-ctrl", &s->mr_ps, 0xec920000, 0x1000);
+    versal_unimp_area(s, "crf", &s->mr_ps, 0xec200000, 0x100000);
+
+    versal_unimp_common(s);
+}
+
 static uint32_t fdt_add_clk_node(Versal *s, const char *name,
                                  unsigned int freq_hz)
 {
     uint32_t phandle;
 
@@ -1707,13 +1860,12 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
     qemu_fdt_setprop(s->cfg.fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
 
     return phandle;
 }
 
-static void versal_realize(DeviceState *dev, Error **errp)
+static void versal_realize_common(Versal *s)
 {
-    Versal *s = XLNX_VERSAL_BASE(dev);
     DeviceState *slcr, *ospi;
     MemoryRegion *ocm;
     Object *container;
     const VersalMap *map = versal_get_map(s);
     size_t i;
@@ -1782,18 +1934,33 @@ static void versal_realize(DeviceState *dev, Error **errp)
     versal_create_rtc(s, &map->rtc);
     versal_create_cfu(s, &map->cfu);
     versal_create_crl(s);
 
     versal_map_ddr(s, &map->ddr);
-    versal_unimp(s);
 
     /* Create the On Chip Memory (OCM).  */
     ocm = g_new(MemoryRegion, 1);
     memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
     memory_region_add_subregion_overlap(&s->mr_ps, map->ocm.addr, ocm, 0);
 }
 
+static void versal_realize(DeviceState *dev, Error **errp)
+{
+    Versal *s = XLNX_VERSAL_BASE(dev);
+
+    versal_realize_common(s);
+    versal_unimp(s);
+}
+
+static void versal2_realize(DeviceState *dev, Error **errp)
+{
+    Versal *s = XLNX_VERSAL_BASE(dev);
+
+    versal_realize_common(s);
+    versal2_unimp(s);
+}
+
 void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
 {
     DeviceState *sdhci, *card;
 
     sdhci = DEVICE(versal_get_child_idx(s, "sdhci", sd_idx));
@@ -1925,20 +2092,30 @@ static const Property versal_properties[] = {
 
 static void versal_base_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->realize = versal_realize;
     device_class_set_props(dc, versal_properties);
     /* No VMSD since we haven't got any top-level SoC state to save.  */
 }
 
 static void versal_class_init(ObjectClass *klass, const void *data)
 {
     VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     vc->version = VERSAL_VER_VERSAL;
+    dc->realize = versal_realize;
+}
+
+static void versal2_class_init(ObjectClass *klass, const void *data)
+{
+    VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    vc->version = VERSAL_VER_VERSAL2;
+    dc->realize = versal2_realize;
 }
 
 static const TypeInfo versal_base_info = {
     .name = TYPE_XLNX_VERSAL_BASE,
     .parent = TYPE_SYS_BUS_DEVICE,
@@ -1953,12 +2130,19 @@ static const TypeInfo versal_info = {
     .name = TYPE_XLNX_VERSAL,
     .parent = TYPE_XLNX_VERSAL_BASE,
     .class_init = versal_class_init,
 };
 
+static const TypeInfo versal2_info = {
+    .name = TYPE_XLNX_VERSAL2,
+    .parent = TYPE_XLNX_VERSAL_BASE,
+    .class_init = versal2_class_init,
+};
+
 static void versal_register_types(void)
 {
     type_register_static(&versal_base_info);
     type_register_static(&versal_info);
+    type_register_static(&versal2_info);
 }
 
 type_init(versal_register_types);
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (40 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 20:45   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes Luc Michel
                   ` (5 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

To align with current branding and ensure coherency with the upcoming
versal2 machine, rename the xlnx-versal-virt machine to amd-versal-virt.
Keep an alias of the old name to the new one for command-line backward
compatibility.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 docs/system/arm/xlnx-versal-virt.rst | 26 +++++++++++++++-----------
 hw/arm/xlnx-versal-virt.c            | 11 +++++++----
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
index c5f35f28e4f..2c63fbf519f 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -1,21 +1,25 @@
-Xilinx Versal Virt (``xlnx-versal-virt``)
-=========================================
+AMD Versal Virt (``amd-versal-virt``)
+=====================================
 
-Xilinx Versal is a family of heterogeneous multi-core SoCs
+AMD Versal is a family of heterogeneous multi-core SoCs
 (System on Chip) that combine traditional hardened CPUs and I/O
 peripherals in a Processing System (PS) with runtime programmable
 FPGA logic (PL) and an Artificial Intelligence Engine (AIE).
 
+QEMU implements the Versal Series variant of Versal SoCs, with the
+``amd-versal-virt`` machine. The alias ``xlnx-versal-virt`` is kept for
+backward compatibility.
+
 More details here:
-https://www.xilinx.com/products/silicon-devices/acap/versal.html
+https://www.amd.com/en/products/adaptive-socs-and-fpgas/versal.html
 
 The family of Versal SoCs share a single architecture but come in
 different parts with different speed grades, amounts of PL and
 other differences.
 
-The Xilinx Versal Virt board in QEMU is a model of a virtual board
+The AMD Versal Virt board in QEMU is a model of a virtual board
 (does not exist in reality) with a virtual Versal SoC without I/O
 limitations. Currently, we support the following cores and devices:
 
 Implemented CPU cores:
 
@@ -72,11 +76,11 @@ A few examples:
 
 Direct Linux boot of a generic ARM64 upstream Linux kernel:
 
 .. code-block:: bash
 
-  $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
+  $ qemu-system-aarch64 -M amd-versal-virt -m 2G \
       -serial mon:stdio -display none \
       -kernel arch/arm64/boot/Image \
       -nic user -nic user \
       -device virtio-rng-device,bus=virtio-mmio-bus.0 \
       -drive if=none,index=0,file=hd0.qcow2,id=hd0,snapshot \
@@ -85,11 +89,11 @@ Direct Linux boot of a generic ARM64 upstream Linux kernel:
 
 Direct Linux boot of PetaLinux 2019.2:
 
 .. code-block:: bash
 
-  $ qemu-system-aarch64  -M xlnx-versal-virt -m 2G \
+  $ qemu-system-aarch64  -M amd-versal-virt -m 2G \
       -serial mon:stdio -display none \
       -kernel petalinux-v2019.2/Image \
       -append "rdinit=/sbin/init console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8" \
       -net nic,model=cadence_gem,netdev=net0 -netdev user,id=net0 \
       -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
@@ -98,11 +102,11 @@ Direct Linux boot of PetaLinux 2019.2:
 Boot PetaLinux 2019.2 via ARM Trusted Firmware (2018.3 because the 2019.2
 version of ATF tries to configure the CCI which we don't model) and U-boot:
 
 .. code-block:: bash
 
-  $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
+  $ qemu-system-aarch64 -M amd-versal-virt -m 2G \
       -serial stdio -display none \
       -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
       -device loader,file=petalinux-v2019.2/u-boot.elf \
       -device loader,addr=0x20000000,file=petalinux-v2019.2/Image \
       -nic user -nic user \
@@ -123,11 +127,11 @@ Run the following at the U-Boot prompt:
 
 Boot Linux as DOM0 on Xen via U-Boot:
 
 .. code-block:: bash
 
-  $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
+  $ qemu-system-aarch64 -M amd-versal-virt -m 4G \
       -serial stdio -display none \
       -device loader,file=petalinux-v2019.2/u-boot.elf,cpu-num=0 \
       -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
       -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
       -nic user -nic user \
@@ -151,11 +155,11 @@ Run the following at the U-Boot prompt:
 
 Boot Linux as Dom0 on Xen via ARM Trusted Firmware and U-Boot:
 
 .. code-block:: bash
 
-  $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
+  $ qemu-system-aarch64 -M amd-versal-virt -m 4G \
       -serial stdio -display none \
       -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
       -device loader,file=petalinux-v2019.2/u-boot.elf \
       -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
       -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
@@ -225,11 +229,11 @@ To use a different index value, N, from default of 1, add:
 
   Thus, a file backend should be used with caution, and 'format=luks'
   is highly recommended (albeit with usage complexity).
 
   Better yet, do not use actual product data when running guest image
-  on this Xilinx Versal Virt board.
+  on this AMD Versal Virt board.
 
 Using CANFDs for Versal Virt
 """"""""""""""""""""""""""""
 Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
 implementation. Bus connection and socketCAN connection for each CAN module
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 5e47a20922a..daacbfb984e 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -1,7 +1,7 @@
 /*
- * Xilinx Versal Virtual board.
+ * AMD/Xilinx Versal Virtual board.
  *
  * Copyright (c) 2018 Xilinx Inc.
  * Copyright (c) 2025, Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
@@ -24,11 +24,11 @@
 #include "hw/arm/boot.h"
 #include "target/arm/multiprocessing.h"
 #include "qom/object.h"
 #include "target/arm/cpu.h"
 
-#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
+#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
 OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
 
 #define XLNX_VERSAL_NUM_OSPI_FLASH 4
 
 struct VersalVirt {
@@ -53,10 +53,11 @@ struct VersalVirt {
 };
 
 static void fdt_create(VersalVirt *s)
 {
     MachineClass *mc = MACHINE_GET_CLASS(s);
+    const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
 
     s->fdt = create_device_tree(&s->fdt_size);
     if (!s->fdt) {
         error_report("create_device_tree() failed");
         exit(1);
@@ -70,11 +71,12 @@ static void fdt_create(VersalVirt *s)
     qemu_fdt_add_subnode(s->fdt, "/chosen");
     qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
     qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
-    qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
+    qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
+                     sizeof(versal_compat));
 }
 
 static void fdt_add_clk_node(VersalVirt *s, const char *name,
                              unsigned int freq_hz, uint32_t phandle)
 {
@@ -346,11 +348,12 @@ static void versal_virt_machine_finalize(Object *obj)
 static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
     int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
 
-    mc->desc = "Xilinx Versal Virtual development board";
+    mc->desc = "AMD Versal Virtual development board";
+    mc->alias = "xlnx-versal-virt";
     mc->init = versal_virt_init;
     mc->min_cpus = num_cpu;
     mc->max_cpus = num_cpu;
     mc->default_cpus = num_cpu;
     mc->no_cdrom = true;
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (41 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:00   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up Luc Michel
                   ` (4 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Split the xlnx-versal-virt machine type into a base abstract type and a
concrete type. There is no functional change. This is in preparation for
versal2 machine.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal-virt.c | 74 +++++++++++++++++++++++++++------------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index daacbfb984e..9b20aef8b07 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -24,12 +24,15 @@
 #include "hw/arm/boot.h"
 #include "target/arm/multiprocessing.h"
 #include "qom/object.h"
 #include "target/arm/cpu.h"
 
+#define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
+    MACHINE_TYPE_NAME("amd-versal-virt-base")
+OBJECT_DECLARE_TYPE(VersalVirt, VersalVirtClass, XLNX_VERSAL_VIRT_BASE_MACHINE)
+
 #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
-OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
 
 #define XLNX_VERSAL_NUM_OSPI_FLASH 4
 
 struct VersalVirt {
     MachineState parent_obj;
@@ -50,10 +53,16 @@ struct VersalVirt {
         bool secure;
         char *ospi_model;
     } cfg;
 };
 
+struct VersalVirtClass {
+    MachineClass parent_class;
+
+    VersalVersion version;
+};
+
 static void fdt_create(VersalVirt *s)
 {
     MachineClass *mc = MACHINE_GET_CLASS(s);
     const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
 
@@ -191,27 +200,28 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
     versal_sdhci_plug_card(&s->soc, idx, blk);
 }
 
 static char *versal_get_ospi_model(Object *obj, Error **errp)
 {
-    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
+    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
 
     return g_strdup(s->cfg.ospi_model);
 }
 
 static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
 {
-    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
+    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
 
     g_free(s->cfg.ospi_model);
     s->cfg.ospi_model = g_strdup(value);
 }
 
 
 static void versal_virt_init(MachineState *machine)
 {
-    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
+    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(machine);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(machine);
     int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
     int i;
 
     /*
      * If the user provides an Operating System to be loaded, we expect them
@@ -239,15 +249,15 @@ static void versal_virt_init(MachineState *machine)
     if (machine->kernel_filename) {
         psci_conduit = QEMU_PSCI_CONDUIT_SMC;
     }
 
     object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
-                            TYPE_XLNX_VERSAL);
+                            versal_get_class(vvc->version));
     object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
                              &error_abort);
 
-    for (i = 0; i < versal_get_num_can(VERSAL_VER_VERSAL); i++) {
+    for (i = 0; i < versal_get_num_can(vvc->version); i++) {
         g_autofree char *prop_name = g_strdup_printf("canbus%d", i);
 
         object_property_set_link(OBJECT(&s->soc), prop_name,
                                  OBJECT(s->canbus[i]),
                                  &error_abort);
@@ -272,11 +282,11 @@ static void versal_virt_init(MachineState *machine)
 
     /* Attach efuse backend, if given */
     efuse_attach_drive(s);
 
     /* Plug SD cards */
-    for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
+    for (i = 0; i < versal_get_num_sdhci(vvc->version); i++) {
         sd_plug_card(s, i, drive_get(IF_SD, 0, i));
     }
 
     s->binfo.ram_size = machine->ram_size;
     s->binfo.loader_start = 0x0;
@@ -316,14 +326,15 @@ static void versal_virt_init(MachineState *machine)
     }
 }
 
 static void versal_virt_machine_instance_init(Object *obj)
 {
-    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
+    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(s);
     size_t i, num_can;
 
-    num_can = versal_get_num_can(VERSAL_VER_VERSAL);
+    num_can = versal_get_num_can(vvc->version);
     s->canbus = g_new0(CanBusState *, num_can);
 
     /*
      * User can set canbusx properties to can-bus object and optionally connect
      * to socketcan interface via command line.
@@ -337,47 +348,66 @@ static void versal_virt_machine_instance_init(Object *obj)
     }
 }
 
 static void versal_virt_machine_finalize(Object *obj)
 {
-    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
+    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
 
     g_free(s->cfg.ospi_model);
     g_free(s->canbus);
 }
 
-static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
+static void versal_virt_machine_class_init_common(ObjectClass *oc)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
-    int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(mc);
+    int num_cpu = versal_get_num_cpu(vvc->version);
 
-    mc->desc = "AMD Versal Virtual development board";
-    mc->alias = "xlnx-versal-virt";
-    mc->init = versal_virt_init;
-    mc->min_cpus = num_cpu;
-    mc->max_cpus = num_cpu;
-    mc->default_cpus = num_cpu;
     mc->no_cdrom = true;
     mc->auto_create_sdcard = true;
     mc->default_ram_id = "ddr";
+    mc->min_cpus = num_cpu;
+    mc->max_cpus = num_cpu;
+    mc->default_cpus = num_cpu;
+    mc->init = versal_virt_init;
+
     object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
                                    versal_set_ospi_model);
     object_class_property_set_description(oc, "ospi-flash",
                                           "Change the OSPI Flash model");
 }
 
-static const TypeInfo versal_virt_machine_init_typeinfo = {
-    .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
+static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(oc);
+
+    mc->desc = "AMD Versal Virtual development board";
+    mc->alias = "xlnx-versal-virt";
+    vvc->version = VERSAL_VER_VERSAL;
+
+    versal_virt_machine_class_init_common(oc);
+}
+
+static const TypeInfo versal_virt_base_machine_init_typeinfo = {
+    .name       = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
     .parent     = TYPE_MACHINE,
-    .class_init = versal_virt_machine_class_init,
+    .class_size = sizeof(VersalVirtClass),
     .instance_init = versal_virt_machine_instance_init,
     .instance_size = sizeof(VersalVirt),
     .instance_finalize = versal_virt_machine_finalize,
+    .abstract = true,
+};
+
+static const TypeInfo versal_virt_machine_init_typeinfo = {
+    .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
+    .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
+    .class_init = versal_virt_machine_class_init,
 };
 
 static void versal_virt_machine_init_register_types(void)
 {
+    type_register_static(&versal_virt_base_machine_init_typeinfo);
     type_register_static(&versal_virt_machine_init_typeinfo);
 }
 
 type_init(versal_virt_machine_init_register_types)
-
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (42 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:00   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices Luc Michel
                   ` (3 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Remove now unused clock nodes. They have been replaced by the ones
created in the SoC. Remove the unused cfg.secure VersalVirt field.
Remove unecessary include directives.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/arm/xlnx-versal-virt.c | 24 ------------------------
 1 file changed, 24 deletions(-)

diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 9b20aef8b07..154ed7332c3 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -17,14 +17,12 @@
 #include "system/address-spaces.h"
 #include "hw/block/flash.h"
 #include "hw/boards.h"
 #include "hw/sysbus.h"
 #include "hw/arm/fdt.h"
-#include "hw/qdev-properties.h"
 #include "hw/arm/xlnx-versal.h"
 #include "hw/arm/boot.h"
-#include "target/arm/multiprocessing.h"
 #include "qom/object.h"
 #include "target/arm/cpu.h"
 
 #define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
     MACHINE_TYPE_NAME("amd-versal-virt-base")
@@ -39,20 +37,15 @@ struct VersalVirt {
 
     Versal soc;
 
     void *fdt;
     int fdt_size;
-    struct {
-        uint32_t clk_125Mhz;
-        uint32_t clk_25Mhz;
-    } phandle;
     struct arm_boot_info binfo;
 
     CanBusState **canbus;
 
     struct {
-        bool secure;
         char *ospi_model;
     } cfg;
 };
 
 struct VersalVirtClass {
@@ -70,35 +63,20 @@ static void fdt_create(VersalVirt *s)
     if (!s->fdt) {
         error_report("create_device_tree() failed");
         exit(1);
     }
 
-    /* Allocate all phandles.  */
-    s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
-    s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
-
     /* Create /chosen node for load_dtb.  */
     qemu_fdt_add_subnode(s->fdt, "/chosen");
     qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
     qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
     qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
                      sizeof(versal_compat));
 }
 
-static void fdt_add_clk_node(VersalVirt *s, const char *name,
-                             unsigned int freq_hz, uint32_t phandle)
-{
-    qemu_fdt_add_subnode(s->fdt, name);
-    qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
-    qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
-    qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
-    qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
-    qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
-}
-
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
     char **node_path;
     int n = 0;
@@ -263,12 +241,10 @@ static void versal_virt_init(MachineState *machine)
                                  &error_abort);
     }
 
     fdt_create(s);
     versal_set_fdt(&s->soc, s->fdt);
-    fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
-    fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
 
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
     create_virtio_regions(s);
 
     /*
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (43 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:01   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb Luc Michel
                   ` (2 subsequent siblings)
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Update the list of supported devices in the Versal SoCs.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 docs/system/arm/xlnx-versal-virt.rst | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
index 2c63fbf519f..94c8bacf61a 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -21,15 +21,15 @@ The AMD Versal Virt board in QEMU is a model of a virtual board
 (does not exist in reality) with a virtual Versal SoC without I/O
 limitations. Currently, we support the following cores and devices:
 
 Implemented CPU cores:
 
-- 2 ACPUs (ARM Cortex-A72)
+- 2 ACPUs (ARM Cortex-A72) with their GICv3 and ITS
+- 2 RCPUs (ARM Cortex-R5F) with their GICv2
 
 Implemented devices:
 
-- Interrupt controller (ARM GICv3)
 - 2 UARTs (ARM PL011)
 - An RTC (Versal built-in)
 - 2 GEMs (Cadence MACB Ethernet MACs)
 - 8 ADMA (Xilinx zDMA) channels
 - 2 SD Controllers
@@ -37,10 +37,13 @@ Implemented devices:
 - XRAM (4MB of on chip Accelerator RAM)
 - DDR memory
 - BBRAM (36 bytes of Battery-backed RAM)
 - eFUSE (3072 bytes of one-time field-programmable bit array)
 - 2 CANFDs
+- USB controller
+- OSPI controller
+- TRNG controller
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
 Other differences between the hardware and the QEMU model:
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (44 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:02   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine Luc Michel
  2025-07-16  9:54 ` [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine Luc Michel
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add a note in the DTB section explaining how to dump the generated DTB
using the dumpdtb machine option.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 docs/system/arm/xlnx-versal-virt.rst | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
index 94c8bacf61a..5d7fa18592b 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -63,11 +63,17 @@ Users can load firmware or boot-loaders with the ``-device loader`` options.
 
 When loading an OS, QEMU generates a DTB and selects an appropriate address
 where it gets loaded. This DTB will be passed to the kernel in register x0.
 
 If there's no ``-kernel`` option, we generate a DTB and place it at 0x1000
-for boot-loaders or firmware to pick it up.
+for boot-loaders or firmware to pick it up. To dump and observe the generated
+DTB, one can use the ``dumpdtb`` machine option:
+
+.. code-block:: bash
+
+  $ qemu-system-aarch64 -M amd-versal-virt,dumpdtb=example.dtb -m 2G
+
 
 If users want to provide their own DTB, they can use the ``-dtb`` option.
 These DTBs will have their memory nodes modified to match QEMU's
 selected ram_size option before they get passed to the kernel or FW.
 
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (45 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:08   ` Francisco Iglesias
  2025-07-16  9:54 ` [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine Luc Michel
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add the Versal Gen 2 Virtual development machine embedding a
versal2 SoC. This machine follows the same principle than the
xlnx-versal-virt machine. It creates its own DTB and feeds it to the
software payload. This way only implemented devices are exposed to the
guest and the user does not need to provide a DTB.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 docs/system/arm/xlnx-versal-virt.rst | 49 ++++++++++++++++++++++++----
 hw/arm/xlnx-versal-virt.c            | 37 +++++++++++++++++++--
 2 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
index 5d7fa18592b..af56b275413 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -1,16 +1,18 @@
-AMD Versal Virt (``amd-versal-virt``)
-=====================================
+AMD Versal Virt (``amd-versal-virt``, ``amd-versal2-virt``)
+===========================================================
 
 AMD Versal is a family of heterogeneous multi-core SoCs
 (System on Chip) that combine traditional hardened CPUs and I/O
 peripherals in a Processing System (PS) with runtime programmable
 FPGA logic (PL) and an Artificial Intelligence Engine (AIE).
 
-QEMU implements the Versal Series variant of Versal SoCs, with the
-``amd-versal-virt`` machine. The alias ``xlnx-versal-virt`` is kept for
-backward compatibility.
+QEMU implements two variants of Versal SoCs:
+
+- Versal (the ``amd-versal-virt`` machine, the alias ``xlnx-versal-virt`` is
+  kept for backward compatibility)
+- Versal Gen 2 (the ``amd-versal2-virt`` machine)
 
 More details here:
 https://www.amd.com/en/products/adaptive-socs-and-fpgas/versal.html
 
 The family of Versal SoCs share a single architecture but come in
@@ -19,10 +21,12 @@ other differences.
 
 The AMD Versal Virt board in QEMU is a model of a virtual board
 (does not exist in reality) with a virtual Versal SoC without I/O
 limitations. Currently, we support the following cores and devices:
 
+Versal
+""""""
 Implemented CPU cores:
 
 - 2 ACPUs (ARM Cortex-A72) with their GICv3 and ITS
 - 2 RCPUs (ARM Cortex-R5F) with their GICv2
 
@@ -41,20 +45,42 @@ Implemented devices:
 - 2 CANFDs
 - USB controller
 - OSPI controller
 - TRNG controller
 
+Versal Gen 2
+""""""""""""
+Implemented CPU cores:
+
+- 8 ACPUs (ARM Cortex-A78AE) with their GICv3 and ITS
+- 10 RCPUs (ARM Cortex-R52) with their GICv3 (one per cluster)
+
+Implemented devices:
+
+- 2 UARTs (ARM PL011)
+- An RTC (Versal built-in)
+- 3 GEMs (Cadence MACB Ethernet MACs)
+- 8 ADMA (Xilinx zDMA) channels
+- 2 SD Controllers
+- OCM (256KB of On Chip Memory)
+- DDR memory
+- BBRAM (36 bytes of Battery-backed RAM)
+- 2 CANFDs
+- 2 USB controllers
+- OSPI controller
+- TRNG controller
+
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
 Other differences between the hardware and the QEMU model:
 
 - QEMU allows the amount of DDR memory provided to be specified with the
   ``-m`` argument. If a DTB is provided on the command line then QEMU will
   edit it to include suitable entries describing the Versal DDR memory ranges.
 
-- QEMU provides 8 virtio-mmio virtio transports; these start at
-  address ``0xa0000000`` and have IRQs from 111 and upwards.
+- QEMU provides 8 virtio-mmio virtio transports. They use reserved memory
+  regions and IRQ pins to avoid conflicts with real SoC peripherals.
 
 Running
 """""""
 If the user provides an Operating System to be loaded, we expect users
 to use the ``-kernel`` command line option.
@@ -212,10 +238,15 @@ To use a different index value, N, from default of 0, add:
 
   -global driver=xlnx.bbram-ctrl,property=drive-index,value=N
 
 eFUSE File Backend
 """"""""""""""""""
+
+.. note::
+   The eFUSE device is not implemented in the Versal Gen 2 QEMU model
+   yet.
+
 eFUSE can have an optional file backend, which must be a seekable
 binary file with a size of 3072 bytes or larger. A file with all
 binary 0s is a 'blank'.
 
 To add a file-backend for the eFUSE:
@@ -269,5 +300,9 @@ To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
 
 .. code-block:: bash
 
     -object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
     -object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
+
+.. note::
+   Versal Gen 2 has 4 CAN controllers. ``canbus0`` to ``canbus3`` can
+   be specified on the command line.
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 154ed7332c3..8cfb7d0c380 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -1,7 +1,7 @@
 /*
- * AMD/Xilinx Versal Virtual board.
+ * AMD/Xilinx Versal family Virtual board.
  *
  * Copyright (c) 2018 Xilinx Inc.
  * Copyright (c) 2025, Advanced Micro Devices, Inc.
  * Written by Edgar E. Iglesias
  *
@@ -27,10 +27,11 @@
 #define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
     MACHINE_TYPE_NAME("amd-versal-virt-base")
 OBJECT_DECLARE_TYPE(VersalVirt, VersalVirtClass, XLNX_VERSAL_VIRT_BASE_MACHINE)
 
 #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
+#define TYPE_XLNX_VERSAL2_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal2-virt")
 
 #define XLNX_VERSAL_NUM_OSPI_FLASH 4
 
 struct VersalVirt {
     MachineState parent_obj;
@@ -55,11 +56,13 @@ struct VersalVirtClass {
 };
 
 static void fdt_create(VersalVirt *s)
 {
     MachineClass *mc = MACHINE_GET_CLASS(s);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(s);
     const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
+    const char versal2_compat[] = "amd-versal2-virt";
 
     s->fdt = create_device_tree(&s->fdt_size);
     if (!s->fdt) {
         error_report("create_device_tree() failed");
         exit(1);
@@ -69,12 +72,22 @@ static void fdt_create(VersalVirt *s)
     qemu_fdt_add_subnode(s->fdt, "/chosen");
     qemu_fdt_add_subnode(s->fdt, "/aliases");
 
     /* Header */
     qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
-    qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
-                     sizeof(versal_compat));
+
+    switch (vvc->version) {
+    case VERSAL_VER_VERSAL:
+        qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
+                         sizeof(versal_compat));
+        break;
+
+    case VERSAL_VER_VERSAL2:
+        qemu_fdt_setprop(s->fdt, "/", "compatible", versal2_compat,
+                         sizeof(versal2_compat));
+        break;
+    }
 }
 
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
     Error *err = NULL;
@@ -362,10 +375,21 @@ static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
     vvc->version = VERSAL_VER_VERSAL;
 
     versal_virt_machine_class_init_common(oc);
 }
 
+static void versal2_virt_machine_class_init(ObjectClass *oc, const void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(oc);
+
+    mc->desc = "AMD Versal Gen 2 Virtual development board";
+    vvc->version = VERSAL_VER_VERSAL2;
+
+    versal_virt_machine_class_init_common(oc);
+}
+
 static const TypeInfo versal_virt_base_machine_init_typeinfo = {
     .name       = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
     .parent     = TYPE_MACHINE,
     .class_size = sizeof(VersalVirtClass),
     .instance_init = versal_virt_machine_instance_init,
@@ -378,12 +402,19 @@ static const TypeInfo versal_virt_machine_init_typeinfo = {
     .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
     .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
     .class_init = versal_virt_machine_class_init,
 };
 
+static const TypeInfo versal2_virt_machine_init_typeinfo = {
+    .name       = TYPE_XLNX_VERSAL2_VIRT_MACHINE,
+    .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
+    .class_init = versal2_virt_machine_class_init,
+};
+
 static void versal_virt_machine_init_register_types(void)
 {
     type_register_static(&versal_virt_base_machine_init_typeinfo);
     type_register_static(&versal_virt_machine_init_typeinfo);
+    type_register_static(&versal2_virt_machine_init_typeinfo);
 }
 
 type_init(versal_virt_machine_init_register_types)
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine
  2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
                   ` (46 preceding siblings ...)
  2025-07-16  9:54 ` [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine Luc Michel
@ 2025-07-16  9:54 ` Luc Michel
  2025-07-31 21:09   ` Francisco Iglesias
  47 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-07-16  9:54 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Add a test for the amd-versal2-virt machine using the same command line,
kernel, initrd than the ones used for amd-versal-virt.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 tests/functional/test_aarch64_xlnx_versal.py | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tests/functional/test_aarch64_xlnx_versal.py b/tests/functional/test_aarch64_xlnx_versal.py
index 4b9c49e5d64..f32d904ef7e 100755
--- a/tests/functional/test_aarch64_xlnx_versal.py
+++ b/tests/functional/test_aarch64_xlnx_versal.py
@@ -18,12 +18,12 @@ class XlnxVersalVirtMachine(LinuxKernelTest):
         ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/'
          'installer-arm64/20101020ubuntu543.19/images/netboot/'
          '/ubuntu-installer/arm64/initrd.gz'),
         'e7a5e716b6f516d8be315c06e7331aaf16994fe4222e0e7cfb34bc015698929e')
 
-    def test_aarch64_xlnx_versal_virt(self):
-        self.set_machine('xlnx-versal-virt')
+    def common_aarch64_amd_versal_virt(self, machine):
+        self.set_machine(machine)
         kernel_path = self.ASSET_KERNEL.fetch()
         initrd_path = self.ASSET_INITRD.fetch()
 
         self.vm.set_console()
         self.vm.add_args('-m', '2G',
@@ -31,7 +31,13 @@ def test_aarch64_xlnx_versal_virt(self):
                          '-kernel', kernel_path,
                          '-initrd', initrd_path)
         self.vm.launch()
         self.wait_for_console_pattern('Checked W+X mappings: passed')
 
+    def test_aarch64_amd_versal_virt(self):
+        self.common_aarch64_amd_versal_virt('amd-versal-virt')
+
+    def test_aarch64_amd_versal2_virt(self):
+        self.common_aarch64_amd_versal_virt('amd-versal2-virt')
+
 if __name__ == '__main__':
     LinuxKernelTest.main()
-- 
2.50.0



^ permalink raw reply related	[flat|nested] 106+ messages in thread

* Re: [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization
  2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
@ 2025-07-24  8:30   ` Francisco Iglesias
  2025-07-28  8:47   ` Boddu, Sai Pavan
  1 sibling, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-24  8:30 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu, Jason Wang

On Wed, Jul 16, 2025 at 11:53:43AM +0200, Luc Michel wrote:
> The gem_init_register_masks function was called at init time but it
> relies on the num-priority-queues property. Call it at realize time
> instead.
> 
> Fixes: 4c70e32f05f ("net: cadence_gem: Define access permission for interrupt registers")
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> ---
>  hw/net/cadence_gem.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
> index 50025d5a6f2..44446666deb 100644
> --- a/hw/net/cadence_gem.c
> +++ b/hw/net/cadence_gem.c
> @@ -1754,10 +1754,11 @@ static void gem_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < s->num_priority_queues; ++i) {
>          sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
>      }
>  
> +    gem_init_register_masks(s);
>      qemu_macaddr_default_if_unset(&s->conf.macaddr);
>  
>      s->nic = qemu_new_nic(&net_gem_info, &s->conf,
>                            object_get_typename(OBJECT(dev)), dev->id,
>                            &dev->mem_reentrancy_guard, s);
> @@ -1774,11 +1775,10 @@ static void gem_init(Object *obj)
>      CadenceGEMState *s = CADENCE_GEM(obj);
>      DeviceState *dev = DEVICE(obj);
>  
>      DB_PRINT("\n");
>  
> -    gem_init_register_masks(s);
>      memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
>                            "enet", sizeof(s->regs));
>  
>      sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
>  }
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* RE: [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization
  2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
  2025-07-24  8:30   ` Francisco Iglesias
@ 2025-07-28  8:47   ` Boddu, Sai Pavan
  1 sibling, 0 replies; 106+ messages in thread
From: Boddu, Sai Pavan @ 2025-07-28  8:47 UTC (permalink / raw)
  To: Michel, Luc, qemu-devel@nongnu.org, qemu-arm@nongnu.org
  Cc: Michel, Luc, Peter Maydell, Iglesias, Francisco, Iglesias, Edgar,
	Philippe Mathieu-Daudé, Alistair Francis, Konrad, Frederic,
	Jason Wang

[AMD Official Use Only - AMD Internal Distribution Only]

>-----Original Message-----
>From: Luc Michel <luc.michel@amd.com>
>Sent: Wednesday, July 16, 2025 3:24 PM
>To: qemu-devel@nongnu.org; qemu-arm@nongnu.org
>Cc: Michel, Luc <Luc.Michel@amd.com>; Peter Maydell
><peter.maydell@linaro.org>; Iglesias, Francisco <francisco.iglesias@amd.com>;
>Iglesias, Edgar <Edgar.Iglesias@amd.com>; Philippe Mathieu-Daudé
><philmd@linaro.org>; Alistair Francis <alistair@alistair23.me>; Konrad, Frederic
><Frederic.Konrad@amd.com>; Boddu, Sai Pavan <sai.pavan.boddu@amd.com>;
>Jason Wang <jasowang@redhat.com>
>Subject: [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization
>
>The gem_init_register_masks function was called at init time but it relies on the num-
>priority-queues property. Call it at realize time instead.
>
>Fixes: 4c70e32f05f ("net: cadence_gem: Define access permission for interrupt
>registers")
>Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Sai Pavan Boddu <sai.pavan.boddu@amd.com>

>---
> hw/net/cadence_gem.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index
>50025d5a6f2..44446666deb 100644
>--- a/hw/net/cadence_gem.c
>+++ b/hw/net/cadence_gem.c
>@@ -1754,10 +1754,11 @@ static void gem_realize(DeviceState *dev, Error **errp)
>
>     for (i = 0; i < s->num_priority_queues; ++i) {
>         sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
>     }
>
>+    gem_init_register_masks(s);
>     qemu_macaddr_default_if_unset(&s->conf.macaddr);
>
>     s->nic = qemu_new_nic(&net_gem_info, &s->conf,
>                           object_get_typename(OBJECT(dev)), dev->id,
>                           &dev->mem_reentrancy_guard, s); @@ -1774,11 +1775,10 @@
>static void gem_init(Object *obj)
>     CadenceGEMState *s = CADENCE_GEM(obj);
>     DeviceState *dev = DEVICE(obj);
>
>     DB_PRINT("\n");
>
>-    gem_init_register_masks(s);
>     memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
>                           "enet", sizeof(s->regs));
>
>     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);  }
>--
>2.50.0



^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type
  2025-07-16  9:53 ` [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type Luc Michel
@ 2025-07-28 16:59   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 16:59 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Luc,

On Wed, Jul 16, 2025 at 11:53:44AM +0200, Luc Michel wrote:
> Split the xlnx-versal device into two classes, a base, abstract class
> and the existing concrete one. Introduce a VersalVersion type that will
> be used across several device models when versal2 implementation is
> added.
> 
> This is in preparation for versal2 implementation.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
>  include/hw/arm/xlnx-versal-version.h | 15 ++++++++++++++
>  include/hw/arm/xlnx-versal.h         | 12 ++++++++++-
>  hw/arm/xlnx-versal.c                 | 31 +++++++++++++++++++++-------
>  3 files changed, 50 insertions(+), 8 deletions(-)
>  create mode 100644 include/hw/arm/xlnx-versal-version.h
> 
> diff --git a/include/hw/arm/xlnx-versal-version.h b/include/hw/arm/xlnx-versal-version.h
> new file mode 100644
> index 00000000000..46eb165a2bd
> --- /dev/null
> +++ b/include/hw/arm/xlnx-versal-version.h
> @@ -0,0 +1,15 @@
> +/*
> + * AMD Versal versions
> + *
> + * Copyright (c) 2025, Advanced Micro Devices, Inc.

nitpick:
s/2025,/2025/

Otherwise:

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_ARM_XLNX_VERSAL_VERSION_H
> +#define HW_ARM_XLNX_VERSAL_VERSION_H
> +
> +typedef enum VersalVersion {
> +    VERSAL_VER_VERSAL,
> +} VersalVersion;
> +
> +#endif
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 05ed641b6b6..1f92e314d6c 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -1,9 +1,10 @@
>  /*
>   * Model of the Xilinx Versal
>   *
>   * Copyright (c) 2018 Xilinx Inc.
> + * Copyright (c) 2025 Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 or
>   * (at your option) any later version.
> @@ -33,13 +34,16 @@
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "target/arm/cpu.h"
> +#include "hw/arm/xlnx-versal-version.h"
> +
> +#define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
> +OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  
>  #define TYPE_XLNX_VERSAL "xlnx-versal"
> -OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
>  
>  #define XLNX_VERSAL_NR_ACPUS   2
>  #define XLNX_VERSAL_NR_RCPUS   2
>  #define XLNX_VERSAL_NR_UARTS   2
>  #define XLNX_VERSAL_NR_GEMS    2
> @@ -135,10 +139,16 @@ struct Versal {
>      struct {
>          MemoryRegion *mr_ddr;
>      } cfg;
>  };
>  
> +struct VersalClass {
> +    SysBusDeviceClass parent;
> +
> +    VersalVersion version;
> +};
> +
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
>  
>  #define VERSAL_GIC_MAINT_IRQ        9
>  #define VERSAL_TIMER_VIRT_IRQ       11
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index a42b9e7140b..4da656318f6 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -1,9 +1,10 @@
>  /*
>   * Xilinx Versal SoC model.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
> + * Copyright (c) 2025 Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 or
>   * (at your option) any later version.
> @@ -918,11 +919,11 @@ static void versal_unimp(Versal *s)
>                                  gpio_in);
>  }
>  
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
> -    Versal *s = XLNX_VERSAL(dev);
> +    Versal *s = XLNX_VERSAL_BASE(dev);
>      qemu_irq pic[XLNX_VERSAL_NR_IRQS];
>  
>      versal_create_apu_cpus(s);
>      versal_create_apu_gic(s, pic);
>      versal_create_rpu_cpus(s);
> @@ -953,13 +954,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
>      memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
>                                          &s->lpd.rpu.mr_ps_alias, 0);
>  }
>  
> -static void versal_init(Object *obj)
> +static void versal_base_init(Object *obj)
>  {
> -    Versal *s = XLNX_VERSAL(obj);
> +    Versal *s = XLNX_VERSAL_BASE(obj);
>  
>      memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
>      memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
>      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
>      memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
> @@ -973,28 +974,44 @@ static const Property versal_properties[] = {
>                        TYPE_CAN_BUS, CanBusState *),
>      DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
>                        TYPE_CAN_BUS, CanBusState *),
>  };
>  
> -static void versal_class_init(ObjectClass *klass, const void *data)
> +static void versal_base_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = versal_realize;
>      device_class_set_props(dc, versal_properties);
>      /* No VMSD since we haven't got any top-level SoC state to save.  */
>  }
>  
> -static const TypeInfo versal_info = {
> -    .name = TYPE_XLNX_VERSAL,
> +static void versal_class_init(ObjectClass *klass, const void *data)
> +{
> +    VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
> +
> +    vc->version = VERSAL_VER_VERSAL;
> +}
> +
> +static const TypeInfo versal_base_info = {
> +    .name = TYPE_XLNX_VERSAL_BASE,
>      .parent = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(Versal),
> -    .instance_init = versal_init,
> +    .instance_init = versal_base_init,
> +    .class_init = versal_base_class_init,
> +    .class_size = sizeof(VersalClass),
> +    .abstract = true,
> +};
> +
> +static const TypeInfo versal_info = {
> +    .name = TYPE_XLNX_VERSAL,
> +    .parent = TYPE_XLNX_VERSAL_BASE,
>      .class_init = versal_class_init,
>  };
>  
>  static void versal_register_types(void)
>  {
> +    type_register_static(&versal_base_info);
>      type_register_static(&versal_info);
>  }
>  
>  type_init(versal_register_types);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation
  2025-07-16  9:53 ` [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation Luc Michel
@ 2025-07-28 17:13   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 17:13 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Luc,

On Wed, Jul 16, 2025 at 11:53:45AM +0200, Luc Michel wrote:
> The following commits will move FDT creation logic from the
> xlnx-versal-virt machine to the xlnx-versal SoC itself. Prepare this by
> passing the FDT handle to the SoC before it is realized. If no FDT is
> passed, a dummy one is created internally as a stub to the fdt function
> calls.
> 
> For now the SoC only creates the two clock nodes. The ones from the
> xlnx-versal virt machine are renamed with a `old-' prefix and will be
> removed once they are not referenced anymore.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
>  include/hw/arm/xlnx-versal.h | 12 ++++++++++++
>  hw/arm/xlnx-versal-virt.c    | 11 +++++++----
>  hw/arm/xlnx-versal.c         | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 49 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 1f92e314d6c..f2a62b43552 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -134,21 +134,33 @@ struct Versal {
>          XlnxVersalCFrameBcastReg cframe_bcast;
>  
>          OrIRQState apb_irq_orgate;
>      } pmc;
>  
> +    struct {
> +        uint32_t clk_25mhz;
> +        uint32_t clk_125mhz;
> +    } phandle;
> +
>      struct {
>          MemoryRegion *mr_ddr;
> +        void *fdt;
>      } cfg;
>  };
>  
>  struct VersalClass {
>      SysBusDeviceClass parent;
>  
>      VersalVersion version;
>  };
>  
> +static inline void versal_set_fdt(Versal *s, void *fdt)
> +{
> +    g_assert(!qdev_is_realized(DEVICE(s)));
> +    s->cfg.fdt = fdt;
> +}
> +
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
>  
>  #define VERSAL_GIC_MAINT_IRQ        9
>  #define VERSAL_TIMER_VIRT_IRQ       11
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index adadbb72902..c30dcca424c 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -1,9 +1,10 @@
>  /*
>   * Xilinx Versal Virtual board.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
> + * Copyright (c) 2025, Advanced Micro Devices, Inc.

s/2025,/2025/

Otherwise:

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

>   * Written by Edgar E. Iglesias
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 or
>   * (at your option) any later version.
> @@ -695,14 +696,13 @@ static void versal_virt_init(MachineState *machine)
>                               &error_abort);
>      object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
>                               &error_abort);
>      object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
>                               &error_abort);
> -    sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
>  
>      fdt_create(s);
> -    create_virtio_regions(s);
> +    versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gem_nodes(s);
>      fdt_add_uart_nodes(s);
>      fdt_add_canfd_nodes(s);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
> @@ -712,12 +712,15 @@ static void versal_virt_init(MachineState *machine)
>      fdt_add_rtc_node(s);
>      fdt_add_bbram_node(s);
>      fdt_add_efuse_ctrl_node(s);
>      fdt_add_efuse_cache_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
> -    fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
> -    fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
> +    fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
> +    fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
> +
> +    sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
> +    create_virtio_regions(s);
>  
>      /* Make the APU cpu address space visible to virtio and other
>       * modules unaware of multiple address-spaces.  */
>      memory_region_add_subregion_overlap(get_system_memory(),
>                                          0, &s->soc.fpd.apu.mr, 0);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 4da656318f6..7bb55751e5c 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -22,10 +22,12 @@
>  #include "hw/misc/unimp.h"
>  #include "hw/arm/xlnx-versal.h"
>  #include "qemu/log.h"
>  #include "target/arm/cpu-qom.h"
>  #include "target/arm/gtimer.h"
> +#include "system/device_tree.h"
> +#include "hw/arm/fdt.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -917,14 +919,42 @@ static void versal_unimp(Versal *s)
>      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
>                                  SYSBUS_DEVICE_GPIO_IRQ, 0,
>                                  gpio_in);
>  }
>  
> +static uint32_t fdt_add_clk_node(Versal *s, const char *name,
> +                                 unsigned int freq_hz)
> +{
> +    uint32_t phandle;
> +
> +    phandle = qemu_fdt_alloc_phandle(s->cfg.fdt);
> +
> +    qemu_fdt_add_subnode(s->cfg.fdt, name);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, name, "phandle", phandle);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, name, "clock-frequency", freq_hz);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, name, "#clock-cells", 0x0);
> +    qemu_fdt_setprop_string(s->cfg.fdt, name, "compatible", "fixed-clock");
> +    qemu_fdt_setprop(s->cfg.fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
> +
> +    return phandle;
> +}
> +
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
>      Versal *s = XLNX_VERSAL_BASE(dev);
>      qemu_irq pic[XLNX_VERSAL_NR_IRQS];
> +    const VersalMap *map = versal_get_map(s);
> +    size_t i;
> +
> +    if (s->cfg.fdt == NULL) {
> +        int fdt_size;
> +
> +        s->cfg.fdt = create_device_tree(&fdt_size);
> +    }
> +
> +    s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
> +    s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
>  
>      versal_create_apu_cpus(s);
>      versal_create_apu_gic(s, pic);
>      versal_create_rpu_cpus(s);
>      versal_create_uarts(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation
  2025-07-16  9:53 ` [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation Luc Michel
@ 2025-07-28 17:29   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 17:29 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:46AM +0200, Luc Michel wrote:
> Refactor the UARTs creations. The VersalMap struct is now used to
> describe the SoC and its peripherals. For now it contains the two UARTs
> mapping information. The creation function now embeds the FDT creation
> logic as well. The devices are now created dynamically using qdev_new
> and (qdev|sysbus)_realize_and_unref.
> 
> This will allow to rely entirely on the VersalMap structure to create
> the SoC and allow easy addition of new SoCs of the same family (like
> versal2 coming with next commits).
> 
> Note that the connection to the CRL is removed for now and will be
> re-added by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |   2 -
>  hw/arm/xlnx-versal-virt.c    |  36 +--------
>  hw/arm/xlnx-versal.c         | 142 ++++++++++++++++++++++++++++-------
>  3 files changed, 117 insertions(+), 63 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index f2a62b43552..b01ddeb1423 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -16,11 +16,10 @@
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/sd/sdhci.h"
>  #include "hw/intc/arm_gicv3.h"
> -#include "hw/char/pl011.h"
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/net/cadence_gem.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
> @@ -78,11 +77,10 @@ struct Versal {
>  
>      struct {
>          MemoryRegion mr_ocm;
>  
>          struct {
> -            PL011State uart[XLNX_VERSAL_NR_UARTS];
>              CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
>              OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
>              XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
>              VersalUsb2 usb;
>              CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index c30dcca424c..7213ead466d 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -75,10 +75,11 @@ static void fdt_create(VersalVirt *s)
>  
>      s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
>      /* Create /chosen node for load_dtb.  */
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
> +    qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
>      qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
>      qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
>      qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
> @@ -206,44 +207,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
>      qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
>      qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
>      g_free(name);
>  }
>  
> -static void fdt_add_uart_nodes(VersalVirt *s)
> -{
> -    uint64_t addrs[] = { MM_UART1, MM_UART0 };
> -    unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
> -    const char compat[] = "arm,pl011\0arm,sbsa-uart";
> -    const char clocknames[] = "uartclk\0apb_pclk";
> -    int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> -        char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
> -        qemu_fdt_add_subnode(s->fdt, name);
> -        qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
> -        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
> -        qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                     2, addrs[i], 2, 0x1000);
> -        qemu_fdt_setprop(s->fdt, name, "compatible",
> -                         compat, sizeof(compat));
> -        qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
> -
> -        if (addrs[i] == MM_UART0) {
> -            /* Select UART0.  */
> -            qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
> -        }
> -        g_free(name);
> -    }
> -}
> -
>  static void fdt_add_canfd_nodes(VersalVirt *s)
>  {
>      uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
>      uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
>      unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
> @@ -700,11 +667,10 @@ static void versal_virt_init(MachineState *machine)
>                               &error_abort);
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gem_nodes(s);
> -    fdt_add_uart_nodes(s);
>      fdt_add_canfd_nodes(s);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_zdma_nodes(s);
>      fdt_add_usb_xhci_nodes(s);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 7bb55751e5c..87468cbc291 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -24,18 +24,96 @@
>  #include "qemu/log.h"
>  #include "target/arm/cpu-qom.h"
>  #include "target/arm/gtimer.h"
>  #include "system/device_tree.h"
>  #include "hw/arm/fdt.h"
> +#include "hw/char/pl011.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
>  #define VERSAL_NUM_PMC_APB_IRQS 18
>  #define NUM_OSPI_IRQ_LINES 3
>  
> +typedef struct VersalSimplePeriphMap {
> +    uint64_t addr;
> +    int irq;
> +} VersalSimplePeriphMap;
> +
> +typedef struct VersalMap {
> +    VersalSimplePeriphMap uart[2];
> +    size_t num_uart;
> +} VersalMap;
> +
> +static const VersalMap VERSAL_MAP = {
> +    .uart[0] = { 0xff000000, 18 },
> +    .uart[1] = { 0xff010000, 19 },
> +    .num_uart = 2,
> +};
> +
> +static const VersalMap *VERSION_TO_MAP[] = {
> +    [VERSAL_VER_VERSAL] = &VERSAL_MAP,
> +};
> +
> +static inline VersalVersion versal_get_version(Versal *s)
> +{
> +    return XLNX_VERSAL_BASE_GET_CLASS(s)->version;
> +}
> +
> +static inline const VersalMap *versal_get_map(Versal *s)
> +{
> +    return VERSION_TO_MAP[versal_get_version(s)];
> +}
> +
> +
> +static qemu_irq versal_get_irq(Versal *s, int irq_idx)
> +{
> +    return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
> +}
> +
> +static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
> +                                      int sbd_idx, int irq_idx)
> +{
> +    qemu_irq irq = versal_get_irq(s, irq_idx);
> +
> +    if (irq == NULL) {
> +        return;
> +    }
> +
> +    sysbus_connect_irq(sbd, sbd_idx, irq);
> +}
> +
> +static inline char *versal_fdt_add_subnode(Versal *s, const char *path,
> +                                           uint64_t at, const char *compat,
> +                                           size_t compat_sz)
> +{
> +    char *p;
> +
> +    p = g_strdup_printf("%s@%" PRIx64, path, at);
> +    qemu_fdt_add_subnode(s->cfg.fdt, p);
> +
> +    if (!strncmp(compat, "memory", compat_sz)) {
> +        qemu_fdt_setprop(s->cfg.fdt, p, "device_type", compat, compat_sz);
> +    } else {
> +        qemu_fdt_setprop(s->cfg.fdt, p, "compatible", compat, compat_sz);
> +    }
> +
> +    return p;
> +}
> +
> +static inline char *versal_fdt_add_simple_subnode(Versal *s, const char *path,
> +                                                  uint64_t addr, uint64_t len,
> +                                                  const char *compat,
> +                                                  size_t compat_sz)
> +{
> +    char *p = versal_fdt_add_subnode(s, path, addr, compat, compat_sz);
> +
> +    qemu_fdt_setprop_sized_cells(s->cfg.fdt, p, "reg", 2, addr, 2, len);
> +    return p;
> +}
> +
>  static void versal_create_apu_cpus(Versal *s)
>  {
>      int i;
>  
>      object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
> @@ -165,32 +243,48 @@ static void versal_create_rpu_cpus(Versal *s)
>      }
>  
>      qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
>  }
>  
> -static void versal_create_uarts(Versal *s, qemu_irq *pic)
> +static void versal_create_uart(Versal *s,
> +                               const VersalSimplePeriphMap *map,
> +                               int chardev_idx)
>  {
> -    int i;
> +    DeviceState *dev;
> +    MemoryRegion *mr;
> +    g_autofree char *node;
> +    g_autofree char *alias;
> +    const char compatible[] = "arm,pl011\0arm,sbsa-uart";
> +    const char clocknames[] = "uartclk\0apb_pclk";
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
> -        static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
> -        static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
> -        char *name = g_strdup_printf("uart%d", i);
> -        DeviceState *dev;
> -        MemoryRegion *mr;
> +    dev = qdev_new(TYPE_PL011);
> +    object_property_add_child(OBJECT(s), "uart[*]", OBJECT(dev));
> +    qdev_prop_set_chr(dev, "chardev", serial_hd(chardev_idx));
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>  
> -        object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i],
> -                                TYPE_PL011);
> -        dev = DEVICE(&s->lpd.iou.uart[i]);
> -        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> -        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> +    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
>  
> -        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> -        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
> +    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
>  
> -        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
> -        g_free(name);
> +    node = versal_fdt_add_simple_subnode(s, "/uart", map->addr, 0x1000,
> +                                         compatible, sizeof(compatible));
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "current-speed", 115200);
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                           s->phandle.clk_125mhz, s->phandle.clk_125mhz);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names", clocknames,
> +                     sizeof(clocknames));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
> +                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "u-boot,dm-pre-reloc", NULL, 0);
> +
> +    alias = g_strdup_printf("serial%d", chardev_idx);
> +    qemu_fdt_setprop_string(s->cfg.fdt, "/aliases", alias, node);
> +
> +    if (chardev_idx == 0) {
> +        qemu_fdt_setprop_string(s->cfg.fdt, "/chosen", "stdout-path", node);
>      }
>  }
>  
>  static void versal_create_canfds(Versal *s, qemu_irq *pic)
>  {
> @@ -781,18 +875,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
>          object_property_set_link(OBJECT(&s->lpd.crl),
>                                   name, OBJECT(&s->lpd.iou.adma[i]),
>                                   &error_abort);
>      }
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
> -        g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
> -
> -        object_property_set_link(OBJECT(&s->lpd.crl),
> -                                 name, OBJECT(&s->lpd.iou.uart[i]),
> -                                 &error_abort);
> -    }
> -
>      object_property_set_link(OBJECT(&s->lpd.crl),
>                               "usb", OBJECT(&s->lpd.iou.usb),
>                               &error_abort);
>  
>      sysbus_realize(sbd, &error_fatal);
> @@ -955,11 +1041,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
>  
>      versal_create_apu_cpus(s);
>      versal_create_apu_gic(s, pic);
>      versal_create_rpu_cpus(s);
> -    versal_create_uarts(s, pic);
> +
> +    for (i = 0; i < map->num_uart; i++) {
> +        versal_create_uart(s, &map->uart[i], i);
> +    }
> +
>      versal_create_canfds(s, pic);
>      versal_create_usbs(s, pic);
>      versal_create_gems(s, pic);
>      versal_create_admas(s, pic);
>      versal_create_sds(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 05/48] hw/arm/xlnx-versal: canfd: refactor creation
  2025-07-16  9:53 ` [PATCH 05/48] hw/arm/xlnx-versal: canfd: " Luc Michel
@ 2025-07-28 20:44   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 20:44 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:47AM +0200, Luc Michel wrote:
> Refactor the CAN controllers creation using the VersalMap structure.
> 
> Note that the connection to the CRL is removed for now and will be
> re-added by next commits.
> 
> The xlnx-versal-virt machine now dynamically creates the correct amount
> of CAN bus link properties based on the number of CAN controller
> advertised by the SoC.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  7 +--
>  hw/arm/xlnx-versal-virt.c    | 73 ++++++++++--------------------
>  hw/arm/xlnx-versal.c         | 86 +++++++++++++++++++++++++-----------
>  3 files changed, 87 insertions(+), 79 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index b01ddeb1423..007c91b596e 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -29,11 +29,11 @@
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/misc/xlnx-versal-trng.h"
> -#include "hw/net/xlnx-versal-canfd.h"
> +#include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
> @@ -81,12 +81,10 @@ struct Versal {
>          struct {
>              CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
>              OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
>              XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
>              VersalUsb2 usb;
> -            CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
> -            XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
>          } iou;
>  
>          /* Real-time Processing Unit.  */
>          struct {
>              MemoryRegion mr;
> @@ -139,10 +137,11 @@ struct Versal {
>          uint32_t clk_125mhz;
>      } phandle;
>  
>      struct {
>          MemoryRegion *mr_ddr;
> +        CanBusState **canbus;
>          void *fdt;
>      } cfg;
>  };
>  
>  struct VersalClass {
> @@ -155,10 +154,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>  {
>      g_assert(!qdev_is_realized(DEVICE(s)));
>      s->cfg.fdt = fdt;
>  }
>  
> +int versal_get_num_can(VersalVersion version);
> +
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
>  
>  #define VERSAL_GIC_MAINT_IRQ        9
>  #define VERSAL_TIMER_VIRT_IRQ       11
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 7213ead466d..18a3ea169d0 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -41,15 +41,15 @@ struct VersalVirt {
>          uint32_t ethernet_phy[2];
>          uint32_t clk_125Mhz;
>          uint32_t clk_25Mhz;
>          uint32_t usb;
>          uint32_t dwc;
> -        uint32_t canfd[2];
>      } phandle;
>      struct arm_boot_info binfo;
>  
> -    CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
> +    CanBusState **canbus;
> +
>      struct {
>          bool secure;
>      } cfg;
>      char *ospi_model;
>  };
> @@ -207,42 +207,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
>      qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
>      qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
>      g_free(name);
>  }
>  
> -static void fdt_add_canfd_nodes(VersalVirt *s)
> -{
> -    uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
> -    uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
> -    unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
> -    const char clocknames[] = "can_clk\0s_axi_aclk";
> -    int i;
> -
> -    /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
> -    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> -        char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
> -        qemu_fdt_add_subnode(s->fdt, name);
> -
> -        qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
> -        qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
> -
> -        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> -        qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                     2, addrs[i], 2, size[i]);
> -        qemu_fdt_setprop_string(s->fdt, name, "compatible",
> -                                "xlnx,canfd-2.0");
> -
> -        g_free(name);
> -    }
> -}
> -
>  static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
>                                       uint32_t phandle)
>  {
>      char *name = g_strdup_printf("%s/fixed-link", gemname);
>  
> @@ -659,19 +627,22 @@ static void versal_virt_init(MachineState *machine)
>  
>      object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
>                              TYPE_XLNX_VERSAL);
>      object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
>                               &error_abort);
> -    object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
> -                             &error_abort);
> -    object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
> -                             &error_abort);
> +
> +    for (i = 0; i < versal_get_num_can(VERSAL_VER_VERSAL); i++) {
> +        g_autofree char *prop_name = g_strdup_printf("canbus%d", i);
> +
> +        object_property_set_link(OBJECT(&s->soc), prop_name,
> +                                 OBJECT(s->canbus[i]),
> +                                 &error_abort);
> +    }
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gem_nodes(s);
> -    fdt_add_canfd_nodes(s);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_zdma_nodes(s);
>      fdt_add_usb_xhci_nodes(s);
>      fdt_add_sd_nodes(s);
> @@ -753,30 +724,34 @@ static void versal_virt_init(MachineState *machine)
>  }
>  
>  static void versal_virt_machine_instance_init(Object *obj)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +    size_t i, num_can;
> +
> +    num_can = versal_get_num_can(VERSAL_VER_VERSAL);
> +    s->canbus = g_new0(CanBusState *, num_can);
>  
>      /*
> -     * User can set canbus0 and canbus1 properties to can-bus object and connect
> -     * to socketcan(optional) interface via command line.
> +     * User can set canbusx properties to can-bus object and optionally connect
> +     * to socketcan interface via command line.
>       */
> -    object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
> -                             (Object **)&s->canbus[0],
> -                             object_property_allow_set_link,
> -                             0);
> -    object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
> -                             (Object **)&s->canbus[1],
> -                             object_property_allow_set_link,
> -                             0);
> +    for (i = 0; i < num_can; i++) {
> +        g_autofree char *prop_name = g_strdup_printf("canbus%zu", i);
> +
> +        object_property_add_link(obj, prop_name, TYPE_CAN_BUS,
> +                                 (Object **) &s->canbus[i],
> +                                 object_property_allow_set_link, 0);
> +    }
>  }
>  
>  static void versal_virt_machine_finalize(Object *obj)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>  
>      g_free(s->ospi_model);
> +    g_free(s->canbus);
>  }
>  
>  static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
>  {
>      MachineClass *mc = MACHINE_CLASS(oc);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 87468cbc291..5dccf231942 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -25,10 +25,11 @@
>  #include "target/arm/cpu-qom.h"
>  #include "target/arm/gtimer.h"
>  #include "system/device_tree.h"
>  #include "hw/arm/fdt.h"
>  #include "hw/char/pl011.h"
> +#include "hw/net/xlnx-versal-canfd.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -41,16 +42,23 @@ typedef struct VersalSimplePeriphMap {
>  } VersalSimplePeriphMap;
>  
>  typedef struct VersalMap {
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
> +
> +    VersalSimplePeriphMap canfd[4];
> +    size_t num_canfd;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
>      .num_uart = 2,
> +
> +    .canfd[0] = { 0xff060000, 20 },
> +    .canfd[1] = { 0xff070000, 21 },
> +    .num_canfd = 2,
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -284,40 +292,46 @@ static void versal_create_uart(Versal *s,
>      if (chardev_idx == 0) {
>          qemu_fdt_setprop_string(s->cfg.fdt, "/chosen", "stdout-path", node);
>      }
>  }
>  
> -static void versal_create_canfds(Versal *s, qemu_irq *pic)
> +static void versal_create_canfd(Versal *s, const VersalSimplePeriphMap *map,
> +                                CanBusState *bus)
>  {
> -    int i;
> -    uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
> -    uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
> +    SysBusDevice *sbd;
> +    MemoryRegion *mr;
> +    g_autofree char *node;
> +    const char compatible[] = "xlnx,canfd-2.0";
> +    const char clocknames[] = "can_clk\0s_axi_aclk";
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
> -        char *name = g_strdup_printf("canfd%d", i);
> -        SysBusDevice *sbd;
> -        MemoryRegion *mr;
> +    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XILINX_CANFD));
> +    object_property_add_child(OBJECT(s), "canfd[*]", OBJECT(sbd));
>  
> -        object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
> -                                TYPE_XILINX_CANFD);
> -        sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);
> +    object_property_set_int(OBJECT(sbd), "ext_clk_freq",
> +                            25 * 1000 * 1000 , &error_abort);
>  
> -        object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
> -                                XLNX_VERSAL_CANFD_REF_CLK , &error_abort);
> +    object_property_set_link(OBJECT(sbd), "canfdbus", OBJECT(bus),
> +                             &error_abort);
>  
> -        object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
> -                                 OBJECT(s->lpd.iou.canbus[i]),
> -                                 &error_abort);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
>  
> -        sysbus_realize(sbd, &error_fatal);
> +    mr = sysbus_mmio_get_region(sbd, 0);
> +    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
>  
> -        mr = sysbus_mmio_get_region(sbd, 0);
> -        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
> +    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
>  
> -        sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
> -        g_free(name);
> -    }
> +    node = versal_fdt_add_simple_subnode(s, "/canfd", map->addr, 0x10000,
> +                                         compatible, sizeof(compatible));
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "rx-fifo-depth", 0x40);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "tx-mailbox-count", 0x20);
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                           s->phandle.clk_25mhz, s->phandle.clk_25mhz);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
> +                     clocknames, sizeof(clocknames));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
> +                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>  }
>  
>  static void versal_create_usbs(Versal *s, qemu_irq *pic)
>  {
>      DeviceState *dev;
> @@ -1046,11 +1060,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_uart; i++) {
>          versal_create_uart(s, &map->uart[i], i);
>      }
>  
> -    versal_create_canfds(s, pic);
> +    for (i = 0; i < map->num_canfd; i++) {
> +        versal_create_canfd(s, &map->canfd[i], s->cfg.canbus[i]);
> +    }
> +
>      versal_create_usbs(s, pic);
>      versal_create_gems(s, pic);
>      versal_create_admas(s, pic);
>      versal_create_sds(s, pic);
>      versal_create_pmc_apb_irq_orgate(s, pic);
> @@ -1074,28 +1091,43 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
>      memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
>                                          &s->lpd.rpu.mr_ps_alias, 0);
>  }
>  
> +int versal_get_num_can(VersalVersion version)
> +{
> +    const VersalMap *map = VERSION_TO_MAP[version];
> +
> +    return map->num_canfd;
> +}
> +
>  static void versal_base_init(Object *obj)
>  {
>      Versal *s = XLNX_VERSAL_BASE(obj);
> +    size_t i, num_can;
>  
>      memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
>      memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
>      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
>      memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
>                               "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
> +
> +    num_can = versal_get_map(s)->num_canfd;
> +    s->cfg.canbus = g_new0(CanBusState *, num_can);
> +
> +    for (i = 0; i < num_can; i++) {
> +        g_autofree char *prop_name = g_strdup_printf("canbus%zu", i);
> +
> +        object_property_add_link(obj, prop_name, TYPE_CAN_BUS,
> +                                 (Object **) &s->cfg.canbus[i],
> +                                 object_property_allow_set_link, 0);
> +    }
>  }
>  
>  static const Property versal_properties[] = {
>      DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
>                       MemoryRegion *),
> -    DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
> -                      TYPE_CAN_BUS, CanBusState *),
> -    DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
> -                      TYPE_CAN_BUS, CanBusState *),
>  };
>  
>  static void versal_base_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 06/48] hw/arm/xlnx-versal: sdhci: refactor creation
  2025-07-16  9:53 ` [PATCH 06/48] hw/arm/xlnx-versal: sdhci: " Luc Michel
@ 2025-07-28 20:50   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 20:50 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:48AM +0200, Luc Michel wrote:
> Refactor the SDHCI controllers creation using the VersalMap structure.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  5 +-
>  hw/arm/xlnx-versal-virt.c    | 43 ++--------------
>  hw/arm/xlnx-versal.c         | 96 ++++++++++++++++++++++++++++--------
>  3 files changed, 83 insertions(+), 61 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 007c91b596e..4a7a2d85aac 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -14,11 +14,10 @@
>  #define XLNX_VERSAL_H
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
> -#include "hw/sd/sdhci.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/net/cadence_gem.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
> @@ -103,11 +102,10 @@ struct Versal {
>      } lpd;
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
>          struct {
> -            SDHCIState sd[XLNX_VERSAL_NR_SDS];
>              XlnxVersalPmcIouSlcr slcr;
>  
>              struct {
>                  XlnxVersalOspi ospi;
>                  XlnxCSUDMA dma_src;
> @@ -154,11 +152,14 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>  {
>      g_assert(!qdev_is_realized(DEVICE(s)));
>      s->cfg.fdt = fdt;
>  }
>  
> +void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
> +
>  int versal_get_num_can(VersalVersion version);
> +int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
>  
>  #define VERSAL_GIC_MAINT_IRQ        9
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 18a3ea169d0..99ce84d5a46 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -282,36 +282,10 @@ static void fdt_add_zdma_nodes(VersalVirt *s)
>          qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
>          g_free(name);
>      }
>  }
>  
> -static void fdt_add_sd_nodes(VersalVirt *s)
> -{
> -    const char clocknames[] = "clk_xin\0clk_ahb";
> -    const char compat[] = "arasan,sdhci-8.9a";
> -    int i;
> -
> -    for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
> -        uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i;
> -        char *name = g_strdup_printf("/sdhci@%" PRIx64, addr);
> -
> -        qemu_fdt_add_subnode(s->fdt, name);
> -
> -        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> -        qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2,
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                     2, addr, 2, MM_PMC_SD0_SIZE);
> -        qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -        g_free(name);
> -    }
> -}
> -
>  static void fdt_add_rtc_node(VersalVirt *s)
>  {
>      const char compat[] = "xlnx,zynqmp-rtc";
>      const char interrupt_names[] = "alarm\0sec";
>      char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
> @@ -562,20 +536,15 @@ static void efuse_attach_drive(XlnxEFuse *dev)
>      if (blk) {
>          qdev_prop_set_drive(DEVICE(dev), "drive", blk);
>      }
>  }
>  
> -static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
> +static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
>  {
>      BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
> -    DeviceState *card;
>  
> -    card = qdev_new(TYPE_SD_CARD);
> -    object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
> -    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
> -    qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"),
> -                           &error_fatal);
> +    versal_sdhci_plug_card(&s->soc, idx, blk);
>  }
>  
>  static char *versal_get_ospi_model(Object *obj, Error **errp)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> @@ -643,11 +612,10 @@ static void versal_virt_init(MachineState *machine)
>      fdt_add_gem_nodes(s);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_zdma_nodes(s);
>      fdt_add_usb_xhci_nodes(s);
> -    fdt_add_sd_nodes(s);
>      fdt_add_rtc_node(s);
>      fdt_add_bbram_node(s);
>      fdt_add_efuse_ctrl_node(s);
>      fdt_add_efuse_cache_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
> @@ -666,14 +634,13 @@ static void versal_virt_init(MachineState *machine)
>      bbram_attach_drive(&s->soc.pmc.bbram);
>  
>      /* Attach efuse backend, if given */
>      efuse_attach_drive(&s->soc.pmc.efuse);
>  
> -    /* Plugin SD cards.  */
> -    for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
> -        sd_plugin_card(&s->soc.pmc.iou.sd[i],
> -                       drive_get(IF_SD, 0, i));
> +    /* Plug SD cards */
> +    for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
> +        sd_plug_card(s, i, drive_get(IF_SD, 0, i));
>      }
>  
>      s->binfo.ram_size = machine->ram_size;
>      s->binfo.loader_start = 0x0;
>      s->binfo.get_dtb = versal_virt_get_dtb;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 5dccf231942..b963a05935b 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -26,10 +26,11 @@
>  #include "target/arm/gtimer.h"
>  #include "system/device_tree.h"
>  #include "hw/arm/fdt.h"
>  #include "hw/char/pl011.h"
>  #include "hw/net/xlnx-versal-canfd.h"
> +#include "hw/sd/sdhci.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -45,20 +46,27 @@ typedef struct VersalMap {
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
>  
>      VersalSimplePeriphMap canfd[4];
>      size_t num_canfd;
> +
> +    VersalSimplePeriphMap sdhci[2];
> +    size_t num_sdhci;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
>      .num_uart = 2,
>  
>      .canfd[0] = { 0xff060000, 20 },
>      .canfd[1] = { 0xff070000, 21 },
>      .num_canfd = 2,
> +
> +    .sdhci[0] = { 0xf1040000, 126 },
> +    .sdhci[1] = { 0xf1050000, 128 },
> +    .num_sdhci = 2,
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -71,10 +79,22 @@ static inline VersalVersion versal_get_version(Versal *s)
>  static inline const VersalMap *versal_get_map(Versal *s)
>  {
>      return VERSION_TO_MAP[versal_get_version(s)];
>  }
>  
> +static inline Object *versal_get_child(Versal *s, const char *child)
> +{
> +    return object_resolve_path_at(OBJECT(s), child);
> +}
> +
> +static inline Object *versal_get_child_idx(Versal *s, const char *child,
> +                                           size_t idx)
> +{
> +    g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
> +
> +    return versal_get_child(s, n);
> +}
>  
>  static qemu_irq versal_get_irq(Versal *s, int irq_idx)
>  {
>      return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
>  }
> @@ -422,36 +442,43 @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
>          g_free(name);
>      }
>  }
>  
>  #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
> -static void versal_create_sds(Versal *s, qemu_irq *pic)
> +static void versal_create_sdhci(Versal *s,
> +                                const VersalSimplePeriphMap *map)
>  {
> -    int i;
> +    DeviceState *dev;
> +    MemoryRegion *mr;
> +    g_autofree char *node;
> +    const char compatible[] = "arasan,sdhci-8.9a";
> +    const char clocknames[] = "clk_xin\0clk_ahb";
>  
> -    for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
> -        DeviceState *dev;
> -        MemoryRegion *mr;
> +    dev = qdev_new(TYPE_SYSBUS_SDHCI);
> +    object_property_add_child(OBJECT(s), "sdhci[*]", OBJECT(dev));
>  
> -        object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i],
> -                                TYPE_SYSBUS_SDHCI);
> -        dev = DEVICE(&s->pmc.iou.sd[i]);
> +    object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
> +                             &error_fatal);
> +    object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
> +                             &error_fatal);
> +    object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>  
> -        object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
> -                                 &error_fatal);
> -        object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
> -                                 &error_fatal);
> -        object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
> -        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> +    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
>  
> -        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> -        memory_region_add_subregion(&s->mr_ps,
> -                                    MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
> +    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
>  
> -        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
> -                           pic[VERSAL_SD0_IRQ_0 + i * 2]);
> -    }
> +    node = versal_fdt_add_simple_subnode(s, "/sdhci", map->addr, 0x10000,
> +                                         compatible, sizeof(compatible));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                           s->phandle.clk_25mhz, s->phandle.clk_25mhz);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
> +                     clocknames, sizeof(clocknames));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                           GIC_FDT_IRQ_TYPE_SPI, map->irq,
> +                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>  }
>  
>  static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
>  {
>      DeviceState *orgate;
> @@ -1064,14 +1091,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_canfd; i++) {
>          versal_create_canfd(s, &map->canfd[i], s->cfg.canbus[i]);
>      }
>  
> +    for (i = 0; i < map->num_sdhci; i++) {
> +        versal_create_sdhci(s, &map->sdhci[i]);
> +    }
> +
>      versal_create_usbs(s, pic);
>      versal_create_gems(s, pic);
>      versal_create_admas(s, pic);
> -    versal_create_sds(s, pic);
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_xrams(s, pic);
>      versal_create_bbram(s, pic);
> @@ -1091,17 +1121,41 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
>      memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
>                                          &s->lpd.rpu.mr_ps_alias, 0);
>  }
>  
> +void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
> +{
> +    DeviceState *sdhci, *card;
> +
> +    sdhci = DEVICE(versal_get_child_idx(s, "sdhci", sd_idx));
> +
> +    if (sdhci == NULL) {
> +        return;
> +    }
> +
> +    card = qdev_new(TYPE_SD_CARD);
> +    object_property_add_child(OBJECT(sdhci), "card[*]", OBJECT(card));
> +    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
> +    qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
> +                           &error_fatal);
> +}
> +
>  int versal_get_num_can(VersalVersion version)
>  {
>      const VersalMap *map = VERSION_TO_MAP[version];
>  
>      return map->num_canfd;
>  }
>  
> +int versal_get_num_sdhci(VersalVersion version)
> +{
> +    const VersalMap *map = VERSION_TO_MAP[version];
> +
> +    return map->num_sdhci;
> +}
> +
>  static void versal_base_init(Object *obj)
>  {
>      Versal *s = XLNX_VERSAL_BASE(obj);
>      size_t i, num_can;
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 07/48] hw/arm/xlnx-versal: gem: refactor creation
  2025-07-16  9:53 ` [PATCH 07/48] hw/arm/xlnx-versal: gem: " Luc Michel
@ 2025-07-28 20:56   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 20:56 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:49AM +0200, Luc Michel wrote:
> Refactor the GEM ethernet controllers creation using the VersalMap
> structure.
> 
> Note that the connection to the CRL is removed for now and will be
> re-added by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |   3 -
>  hw/arm/xlnx-versal-virt.c    |  54 -------------
>  hw/arm/xlnx-versal.c         | 151 +++++++++++++++++++++++++----------
>  3 files changed, 108 insertions(+), 100 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 4a7a2d85aac..1fcc2b623da 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -16,11 +16,10 @@
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/dma/xlnx-zdma.h"
> -#include "hw/net/cadence_gem.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/nvram/xlnx-bbram.h"
> @@ -76,12 +75,10 @@ struct Versal {
>  
>      struct {
>          MemoryRegion mr_ocm;
>  
>          struct {
> -            CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
> -            OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS];
>              XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
>              VersalUsb2 usb;
>          } iou;
>  
>          /* Real-time Processing Unit.  */
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 99ce84d5a46..09f87dc76dd 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -36,11 +36,10 @@ struct VersalVirt {
>  
>      void *fdt;
>      int fdt_size;
>      struct {
>          uint32_t gic;
> -        uint32_t ethernet_phy[2];
>          uint32_t clk_125Mhz;
>          uint32_t clk_25Mhz;
>          uint32_t usb;
>          uint32_t dwc;
>      } phandle;
> @@ -55,23 +54,19 @@ struct VersalVirt {
>  };
>  
>  static void fdt_create(VersalVirt *s)
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(s);
> -    int i;
>  
>      s->fdt = create_device_tree(&s->fdt_size);
>      if (!s->fdt) {
>          error_report("create_device_tree() failed");
>          exit(1);
>      }
>  
>      /* Allocate all phandles.  */
>      s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
> -    for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
> -        s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
> -    }
>      s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
>  
>      s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
> @@ -207,58 +202,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
>      qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
>      qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
>      g_free(name);
>  }
>  
> -static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
> -                                     uint32_t phandle)
> -{
> -    char *name = g_strdup_printf("%s/fixed-link", gemname);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -    qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
> -    qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
> -    qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
> -    g_free(name);
> -}
> -
> -static void fdt_add_gem_nodes(VersalVirt *s)
> -{
> -    uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
> -    unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
> -    const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
> -    const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
> -    int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> -        char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
> -        qemu_fdt_add_subnode(s->fdt, name);
> -
> -        fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
> -        qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
> -        qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
> -                              s->phandle.ethernet_phy[i]);
> -        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
> -                               s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
> -        qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> -                               GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                     2, addrs[i], 2, 0x1000);
> -        qemu_fdt_setprop(s->fdt, name, "compatible",
> -                         compat_gem, sizeof(compat_gem));
> -        qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
> -        qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
> -        g_free(name);
> -    }
> -}
> -
>  static void fdt_add_zdma_nodes(VersalVirt *s)
>  {
>      const char clocknames[] = "clk_main\0clk_apb";
>      const char compat[] = "xlnx,zynqmp-dma-1.0";
>      int i;
> @@ -607,11 +554,10 @@ static void versal_virt_init(MachineState *machine)
>                                   &error_abort);
>      }
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
> -    fdt_add_gem_nodes(s);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_zdma_nodes(s);
>      fdt_add_usb_xhci_nodes(s);
>      fdt_add_rtc_node(s);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index b963a05935b..062f9a91a6c 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -27,10 +27,11 @@
>  #include "system/device_tree.h"
>  #include "hw/arm/fdt.h"
>  #include "hw/char/pl011.h"
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/sd/sdhci.h"
> +#include "hw/net/cadence_gem.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -49,10 +50,18 @@ typedef struct VersalMap {
>      VersalSimplePeriphMap canfd[4];
>      size_t num_canfd;
>  
>      VersalSimplePeriphMap sdhci[2];
>      size_t num_sdhci;
> +
> +    struct VersalGemMap {
> +        VersalSimplePeriphMap map;
> +        size_t num_prio_queue;
> +        const char *phy_mode;
> +        const uint32_t speed;
> +    } gem[3];
> +    size_t num_gem;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -63,10 +72,14 @@ static const VersalMap VERSAL_MAP = {
>      .num_canfd = 2,
>  
>      .sdhci[0] = { 0xf1040000, 126 },
>      .sdhci[1] = { 0xf1050000, 128 },
>      .num_sdhci = 2,
> +
> +    .gem[0] = { { 0xff0c0000, 56 }, 2, "rgmii-id", 1000 },
> +    .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
> +    .num_gem = 2,
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -109,10 +122,22 @@ static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
>      }
>  
>      sysbus_connect_irq(sbd, sbd_idx, irq);
>  }
>  
> +static void versal_qdev_connect_gpio_out(Versal *s, DeviceState *dev,
> +                                         int dev_idx, int irq_idx)
> +{
> +    qemu_irq irq = versal_get_irq(s, irq_idx);
> +
> +    if (irq == NULL) {
> +        return;
> +    }
> +
> +    qdev_connect_gpio_out(dev, dev_idx, irq);
> +}
> +
>  static inline char *versal_fdt_add_subnode(Versal *s, const char *path,
>                                             uint64_t at, const char *compat,
>                                             size_t compat_sz)
>  {
>      char *p;
> @@ -138,10 +163,25 @@ static inline char *versal_fdt_add_simple_subnode(Versal *s, const char *path,
>  
>      qemu_fdt_setprop_sized_cells(s->cfg.fdt, p, "reg", 2, addr, 2, len);
>      return p;
>  }
>  
> +static inline DeviceState *create_or_gate(Versal *s, Object *parent,
> +                                          const char *name, uint16_t num_lines,
> +                                          int irq_idx)
> +{
> +    DeviceState *or;
> +
> +    or = qdev_new(TYPE_OR_IRQ);
> +    qdev_prop_set_uint16(or, "num-lines", num_lines);
> +    object_property_add_child(parent, name, OBJECT(or));
> +    qdev_realize_and_unref(or, NULL, &error_abort);
> +    versal_qdev_connect_gpio_out(s, or, 0, irq_idx);
> +
> +    return or;
> +}
> +
>  static void versal_create_apu_cpus(Versal *s)
>  {
>      int i;
>  
>      object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
> @@ -375,50 +415,80 @@ static void versal_create_usbs(Versal *s, qemu_irq *pic)
>  
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
>      memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
>  }
>  
> -static void versal_create_gems(Versal *s, qemu_irq *pic)
> +static void versal_create_gem(Versal *s,
> +                              const struct VersalGemMap *map)
>  {
> +    DeviceState *dev;
> +    MemoryRegion *mr;
> +    DeviceState *or;
>      int i;
> +    g_autofree char *node;
> +    g_autofree char *phy_node;
> +    int phy_phandle;
> +    const char compatible[] = "cdns,zynqmp-gem\0cdns,gem";
> +    const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
> +    g_autofree uint32_t *irq_prop;
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
> -        static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
> -        static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
> -        char *name = g_strdup_printf("gem%d", i);
> -        DeviceState *dev;
> -        MemoryRegion *mr;
> -        OrIRQState *or_irq;
> -
> -        object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
> -                                TYPE_CADENCE_GEM);
> -        or_irq = &s->lpd.iou.gem_irq_orgate[i];
> -        object_initialize_child(OBJECT(s), "gem-irq-orgate[*]",
> -                                or_irq, TYPE_OR_IRQ);
> -        dev = DEVICE(&s->lpd.iou.gem[i]);
> -        qemu_configure_nic_device(dev, true, NULL);
> -        object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
> -        object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
> -                                &error_abort);
> -        object_property_set_int(OBJECT(or_irq),
> -                                "num-lines", 2, &error_fatal);
> -        qdev_realize(DEVICE(or_irq), NULL, &error_fatal);
> -        qdev_connect_gpio_out(DEVICE(or_irq), 0, pic[irqs[i]]);
> -
> -        object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
> -                                 &error_abort);
> -        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> -
> -        mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> -        memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
> -
> -        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(or_irq), 0));
> -        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(or_irq), 1));
> -        g_free(name);
> +    dev = qdev_new(TYPE_CADENCE_GEM);
> +    object_property_add_child(OBJECT(s), "gem[*]", OBJECT(dev));
> +
> +    qemu_configure_nic_device(dev, true, NULL);
> +    object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
> +    object_property_set_int(OBJECT(dev), "num-priority-queues",
> +                            map->num_prio_queue, &error_abort);
> +
> +    object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
> +                             &error_abort);
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> +
> +    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> +    memory_region_add_subregion(&s->mr_ps, map->map.addr, mr);
> +
> +    /*
> +     * The GEM controller exposes one IRQ line per priority queue. In Versal
> +     * family devices, those are OR'ed together.
> +     */
> +    or = create_or_gate(s, OBJECT(dev), "irq-orgate",
> +                        map->num_prio_queue, map->map.irq);
> +
> +    for (i = 0; i < map->num_prio_queue; i++) {
> +        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, qdev_get_gpio_in(or, i));
> +    }
> +
> +    node = versal_fdt_add_simple_subnode(s, "/ethernet", map->map.addr, 0x1000,
> +                                         compatible, sizeof(compatible));
> +    phy_node = g_strdup_printf("%s/fixed-link", node);
> +    phy_phandle = qemu_fdt_alloc_phandle(s->cfg.fdt);
> +
> +    /* Fixed link PHY node */
> +    qemu_fdt_add_subnode(s->cfg.fdt, phy_node);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, phy_node, "phandle", phy_phandle);
> +    qemu_fdt_setprop(s->cfg.fdt, phy_node, "full-duplex", NULL, 0);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, phy_node, "speed", map->speed);
> +
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "phy-mode", map->phy_mode);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "phy-handle", phy_phandle);
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                           s->phandle.clk_25mhz, s->phandle.clk_25mhz,
> +                           s->phandle.clk_125mhz, s->phandle.clk_125mhz);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
> +                     clocknames, sizeof(clocknames));
> +
> +    irq_prop = g_new(uint32_t, map->num_prio_queue * 3);
> +    for (i = 0; i < map->num_prio_queue; i++) {
> +        irq_prop[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
> +        irq_prop[3 * i + 1] = cpu_to_be32(map->map.irq);
> +        irq_prop[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>      }
> +    qemu_fdt_setprop(s->cfg.fdt, node, "interrupts", irq_prop,
> +                     sizeof(uint32_t) * map->num_prio_queue * 3);
>  }
>  
> +
>  static void versal_create_admas(Versal *s, qemu_irq *pic)
>  {
>      int i;
>  
>      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
> @@ -900,18 +970,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
>          object_property_set_link(OBJECT(&s->lpd.crl),
>                                   name, OBJECT(&s->lpd.rpu.cpu[i]),
>                                   &error_abort);
>      }
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
> -        g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
> -
> -        object_property_set_link(OBJECT(&s->lpd.crl),
> -                                 name, OBJECT(&s->lpd.iou.gem[i]),
> -                                 &error_abort);
> -    }
> -
>      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
>          g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
>  
>          object_property_set_link(OBJECT(&s->lpd.crl),
>                                   name, OBJECT(&s->lpd.iou.adma[i]),
> @@ -1095,12 +1157,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_sdhci; i++) {
>          versal_create_sdhci(s, &map->sdhci[i]);
>      }
>  
> +    for (i = 0; i < map->num_gem; i++) {
> +        versal_create_gem(s, &map->gem[i]);
> +    }
> +
>      versal_create_usbs(s, pic);
> -    versal_create_gems(s, pic);
>      versal_create_admas(s, pic);
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_xrams(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 08/48] hw/arm/xlnx-versal: adma: refactor creation
  2025-07-16  9:53 ` [PATCH 08/48] hw/arm/xlnx-versal: adma: " Luc Michel
@ 2025-07-28 21:02   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 21:02 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:50AM +0200, Luc Michel wrote:
> Refactor the ADMA creation using the VersalMap structure.
> 
> Note that the connection to the CRL is removed for now and will be
> re-added by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  2 -
>  hw/arm/xlnx-versal-virt.c    | 28 --------------
>  hw/arm/xlnx-versal.c         | 72 ++++++++++++++++++++++++------------
>  3 files changed, 48 insertions(+), 54 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 1fcc2b623da..4eeea98ff34 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -15,11 +15,10 @@
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
> -#include "hw/dma/xlnx-zdma.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/nvram/xlnx-bbram.h"
> @@ -75,11 +74,10 @@ struct Versal {
>  
>      struct {
>          MemoryRegion mr_ocm;
>  
>          struct {
> -            XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
>              VersalUsb2 usb;
>          } iou;
>  
>          /* Real-time Processing Unit.  */
>          struct {
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 09f87dc76dd..1922a90019c 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -202,37 +202,10 @@ static void fdt_add_usb_xhci_nodes(VersalVirt *s)
>      qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
>      qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
>      g_free(name);
>  }
>  
> -static void fdt_add_zdma_nodes(VersalVirt *s)
> -{
> -    const char clocknames[] = "clk_main\0clk_apb";
> -    const char compat[] = "xlnx,zynqmp-dma-1.0";
> -    int i;
> -
> -    for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
> -        uint64_t addr = MM_ADMA_CH0 + MM_ADMA_CH0_SIZE * i;
> -        char *name = g_strdup_printf("/dma@%" PRIx64, addr);
> -
> -        qemu_fdt_add_subnode(s->fdt, name);
> -
> -        qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
> -        qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> -        qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                     2, addr, 2, 0x1000);
> -        qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -        g_free(name);
> -    }
> -}
> -
>  static void fdt_add_rtc_node(VersalVirt *s)
>  {
>      const char compat[] = "xlnx,zynqmp-rtc";
>      const char interrupt_names[] = "alarm\0sec";
>      char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
> @@ -556,11 +529,10 @@ static void versal_virt_init(MachineState *machine)
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
> -    fdt_add_zdma_nodes(s);
>      fdt_add_usb_xhci_nodes(s);
>      fdt_add_rtc_node(s);
>      fdt_add_bbram_node(s);
>      fdt_add_efuse_ctrl_node(s);
>      fdt_add_efuse_cache_node(s);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 062f9a91a6c..97cd991be10 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -28,10 +28,11 @@
>  #include "hw/arm/fdt.h"
>  #include "hw/char/pl011.h"
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/sd/sdhci.h"
>  #include "hw/net/cadence_gem.h"
> +#include "hw/dma/xlnx-zdma.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -58,10 +59,20 @@ typedef struct VersalMap {
>          size_t num_prio_queue;
>          const char *phy_mode;
>          const uint32_t speed;
>      } gem[3];
>      size_t num_gem;
> +
> +    struct VersalZDMAMap {
> +        const char *name;
> +        VersalSimplePeriphMap map;
> +        size_t num_chan;
> +        uint64_t chan_stride;
> +        int irq_stride;
> +    } zdma[2];
> +    size_t num_zdma;
> +
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -76,10 +87,13 @@ static const VersalMap VERSAL_MAP = {
>      .num_sdhci = 2,
>  
>      .gem[0] = { { 0xff0c0000, 56 }, 2, "rgmii-id", 1000 },
>      .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
>      .num_gem = 2,
> +
> +    .zdma[0] = { "adma", { 0xffa80000, 60 }, 8, 0x10000, 1 },
> +    .num_zdma = 1,
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -484,34 +498,49 @@ static void versal_create_gem(Versal *s,
>      }
>      qemu_fdt_setprop(s->cfg.fdt, node, "interrupts", irq_prop,
>                       sizeof(uint32_t) * map->num_prio_queue * 3);
>  }
>  
> -
> -static void versal_create_admas(Versal *s, qemu_irq *pic)
> +static void versal_create_zdma(Versal *s,
> +                               const struct VersalZDMAMap *map)
>  {
> -    int i;
> +    DeviceState *dev;
> +    MemoryRegion *mr;
> +    g_autofree char *name;
> +    const char compatible[] = "xlnx,zynqmp-dma-1.0";
> +    const char clocknames[] = "clk_main\0clk_apb";
> +    size_t i;
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
> -        char *name = g_strdup_printf("adma%d", i);
> -        DeviceState *dev;
> -        MemoryRegion *mr;
> +    name = g_strdup_printf("%s[*]", map->name);
>  
> -        object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i],
> -                                TYPE_XLNX_ZDMA);
> -        dev = DEVICE(&s->lpd.iou.adma[i]);
> +    for (i = 0; i < map->num_chan; i++) {
> +        uint64_t addr = map->map.addr + map->chan_stride * i;
> +        int irq = map->map.irq + map->irq_stride * i;
> +        g_autofree char *node;
> +
> +        dev = qdev_new(TYPE_XLNX_ZDMA);
> +        object_property_add_child(OBJECT(s), name, OBJECT(dev));
>          object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
>          object_property_set_link(OBJECT(dev), "dma",
>                                   OBJECT(get_system_memory()), &error_fatal);
> -        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>  
>          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> -        memory_region_add_subregion(&s->mr_ps,
> -                                    MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
> +        memory_region_add_subregion(&s->mr_ps, addr, mr);
>  
> -        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
> -        g_free(name);
> +        versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, irq);
> +
> +        node = versal_fdt_add_simple_subnode(s, "/dma", addr, 0x1000,
> +                                             compatible, sizeof(compatible));
> +        qemu_fdt_setprop_cell(s->cfg.fdt, node, "xlnx,bus-width", 64);
> +        qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                               s->phandle.clk_25mhz, s->phandle.clk_25mhz);
> +        qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
> +                         clocknames, sizeof(clocknames));
> +        qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                               GIC_FDT_IRQ_TYPE_SPI, irq,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>      }
>  }
>  
>  #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
>  static void versal_create_sdhci(Versal *s,
> @@ -970,18 +999,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
>          object_property_set_link(OBJECT(&s->lpd.crl),
>                                   name, OBJECT(&s->lpd.rpu.cpu[i]),
>                                   &error_abort);
>      }
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
> -        g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
> -
> -        object_property_set_link(OBJECT(&s->lpd.crl),
> -                                 name, OBJECT(&s->lpd.iou.adma[i]),
> -                                 &error_abort);
> -    }
> -
>      object_property_set_link(OBJECT(&s->lpd.crl),
>                               "usb", OBJECT(&s->lpd.iou.usb),
>                               &error_abort);
>  
>      sysbus_realize(sbd, &error_fatal);
> @@ -1161,12 +1182,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_gem; i++) {
>          versal_create_gem(s, &map->gem[i]);
>      }
>  
> +    for (i = 0; i < map->num_zdma; i++) {
> +        versal_create_zdma(s, &map->zdma[i]);
> +    }
> +
>      versal_create_usbs(s, pic);
> -    versal_create_admas(s, pic);
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_xrams(s, pic);
>      versal_create_bbram(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 09/48] hw/arm/xlnx-versal: xram: refactor creation
  2025-07-16  9:53 ` [PATCH 09/48] hw/arm/xlnx-versal: xram: " Luc Michel
@ 2025-07-28 21:05   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 21:05 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:51AM +0200, Luc Michel wrote:
> Refactor the XRAM devices creation using the VersalMap structure.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  6 ----
>  hw/arm/xlnx-versal.c         | 59 +++++++++++++++++++++---------------
>  2 files changed, 35 insertions(+), 30 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 4eeea98ff34..71c3314b8b4 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -18,11 +18,10 @@
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
> -#include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/nvram/xlnx-bbram.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
> @@ -86,15 +85,10 @@ struct Versal {
>  
>              CPUClusterState cluster;
>              ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
>          } rpu;
>  
> -        struct {
> -            OrIRQState irq_orgate;
> -            XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
> -        } xram;
> -
>          XlnxVersalCRL crl;
>      } lpd;
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 97cd991be10..6c5eb6d3fd5 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -29,10 +29,11 @@
>  #include "hw/char/pl011.h"
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/sd/sdhci.h"
>  #include "hw/net/cadence_gem.h"
>  #include "hw/dma/xlnx-zdma.h"
> +#include "hw/misc/xlnx-versal-xramc.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -69,10 +70,18 @@ typedef struct VersalMap {
>          uint64_t chan_stride;
>          int irq_stride;
>      } zdma[2];
>      size_t num_zdma;
>  
> +    struct VersalXramMap {
> +        uint64_t mem;
> +        uint64_t mem_stride;
> +        uint64_t ctrl;
> +        uint64_t ctrl_stride;
> +        int irq;
> +        size_t num;
> +    } xram;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -90,10 +99,17 @@ static const VersalMap VERSAL_MAP = {
>      .gem[1] = { { 0xff0d0000, 58 }, 2, "rgmii-id", 1000 },
>      .num_gem = 2,
>  
>      .zdma[0] = { "adma", { 0xffa80000, 60 }, 8, 0x10000, 1 },
>      .num_zdma = 1,
> +
> +    .xram = {
> +        .num = 4,
> +        .mem = 0xfe800000, .mem_stride = 1 * MiB,
> +        .ctrl = 0xff8e0000, .ctrl_stride = 0x10000,
> +        .irq = 79,
> +    },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -633,41 +649,35 @@ static void versal_create_trng(Versal *s, qemu_irq *pic)
>      mr = sysbus_mmio_get_region(sbd, 0);
>      memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr);
>      sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
>  }
>  
> -static void versal_create_xrams(Versal *s, qemu_irq *pic)
> +static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
>  {
> -    int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
> -    DeviceState *orgate;
> -    int i;
> +    SysBusDevice *sbd;
> +    MemoryRegion *mr;
> +    DeviceState *or;
> +    size_t i;
>  
> -    /* XRAM IRQs get ORed into a single line.  */
> -    object_initialize_child(OBJECT(s), "xram-irq-orgate",
> -                            &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
> -    orgate = DEVICE(&s->lpd.xram.irq_orgate);
> -    object_property_set_int(OBJECT(orgate),
> -                            "num-lines", nr_xrams, &error_fatal);
> -    qdev_realize(orgate, NULL, &error_fatal);
> -    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
> +    or = create_or_gate(s, OBJECT(s), "xram-orgate", map->num, map->irq);
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
> -        SysBusDevice *sbd;
> -        MemoryRegion *mr;
> +    for (i = 0; i < map->num; i++) {
> +        hwaddr ctrl, mem;
>  
> -        object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
> -                                TYPE_XLNX_XRAM_CTRL);
> -        sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
> -        sysbus_realize(sbd, &error_fatal);
> +        sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_XRAM_CTRL));
> +        object_property_add_child(OBJECT(s), "xram[*]", OBJECT(sbd));
> +        sysbus_realize_and_unref(sbd, &error_fatal);
> +
> +        ctrl = map->ctrl + map->ctrl_stride * i;
> +        mem = map->mem + map->mem_stride * i;
>  
>          mr = sysbus_mmio_get_region(sbd, 0);
> -        memory_region_add_subregion(&s->mr_ps,
> -                                    MM_XRAMC + i * MM_XRAMC_SIZE, mr);
> +        memory_region_add_subregion(&s->mr_ps, ctrl, mr);
>          mr = sysbus_mmio_get_region(sbd, 1);
> -        memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
> +        memory_region_add_subregion(&s->mr_ps, mem, mr);
>  
> -        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
> +        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(or, i));
>      }
>  }
>  
>  static void versal_create_bbram(Versal *s, qemu_irq *pic)
>  {
> @@ -1186,15 +1196,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_zdma; i++) {
>          versal_create_zdma(s, &map->zdma[i]);
>      }
>  
> +    versal_create_xrams(s, &map->xram);
> +
>      versal_create_usbs(s, pic);
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
> -    versal_create_xrams(s, pic);
>      versal_create_bbram(s, pic);
>      versal_create_efuse(s, pic);
>      versal_create_pmc_iou_slcr(s, pic);
>      versal_create_ospi(s, pic);
>      versal_create_crl(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 10/48] hw/arm/xlnx-versal: usb: refactor creation
  2025-07-16  9:53 ` [PATCH 10/48] hw/arm/xlnx-versal: usb: " Luc Michel
@ 2025-07-28 21:13   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-28 21:13 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:52AM +0200, Luc Michel wrote:
> Refactor the USB controller creation using the VersalMap structure.
> 
> Note that the connection to the CRL is removed for now and will be
> re-added by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  5 ---
>  hw/arm/xlnx-versal-virt.c    | 56 +--------------------------
>  hw/arm/xlnx-versal.c         | 74 +++++++++++++++++++++++++++++-------
>  3 files changed, 62 insertions(+), 73 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 71c3314b8b4..5d4b30f0ff9 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -17,11 +17,10 @@
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
> -#include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/nvram/xlnx-bbram.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
> @@ -72,14 +71,10 @@ struct Versal {
>      } noc;
>  
>      struct {
>          MemoryRegion mr_ocm;
>  
> -        struct {
> -            VersalUsb2 usb;
> -        } iou;
> -
>          /* Real-time Processing Unit.  */
>          struct {
>              MemoryRegion mr;
>              MemoryRegion mr_ps_alias;
>  
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 1922a90019c..36341b825eb 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -12,10 +12,11 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "system/device_tree.h"
> +#include "system/address-spaces.h"
>  #include "hw/block/flash.h"
>  #include "hw/boards.h"
>  #include "hw/sysbus.h"
>  #include "hw/arm/fdt.h"
>  #include "hw/qdev-properties.h"
> @@ -38,12 +39,10 @@ struct VersalVirt {
>      int fdt_size;
>      struct {
>          uint32_t gic;
>          uint32_t clk_125Mhz;
>          uint32_t clk_25Mhz;
> -        uint32_t usb;
> -        uint32_t dwc;
>      } phandle;
>      struct arm_boot_info binfo;
>  
>      CanBusState **canbus;
>  
> @@ -66,12 +65,10 @@ static void fdt_create(VersalVirt *s)
>      /* Allocate all phandles.  */
>      s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
>  
> -    s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
> -    s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
>      /* Create /chosen node for load_dtb.  */
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
>      qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
> @@ -152,60 +149,10 @@ static void fdt_add_timer_nodes(VersalVirt *s)
>              GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
>      qemu_fdt_setprop(s->fdt, "/timer", "compatible",
>                       compat, sizeof(compat));
>  }
>  
> -static void fdt_add_usb_xhci_nodes(VersalVirt *s)
> -{
> -    const char clocknames[] = "bus_clk\0ref_clk";
> -    const char irq_name[] = "dwc_usb3";
> -    const char compatVersalDWC3[] = "xlnx,versal-dwc3";
> -    const char compatDWC3[] = "snps,dwc3";
> -    char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -    qemu_fdt_setprop(s->fdt, name, "compatible",
> -                         compatVersalDWC3, sizeof(compatVersalDWC3));
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_USB2_CTRL_REGS,
> -                                 2, MM_USB2_CTRL_REGS_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "clock-names",
> -                         clocknames, sizeof(clocknames));
> -    qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> -                               s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
> -    qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
> -    qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
> -    qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
> -    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
> -    g_free(name);
> -
> -    name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
> -                           MM_USB2_CTRL_REGS, MM_USB_0);
> -    qemu_fdt_add_subnode(s->fdt, name);
> -    qemu_fdt_setprop(s->fdt, name, "compatible",
> -                     compatDWC3, sizeof(compatDWC3));
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_USB_0, 2, MM_USB_0_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> -                     irq_name, sizeof(irq_name));
> -    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
> -                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -    qemu_fdt_setprop_cell(s->fdt, name,
> -                          "snps,quirk-frame-length-adjustment", 0x20);
> -    qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
> -    qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
> -    qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
> -    qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
> -    qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
> -    qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
> -    qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
> -    qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
> -    qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
> -    g_free(name);
> -}
> -
>  static void fdt_add_rtc_node(VersalVirt *s)
>  {
>      const char compat[] = "xlnx,zynqmp-rtc";
>      const char interrupt_names[] = "alarm\0sec";
>      char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
> @@ -529,11 +476,10 @@ static void versal_virt_init(MachineState *machine)
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
> -    fdt_add_usb_xhci_nodes(s);
>      fdt_add_rtc_node(s);
>      fdt_add_bbram_node(s);
>      fdt_add_efuse_ctrl_node(s);
>      fdt_add_efuse_cache_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 6c5eb6d3fd5..4e4df0851e8 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -30,10 +30,11 @@
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/sd/sdhci.h"
>  #include "hw/net/cadence_gem.h"
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
> +#include "hw/usb/xlnx-usb-subsystem.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -78,10 +79,17 @@ typedef struct VersalMap {
>          uint64_t ctrl;
>          uint64_t ctrl_stride;
>          int irq;
>          size_t num;
>      } xram;
> +
> +    struct VersalUsbMap {
> +        uint64_t xhci;
> +        uint64_t ctrl;
> +        int irq;
> +    } usb[2];
> +    size_t num_usb;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -106,10 +114,13 @@ static const VersalMap VERSAL_MAP = {
>          .num = 4,
>          .mem = 0xfe800000, .mem_stride = 1 * MiB,
>          .ctrl = 0xff8e0000, .ctrl_stride = 0x10000,
>          .irq = 79,
>      },
> +
> +    .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
> +    .num_usb = 1,
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -420,33 +431,71 @@ static void versal_create_canfd(Versal *s, const VersalSimplePeriphMap *map,
>      qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
>                             GIC_FDT_IRQ_TYPE_SPI, map->irq,
>                             GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>  }
>  
> -static void versal_create_usbs(Versal *s, qemu_irq *pic)
> +static void versal_create_usb(Versal *s,
> +                              const struct VersalUsbMap *map)
>  {
>      DeviceState *dev;
>      MemoryRegion *mr;
> +    g_autofree char *node, *subnode;
> +    const char clocknames[] = "bus_clk\0ref_clk";
> +    const char irq_name[] = "dwc_usb3";
> +    const char compat_versal_dwc3[] = "xlnx,versal-dwc3";
> +    const char compat_dwc3[] = "snps,dwc3";
>  
> -    object_initialize_child(OBJECT(s), "usb2", &s->lpd.iou.usb,
> -                            TYPE_XILINX_VERSAL_USB2);
> -    dev = DEVICE(&s->lpd.iou.usb);
> +    dev = qdev_new(TYPE_XILINX_VERSAL_USB2);
> +    object_property_add_child(OBJECT(s), "usb[*]", OBJECT(dev));
>  
>      object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
>                               &error_abort);
>      qdev_prop_set_uint32(dev, "intrs", 1);
>      qdev_prop_set_uint32(dev, "slots", 2);
>  
> -    sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>  
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> -    memory_region_add_subregion(&s->mr_ps, MM_USB_0, mr);
> +    memory_region_add_subregion(&s->mr_ps, map->xhci, mr);
>  
> -    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_USB0_IRQ_0]);
> +    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->irq);
>  
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> -    memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
> +    memory_region_add_subregion(&s->mr_ps, map->ctrl, mr);
> +
> +    node = versal_fdt_add_simple_subnode(s, "/usb", map->ctrl, 0x10000,
> +                                         compat_versal_dwc3,
> +                                         sizeof(compat_versal_dwc3));
> +    qemu_fdt_setprop(s->cfg.fdt, node, "clock-names",
> +                         clocknames, sizeof(clocknames));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "clocks",
> +                               s->phandle.clk_25mhz, s->phandle.clk_125mhz);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "ranges", NULL, 0);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#address-cells", 2);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#size-cells", 2);
> +
> +    subnode = g_strdup_printf("/%s/dwc3", node);
> +    g_free(node);
> +
> +    node = versal_fdt_add_simple_subnode(s, subnode, map->xhci, 0x10000,
> +                                         compat_dwc3,
> +                                         sizeof(compat_dwc3));
> +    qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-names",
> +                     irq_name, sizeof(irq_name));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                               GIC_FDT_IRQ_TYPE_SPI, map->irq,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node,
> +                          "snps,quirk-frame-length-adjustment", 0x20);
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "#stream-id-cells", 1);
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "dr_mode", "host");
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "phy-names", "usb3-phy");
> +    qemu_fdt_setprop(s->cfg.fdt, node, "snps,dis_u2_susphy_quirk", NULL, 0);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "snps,dis_u3_susphy_quirk", NULL, 0);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "snps,refclk_fladj", NULL, 0);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "snps,mask_phy_reset", NULL, 0);
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "maximum-speed", "high-speed");
>  }
>  
>  static void versal_create_gem(Versal *s,
>                                const struct VersalGemMap *map)
>  {
> @@ -1009,14 +1058,10 @@ static void versal_create_crl(Versal *s, qemu_irq *pic)
>          object_property_set_link(OBJECT(&s->lpd.crl),
>                                   name, OBJECT(&s->lpd.rpu.cpu[i]),
>                                   &error_abort);
>      }
>  
> -    object_property_set_link(OBJECT(&s->lpd.crl),
> -                             "usb", OBJECT(&s->lpd.iou.usb),
> -                             &error_abort);
> -
>      sysbus_realize(sbd, &error_fatal);
>      memory_region_add_subregion(&s->mr_ps, MM_CRL,
>                                  sysbus_mmio_get_region(sbd, 0));
>      sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
>  }
> @@ -1198,11 +1243,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
>          versal_create_zdma(s, &map->zdma[i]);
>      }
>  
>      versal_create_xrams(s, &map->xram);
>  
> -    versal_create_usbs(s, pic);
> +    for (i = 0; i < map->num_usb; i++) {
> +        versal_create_usb(s, &map->usb[i]);
> +    }
> +
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_bbram(s, pic);
>      versal_create_efuse(s, pic);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 11/48] hw/arm/xlnx-versal: efuse: refactor creation
  2025-07-16  9:53 ` [PATCH 11/48] hw/arm/xlnx-versal: efuse: " Luc Michel
@ 2025-07-29 13:25   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 13:25 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:53AM +0200, Luc Michel wrote:
> Refactore the eFuse devices creation using the VersalMap structure.
> 
> Note that the corresponding FDT nodes are removed. They do not
> correspond to any real node in standard Versal DTBs. No matching drivers
> exist for them.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  5 +--
>  hw/arm/xlnx-versal-virt.c    | 43 ++------------------
>  hw/arm/xlnx-versal.c         | 78 +++++++++++++++++++++++-------------
>  3 files changed, 54 insertions(+), 72 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 5d4b30f0ff9..79ca9b13321 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -18,11 +18,10 @@
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/nvram/xlnx-bbram.h"
> -#include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/misc/xlnx-versal-trng.h"
> @@ -100,13 +99,10 @@ struct Versal {
>          } iou;
>  
>          XlnxZynqMPRTC rtc;
>          XlnxVersalTRng trng;
>          XlnxBBRam bbram;
> -        XlnxEFuse efuse;
> -        XlnxVersalEFuseCtrl efuse_ctrl;
> -        XlnxVersalEFuseCache efuse_cache;
>          XlnxVersalCFUAPB cfu_apb;
>          XlnxVersalCFUFDRO cfu_fdro;
>          XlnxVersalCFUSFR cfu_sfr;
>          XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
>          XlnxVersalCFrameBcastReg cframe_bcast;
> @@ -137,10 +133,11 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>      g_assert(!qdev_is_realized(DEVICE(s)));
>      s->cfg.fdt = fdt;
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
> +void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
>  
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 36341b825eb..d3c84d1955a 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -190,45 +190,10 @@ static void fdt_add_bbram_node(VersalVirt *s)
>                                   2, MM_PMC_BBRAM_CTRL_SIZE);
>      qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
>      g_free(name);
>  }
>  
> -static void fdt_add_efuse_ctrl_node(VersalVirt *s)
> -{
> -    const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
> -    const char interrupt_names[] = "pmc_efuse";
> -    char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -
> -    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
> -                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> -                     interrupt_names, sizeof(interrupt_names));
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_PMC_EFUSE_CTRL,
> -                                 2, MM_PMC_EFUSE_CTRL_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -    g_free(name);
> -}
> -
> -static void fdt_add_efuse_cache_node(VersalVirt *s)
> -{
> -    const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
> -    char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
> -                                 MM_PMC_EFUSE_CACHE);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_PMC_EFUSE_CACHE,
> -                                 2, MM_PMC_EFUSE_CACHE_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -    g_free(name);
> -}
> -
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
>      char **node_path;
>      int n = 0;
> @@ -391,19 +356,19 @@ static void bbram_attach_drive(XlnxBBRam *dev)
>      if (blk) {
>          qdev_prop_set_drive(DEVICE(dev), "drive", blk);
>      }
>  }
>  
> -static void efuse_attach_drive(XlnxEFuse *dev)
> +static void efuse_attach_drive(VersalVirt *s)
>  {
>      DriveInfo *dinfo;
>      BlockBackend *blk;
>  
>      dinfo = drive_get_by_index(IF_PFLASH, 1);
>      blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
>      if (blk) {
> -        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
> +        versal_efuse_attach_drive(&s->soc, blk);
>      }
>  }
>  
>  static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
>  {
> @@ -478,12 +443,10 @@ static void versal_virt_init(MachineState *machine)
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_rtc_node(s);
>      fdt_add_bbram_node(s);
> -    fdt_add_efuse_ctrl_node(s);
> -    fdt_add_efuse_cache_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
>      fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
>      fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
>  
>      sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
> @@ -496,11 +459,11 @@ static void versal_virt_init(MachineState *machine)
>  
>      /* Attach bbram backend, if given */
>      bbram_attach_drive(&s->soc.pmc.bbram);
>  
>      /* Attach efuse backend, if given */
> -    efuse_attach_drive(&s->soc.pmc.efuse);
> +    efuse_attach_drive(s);
>  
>      /* Plug SD cards */
>      for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
>          sd_plug_card(s, i, drive_get(IF_SD, 0, i));
>      }
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 4e4df0851e8..ed202b0fcda 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -31,10 +31,11 @@
>  #include "hw/sd/sdhci.h"
>  #include "hw/net/cadence_gem.h"
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
> +#include "hw/nvram/xlnx-versal-efuse.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -86,10 +87,16 @@ typedef struct VersalMap {
>          uint64_t xhci;
>          uint64_t ctrl;
>          int irq;
>      } usb[2];
>      size_t num_usb;
> +
> +    struct VersalEfuseMap {
> +        uint64_t ctrl;
> +        uint64_t cache;
> +        int irq;
> +    } efuse;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -117,10 +124,12 @@ static const VersalMap VERSAL_MAP = {
>          .irq = 79,
>      },
>  
>      .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
>      .num_usb = 1,
> +
> +    .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -744,46 +753,45 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic)
>                                  sysbus_mmio_get_region(sbd, 0));
>      sysbus_connect_irq(sbd, 0,
>                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1));
>  }
>  
> -static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base)
> +static void versal_create_efuse(Versal *s,
> +                                const struct VersalEfuseMap *map)
>  {
> -    SysBusDevice *part = SYS_BUS_DEVICE(dev);
> +    DeviceState *bits;
> +    DeviceState *ctrl;
> +    DeviceState *cache;
>  
> -    object_property_set_link(OBJECT(part), "efuse",
> -                             OBJECT(&s->pmc.efuse), &error_abort);
> +    ctrl = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CTRL);
> +    cache = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CACHE);
> +    bits = qdev_new(TYPE_XLNX_EFUSE);
>  
> -    sysbus_realize(part, &error_abort);
> -    memory_region_add_subregion(&s->mr_ps, base,
> -                                sysbus_mmio_get_region(part, 0));
> -}
> +    qdev_prop_set_uint32(bits, "efuse-nr", 3);
> +    qdev_prop_set_uint32(bits, "efuse-size", 8192);
>  
> -static void versal_create_efuse(Versal *s, qemu_irq *pic)
> -{
> -    Object *bits = OBJECT(&s->pmc.efuse);
> -    Object *ctrl = OBJECT(&s->pmc.efuse_ctrl);
> -    Object *cache = OBJECT(&s->pmc.efuse_cache);
> +    object_property_add_child(OBJECT(s), "efuse", OBJECT(bits));
> +    qdev_realize_and_unref(bits, NULL, &error_abort);
>  
> -    object_initialize_child(OBJECT(s), "efuse-ctrl", &s->pmc.efuse_ctrl,
> -                            TYPE_XLNX_VERSAL_EFUSE_CTRL);
> +    object_property_set_link(OBJECT(ctrl), "efuse", OBJECT(bits), &error_abort);
>  
> -    object_initialize_child(OBJECT(s), "efuse-cache", &s->pmc.efuse_cache,
> -                            TYPE_XLNX_VERSAL_EFUSE_CACHE);
> +    object_property_set_link(OBJECT(cache), "efuse", OBJECT(bits),
> +                             &error_abort);
>  
> -    object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
> -                                       sizeof(s->pmc.efuse),
> -                                       TYPE_XLNX_EFUSE, &error_abort,
> -                                       "efuse-nr", "3",
> -                                       "efuse-size", "8192",
> -                                       NULL);
> +    object_property_add_child(OBJECT(s), "efuse-cache", OBJECT(cache));
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(cache), &error_abort);
>  
> -    qdev_realize(DEVICE(bits), NULL, &error_abort);
> -    versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL);
> -    versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE);
> +    object_property_add_child(OBJECT(s), "efuse-ctrl", OBJECT(ctrl));
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(ctrl), &error_abort);
>  
> -    sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]);
> +    memory_region_add_subregion(&s->mr_ps, map->ctrl,
> +                                sysbus_mmio_get_region(SYS_BUS_DEVICE(ctrl),
> +                                                       0));
> +    memory_region_add_subregion(&s->mr_ps, map->cache,
> +                                sysbus_mmio_get_region(SYS_BUS_DEVICE(cache),
> +                                                       0));
> +    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(ctrl), 0, map->irq);
>  }
>  
>  static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
>  {
>      SysBusDevice *sbd;
> @@ -1247,15 +1255,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      for (i = 0; i < map->num_usb; i++) {
>          versal_create_usb(s, &map->usb[i]);
>      }
>  
> +    versal_create_efuse(s, &map->efuse);
> +
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_bbram(s, pic);
> -    versal_create_efuse(s, pic);
>      versal_create_pmc_iou_slcr(s, pic);
>      versal_create_ospi(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
> @@ -1286,10 +1295,23 @@ void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
>      qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
>      qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
>                             &error_fatal);
>  }
>  
> +void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
> +{
> +    DeviceState *efuse;
> +
> +    efuse = DEVICE(versal_get_child(s, "efuse"));
> +
> +    if (efuse == NULL) {
> +        return;
> +    }
> +
> +    qdev_prop_set_drive(efuse, "drive", blk);
> +}
> +
>  int versal_get_num_can(VersalVersion version)
>  {
>      const VersalMap *map = VERSION_TO_MAP[version];
>  
>      return map->num_canfd;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 12/48] hw/arm/xlnx-versal: ospi: refactor creation
  2025-07-16  9:53 ` [PATCH 12/48] hw/arm/xlnx-versal: ospi: " Luc Michel
@ 2025-07-29 13:34   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 13:34 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:54AM +0200, Luc Michel wrote:
> Refactor the OSPI controller creation using the VersalMap structure.
> 
> Note that the connection to the PMC IOU SLCR is removed for now and will
> be re-added by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  12 +--
>  hw/arm/xlnx-versal-virt.c    |  41 ++++------
>  hw/arm/xlnx-versal.c         | 142 ++++++++++++++++++++---------------
>  3 files changed, 98 insertions(+), 97 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 79ca9b13321..b7ef255d6fd 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -18,12 +18,10 @@
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/nvram/xlnx-bbram.h"
> -#include "hw/ssi/xlnx-versal-ospi.h"
> -#include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
> @@ -86,18 +84,10 @@ struct Versal {
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
>          struct {
>              XlnxVersalPmcIouSlcr slcr;
> -
> -            struct {
> -                XlnxVersalOspi ospi;
> -                XlnxCSUDMA dma_src;
> -                XlnxCSUDMA dma_dst;
> -                MemoryRegion linear_mr;
> -                OrIRQState irq_orgate;
> -            } ospi;
>          } iou;
>  
>          XlnxZynqMPRTC rtc;
>          XlnxVersalTRng trng;
>          XlnxBBRam bbram;
> @@ -134,10 +124,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>      s->cfg.fdt = fdt;
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
>  void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
> +void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
> +                              BlockBackend *blk);
>  
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index d3c84d1955a..43f3c3d0be9 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -46,12 +46,12 @@ struct VersalVirt {
>  
>      CanBusState **canbus;
>  
>      struct {
>          bool secure;
> +        char *ospi_model;
>      } cfg;
> -    char *ospi_model;
>  };
>  
>  static void fdt_create(VersalVirt *s)
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(s);
> @@ -379,19 +379,19 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
>  
>  static char *versal_get_ospi_model(Object *obj, Error **errp)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>  
> -    return g_strdup(s->ospi_model);
> +    return g_strdup(s->cfg.ospi_model);
>  }
>  
>  static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>  
> -    g_free(s->ospi_model);
> -    s->ospi_model = g_strdup(value);
> +    g_free(s->cfg.ospi_model);
> +    s->cfg.ospi_model = g_strdup(value);
>  }
>  
>  
>  static void versal_virt_init(MachineState *machine)
>  {
> @@ -480,42 +480,31 @@ static void versal_virt_init(MachineState *machine)
>          s->binfo.dtb_limit = 0x1000000;
>      }
>      arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
>  
>      for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
> -        BusState *spi_bus;
> -        DeviceState *flash_dev;
>          ObjectClass *flash_klass;
> -        qemu_irq cs_line;
>          DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
> +        BlockBackend *blk;
> +        const char *mdl;
>  
> -        spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
> -
> -        if (s->ospi_model) {
> -            flash_klass = object_class_by_name(s->ospi_model);
> +        if (s->cfg.ospi_model) {
> +            flash_klass = object_class_by_name(s->cfg.ospi_model);
>              if (!flash_klass ||
>                  object_class_is_abstract(flash_klass) ||
>                  !object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
>                  error_report("'%s' is either abstract or"
> -                       " not a subtype of m25p80", s->ospi_model);
> +                       " not a subtype of m25p80", s->cfg.ospi_model);
>                  exit(1);
>              }
> +            mdl = s->cfg.ospi_model;
> +        } else {
> +            mdl = "mt35xu01g";
>          }
>  
> -        flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
> -
> -        if (dinfo) {
> -            qdev_prop_set_drive_err(flash_dev, "drive",
> -                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
> -        }
> -        qdev_prop_set_uint8(flash_dev, "cs", i);
> -        qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
> -
> -        cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
> -
> -        sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
> -                           i + 1, cs_line);
> +        blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
> +        versal_ospi_create_flash(&s->soc, i, mdl, blk);
>      }
>  }
>  
>  static void versal_virt_machine_instance_init(Object *obj)
>  {
> @@ -540,11 +529,11 @@ static void versal_virt_machine_instance_init(Object *obj)
>  
>  static void versal_virt_machine_finalize(Object *obj)
>  {
>      VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>  
> -    g_free(s->ospi_model);
> +    g_free(s->cfg.ospi_model);
>      g_free(s->canbus);
>  }
>  
>  static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
>  {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index ed202b0fcda..58176fa11e5 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -32,10 +32,11 @@
>  #include "hw/net/cadence_gem.h"
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
> +#include "hw/ssi/xlnx-versal-ospi.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -93,10 +94,19 @@ typedef struct VersalMap {
>      struct VersalEfuseMap {
>          uint64_t ctrl;
>          uint64_t cache;
>          int irq;
>      } efuse;
> +
> +    struct VersalOspiMap {
> +        uint64_t ctrl;
> +        uint64_t dac;
> +        uint64_t dac_sz;
> +        uint64_t dma_src;
> +        uint64_t dma_dst;
> +        int irq;
> +    } ospi;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -126,10 +136,17 @@ static const VersalMap VERSAL_MAP = {
>  
>      .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
>      .num_usb = 1,
>  
>      .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
> +
> +    .ospi = {
> +        .ctrl = 0xf1010000,
> +        .dac = 0xc0000000, .dac_sz = 0x20000000,
> +        .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
> +        .irq = 124,
> +    },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -807,99 +824,78 @@ static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
>  
>      sysbus_connect_irq(sbd, 0,
>                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
>  }
>  
> -static void versal_create_ospi(Versal *s, qemu_irq *pic)
> +static DeviceState *versal_create_ospi(Versal *s,
> +                                       const struct VersalOspiMap *map)
>  {
>      SysBusDevice *sbd;
>      MemoryRegion *mr_dac;
> -    qemu_irq ospi_mux_sel;
> -    DeviceState *orgate;
> +    DeviceState *dev, *dma_dst, *dma_src, *orgate;
> +    MemoryRegion *linear_mr = g_new(MemoryRegion, 1);
>  
> -    memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s),
> -                       "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE);
> +    dev = qdev_new(TYPE_XILINX_VERSAL_OSPI);
> +    object_property_add_child(OBJECT(s), "ospi", OBJECT(dev));
>  
> -    object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi,
> -                            TYPE_XILINX_VERSAL_OSPI);
> +    memory_region_init(linear_mr, OBJECT(dev), "linear-mr", map->dac_sz);
>  
> -    mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1);
> -    memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac);
> +    mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> +    memory_region_add_subregion(linear_mr, 0x0, mr_dac);
>  
>      /* Create the OSPI destination DMA */
> -    object_initialize_child(OBJECT(s), "versal-ospi-dma-dst",
> -                            &s->pmc.iou.ospi.dma_dst,
> -                            TYPE_XLNX_CSU_DMA);
> +    dma_dst = qdev_new(TYPE_XLNX_CSU_DMA);
> +    object_property_add_child(OBJECT(dev), "dma-dst-dev", OBJECT(dma_dst));
> +    object_property_set_link(OBJECT(dma_dst), "dma",
> +                             OBJECT(get_system_memory()), &error_abort);
>  
> -    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst),
> -                            "dma", OBJECT(get_system_memory()),
> -                             &error_abort);
> +    sbd = SYS_BUS_DEVICE(dma_dst);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst);
> -    sysbus_realize(sbd, &error_fatal);
> -
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST,
> +    memory_region_add_subregion(&s->mr_ps, map->dma_dst,
>                                  sysbus_mmio_get_region(sbd, 0));
>  
>      /* Create the OSPI source DMA */
> -    object_initialize_child(OBJECT(s), "versal-ospi-dma-src",
> -                            &s->pmc.iou.ospi.dma_src,
> -                            TYPE_XLNX_CSU_DMA);
> +    dma_src = qdev_new(TYPE_XLNX_CSU_DMA);
> +    object_property_add_child(OBJECT(dev), "dma-src-dev", OBJECT(dma_src));
>  
> -    object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst",
> -                             false, &error_abort);
> +    object_property_set_bool(OBJECT(dma_src), "is-dst", false, &error_abort);
>  
> -    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
> -                            "dma", OBJECT(mr_dac), &error_abort);
> -
> -    object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
> -                            "stream-connected-dma",
> -                             OBJECT(&s->pmc.iou.ospi.dma_dst),
> +    object_property_set_link(OBJECT(dma_src), "dma", OBJECT(mr_dac),
>                               &error_abort);
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src);
> -    sysbus_realize(sbd, &error_fatal);
> +    object_property_set_link(OBJECT(dma_src), "stream-connected-dma",
> +                             OBJECT(dma_dst), &error_abort);
>  
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC,
> +    sbd = SYS_BUS_DEVICE(dma_src);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
> +
> +    memory_region_add_subregion(&s->mr_ps, map->dma_src,
>                                  sysbus_mmio_get_region(sbd, 0));
>  
>      /* Realize the OSPI */
> -    object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src",
> -                             OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort);
> +    object_property_set_link(OBJECT(dev), "dma-src",
> +                             OBJECT(dma_src), &error_abort);
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi);
> -    sysbus_realize(sbd, &error_fatal);
> +    sbd = SYS_BUS_DEVICE(dev);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
>  
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI,
> +    memory_region_add_subregion(&s->mr_ps, map->ctrl,
>                                  sysbus_mmio_get_region(sbd, 0));
>  
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC,
> -                                &s->pmc.iou.ospi.linear_mr);
> -
> -    /* ospi_mux_sel */
> -    ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi),
> -                                          "ospi-mux-sel", 0);
> -    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0,
> -                                ospi_mux_sel);
> +    memory_region_add_subregion(&s->mr_ps, map->dac,
> +                                linear_mr);
>  
>      /* OSPI irq */
> -    object_initialize_child(OBJECT(s), "ospi-irq-orgate",
> -                            &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ);
> -    object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate),
> -                            "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal);
> +    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
> +                            map->irq);
>  
> -    orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate);
> -    qdev_realize(orgate, NULL, &error_fatal);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
> +    sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
>  
> -    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0,
> -                       qdev_get_gpio_in(orgate, 0));
> -    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0,
> -                       qdev_get_gpio_in(orgate, 1));
> -    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0,
> -                       qdev_get_gpio_in(orgate, 2));
> -
> -    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
> +    return dev;
>  }
>  
>  static void versal_create_cfu(Versal *s, qemu_irq *pic)
>  {
>      SysBusDevice *sbd;
> @@ -1256,17 +1252,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      for (i = 0; i < map->num_usb; i++) {
>          versal_create_usb(s, &map->usb[i]);
>      }
>  
>      versal_create_efuse(s, &map->efuse);
> +    versal_create_ospi(s, &map->ospi);
>  
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_bbram(s, pic);
>      versal_create_pmc_iou_slcr(s, pic);
> -    versal_create_ospi(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
> @@ -1308,10 +1304,34 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
>      }
>  
>      qdev_prop_set_drive(efuse, "drive", blk);
>  }
>  
> +void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
> +                              BlockBackend *blk)
> +{
> +    BusState *spi_bus;
> +    DeviceState *flash, *ospi;
> +    qemu_irq cs_line;
> +
> +    ospi = DEVICE(versal_get_child(s, "ospi"));
> +    spi_bus = qdev_get_child_bus(ospi, "spi0");
> +
> +    flash = qdev_new(flash_mdl);
> +
> +    if (blk) {
> +        qdev_prop_set_drive_err(flash, "drive", blk, &error_fatal);
> +    }
> +    qdev_prop_set_uint8(flash, "cs", flash_idx);
> +    qdev_realize_and_unref(flash, spi_bus, &error_fatal);
> +
> +    cs_line = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
> +
> +    sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
> +                       flash_idx + 1, cs_line);
> +}
> +
>  int versal_get_num_can(VersalVersion version)
>  {
>      const VersalMap *map = VERSION_TO_MAP[version];
>  
>      return map->num_canfd;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-07-16  9:53 ` [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs Luc Michel
@ 2025-07-29 13:42   ` Francisco Iglesias
  2025-08-04 12:24   ` Peter Maydell
  1 sibling, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 13:42 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:55AM +0200, Luc Michel wrote:
> Improve the IRQ index in the VersalMap structure to turn it into a
> descriptor:
>    - the lower 16 bits still represent the IRQ index
>    - bit 18 is used to indicate a shared IRQ connected to a OR gate
>    - bits 19 to 22 indicate the index on the OR gate.
> 
> This allows to share an IRQ among multiple devices. An OR gate is
> created to connect the devices to the actual IRQ pin.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 62 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 61 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 58176fa11e5..89c93278336 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -41,10 +41,21 @@
>  #define GEM_REVISION        0x40070106
>  
>  #define VERSAL_NUM_PMC_APB_IRQS 18
>  #define NUM_OSPI_IRQ_LINES 3
>  
> +/*
> + * IRQ descriptor to catch the following cases:
> + *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
> + */
> +FIELD(VERSAL_IRQ, IRQ, 0, 16)
> +FIELD(VERSAL_IRQ, ORED, 18, 1)
> +FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
> +
> +#define OR_IRQ(irq, or_idx) \
> +    (R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
> +
>  typedef struct VersalSimplePeriphMap {
>      uint64_t addr;
>      int irq;
>  } VersalSimplePeriphMap;
>  
> @@ -172,13 +183,56 @@ static inline Object *versal_get_child_idx(Versal *s, const char *child,
>      g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
>  
>      return versal_get_child(s, n);
>  }
>  
> +/*
> + * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
> + * used to return the corresponding or gate input IRQ. The or gate is created if
> + * not already existant.
> + *
> + * Or gates are placed under the /soc/irq-or-gates QOM container.
> + */
> +static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
> +                                          qemu_irq target_irq)
> +{
> +    Object *container = versal_get_child(s, "irq-or-gates");
> +    DeviceState *dev;
> +    g_autofree char *name;
> +    int idx, or_idx;
> +
> +    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> +    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> +
> +    name = g_strdup_printf("irq[%d]", idx);
> +    dev = DEVICE(object_resolve_path_at(container, name));
> +
> +    if (dev == NULL) {
> +        dev = qdev_new(TYPE_OR_IRQ);
> +        object_property_add_child(container, name, OBJECT(dev));
> +        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
> +        qdev_realize_and_unref(dev, NULL, &error_abort);
> +        qdev_connect_gpio_out(dev, 0, target_irq);
> +    }
> +
> +    return qdev_get_gpio_in(dev, or_idx);
> +}
> +
>  static qemu_irq versal_get_irq(Versal *s, int irq_idx)
>  {
> -    return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
> +    qemu_irq irq;
> +    bool ored;
> +
> +    ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
> +
> +    irq = qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
> +
> +    if (ored) {
> +        irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
> +    }
> +
> +    return irq;
>  }
>  
>  static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
>                                        int sbd_idx, int irq_idx)
>  {
> @@ -1209,10 +1263,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>  
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
>      Versal *s = XLNX_VERSAL_BASE(dev);
>      qemu_irq pic[XLNX_VERSAL_NR_IRQS];
> +    Object *container;
>      const VersalMap *map = versal_get_map(s);
>      size_t i;
>  
>      if (s->cfg.fdt == NULL) {
>          int fdt_size;
> @@ -1223,10 +1278,15 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
>      s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
>  
>      versal_create_apu_cpus(s);
>      versal_create_apu_gic(s, pic);
> +
> +    container = object_new(TYPE_CONTAINER);
> +    object_property_add_child(OBJECT(s), "irq-or-gates", container);
> +    object_unref(container);
> +
>      versal_create_rpu_cpus(s);
>  
>      for (i = 0; i < map->num_uart; i++) {
>          versal_create_uart(s, &map->uart[i], i);
>      }
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation
  2025-07-16  9:53 ` [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation Luc Michel
@ 2025-07-29 19:41   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 19:41 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:56AM +0200, Luc Michel wrote:
> Refactor the PMC IOU SLCR device creation using the VersalMap structure.
> This is the first user of a shared IRQ using an OR gate. The OSPI
> controller is reconnected to the SLCR.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  5 ----
>  hw/arm/xlnx-versal.c         | 48 +++++++++++++++++++++---------------
>  2 files changed, 28 insertions(+), 25 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index b7ef255d6fd..78442e6c2c5 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -19,11 +19,10 @@
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/nvram/xlnx-bbram.h"
>  #include "hw/misc/xlnx-versal-crl.h"
> -#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "target/arm/cpu.h"
> @@ -82,14 +81,10 @@ struct Versal {
>          XlnxVersalCRL crl;
>      } lpd;
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
> -        struct {
> -            XlnxVersalPmcIouSlcr slcr;
> -        } iou;
> -
>          XlnxZynqMPRTC rtc;
>          XlnxVersalTRng trng;
>          XlnxBBRam bbram;
>          XlnxVersalCFUAPB cfu_apb;
>          XlnxVersalCFUFDRO cfu_fdro;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 89c93278336..d34a36e18aa 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -33,10 +33,11 @@
>  #include "hw/dma/xlnx-zdma.h"
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
> +#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -114,10 +115,12 @@ typedef struct VersalMap {
>          uint64_t dac_sz;
>          uint64_t dma_src;
>          uint64_t dma_dst;
>          int irq;
>      } ospi;
> +
> +    VersalSimplePeriphMap pmc_iou_slcr;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -154,10 +157,12 @@ static const VersalMap VERSAL_MAP = {
>          .ctrl = 0xf1010000,
>          .dac = 0xc0000000, .dac_sz = 0x20000000,
>          .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
>          .irq = 124,
>      },
> +
> +    .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -861,25 +866,28 @@ static void versal_create_efuse(Versal *s,
>                                  sysbus_mmio_get_region(SYS_BUS_DEVICE(cache),
>                                                         0));
>      versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(ctrl), 0, map->irq);
>  }
>  
> -static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
> +static DeviceState *versal_create_pmc_iou_slcr(Versal *s,
> +                                               const VersalSimplePeriphMap *map)
>  {
>      SysBusDevice *sbd;
> +    DeviceState *dev;
>  
> -    object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr,
> -                            TYPE_XILINX_VERSAL_PMC_IOU_SLCR);
> +    dev = qdev_new(TYPE_XILINX_VERSAL_PMC_IOU_SLCR);
> +    object_property_add_child(OBJECT(s), "pmc-iou-slcr", OBJECT(dev));
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr);
> -    sysbus_realize(sbd, &error_fatal);
> +    sbd = SYS_BUS_DEVICE(dev);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
>  
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR,
> +    memory_region_add_subregion(&s->mr_ps, map->addr,
>                                  sysbus_mmio_get_region(sbd, 0));
>  
> -    sysbus_connect_irq(sbd, 0,
> -                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
> +    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
> +
> +    return dev;
>  }
>  
>  static DeviceState *versal_create_ospi(Versal *s,
>                                         const struct VersalOspiMap *map)
>  {
> @@ -1201,10 +1209,11 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
>                    "is not yet implemented\n");
>  }
>  
>  static void versal_unimp(Versal *s)
>  {
> +    DeviceState *slcr;
>      qemu_irq gpio_in;
>  
>      versal_unimp_area(s, "psm", &s->mr_ps,
>                          MM_PSM_START, MM_PSM_END - MM_PSM_START);
>      versal_unimp_area(s, "crf", &s->mr_ps,
> @@ -1223,27 +1232,22 @@ static void versal_unimp(Versal *s)
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
>                              "qspi-ospi-mux-sel-dummy", 1);
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr,
>                              "irq-parity-imr-dummy", 1);
>  
> +    slcr = DEVICE(versal_get_child(s, "pmc-iou-slcr"));
>      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0);
> -    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0,
> -                                gpio_in);
> +    qdev_connect_gpio_out_named(slcr, "sd-emmc-sel", 0, gpio_in);
>  
>      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1);
> -    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1,
> -                                gpio_in);
> +    qdev_connect_gpio_out_named(slcr, "sd-emmc-sel", 1, gpio_in);
>  
>      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0);
> -    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
> -                                "qspi-ospi-mux-sel", 0,
> -                                gpio_in);
> +    qdev_connect_gpio_out_named(slcr, "qspi-ospi-mux-sel", 0, gpio_in);
>  
>      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0);
> -    qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
> -                                SYSBUS_DEVICE_GPIO_IRQ, 0,
> -                                gpio_in);
> +    qdev_connect_gpio_out_named(slcr, SYSBUS_DEVICE_GPIO_IRQ, 0, gpio_in);
>  }
>  
>  static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>                                   unsigned int freq_hz)
>  {
> @@ -1262,10 +1266,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>  }
>  
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
>      Versal *s = XLNX_VERSAL_BASE(dev);
> +    DeviceState *slcr, *ospi;
>      qemu_irq pic[XLNX_VERSAL_NR_IRQS];
>      Object *container;
>      const VersalMap *map = versal_get_map(s);
>      size_t i;
>  
> @@ -1312,17 +1317,20 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      for (i = 0; i < map->num_usb; i++) {
>          versal_create_usb(s, &map->usb[i]);
>      }
>  
>      versal_create_efuse(s, &map->efuse);
> -    versal_create_ospi(s, &map->ospi);
> +    ospi = versal_create_ospi(s, &map->ospi);
> +    slcr = versal_create_pmc_iou_slcr(s, &map->pmc_iou_slcr);
>  
> +    qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
> +                                qdev_get_gpio_in_named(ospi,
> +                                                       "ospi-mux-sel", 0));
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
>      versal_create_bbram(s, pic);
> -    versal_create_pmc_iou_slcr(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 15/48] hw/arm/xlnx-versal: bbram: refactor creation
  2025-07-16  9:53 ` [PATCH 15/48] hw/arm/xlnx-versal: bbram: " Luc Michel
@ 2025-07-29 19:48   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 19:48 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:57AM +0200, Luc Michel wrote:
> Refactor the BBRAM device creation using the VersalMap structure.
> 
> Note that the corresponding FDT node is removed. It does not correspond
> to any real node in standard Versal DTBs. No matching drivers exist for
> it.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  3 +--
>  hw/arm/xlnx-versal-virt.c    | 27 +++---------------------
>  hw/arm/xlnx-versal.c         | 41 +++++++++++++++++++++++++-----------
>  3 files changed, 33 insertions(+), 38 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 78442e6c2c5..9adce02f8a9 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -17,11 +17,10 @@
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
> -#include "hw/nvram/xlnx-bbram.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
> @@ -83,11 +82,10 @@ struct Versal {
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
>          XlnxZynqMPRTC rtc;
>          XlnxVersalTRng trng;
> -        XlnxBBRam bbram;
>          XlnxVersalCFUAPB cfu_apb;
>          XlnxVersalCFUFDRO cfu_fdro;
>          XlnxVersalCFUSFR cfu_sfr;
>          XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
>          XlnxVersalCFrameBcastReg cframe_bcast;
> @@ -119,10 +117,11 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>      s->cfg.fdt = fdt;
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
>  void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
> +void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>                                BlockBackend *blk);
>  
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 43f3c3d0be9..2d7e8a5955a 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -170,30 +170,10 @@ static void fdt_add_rtc_node(VersalVirt *s)
>                                   2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
>      qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
>      g_free(name);
>  }
>  
> -static void fdt_add_bbram_node(VersalVirt *s)
> -{
> -    const char compat[] = TYPE_XLNX_BBRAM;
> -    const char interrupt_names[] = "bbram-error";
> -    char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -
> -    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ,
> -                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> -                     interrupt_names, sizeof(interrupt_names));
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_PMC_BBRAM_CTRL,
> -                                 2, MM_PMC_BBRAM_CTRL_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -    g_free(name);
> -}
> -
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
>      char **node_path;
>      int n = 0;
> @@ -344,19 +324,19 @@ static void create_virtio_regions(VersalVirt *s)
>          qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
>          g_free(name);
>      }
>  }
>  
> -static void bbram_attach_drive(XlnxBBRam *dev)
> +static void bbram_attach_drive(VersalVirt *s)
>  {
>      DriveInfo *dinfo;
>      BlockBackend *blk;
>  
>      dinfo = drive_get_by_index(IF_PFLASH, 0);
>      blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
>      if (blk) {
> -        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
> +        versal_bbram_attach_drive(&s->soc, blk);
>      }
>  }
>  
>  static void efuse_attach_drive(VersalVirt *s)
>  {
> @@ -442,11 +422,10 @@ static void versal_virt_init(MachineState *machine)
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
>      fdt_add_rtc_node(s);
> -    fdt_add_bbram_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
>      fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
>      fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
>  
>      sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
> @@ -456,11 +435,11 @@ static void versal_virt_init(MachineState *machine)
>       * modules unaware of multiple address-spaces.  */
>      memory_region_add_subregion_overlap(get_system_memory(),
>                                          0, &s->soc.fpd.apu.mr, 0);
>  
>      /* Attach bbram backend, if given */
> -    bbram_attach_drive(&s->soc.pmc.bbram);
> +    bbram_attach_drive(s);
>  
>      /* Attach efuse backend, if given */
>      efuse_attach_drive(s);
>  
>      /* Plug SD cards */
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index d34a36e18aa..615eea54372 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -34,10 +34,11 @@
>  #include "hw/misc/xlnx-versal-xramc.h"
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
> +#include "hw/nvram/xlnx-bbram.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -117,10 +118,11 @@ typedef struct VersalMap {
>          uint64_t dma_dst;
>          int irq;
>      } ospi;
>  
>      VersalSimplePeriphMap pmc_iou_slcr;
> +    VersalSimplePeriphMap bbram;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -159,10 +161,11 @@ static const VersalMap VERSAL_MAP = {
>          .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
>          .irq = 124,
>      },
>  
>      .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
> +    .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -811,26 +814,25 @@ static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
>  
>          sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(or, i));
>      }
>  }
>  
> -static void versal_create_bbram(Versal *s, qemu_irq *pic)
> +static void versal_create_bbram(Versal *s,
> +                                const VersalSimplePeriphMap *map)
>  {
> +    DeviceState *dev;
>      SysBusDevice *sbd;
>  
> -    object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram,
> -                                       sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM,
> -                                       &error_fatal,
> -                                       "crc-zpads", "0",
> -                                       NULL);
> -    sbd = SYS_BUS_DEVICE(&s->pmc.bbram);
> +    dev = qdev_new(TYPE_XLNX_BBRAM);
> +    sbd = SYS_BUS_DEVICE(dev);
>  
> -    sysbus_realize(sbd, &error_fatal);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL,
> +    object_property_add_child(OBJECT(s), "bbram", OBJECT(dev));
> +    qdev_prop_set_uint32(dev, "crc-zpads", 0);
> +    sysbus_realize_and_unref(sbd, &error_abort);
> +    memory_region_add_subregion(&s->mr_ps, map->addr,
>                                  sysbus_mmio_get_region(sbd, 0));
> -    sysbus_connect_irq(sbd, 0,
> -                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1));
> +    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
>  }
>  
>  static void versal_create_efuse(Versal *s,
>                                  const struct VersalEfuseMap *map)
>  {
> @@ -1323,14 +1325,16 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      slcr = versal_create_pmc_iou_slcr(s, &map->pmc_iou_slcr);
>  
>      qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
>                                  qdev_get_gpio_in_named(ospi,
>                                                         "ospi-mux-sel", 0));
> +
> +    versal_create_bbram(s, &map->bbram);
> +
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
>      versal_create_trng(s, pic);
> -    versal_create_bbram(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
> @@ -1372,10 +1376,23 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
>      }
>  
>      qdev_prop_set_drive(efuse, "drive", blk);
>  }
>  
> +void versal_bbram_attach_drive(Versal *s, BlockBackend *blk)
> +{
> +    DeviceState *bbram;
> +
> +    bbram = DEVICE(versal_get_child(s, "bbram"));
> +
> +    if (bbram == NULL) {
> +        return;
> +    }
> +
> +    qdev_prop_set_drive(bbram, "drive", blk);
> +}
> +
>  void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>                                BlockBackend *blk)
>  {
>      BusState *spi_bus;
>      DeviceState *flash, *ospi;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 16/48] hw/arm/xlnx-versal: trng: refactor creation
  2025-07-16  9:53 ` [PATCH 16/48] hw/arm/xlnx-versal: trng: " Luc Michel
@ 2025-07-29 19:50   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 19:50 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:58AM +0200, Luc Michel wrote:
> Refactor the TRNG device creation using the VersalMap structure.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  2 --
>  hw/arm/xlnx-versal.c         | 18 ++++++++++--------
>  2 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 9adce02f8a9..bba96201d37 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -18,11 +18,10 @@
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/misc/xlnx-versal-crl.h"
> -#include "hw/misc/xlnx-versal-trng.h"
>  #include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
> @@ -81,11 +80,10 @@ struct Versal {
>      } lpd;
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
>          XlnxZynqMPRTC rtc;
> -        XlnxVersalTRng trng;
>          XlnxVersalCFUAPB cfu_apb;
>          XlnxVersalCFUFDRO cfu_fdro;
>          XlnxVersalCFUSFR cfu_sfr;
>          XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
>          XlnxVersalCFrameBcastReg cframe_bcast;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 615eea54372..45d9fc1e282 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -35,10 +35,11 @@
>  #include "hw/usb/xlnx-usb-subsystem.h"
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/nvram/xlnx-bbram.h"
> +#include "hw/misc/xlnx-versal-trng.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -119,10 +120,11 @@ typedef struct VersalMap {
>          int irq;
>      } ospi;
>  
>      VersalSimplePeriphMap pmc_iou_slcr;
>      VersalSimplePeriphMap bbram;
> +    VersalSimplePeriphMap trng;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -162,10 +164,11 @@ static const VersalMap VERSAL_MAP = {
>          .irq = 124,
>      },
>  
>      .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
>      .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
> +    .trng = { 0xf1230000, 141 },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -771,23 +774,22 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
>       */
>      sysbus_connect_irq(sbd, 1,
>                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0));
>  }
>  
> -static void versal_create_trng(Versal *s, qemu_irq *pic)
> +static void versal_create_trng(Versal *s, const VersalSimplePeriphMap *map)
>  {
>      SysBusDevice *sbd;
>      MemoryRegion *mr;
>  
> -    object_initialize_child(OBJECT(s), "trng", &s->pmc.trng,
> -                            TYPE_XLNX_VERSAL_TRNG);
> -    sbd = SYS_BUS_DEVICE(&s->pmc.trng);
> -    sysbus_realize(sbd, &error_fatal);
> +    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_VERSAL_TRNG));
> +    object_property_add_child(OBJECT(s), "trng", OBJECT(sbd));
> +    sysbus_realize_and_unref(sbd, &error_abort);
>  
>      mr = sysbus_mmio_get_region(sbd, 0);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr);
> -    sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
> +    memory_region_add_subregion(&s->mr_ps, map->addr, mr);
> +    versal_sysbus_connect_irq(s, sbd, 0, map->irq);
>  }
>  
>  static void versal_create_xrams(Versal *s, const struct VersalXramMap *map)
>  {
>      SysBusDevice *sbd;
> @@ -1327,14 +1329,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      qdev_connect_gpio_out_named(slcr, "ospi-mux-sel", 0,
>                                  qdev_get_gpio_in_named(ospi,
>                                                         "ospi-mux-sel", 0));
>  
>      versal_create_bbram(s, &map->bbram);
> +    versal_create_trng(s, &map->trng);
>  
>      versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_rtc(s, pic);
> -    versal_create_trng(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 17/48] hw/arm/xlnx-versal: rtc: refactor creation
  2025-07-16  9:53 ` [PATCH 17/48] hw/arm/xlnx-versal: rtc: " Luc Michel
@ 2025-07-29 19:54   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 19:54 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:53:59AM +0200, Luc Michel wrote:
> Refactor the RTC device creation using the VersalMap structure.
> 
> The sysbus IRQ output 0 (APB IRQ) is connected instead of the output 1
> (addr error IRQ). This does not change the current behaviour since the
> RTC model does not implement those IRQs anyway.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  2 --
>  hw/arm/xlnx-versal-virt.c    | 22 --------------------
>  hw/arm/xlnx-versal.c         | 40 ++++++++++++++++++++++++++++--------
>  3 files changed, 31 insertions(+), 33 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index bba96201d37..abdbed15689 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -15,11 +15,10 @@
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
> -#include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "qom/object.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "net/can_emu.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
> @@ -79,11 +78,10 @@ struct Versal {
>          XlnxVersalCRL crl;
>      } lpd;
>  
>      /* The Platform Management Controller subsystem.  */
>      struct {
> -        XlnxZynqMPRTC rtc;
>          XlnxVersalCFUAPB cfu_apb;
>          XlnxVersalCFUFDRO cfu_fdro;
>          XlnxVersalCFUSFR cfu_sfr;
>          XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
>          XlnxVersalCFrameBcastReg cframe_bcast;
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 2d7e8a5955a..01c230491df 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -149,31 +149,10 @@ static void fdt_add_timer_nodes(VersalVirt *s)
>              GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
>      qemu_fdt_setprop(s->fdt, "/timer", "compatible",
>                       compat, sizeof(compat));
>  }
>  
> -static void fdt_add_rtc_node(VersalVirt *s)
> -{
> -    const char compat[] = "xlnx,zynqmp-rtc";
> -    const char interrupt_names[] = "alarm\0sec";
> -    char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
> -
> -    qemu_fdt_add_subnode(s->fdt, name);
> -
> -    qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ,
> -                           GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> -                           GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ,
> -                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -    qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> -                     interrupt_names, sizeof(interrupt_names));
> -    qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> -                                 2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
> -    qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
> -    g_free(name);
> -}
> -
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
>      char **node_path;
>      int n = 0;
> @@ -421,11 +400,10 @@ static void versal_virt_init(MachineState *machine)
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
>      fdt_add_gic_nodes(s);
>      fdt_add_timer_nodes(s);
> -    fdt_add_rtc_node(s);
>      fdt_add_cpu_nodes(s, psci_conduit);
>      fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
>      fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
>  
>      sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 45d9fc1e282..41965531f8d 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -36,10 +36,11 @@
>  #include "hw/nvram/xlnx-versal-efuse.h"
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/nvram/xlnx-bbram.h"
>  #include "hw/misc/xlnx-versal-trng.h"
> +#include "hw/rtc/xlnx-zynqmp-rtc.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -121,10 +122,16 @@ typedef struct VersalMap {
>      } ospi;
>  
>      VersalSimplePeriphMap pmc_iou_slcr;
>      VersalSimplePeriphMap bbram;
>      VersalSimplePeriphMap trng;
> +
> +    struct VersalRtcMap {
> +        VersalSimplePeriphMap map;
> +        int alarm_irq;
> +        int second_irq;
> +    } rtc;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -165,10 +172,14 @@ static const VersalMap VERSAL_MAP = {
>      },
>  
>      .pmc_iou_slcr = { 0xf1060000, OR_IRQ(121, 0) },
>      .bbram = { 0xf11f0000, OR_IRQ(121, 1) },
>      .trng = { 0xf1230000, 141 },
> +    .rtc = {
> +        { 0xf12a0000, OR_IRQ(121, 2) },
> +        .alarm_irq = 142, .second_irq = 143
> +    },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -753,29 +764,40 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
>                              "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal);
>      qdev_realize(orgate, NULL, &error_fatal);
>      qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]);
>  }
>  
> -static void versal_create_rtc(Versal *s, qemu_irq *pic)
> +static void versal_create_rtc(Versal *s, const struct VersalRtcMap *map)
>  {
>      SysBusDevice *sbd;
>      MemoryRegion *mr;
> +    g_autofree char *node;
> +    const char compatible[] = "xlnx,zynqmp-rtc";
> +    const char interrupt_names[] = "alarm\0sec";
>  
> -    object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
> -                            TYPE_XLNX_ZYNQMP_RTC);
> -    sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
> -    sysbus_realize(sbd, &error_fatal);
> +    sbd = SYS_BUS_DEVICE(qdev_new(TYPE_XLNX_ZYNQMP_RTC));
> +    object_property_add_child(OBJECT(s), "rtc", OBJECT(sbd));
> +    sysbus_realize_and_unref(sbd, &error_abort);
>  
>      mr = sysbus_mmio_get_region(sbd, 0);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
> +    memory_region_add_subregion(&s->mr_ps, map->map.addr, mr);
>  
>      /*
>       * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
>       * supports them.
>       */
> -    sysbus_connect_irq(sbd, 1,
> -                       qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0));
> +    versal_sysbus_connect_irq(s, sbd, 0, map->map.irq);
> +
> +    node = versal_fdt_add_simple_subnode(s, "/rtc", map->map.addr, 0x10000,
> +                                         compatible, sizeof(compatible));
> +    qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                           GIC_FDT_IRQ_TYPE_SPI, map->alarm_irq,
> +                           GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> +                           GIC_FDT_IRQ_TYPE_SPI, map->second_irq,
> +                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +    qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-names",
> +                     interrupt_names, sizeof(interrupt_names));
>  }
>  
>  static void versal_create_trng(Versal *s, const VersalSimplePeriphMap *map)
>  {
>      SysBusDevice *sbd;
> @@ -1330,13 +1352,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
>                                  qdev_get_gpio_in_named(ospi,
>                                                         "ospi-mux-sel", 0));
>  
>      versal_create_bbram(s, &map->bbram);
>      versal_create_trng(s, &map->trng);
> +    versal_create_rtc(s, &map->rtc);
>  
>      versal_create_pmc_apb_irq_orgate(s, pic);
> -    versal_create_rtc(s, pic);
>      versal_create_crl(s, pic);
>      versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 18/48] hw/arm/xlnx-versal: cfu: refactor creation
  2025-07-16  9:54 ` [PATCH 18/48] hw/arm/xlnx-versal: cfu: " Luc Michel
@ 2025-07-29 19:58   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 19:58 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:00AM +0200, Luc Michel wrote:
> Refactor the CFU device creation using the VersalMap structure. All
> users of the APB IRQ OR gate have now been converted. The OR gate device
> can be dropped.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  14 --
>  hw/arm/xlnx-versal.c         | 258 ++++++++++++++++-------------------
>  2 files changed, 115 insertions(+), 157 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index abdbed15689..5a685aea6d4 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -13,17 +13,14 @@
>  #ifndef XLNX_VERSAL_H
>  #define XLNX_VERSAL_H
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
> -#include "hw/or-irq.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "qom/object.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "net/can_emu.h"
> -#include "hw/misc/xlnx-versal-cfu.h"
> -#include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
>  #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
>  OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
> @@ -76,21 +73,10 @@ struct Versal {
>          } rpu;
>  
>          XlnxVersalCRL crl;
>      } lpd;
>  
> -    /* The Platform Management Controller subsystem.  */
> -    struct {
> -        XlnxVersalCFUAPB cfu_apb;
> -        XlnxVersalCFUFDRO cfu_fdro;
> -        XlnxVersalCFUSFR cfu_sfr;
> -        XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
> -        XlnxVersalCFrameBcastReg cframe_bcast;
> -
> -        OrIRQState apb_irq_orgate;
> -    } pmc;
> -
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
>      } phandle;
>  
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 41965531f8d..2128dbbad92 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -37,10 +37,13 @@
>  #include "hw/ssi/xlnx-versal-ospi.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
>  #include "hw/nvram/xlnx-bbram.h"
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
> +#include "hw/misc/xlnx-versal-cfu.h"
> +#include "hw/misc/xlnx-versal-cframe-reg.h"
> +#include "hw/or-irq.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -128,10 +131,28 @@ typedef struct VersalMap {
>      struct VersalRtcMap {
>          VersalSimplePeriphMap map;
>          int alarm_irq;
>          int second_irq;
>      } rtc;
> +
> +    struct VersalCfuMap {
> +        uint64_t cframe_base;
> +        uint64_t cframe_stride;
> +        uint64_t cfu_fdro;
> +        uint64_t cframe_bcast_reg;
> +        uint64_t cframe_bcast_fdri;
> +        uint64_t cfu_apb;
> +        uint64_t cfu_stream;
> +        uint64_t cfu_stream_2;
> +        uint64_t cfu_sfr;
> +        int cfu_apb_irq;
> +        int cframe_irq;
> +        size_t num_cframe;
> +        struct VersalCfuCframeCfg {
> +            uint32_t blktype_frames[7];
> +        } cframe_cfg[15];
> +    } cfu;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -176,10 +197,26 @@ static const VersalMap VERSAL_MAP = {
>      .trng = { 0xf1230000, 141 },
>      .rtc = {
>          { 0xf12a0000, OR_IRQ(121, 2) },
>          .alarm_irq = 142, .second_irq = 143
>      },
> +
> +    .cfu = {
> +        .cframe_base = 0xf12d0000, .cframe_stride = 0x1000,
> +        .cframe_bcast_reg = 0xf12ee000, .cframe_bcast_fdri = 0xf12ef000,
> +        .cfu_apb = 0xf12b0000, .cfu_sfr = 0xf12c1000,
> +        .cfu_stream = 0xf12c0000, .cfu_stream_2 = 0xf1f80000,
> +        .cfu_fdro = 0xf12c2000,
> +        .cfu_apb_irq = 120, .cframe_irq = OR_IRQ(121, 3),
> +        .num_cframe = 15,
> +        .cframe_cfg = {
> +            { { 34111, 3528, 12800, 11, 5, 1, 1 } },
> +            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
> +            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
> +            { { 38498, 3841, 15361, 13, 7, 3, 1 } },
> +        },
> +    },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -743,31 +780,10 @@ static void versal_create_sdhci(Versal *s,
>      qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
>                             GIC_FDT_IRQ_TYPE_SPI, map->irq,
>                             GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>  }
>  
> -static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
> -{
> -    DeviceState *orgate;
> -
> -    /*
> -     * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following
> -     * models:
> -     *  - RTC
> -     *  - BBRAM
> -     *  - PMC SLCR
> -     *  - CFRAME regs (input 3 - 17 to the orgate)
> -     */
> -    object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
> -                            &s->pmc.apb_irq_orgate, TYPE_OR_IRQ);
> -    orgate = DEVICE(&s->pmc.apb_irq_orgate);
> -    object_property_set_int(OBJECT(orgate),
> -                            "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal);
> -    qdev_realize(orgate, NULL, &error_fatal);
> -    qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]);
> -}
> -
>  static void versal_create_rtc(Versal *s, const struct VersalRtcMap *map)
>  {
>      SysBusDevice *sbd;
>      MemoryRegion *mr;
>      g_autofree char *node;
> @@ -982,158 +998,115 @@ static DeviceState *versal_create_ospi(Versal *s,
>      sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
>  
>      return dev;
>  }
>  
> -static void versal_create_cfu(Versal *s, qemu_irq *pic)
> +static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
>  {
>      SysBusDevice *sbd;
> -    DeviceState *dev;
> +    Object *container;
> +    DeviceState *cfu_fdro, *cfu_apb, *cfu_sfr, *cframe_bcast;
> +    DeviceState *cframe_irq_or;
>      int i;
> -    const struct {
> +
> +    container = object_new(TYPE_CONTAINER);
> +    object_property_add_child(OBJECT(s), "cfu", container);
> +    object_unref(container);
> +
> +    /* CFU FDRO */
> +    cfu_fdro = qdev_new(TYPE_XLNX_VERSAL_CFU_FDRO);
> +    object_property_add_child(container, "cfu-fdro", OBJECT(cfu_fdro));
> +    sbd = SYS_BUS_DEVICE(cfu_fdro);
> +
> +    sysbus_realize_and_unref(sbd, &error_fatal);
> +    memory_region_add_subregion(&s->mr_ps, map->cfu_fdro,
> +                                sysbus_mmio_get_region(sbd, 0));
> +
> +    /* cframe bcast */
> +    cframe_bcast = qdev_new(TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
> +    object_property_add_child(container, "cframe-bcast", OBJECT(cframe_bcast));
> +
> +    /* CFU APB */
> +    cfu_apb = qdev_new(TYPE_XLNX_VERSAL_CFU_APB);
> +    object_property_add_child(container, "cfu-apb", OBJECT(cfu_apb));
> +
> +    /* IRQ or gate for cframes */
> +    cframe_irq_or = qdev_new(TYPE_OR_IRQ);
> +    object_property_add_child(container, "cframe-irq-or-gate",
> +                              OBJECT(cframe_irq_or));
> +    qdev_prop_set_uint16(cframe_irq_or, "num-lines", map->num_cframe);
> +    qdev_realize_and_unref(cframe_irq_or, NULL, &error_abort);
> +    versal_qdev_connect_gpio_out(s, cframe_irq_or, 0, map->cframe_irq);
> +
> +    /* cframe reg */
> +    for (i = 0; i < map->num_cframe; i++) {
>          uint64_t reg_base;
>          uint64_t fdri_base;
> -    } cframe_addr[] = {
> -        { MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
> -        { MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
> -        { MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
> -        { MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
> -        { MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
> -        { MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
> -        { MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
> -        { MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
> -        { MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
> -        { MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
> -        { MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
> -        { MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
> -        { MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
> -        { MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
> -        { MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
> -    };
> -    const struct {
> -        uint32_t blktype0_frames;
> -        uint32_t blktype1_frames;
> -        uint32_t blktype2_frames;
> -        uint32_t blktype3_frames;
> -        uint32_t blktype4_frames;
> -        uint32_t blktype5_frames;
> -        uint32_t blktype6_frames;
> -    } cframe_cfg[] = {
> -        [0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
> -        [1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
> -        [2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
> -        [3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
> -    };
> +        DeviceState *dev;
> +        g_autofree char *prop_name;
> +        size_t j;
>  
> -    /* CFU FDRO */
> -    object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
> -                            TYPE_XLNX_VERSAL_CFU_FDRO);
> -    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_fdro);
> +        dev = qdev_new(TYPE_XLNX_VERSAL_CFRAME_REG);
> +        object_property_add_child(container, "cframe[*]", OBJECT(dev));
>  
> -    sysbus_realize(sbd, &error_fatal);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
> -                                sysbus_mmio_get_region(sbd, 0));
> +        sbd = SYS_BUS_DEVICE(dev);
>  
> -    /* CFRAME REG */
> -    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
> -        g_autofree char *name = g_strdup_printf("cframe%d", i);
> +        for (j = 0; j < ARRAY_SIZE(map->cframe_cfg[i].blktype_frames); j++) {
> +            g_autofree char *blktype_prop_name;
>  
> -        object_initialize_child(OBJECT(s), name, &s->pmc.cframe[i],
> -                                TYPE_XLNX_VERSAL_CFRAME_REG);
> -
> -        sbd = SYS_BUS_DEVICE(&s->pmc.cframe[i]);
> -        dev = DEVICE(&s->pmc.cframe[i]);
> -
> -        if (i < ARRAY_SIZE(cframe_cfg)) {
> -            object_property_set_int(OBJECT(dev), "blktype0-frames",
> -                                    cframe_cfg[i].blktype0_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype1-frames",
> -                                    cframe_cfg[i].blktype1_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype2-frames",
> -                                    cframe_cfg[i].blktype2_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype3-frames",
> -                                    cframe_cfg[i].blktype3_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype4-frames",
> -                                    cframe_cfg[i].blktype4_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype5-frames",
> -                                    cframe_cfg[i].blktype5_frames,
> -                                    &error_abort);
> -            object_property_set_int(OBJECT(dev), "blktype6-frames",
> -                                    cframe_cfg[i].blktype6_frames,
> +            blktype_prop_name = g_strdup_printf("blktype%zu-frames", j);
> +            object_property_set_int(OBJECT(dev), blktype_prop_name,
> +                                    map->cframe_cfg[i].blktype_frames[j],
>                                      &error_abort);
>          }
> +
>          object_property_set_link(OBJECT(dev), "cfu-fdro",
> -                                 OBJECT(&s->pmc.cfu_fdro), &error_fatal);
> +                                 OBJECT(cfu_fdro), &error_abort);
>  
> -        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
>  
> -        memory_region_add_subregion(&s->mr_ps, cframe_addr[i].reg_base,
> +        reg_base = map->cframe_base + i * map->cframe_stride * 2;
> +        fdri_base = reg_base + map->cframe_stride;
> +        memory_region_add_subregion(&s->mr_ps, reg_base,
>                                      sysbus_mmio_get_region(sbd, 0));
> -        memory_region_add_subregion(&s->mr_ps, cframe_addr[i].fdri_base,
> +        memory_region_add_subregion(&s->mr_ps, fdri_base,
>                                      sysbus_mmio_get_region(sbd, 1));
> -        sysbus_connect_irq(sbd, 0,
> -                           qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate),
> -                                            3 + i));
> -    }
> -
> -    /* CFRAME BCAST */
> -    object_initialize_child(OBJECT(s), "cframe_bcast", &s->pmc.cframe_bcast,
> -                            TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
> +        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(cframe_irq_or, i));
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.cframe_bcast);
> -    dev = DEVICE(&s->pmc.cframe_bcast);
> -
> -    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
> -        g_autofree char *propname = g_strdup_printf("cframe%d", i);
> -        object_property_set_link(OBJECT(dev), propname,
> -                                 OBJECT(&s->pmc.cframe[i]), &error_fatal);
> +        prop_name = g_strdup_printf("cframe%d", i);
> +        object_property_set_link(OBJECT(cframe_bcast), prop_name,
> +                                 OBJECT(dev), &error_abort);
> +        object_property_set_link(OBJECT(cfu_apb), prop_name,
> +                                 OBJECT(dev), &error_abort);
>      }
>  
> -    sysbus_realize(sbd, &error_fatal);
> -
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_REG,
> +    sbd = SYS_BUS_DEVICE(cframe_bcast);
> +    sysbus_realize_and_unref(sbd, &error_abort);
> +    memory_region_add_subregion(&s->mr_ps, map->cframe_bcast_reg,
>                                  sysbus_mmio_get_region(sbd, 0));
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_FDRI,
> +    memory_region_add_subregion(&s->mr_ps, map->cframe_bcast_fdri,
>                                  sysbus_mmio_get_region(sbd, 1));
>  
> -    /* CFU APB */
> -    object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
> -                            TYPE_XLNX_VERSAL_CFU_APB);
> -    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
> -    dev = DEVICE(&s->pmc.cfu_apb);
> -
> -    for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
> -        g_autofree char *propname = g_strdup_printf("cframe%d", i);
> -        object_property_set_link(OBJECT(dev), propname,
> -                                 OBJECT(&s->pmc.cframe[i]), &error_fatal);
> -    }
> -
> -    sysbus_realize(sbd, &error_fatal);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
> +    sbd = SYS_BUS_DEVICE(cfu_apb);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
> +    memory_region_add_subregion(&s->mr_ps, map->cfu_apb,
>                                  sysbus_mmio_get_region(sbd, 0));
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM,
> +    memory_region_add_subregion(&s->mr_ps, map->cfu_stream,
>                                  sysbus_mmio_get_region(sbd, 1));
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM_2,
> +    memory_region_add_subregion(&s->mr_ps, map->cfu_stream_2,
>                                  sysbus_mmio_get_region(sbd, 2));
> -    sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
> +    versal_sysbus_connect_irq(s, sbd, 0, map->cfu_apb_irq);
>  
>      /* CFU SFR */
> -    object_initialize_child(OBJECT(s), "cfu-sfr", &s->pmc.cfu_sfr,
> -                            TYPE_XLNX_VERSAL_CFU_SFR);
> +    cfu_sfr = qdev_new(TYPE_XLNX_VERSAL_CFU_SFR);
> +    object_property_add_child(container, "cfu-sfr", OBJECT(cfu_sfr));
> +    sbd = SYS_BUS_DEVICE(cfu_sfr);
>  
> -    sbd = SYS_BUS_DEVICE(&s->pmc.cfu_sfr);
> -
> -    object_property_set_link(OBJECT(&s->pmc.cfu_sfr),
> -                            "cfu", OBJECT(&s->pmc.cfu_apb), &error_abort);
> -
> -    sysbus_realize(sbd, &error_fatal);
> -    memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_SFR,
> +    object_property_set_link(OBJECT(cfu_sfr),
> +                            "cfu", OBJECT(cfu_apb), &error_abort);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
> +    memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
>                                  sysbus_mmio_get_region(sbd, 0));
>  }
>  
>  static void versal_create_crl(Versal *s, qemu_irq *pic)
>  {
> @@ -1353,14 +1326,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
>                                                         "ospi-mux-sel", 0));
>  
>      versal_create_bbram(s, &map->bbram);
>      versal_create_trng(s, &map->trng);
>      versal_create_rtc(s, &map->rtc);
> +    versal_create_cfu(s, &map->cfu);
>  
> -    versal_create_pmc_apb_irq_orgate(s, pic);
>      versal_create_crl(s, pic);
> -    versal_create_cfu(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
>      memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 19/48] hw/arm/xlnx-versal: crl: refactor creation
  2025-07-16  9:54 ` [PATCH 19/48] hw/arm/xlnx-versal: crl: " Luc Michel
@ 2025-07-29 20:00   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 20:00 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:01AM +0200, Luc Michel wrote:
> Refactor the CRL device creation using the VersalMap structure. The
> connections to the RPU CPUs are temporarily removed and will be
> reintroduced with next refactoring commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  3 ---
>  hw/arm/xlnx-versal.c         | 36 +++++++++++++++++++-----------------
>  2 files changed, 19 insertions(+), 20 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 5a685aea6d4..d3ce13e69de 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -15,11 +15,10 @@
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/intc/arm_gicv3.h"
>  #include "qom/object.h"
> -#include "hw/misc/xlnx-versal-crl.h"
>  #include "net/can_emu.h"
>  #include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
>  #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
> @@ -69,12 +68,10 @@ struct Versal {
>              MemoryRegion mr_ps_alias;
>  
>              CPUClusterState cluster;
>              ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
>          } rpu;
> -
> -        XlnxVersalCRL crl;
>      } lpd;
>  
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 2128dbbad92..ff55ec62301 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -40,10 +40,11 @@
>  #include "hw/misc/xlnx-versal-trng.h"
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "hw/or-irq.h"
> +#include "hw/misc/xlnx-versal-crl.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -149,10 +150,12 @@ typedef struct VersalMap {
>          size_t num_cframe;
>          struct VersalCfuCframeCfg {
>              uint32_t blktype_frames[7];
>          } cframe_cfg[15];
>      } cfu;
> +
> +    VersalSimplePeriphMap crl;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -213,10 +216,12 @@ static const VersalMap VERSAL_MAP = {
>              { { 38498, 3841, 15361, 13, 7, 3, 1 } },
>              { { 38498, 3841, 15361, 13, 7, 3, 1 } },
>              { { 38498, 3841, 15361, 13, 7, 3, 1 } },
>          },
>      },
> +
> +    .crl = { 0xff5e0000, 10 },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -1106,31 +1111,28 @@ static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
>      sysbus_realize_and_unref(sbd, &error_fatal);
>      memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
>                                  sysbus_mmio_get_region(sbd, 0));
>  }
>  
> -static void versal_create_crl(Versal *s, qemu_irq *pic)
> +static inline void versal_create_crl(Versal *s)
>  {
> -    SysBusDevice *sbd;
> -    int i;
> +    const VersalMap *map;
> +    const char *crl_class;
> +    DeviceState *dev;
>  
> -    object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
> -                            TYPE_XLNX_VERSAL_CRL);
> -    sbd = SYS_BUS_DEVICE(&s->lpd.crl);
> +    map = versal_get_map(s);
>  
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
> -        g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
> +    crl_class = TYPE_XLNX_VERSAL_CRL;
> +    dev = qdev_new(crl_class);
> +    object_property_add_child(OBJECT(s), "crl", OBJECT(dev));
>  
> -        object_property_set_link(OBJECT(&s->lpd.crl),
> -                                 name, OBJECT(&s->lpd.rpu.cpu[i]),
> -                                 &error_abort);
> -    }
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
>  
> -    sysbus_realize(sbd, &error_fatal);
> -    memory_region_add_subregion(&s->mr_ps, MM_CRL,
> -                                sysbus_mmio_get_region(sbd, 0));
> -    sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
> +    memory_region_add_subregion(&s->mr_ps, map->crl.addr,
> +                                sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
> +
> +    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
>  }
>  
>  /* This takes the board allocated linear DDR memory and creates aliases
>   * for each split DDR range/aperture on the Versal address map.
>   */
> @@ -1327,12 +1329,12 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      versal_create_bbram(s, &map->bbram);
>      versal_create_trng(s, &map->trng);
>      versal_create_rtc(s, &map->rtc);
>      versal_create_cfu(s, &map->cfu);
> +    versal_create_crl(s);
>  
> -    versal_create_crl(s, pic);
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
>      memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: refactor creation
  2025-07-16  9:54 ` [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: " Luc Michel
@ 2025-07-29 20:04   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 20:04 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:02AM +0200, Luc Michel wrote:
> Refactor the creation of virtio devices. Use the accessors provided by
> the Versal SoC to retrieve the reserved MMIO and IRQ space. Those are
> defined in the VersalMap structure.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  3 +++
>  hw/arm/xlnx-versal-virt.c    | 31 ++++++++++++-------------------
>  hw/arm/xlnx-versal.c         | 26 ++++++++++++++++++++++++++
>  3 files changed, 41 insertions(+), 19 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index d3ce13e69de..af47acb288f 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -100,10 +100,13 @@ void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
>  void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>                                BlockBackend *blk);
>  
> +qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx);
> +hwaddr versal_get_reserved_mmio_addr(Versal *s);
> +
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 01c230491df..a776ee87088 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -269,41 +269,34 @@ static void create_virtio_regions(VersalVirt *s)
>  {
>      int virtio_mmio_size = 0x200;
>      int i;
>  
>      for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
> -        char *name = g_strdup_printf("virtio%d", i);
> -        hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
> -        int irq = VERSAL_RSVD_IRQ_FIRST + i;
> +        hwaddr base = versal_get_reserved_mmio_addr(&s->soc)
> +            + i * virtio_mmio_size;
> +        g_autofree char *node = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
> +        int dtb_irq;
>          MemoryRegion *mr;
>          DeviceState *dev;
>          qemu_irq pic_irq;
>  
> -        pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
> +        pic_irq = versal_get_reserved_irq(&s->soc, i, &dtb_irq);
>          dev = qdev_new("virtio-mmio");
> -        object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev));
> +        object_property_add_child(OBJECT(s), "virtio-mmio[*]", OBJECT(dev));
>          sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
>          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
>          memory_region_add_subregion(&s->soc.mr_ps, base, mr);
> -        g_free(name);
> -    }
>  
> -    for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
> -        hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
> -        int irq = VERSAL_RSVD_IRQ_FIRST + i;
> -        char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
> -
> -        qemu_fdt_add_subnode(s->fdt, name);
> -        qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
> -        qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_SPI, irq,
> +        qemu_fdt_add_subnode(s->fdt, node);
> +        qemu_fdt_setprop(s->fdt, node, "dma-coherent", NULL, 0);
> +        qemu_fdt_setprop_cells(s->fdt, node, "interrupts",
> +                               GIC_FDT_IRQ_TYPE_SPI, dtb_irq,
>                                 GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
> -        qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> +        qemu_fdt_setprop_sized_cells(s->fdt, node, "reg",
>                                       2, base, 2, virtio_mmio_size);
> -        qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
> -        g_free(name);
> +        qemu_fdt_setprop_string(s->fdt, node, "compatible", "virtio,mmio");
>      }
>  }
>  
>  static void bbram_attach_drive(VersalVirt *s)
>  {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index ff55ec62301..fe2c789a557 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -152,10 +152,17 @@ typedef struct VersalMap {
>              uint32_t blktype_frames[7];
>          } cframe_cfg[15];
>      } cfu;
>  
>      VersalSimplePeriphMap crl;
> +
> +    /* reserved MMIO/IRQ space that can safely be used for virtio devices */
> +    struct VersalReserved {
> +        uint64_t mmio_start;
> +        int irq_start;
> +        int irq_num;
> +    } reserved;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -218,10 +225,12 @@ static const VersalMap VERSAL_MAP = {
>              { { 38498, 3841, 15361, 13, 7, 3, 1 } },
>          },
>      },
>  
>      .crl = { 0xff5e0000, 10 },
> +
> +    .reserved = { 0xa0000000, 111, 8 },
>  };
>  
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
>  };
> @@ -1411,10 +1420,27 @@ void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>  
>      sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
>                         flash_idx + 1, cs_line);
>  }
>  
> +qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx)
> +{
> +    const VersalMap *map = versal_get_map(s);
> +
> +    g_assert(idx < map->reserved.irq_num);
> +
> +    *dtb_idx = map->reserved.irq_start + idx;
> +    return versal_get_irq(s, *dtb_idx);
> +}
> +
> +hwaddr versal_get_reserved_mmio_addr(Versal *s)
> +{
> +    const VersalMap *map = versal_get_map(s);
> +
> +    return map->reserved.mmio_start;
> +}
> +
>  int versal_get_num_can(VersalVersion version)
>  {
>      const VersalMap *map = VERSION_TO_MAP[version];
>  
>      return map->num_canfd;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation
  2025-07-16  9:54 ` [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation Luc Michel
@ 2025-07-29 20:13   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 20:13 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:03AM +0200, Luc Michel wrote:
> Refactor the CPU cluster creation using the VersalMap structure. There
> is no functional change. The clusters properties are now described in
> the VersalMap structure. For now only the APU is converted. The RPU will
> be taken care of by next commits.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  11 +-
>  hw/arm/xlnx-versal-virt.c    |  80 +-------
>  hw/arm/xlnx-versal.c         | 346 ++++++++++++++++++++++++++---------
>  3 files changed, 269 insertions(+), 168 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index af47acb288f..ba5719d80f5 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -13,11 +13,10 @@
>  #ifndef XLNX_VERSAL_H
>  #define XLNX_VERSAL_H
>  
>  #include "hw/sysbus.h"
>  #include "hw/cpu/cluster.h"
> -#include "hw/intc/arm_gicv3.h"
>  #include "qom/object.h"
>  #include "net/can_emu.h"
>  #include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
> @@ -41,19 +40,10 @@ OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  struct Versal {
>      /*< private >*/
>      SysBusDevice parent_obj;
>  
>      /*< public >*/
> -    struct {
> -        struct {
> -            MemoryRegion mr;
> -            CPUClusterState cluster;
> -            ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
> -            GICv3State gic;
> -        } apu;
> -    } fpd;
> -
>      MemoryRegion mr_ps;
>  
>      struct {
>          /* 4 ranges to access DDR.  */
>          MemoryRegion mr_ddr_ranges[4];
> @@ -73,10 +63,11 @@ struct Versal {
>      } lpd;
>  
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
> +        uint32_t gic;
>      } phandle;
>  
>      struct {
>          MemoryRegion *mr_ddr;
>          CanBusState **canbus;
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index a776ee87088..55159536ceb 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -36,11 +36,10 @@ struct VersalVirt {
>      Versal soc;
>  
>      void *fdt;
>      int fdt_size;
>      struct {
> -        uint32_t gic;
>          uint32_t clk_125Mhz;
>          uint32_t clk_25Mhz;
>      } phandle;
>      struct arm_boot_info binfo;
>  
> @@ -61,22 +60,18 @@ static void fdt_create(VersalVirt *s)
>          error_report("create_device_tree() failed");
>          exit(1);
>      }
>  
>      /* Allocate all phandles.  */
> -    s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
>      s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
>  
>      /* Create /chosen node for load_dtb.  */
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
>      qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
> -    qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
> -    qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
> -    qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
>      qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
>      qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
>  }
>  
>  static void fdt_add_clk_node(VersalVirt *s, const char *name,
> @@ -88,71 +83,10 @@ static void fdt_add_clk_node(VersalVirt *s, const char *name,
>      qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
>      qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
>      qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
>  }
>  
> -static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
> -{
> -    int i;
> -
> -    qemu_fdt_add_subnode(s->fdt, "/cpus");
> -    qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
> -    qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
> -
> -    for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
> -        char *name = g_strdup_printf("/cpus/cpu@%d", i);
> -        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
> -
> -        qemu_fdt_add_subnode(s->fdt, name);
> -        qemu_fdt_setprop_cell(s->fdt, name, "reg",
> -                              arm_cpu_mp_affinity(armcpu));
> -        if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
> -            qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
> -        }
> -        qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
> -        qemu_fdt_setprop_string(s->fdt, name, "compatible",
> -                                armcpu->dtb_compatible);
> -        g_free(name);
> -    }
> -}
> -
> -static void fdt_add_gic_nodes(VersalVirt *s)
> -{
> -    char *nodename;
> -
> -    nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
> -    qemu_fdt_add_subnode(s->fdt, nodename);
> -    qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
> -    qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
> -                           GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
> -                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> -    qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
> -    qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
> -                                 2, MM_GIC_APU_DIST_MAIN,
> -                                 2, MM_GIC_APU_DIST_MAIN_SIZE,
> -                                 2, MM_GIC_APU_REDIST_0,
> -                                 2, MM_GIC_APU_REDIST_0_SIZE);
> -    qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
> -    qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
> -    g_free(nodename);
> -}
> -
> -static void fdt_add_timer_nodes(VersalVirt *s)
> -{
> -    const char compat[] = "arm,armv8-timer";
> -    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
> -
> -    qemu_fdt_add_subnode(s->fdt, "/timer");
> -    qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
> -            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
> -            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
> -            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
> -            GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
> -    qemu_fdt_setprop(s->fdt, "/timer", "compatible",
> -                     compat, sizeof(compat));
> -}
> -
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
>      char **node_path;
>      int n = 0;
> @@ -391,23 +325,21 @@ static void versal_virt_init(MachineState *machine)
>                                   &error_abort);
>      }
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
> -    fdt_add_gic_nodes(s);
> -    fdt_add_timer_nodes(s);
> -    fdt_add_cpu_nodes(s, psci_conduit);
>      fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
>      fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
>  
>      sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
>      create_virtio_regions(s);
>  
> -    /* Make the APU cpu address space visible to virtio and other
> -     * modules unaware of multiple address-spaces.  */
> -    memory_region_add_subregion_overlap(get_system_memory(),
> -                                        0, &s->soc.fpd.apu.mr, 0);
> +    /*
> +     * Map the SoC address space onto system memory. This will allow virtio and
> +     * other modules unaware of multiple address-spaces to work.
> +     */
> +    memory_region_add_subregion(get_system_memory(), 0, &s->soc.mr_ps);
>  
>      /* Attach bbram backend, if given */
>      bbram_attach_drive(s);
>  
>      /* Attach efuse backend, if given */
> @@ -427,11 +359,11 @@ static void versal_virt_init(MachineState *machine)
>          /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
>           * Offset things by 4K.  */
>          s->binfo.loader_start = 0x1000;
>          s->binfo.dtb_limit = 0x1000000;
>      }
> -    arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
> +    arm_load_kernel(ARM_CPU(qemu_get_cpu(0)), machine, &s->binfo);
>  
>      for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
>          ObjectClass *flash_klass;
>          DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
>          BlockBackend *blk;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index fe2c789a557..5a08ad07b28 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -41,10 +41,11 @@
>  #include "hw/rtc/xlnx-zynqmp-rtc.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "hw/or-irq.h"
>  #include "hw/misc/xlnx-versal-crl.h"
> +#include "hw/intc/arm_gicv3_common.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -65,11 +66,38 @@ FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
>  typedef struct VersalSimplePeriphMap {
>      uint64_t addr;
>      int irq;
>  } VersalSimplePeriphMap;
>  
> +typedef struct VersalGicMap {
> +    int version;
> +    uint64_t dist;
> +    uint64_t redist;
> +    size_t num_irq;
> +} VersalGicMap;
> +
> +enum StartPoweredOffMode {
> +    SPO_SECONDARIES,
> +    SPO_ALL,
> +};
> +
> +typedef struct VersalCpuClusterMap {
> +    VersalGicMap gic;
> +
> +    const char *name;
> +    const char *cpu_model;
> +    size_t num_core;
> +    size_t num_cluster;
> +    uint32_t qemu_cluster_id;
> +    bool dtb_expose;
> +
> +    enum StartPoweredOffMode start_powered_off;
> +} VersalCpuClusterMap;
> +
>  typedef struct VersalMap {
> +    VersalCpuClusterMap apu;
> +
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
>  
>      VersalSimplePeriphMap canfd[4];
>      size_t num_canfd;
> @@ -162,10 +190,26 @@ typedef struct VersalMap {
>          int irq_num;
>      } reserved;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
> +    .apu = {
> +        .name = "apu",
> +        .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
> +        .num_cluster = 1,
> +        .num_core = 2,
> +        .qemu_cluster_id = 0,
> +        .start_powered_off = SPO_SECONDARIES,
> +        .dtb_expose = true,
> +        .gic = {
> +            .version = 3,
> +            .dist = 0xf9000000,
> +            .redist = 0xf9080000,
> +            .num_irq = 192,
> +        },
> +    },
> +
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
>      .num_uart = 2,
>  
>      .canfd[0] = { 0xff060000, 20 },
> @@ -292,14 +336,16 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
>  
>  static qemu_irq versal_get_irq(Versal *s, int irq_idx)
>  {
>      qemu_irq irq;
>      bool ored;
> +    DeviceState *gic;
>  
>      ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
>  
> -    irq = qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
> +    gic = DEVICE(versal_get_child_idx(s, "apu-gic", 0));
> +    irq = qdev_get_gpio_in(gic, irq_idx);
>  
>      if (ored) {
>          irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
>      }
>  
> @@ -372,111 +418,243 @@ static inline DeviceState *create_or_gate(Versal *s, Object *parent,
>      versal_qdev_connect_gpio_out(s, or, 0, irq_idx);
>  
>      return or;
>  }
>  
> -static void versal_create_apu_cpus(Versal *s)
> +static MemoryRegion *create_cpu_mr(Versal *s, DeviceState *cluster,
> +                                   const VersalCpuClusterMap *map)
>  {
> -    int i;
> +    MemoryRegion *mr, *root_alias;
> +    char *name;
>  
> -    object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
> -                            TYPE_CPU_CLUSTER);
> -    qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
> +    mr = g_new(MemoryRegion, 1);
> +    name = g_strdup_printf("%s-mr", map->name);
> +    memory_region_init(mr, OBJECT(cluster), name, UINT64_MAX);
> +    g_free(name);
>  
> -    for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
> -        Object *obj;
> +    root_alias = g_new(MemoryRegion, 1);
> +    name = g_strdup_printf("ps-alias-for-%s", map->name);
> +    memory_region_init_alias(root_alias, OBJECT(cluster), name,
> +                             &s->mr_ps, 0, UINT64_MAX);
> +    g_free(name);
> +    memory_region_add_subregion(mr, 0, root_alias);
>  
> -        object_initialize_child(OBJECT(&s->fpd.apu.cluster),
> -                                "apu-cpu[*]", &s->fpd.apu.cpu[i],
> -                                XLNX_VERSAL_ACPU_TYPE);
> -        obj = OBJECT(&s->fpd.apu.cpu[i]);
> -        if (i) {
> -            /* Secondary CPUs start in powered-down state */
> -            object_property_set_bool(obj, "start-powered-off", true,
> -                                     &error_abort);
> -        }
> -
> -        object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu),
> -                                &error_abort);
> -        object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr),
> -                                 &error_abort);
> -        qdev_realize(DEVICE(obj), NULL, &error_fatal);
> -    }
> -
> -    qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
> +    return mr;
>  }
>  
> -static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
> +static DeviceState *versal_create_gic(Versal *s,
> +                                      const VersalCpuClusterMap *map,
> +                                      MemoryRegion *mr,
> +                                      size_t num_cpu)
>  {
> -    static const uint64_t addrs[] = {
> -        MM_GIC_APU_DIST_MAIN,
> -        MM_GIC_APU_REDIST_0
> -    };
> -    SysBusDevice *gicbusdev;
> -    DeviceState *gicdev;
> +    DeviceState *dev;
> +    SysBusDevice *sbd;
>      QList *redist_region_count;
> -    int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
> -    int i;
> +    g_autofree char *node = NULL;
> +    g_autofree char *name = NULL;
> +    const char compatible[] = "arm,gic-v3";
>  
> -    object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic,
> -                            gicv3_class_name());
> -    gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
> -    gicdev = DEVICE(&s->fpd.apu.gic);
> -    qdev_prop_set_uint32(gicdev, "revision", 3);
> -    qdev_prop_set_uint32(gicdev, "num-cpu", nr_apu_cpus);
> -    qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
> +    dev = qdev_new(gicv3_class_name());
> +    name = g_strdup_printf("%s-gic[*]", map->name);
> +    object_property_add_child(OBJECT(s), name, OBJECT(dev));
> +    sbd = SYS_BUS_DEVICE(dev);
> +    qdev_prop_set_uint32(dev, "revision", 3);
> +    qdev_prop_set_uint32(dev, "num-cpu", num_cpu);
> +    qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32);
>  
>      redist_region_count = qlist_new();
> -    qlist_append_int(redist_region_count, nr_apu_cpus);
> -    qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
> +    qlist_append_int(redist_region_count, num_cpu);
> +    qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
>  
> -    qdev_prop_set_bit(gicdev, "has-security-extensions", true);
> +    qdev_prop_set_bit(dev, "has-security-extensions", true);
> +    object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
>  
> -    sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal);
> +    sysbus_realize_and_unref(sbd, &error_fatal);
>  
> -    for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> -        MemoryRegion *mr;
> +    memory_region_add_subregion(mr, map->gic.dist,
> +                                sysbus_mmio_get_region(sbd, 0));
> +    memory_region_add_subregion(mr, map->gic.redist,
> +                                sysbus_mmio_get_region(sbd, 1));
>  
> -        mr = sysbus_mmio_get_region(gicbusdev, i);
> -        memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
> +    if (map->dtb_expose) {
> +        node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible,
> +                                      sizeof(compatible));
> +        qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
> +        qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
> +        qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
> +                                     2, map->gic.dist,
> +                                     2, 0x10000,
> +                                     2, map->gic.redist,
> +                                     2, GICV3_REDIST_SIZE * num_cpu);
> +        qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> +                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +        qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
>      }
>  
> -    for (i = 0; i < nr_apu_cpus; i++) {
> -        DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
> -        int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
> -        qemu_irq maint_irq;
> -        int ti;
> -        /* Mapping from the output timer irq lines from the CPU to the
> -         * GIC PPI inputs.
> -         */
> -        const int timer_irq[] = {
> -            [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
> -            [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
> -            [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
> -            [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
> -        };
> +    return dev;
> +}
>  
> +static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
> +                               DeviceState *gic, DeviceState *cpu, size_t idx,
> +                               size_t num_cpu)
> +{
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(gic);
> +    int ppibase = map->gic.num_irq + idx * GIC_INTERNAL + GIC_NR_SGIS;
> +    int ti;
> +    bool has_gtimer;
> +    /*
> +     * Mapping from the output timer irq lines from the CPU to the
> +     * GIC PPI inputs.
> +     */
> +    const int timer_irq[] = {
> +        [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
> +        [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
> +        [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
> +        [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
> +    };
> +
> +    has_gtimer = arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_GENERIC_TIMER);
> +
> +    if (has_gtimer) {
>          for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
> -            qdev_connect_gpio_out(cpudev, ti,
> -                                  qdev_get_gpio_in(gicdev,
> +            qdev_connect_gpio_out(cpu, ti,
> +                                  qdev_get_gpio_in(gic,
>                                                     ppibase + timer_irq[ti]));
>          }
> -        maint_irq = qdev_get_gpio_in(gicdev,
> -                                        ppibase + VERSAL_GIC_MAINT_IRQ);
> -        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
> +    }
> +
> +    if (map->gic.version == 3) {
> +        qemu_irq maint_irq;
> +
> +        maint_irq = qdev_get_gpio_in(gic,
> +                                     ppibase + VERSAL_GIC_MAINT_IRQ);
> +        qdev_connect_gpio_out_named(cpu, "gicv3-maintenance-interrupt",
>                                      0, maint_irq);
> -        sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> -        sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
> -                           qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> -        sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
> -                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
> -        sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
> -                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
>      }
>  
> -    for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
> -        pic[i] = qdev_get_gpio_in(gicdev, i);
> +    sysbus_connect_irq(sbd, idx, qdev_get_gpio_in(cpu, ARM_CPU_IRQ));
> +    sysbus_connect_irq(sbd, idx + num_cpu,
> +                       qdev_get_gpio_in(cpu, ARM_CPU_FIQ));
> +    sysbus_connect_irq(sbd, idx + 2 * num_cpu,
> +                       qdev_get_gpio_in(cpu, ARM_CPU_VIRQ));
> +    sysbus_connect_irq(sbd, idx + 3 * num_cpu,
> +                       qdev_get_gpio_in(cpu, ARM_CPU_VFIQ));
> +}
> +
> +static inline void versal_create_and_connect_gic(Versal *s,
> +                                                 const VersalCpuClusterMap *map,
> +                                                 MemoryRegion *mr,
> +                                                 DeviceState **cpus,
> +                                                 size_t num_cpu)
> +{
> +    DeviceState *gic;
> +    size_t i;
> +
> +    gic = versal_create_gic(s, map, mr, num_cpu);
> +
> +    for (i = 0; i < num_cpu; i++) {
> +        connect_gic_to_cpu(map, gic, cpus[i], i, num_cpu);
> +    }
> +}
> +
> +static DeviceState *versal_create_cpu(Versal *s,
> +                                      const VersalCpuClusterMap *map,
> +                                      DeviceState *qemu_cluster,
> +                                      MemoryRegion *cpu_mr,
> +                                      size_t cluster_idx,
> +                                      size_t core_idx)
> +{
> +    DeviceState *cpu = qdev_new(map->cpu_model);
> +    ARMCPU *arm_cpu = ARM_CPU(cpu);
> +    Object *obj = OBJECT(cpu);
> +    bool start_off;
> +    size_t idx = cluster_idx * map->num_core + core_idx;
> +    g_autofree char *name;
> +    g_autofree char *node = NULL;
> +
> +    start_off = map->start_powered_off == SPO_ALL
> +        || ((map->start_powered_off == SPO_SECONDARIES)
> +            && (cluster_idx || core_idx));
> +
> +    name = g_strdup_printf("%s[*]", map->name);
> +    object_property_add_child(OBJECT(qemu_cluster), name, obj);
> +    object_property_set_bool(obj, "start-powered-off", start_off,
> +                             &error_abort);
> +    qdev_prop_set_int32(cpu, "core-count",  map->num_core);
> +    object_property_set_link(obj, "memory", OBJECT(cpu_mr), &error_abort);
> +    qdev_realize_and_unref(cpu, NULL, &error_fatal);
> +
> +    if (!map->dtb_expose) {
> +        return cpu;
> +    }
> +
> +    node = versal_fdt_add_subnode(s, "/cpus/cpu", idx,
> +                                  arm_cpu->dtb_compatible,
> +                                  strlen(arm_cpu->dtb_compatible) + 1);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "reg",
> +                          arm_cpu_mp_affinity(arm_cpu) & ARM64_AFFINITY_MASK);
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "device_type", "cpu");
> +    qemu_fdt_setprop_string(s->cfg.fdt, node, "enable-method", "psci");
> +
> +    return cpu;
> +}
> +
> +static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
> +{
> +    size_t i, j;
> +    DeviceState *cluster;
> +    MemoryRegion *mr;
> +    char *name;
> +    g_autofree DeviceState **cpus;
> +    const char compatible[] = "arm,armv8-timer";
> +    bool has_gtimer;
> +
> +    cluster = qdev_new(TYPE_CPU_CLUSTER);
> +    name = g_strdup_printf("%s-cluster", map->name);
> +    object_property_add_child(OBJECT(s), name, OBJECT(cluster));
> +    g_free(name);
> +    qdev_prop_set_uint32(cluster, "cluster-id", map->qemu_cluster_id);
> +
> +    mr = create_cpu_mr(s, cluster, map);
> +
> +    cpus = g_new(DeviceState *, map->num_cluster * map->num_core);
> +
> +    if (map->dtb_expose) {
> +        qemu_fdt_add_subnode(s->cfg.fdt, "/cpus");
> +        qemu_fdt_setprop_cell(s->cfg.fdt, "/cpus", "#size-cells", 0);
> +        qemu_fdt_setprop_cell(s->cfg.fdt, "/cpus", "#address-cells", 1);
> +    }
> +
> +    for (i = 0; i < map->num_cluster; i++) {
> +        for (j = 0; j < map->num_core; j++) {
> +            DeviceState *cpu = versal_create_cpu(s, map, cluster, mr, i, j);
> +
> +            cpus[i * map->num_core + j] = cpu;
> +        }
> +
> +    }
> +
> +    qdev_realize_and_unref(cluster, NULL, &error_fatal);
> +
> +    versal_create_and_connect_gic(s, map, mr, cpus,
> +                                  map->num_cluster * map->num_core);
> +
> +    has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
> +    if (map->dtb_expose && has_gtimer) {
> +        qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
> +        qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
> +                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> +                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> +                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> +                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ,
> +                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +        qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
> +                         compatible, sizeof(compatible));
>      }
>  }
>  
>  static void versal_create_rpu_cpus(Versal *s)
>  {
> @@ -1277,11 +1455,10 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>  
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
>      Versal *s = XLNX_VERSAL_BASE(dev);
>      DeviceState *slcr, *ospi;
> -    qemu_irq pic[XLNX_VERSAL_NR_IRQS];
>      Object *container;
>      const VersalMap *map = versal_get_map(s);
>      size_t i;
>  
>      if (s->cfg.fdt == NULL) {
> @@ -1290,18 +1467,21 @@ static void versal_realize(DeviceState *dev, Error **errp)
>          s->cfg.fdt = create_device_tree(&fdt_size);
>      }
>  
>      s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
>      s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
> -
> -    versal_create_apu_cpus(s);
> -    versal_create_apu_gic(s, pic);
> +    s->phandle.gic = qemu_fdt_alloc_phandle(s->cfg.fdt);
>  
>      container = object_new(TYPE_CONTAINER);
>      object_property_add_child(OBJECT(s), "irq-or-gates", container);
>      object_unref(container);
>  
> +    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#size-cells", 0x2);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#address-cells", 0x2);
> +
> +    versal_create_cpu_cluster(s, &map->apu);
>      versal_create_rpu_cpus(s);
>  
>      for (i = 0; i < map->num_uart; i++) {
>          versal_create_uart(s, &map->uart[i], i);
>      }
> @@ -1348,11 +1528,10 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      /* Create the On Chip Memory (OCM).  */
>      memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
>                             MM_OCM_SIZE, &error_fatal);
>  
>      memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
> -    memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
>      memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
>                                          &s->lpd.rpu.mr_ps_alias, 0);
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
> @@ -1456,11 +1635,10 @@ int versal_get_num_sdhci(VersalVersion version)
>  static void versal_base_init(Object *obj)
>  {
>      Versal *s = XLNX_VERSAL_BASE(obj);
>      size_t i, num_can;
>  
> -    memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
>      memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
>      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
>      memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
>                               "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping
  2025-07-16  9:54 ` [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping Luc Michel
@ 2025-07-29 20:15   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 20:15 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:04AM +0200, Luc Michel wrote:
> Add a way to configure the MP affinity value of the CPUs given their
> core and cluster IDs. For the Versal APU CPUs, the MP affinity value is
> directly given by the core ID.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 5a08ad07b28..35c32de0159 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -88,10 +88,18 @@ typedef struct VersalCpuClusterMap {
>      size_t num_core;
>      size_t num_cluster;
>      uint32_t qemu_cluster_id;
>      bool dtb_expose;
>  
> +    struct {
> +        uint64_t base;
> +        uint64_t core_mask;
> +        uint64_t core_shift;
> +        uint64_t cluster_mask;
> +        uint64_t cluster_shift;
> +    } mp_affinity;
> +
>      enum StartPoweredOffMode start_powered_off;
>  } VersalCpuClusterMap;
>  
>  typedef struct VersalMap {
>      VersalCpuClusterMap apu;
> @@ -196,10 +204,15 @@ static const VersalMap VERSAL_MAP = {
>          .name = "apu",
>          .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
>          .num_cluster = 1,
>          .num_core = 2,
>          .qemu_cluster_id = 0,
> +        .mp_affinity = {
> +            .base = 0x0,
> +            .core_mask = 0xff,
> +            .core_shift = 0,
> +        },
>          .start_powered_off = SPO_SECONDARIES,
>          .dtb_expose = true,
>          .gic = {
>              .version = 3,
>              .dist = 0xf9000000,
> @@ -565,23 +578,31 @@ static DeviceState *versal_create_cpu(Versal *s,
>                                        size_t core_idx)
>  {
>      DeviceState *cpu = qdev_new(map->cpu_model);
>      ARMCPU *arm_cpu = ARM_CPU(cpu);
>      Object *obj = OBJECT(cpu);
> +    uint64_t affinity;
>      bool start_off;
>      size_t idx = cluster_idx * map->num_core + core_idx;
>      g_autofree char *name;
>      g_autofree char *node = NULL;
>  
> +    affinity = map->mp_affinity.base;
> +    affinity |= (cluster_idx & map->mp_affinity.cluster_mask)
> +        << map->mp_affinity.cluster_shift;
> +    affinity |= (core_idx & map->mp_affinity.core_mask)
> +        << map->mp_affinity.core_shift;
> +
>      start_off = map->start_powered_off == SPO_ALL
>          || ((map->start_powered_off == SPO_SECONDARIES)
>              && (cluster_idx || core_idx));
>  
>      name = g_strdup_printf("%s[*]", map->name);
>      object_property_add_child(OBJECT(qemu_cluster), name, obj);
>      object_property_set_bool(obj, "start-powered-off", start_off,
>                               &error_abort);
> +    qdev_prop_set_uint64(cpu, "mp-affinity", affinity);
>      qdev_prop_set_int32(cpu, "core-count",  map->num_core);
>      object_property_set_link(obj, "memory", OBJECT(cpu_mr), &error_abort);
>      qdev_realize_and_unref(cpu, NULL, &error_fatal);
>  
>      if (!map->dtb_expose) {
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU
  2025-07-16  9:54 ` [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU Luc Michel
@ 2025-07-29 20:16   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-29 20:16 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:05AM +0200, Luc Michel wrote:
> Add the instance of the GIC ITS in the APU.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 35c32de0159..ba8c69bd435 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -42,10 +42,11 @@
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "hw/or-irq.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/intc/arm_gicv3_common.h"
> +#include "hw/intc/arm_gicv3_its_common.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -70,11 +71,13 @@ typedef struct VersalSimplePeriphMap {
>  
>  typedef struct VersalGicMap {
>      int version;
>      uint64_t dist;
>      uint64_t redist;
> +    uint64_t its;
>      size_t num_irq;
> +    bool has_its;
>  } VersalGicMap;
>  
>  enum StartPoweredOffMode {
>      SPO_SECONDARIES,
>      SPO_ALL,
> @@ -216,10 +219,12 @@ static const VersalMap VERSAL_MAP = {
>          .gic = {
>              .version = 3,
>              .dist = 0xf9000000,
>              .redist = 0xf9080000,
>              .num_irq = 192,
> +            .has_its = true,
> +            .its = 0xf9020000,
>          },
>      },
>  
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
> @@ -452,10 +457,52 @@ static MemoryRegion *create_cpu_mr(Versal *s, DeviceState *cluster,
>      memory_region_add_subregion(mr, 0, root_alias);
>  
>      return mr;
>  }
>  
> +static void versal_create_gic_its(Versal *s,
> +                                  const VersalCpuClusterMap *map,
> +                                  DeviceState *gic,
> +                                  MemoryRegion *mr,
> +                                  char *gic_node)
> +{
> +    DeviceState *dev;
> +    SysBusDevice *sbd;
> +    g_autofree char *node_pat = NULL, *node = NULL;
> +    const char compatible[] = "arm,gic-v3-its";
> +
> +    if (!map->gic.has_its) {
> +        return;
> +    }
> +
> +    dev = qdev_new(TYPE_ARM_GICV3_ITS);
> +    sbd = SYS_BUS_DEVICE(dev);
> +
> +    object_property_add_child(OBJECT(gic), "its", OBJECT(dev));
> +    object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(gic),
> +                             &error_abort);
> +
> +    sysbus_realize_and_unref(sbd, &error_abort);
> +
> +    memory_region_add_subregion(mr, map->gic.its,
> +                                sysbus_mmio_get_region(sbd, 0));
> +
> +    if (!map->dtb_expose) {
> +        return;
> +    }
> +
> +    qemu_fdt_setprop(s->cfg.fdt, gic_node, "ranges", NULL, 0);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#address-cells", 2);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#size-cells", 2);
> +
> +    node_pat = g_strdup_printf("%s/its", gic_node);
> +    node = versal_fdt_add_simple_subnode(s, node_pat, map->gic.its, 0x20000,
> +                                         compatible, sizeof(compatible));
> +    qemu_fdt_setprop(s->cfg.fdt, node, "msi-controller", NULL, 0);
> +    qemu_fdt_setprop_cell(s->cfg.fdt, node, "#msi-cells", 1);
> +}
> +
>  static DeviceState *versal_create_gic(Versal *s,
>                                        const VersalCpuClusterMap *map,
>                                        MemoryRegion *mr,
>                                        size_t num_cpu)
>  {
> @@ -477,10 +524,11 @@ static DeviceState *versal_create_gic(Versal *s,
>      redist_region_count = qlist_new();
>      qlist_append_int(redist_region_count, num_cpu);
>      qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
>  
>      qdev_prop_set_bit(dev, "has-security-extensions", true);
> +    qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
>      object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
>  
>      sysbus_realize_and_unref(sbd, &error_fatal);
>  
>      memory_region_add_subregion(mr, map->gic.dist,
> @@ -502,10 +550,12 @@ static DeviceState *versal_create_gic(Versal *s,
>                                 GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>          qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
>      }
>  
> +    versal_create_gic_its(s, map, dev, mr, node);
> +
>      return dev;
>  }
>  
>  static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
>                                 DeviceState *gic, DeviceState *cpu, size_t idx,
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs
  2025-07-16  9:54 ` [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs Luc Michel
@ 2025-07-30 14:26   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 14:26 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:07AM +0200, Luc Michel wrote:
> The Versal SoC contains two GICs: one GICv3 in the APU and one GICv2 in
> the RPU (currently not instantiated). To prepare for the GICv2
> instantiation, add support for multiple GICs when connecting interrupts.
> 
> When a GIC is created, the first-cpu-index property is set on it, and a
> pointer to the GIC is stored in the intc array. When connecting an IRQ,
> a TYPE_SPLIT_IRQ device is created with its num-lines property set to
> the number of GICs in the SoC. The split device is used to fan out the
> IRQ to all the GICs.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  1 +
>  hw/arm/xlnx-versal.c         | 55 +++++++++++++++++++++++++++++++++---
>  2 files changed, 52 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index ba5719d80f5..9b11ffb845d 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -40,10 +40,11 @@ OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  struct Versal {
>      /*< private >*/
>      SysBusDevice parent_obj;
>  
>      /*< public >*/
> +    GArray *intc;
>      MemoryRegion mr_ps;
>  
>      struct {
>          /* 4 ranges to access DDR.  */
>          MemoryRegion mr_ddr_ranges[4];
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index ba8c69bd435..58cd874f81f 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -43,10 +43,11 @@
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "hw/or-irq.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/intc/arm_gicv3_common.h"
>  #include "hw/intc/arm_gicv3_its_common.h"
> +#include "hw/core/split-irq.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -318,10 +319,47 @@ static inline Object *versal_get_child_idx(Versal *s, const char *child,
>      g_autofree char *n = g_strdup_printf("%s[%zu]", child, idx);
>  
>      return versal_get_child(s, n);
>  }
>  
> +/*
> + * The SoC embeds multiple GICs. They all receives the same IRQ lines at the
> + * same index. This function creates a TYPE_SPLIT_IRQ device to fan out the
> + * given IRQ input to all the GICs.
> + *
> + * The TYPE_SPLIT_IRQ devices lie in the /soc/irq-splits QOM container
> + */
> +static qemu_irq versal_get_gic_irq(Versal *s, int irq_idx)
> +{
> +    DeviceState *split;
> +    Object *container = versal_get_child(s, "irq-splits");
> +    int idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> +    g_autofree char *name = g_strdup_printf("irq[%d]", idx);
> +
> +    split = DEVICE(object_resolve_path_at(container, name));
> +
> +    if (split == NULL) {
> +        size_t i;
> +
> +        split = qdev_new(TYPE_SPLIT_IRQ);
> +        qdev_prop_set_uint16(split, "num-lines", s->intc->len);
> +        object_property_add_child(container, name, OBJECT(split));
> +        qdev_realize_and_unref(split, NULL, &error_abort);
> +
> +        for (i = 0; i < s->intc->len; i++) {
> +            DeviceState *gic;
> +
> +            gic = g_array_index(s->intc, DeviceState *, i);
> +            qdev_connect_gpio_out(split, i, qdev_get_gpio_in(gic, idx));
> +        }
> +    } else {
> +        g_assert(FIELD_EX32(irq_idx, VERSAL_IRQ, ORED));
> +    }
> +
> +    return qdev_get_gpio_in(split, 0);
> +}
> +
>  /*
>   * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
>   * used to return the corresponding or gate input IRQ. The or gate is created if
>   * not already existant.
>   *
> @@ -354,16 +392,14 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
>  
>  static qemu_irq versal_get_irq(Versal *s, int irq_idx)
>  {
>      qemu_irq irq;
>      bool ored;
> -    DeviceState *gic;
>  
>      ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
>  
> -    gic = DEVICE(versal_get_child_idx(s, "apu-gic", 0));
> -    irq = qdev_get_gpio_in(gic, irq_idx);
> +    irq = versal_get_gic_irq(s, irq_idx);
>  
>      if (ored) {
>          irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
>      }
>  
> @@ -502,10 +538,11 @@ static void versal_create_gic_its(Versal *s,
>  }
>  
>  static DeviceState *versal_create_gic(Versal *s,
>                                        const VersalCpuClusterMap *map,
>                                        MemoryRegion *mr,
> +                                      int first_cpu_idx,
>                                        size_t num_cpu)
>  {
>      DeviceState *dev;
>      SysBusDevice *sbd;
>      QList *redist_region_count;
> @@ -526,10 +563,11 @@ static DeviceState *versal_create_gic(Versal *s,
>      qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
>  
>      qdev_prop_set_bit(dev, "has-security-extensions", true);
>      qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
>      object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
> +    qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx);
>  
>      sysbus_realize_and_unref(sbd, &error_fatal);
>  
>      memory_region_add_subregion(mr, map->gic.dist,
>                                  sysbus_mmio_get_region(sbd, 0));
> @@ -552,10 +590,12 @@ static DeviceState *versal_create_gic(Versal *s,
>          qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
>      }
>  
>      versal_create_gic_its(s, map, dev, mr, node);
>  
> +    g_array_append_val(s->intc, dev);
> +
>      return dev;
>  }
>  
>  static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
>                                 DeviceState *gic, DeviceState *cpu, size_t idx,
> @@ -609,13 +649,15 @@ static inline void versal_create_and_connect_gic(Versal *s,
>                                                   MemoryRegion *mr,
>                                                   DeviceState **cpus,
>                                                   size_t num_cpu)
>  {
>      DeviceState *gic;
> +    int first_cpu_idx;
>      size_t i;
>  
> -    gic = versal_create_gic(s, map, mr, num_cpu);
> +    first_cpu_idx = CPU(cpus[0])->cpu_index;
> +    gic = versal_create_gic(s, map, mr, first_cpu_idx, num_cpu);
>  
>      for (i = 0; i < num_cpu; i++) {
>          connect_gic_to_cpu(map, gic, cpus[i], i, num_cpu);
>      }
>  }
> @@ -1540,10 +1582,14 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      s->phandle.clk_25mhz = fdt_add_clk_node(s, "/clk25", 25 * 1000 * 1000);
>      s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
>      s->phandle.gic = qemu_fdt_alloc_phandle(s->cfg.fdt);
>  
> +    container = object_new(TYPE_CONTAINER);
> +    object_property_add_child(OBJECT(s), "irq-splits", container);
> +    object_unref(container);
> +
>      container = object_new(TYPE_CONTAINER);
>      object_property_add_child(OBJECT(s), "irq-or-gates", container);
>      object_unref(container);
>  
>      qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
> @@ -1710,10 +1756,11 @@ static void versal_base_init(Object *obj)
>  
>      memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
>      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
>      memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
>                               "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
> +    s->intc = g_array_new(false, false, sizeof(DeviceState *));
>  
>      num_can = versal_get_map(s)->num_canfd;
>      s->cfg.canbus = g_new0(CanBusState *, num_can);
>  
>      for (i = 0; i < num_can; i++) {
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2
  2025-07-16  9:54 ` [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2 Luc Michel
@ 2025-07-30 14:29   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 14:29 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:08AM +0200, Luc Michel wrote:
> Add support for GICv2 instantiation in the Versal SoC. This is in
> preparation for the RPU refactoring.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 82 +++++++++++++++++++++++++++++++++-----------
>  1 file changed, 62 insertions(+), 20 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 58cd874f81f..771f6108558 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -43,10 +43,11 @@
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
>  #include "hw/or-irq.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/intc/arm_gicv3_common.h"
>  #include "hw/intc/arm_gicv3_its_common.h"
> +#include "hw/intc/arm_gic.h"
>  #include "hw/core/split-irq.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
> @@ -72,10 +73,11 @@ typedef struct VersalSimplePeriphMap {
>  
>  typedef struct VersalGicMap {
>      int version;
>      uint64_t dist;
>      uint64_t redist;
> +    uint64_t cpu_iface;
>      uint64_t its;
>      size_t num_irq;
>      bool has_its;
>  } VersalGicMap;
>  
> @@ -504,10 +506,14 @@ static void versal_create_gic_its(Versal *s,
>      DeviceState *dev;
>      SysBusDevice *sbd;
>      g_autofree char *node_pat = NULL, *node = NULL;
>      const char compatible[] = "arm,gic-v3-its";
>  
> +    if (map->gic.version != 3) {
> +        return;
> +    }
> +
>      if (!map->gic.has_its) {
>          return;
>      }
>  
>      dev = qdev_new(TYPE_ARM_GICV3_ITS);
> @@ -543,49 +549,85 @@ static DeviceState *versal_create_gic(Versal *s,
>                                        int first_cpu_idx,
>                                        size_t num_cpu)
>  {
>      DeviceState *dev;
>      SysBusDevice *sbd;
> -    QList *redist_region_count;
>      g_autofree char *node = NULL;
>      g_autofree char *name = NULL;
> -    const char compatible[] = "arm,gic-v3";
> +    const char gicv3_compat[] = "arm,gic-v3";
> +    const char gicv2_compat[] = "arm,cortex-a15-gic";
> +
> +    switch (map->gic.version) {
> +    case 2:
> +        dev = qdev_new(gic_class_name());
> +        break;
> +
> +    case 3:
> +        dev = qdev_new(gicv3_class_name());
> +        break;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
>  
> -    dev = qdev_new(gicv3_class_name());
>      name = g_strdup_printf("%s-gic[*]", map->name);
>      object_property_add_child(OBJECT(s), name, OBJECT(dev));
>      sbd = SYS_BUS_DEVICE(dev);
> -    qdev_prop_set_uint32(dev, "revision", 3);
> +    qdev_prop_set_uint32(dev, "revision", map->gic.version);
>      qdev_prop_set_uint32(dev, "num-cpu", num_cpu);
>      qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32);
> -
> -    redist_region_count = qlist_new();
> -    qlist_append_int(redist_region_count, num_cpu);
> -    qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
> -
>      qdev_prop_set_bit(dev, "has-security-extensions", true);
> -    qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
> -    object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort);
>      qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx);
>  
> +    if (map->gic.version == 3) {
> +        QList *redist_region_count;
> +
> +        redist_region_count = qlist_new();
> +        qlist_append_int(redist_region_count, num_cpu);
> +        qdev_prop_set_array(dev, "redist-region-count", redist_region_count);
> +        qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its);
> +        object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr),
> +                                 &error_abort);
> +
> +    }
> +
>      sysbus_realize_and_unref(sbd, &error_fatal);
>  
>      memory_region_add_subregion(mr, map->gic.dist,
>                                  sysbus_mmio_get_region(sbd, 0));
> -    memory_region_add_subregion(mr, map->gic.redist,
> -                                sysbus_mmio_get_region(sbd, 1));
> +
> +    if (map->gic.version == 3) {
> +        memory_region_add_subregion(mr, map->gic.redist,
> +                                    sysbus_mmio_get_region(sbd, 1));
> +    } else {
> +        memory_region_add_subregion(mr, map->gic.cpu_iface,
> +                                    sysbus_mmio_get_region(sbd, 1));
> +    }
>  
>      if (map->dtb_expose) {
> -        node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible,
> -                                      sizeof(compatible));
> +        if (map->gic.version == 3) {
> +            node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
> +                                          gicv3_compat,
> +                                          sizeof(gicv3_compat));
> +            qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
> +                                         2, map->gic.dist,
> +                                         2, 0x10000,
> +                                         2, map->gic.redist,
> +                                         2, GICV3_REDIST_SIZE * num_cpu);
> +        } else {
> +            node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
> +                                          gicv2_compat,
> +                                          sizeof(gicv2_compat));
> +            qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
> +                                         2, map->gic.dist,
> +                                         2, 0x1000,
> +                                         2, map->gic.cpu_iface,
> +                                         2, 0x1000);
> +        }
> +
>          qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
>          qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
> -        qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
> -                                     2, map->gic.dist,
> -                                     2, 0x10000,
> -                                     2, map->gic.redist,
> -                                     2, GICV3_REDIST_SIZE * num_cpu);
>          qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
>                                 GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>          qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
>      }
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation
  2025-07-16  9:54 ` [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation Luc Michel
@ 2025-07-30 19:03   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:03 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:09AM +0200, Luc Michel wrote:
> Refactor the RPU cluster creation using the VersalMap structure. This
> effectively instantiate the RPU GICv2 which was not instantiated before.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h | 11 -------
>  hw/arm/xlnx-versal-virt.c    |  1 +
>  hw/arm/xlnx-versal.c         | 60 +++++++++++++++---------------------
>  3 files changed, 26 insertions(+), 46 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 9b11ffb845d..62b8d234ecb 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -12,14 +12,12 @@
>  
>  #ifndef XLNX_VERSAL_H
>  #define XLNX_VERSAL_H
>  
>  #include "hw/sysbus.h"
> -#include "hw/cpu/cluster.h"
>  #include "qom/object.h"
>  #include "net/can_emu.h"
> -#include "target/arm/cpu.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
>  #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
>  OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  
> @@ -50,19 +48,10 @@ struct Versal {
>          MemoryRegion mr_ddr_ranges[4];
>      } noc;
>  
>      struct {
>          MemoryRegion mr_ocm;
> -
> -        /* Real-time Processing Unit.  */
> -        struct {
> -            MemoryRegion mr;
> -            MemoryRegion mr_ps_alias;
> -
> -            CPUClusterState cluster;
> -            ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
> -        } rpu;
>      } lpd;
>  
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 55159536ceb..cad345b98e0 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -22,10 +22,11 @@
>  #include "hw/qdev-properties.h"
>  #include "hw/arm/xlnx-versal.h"
>  #include "hw/arm/boot.h"
>  #include "target/arm/multiprocessing.h"
>  #include "qom/object.h"
> +#include "target/arm/cpu.h"
>  
>  #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
>  OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
>  
>  #define XLNX_VERSAL_NUM_OSPI_FLASH 4
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 771f6108558..3905549b32e 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -45,10 +45,12 @@
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/intc/arm_gicv3_common.h"
>  #include "hw/intc/arm_gicv3_its_common.h"
>  #include "hw/intc/arm_gic.h"
>  #include "hw/core/split-irq.h"
> +#include "target/arm/cpu.h"
> +#include "hw/cpu/cluster.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -107,10 +109,11 @@ typedef struct VersalCpuClusterMap {
>      enum StartPoweredOffMode start_powered_off;
>  } VersalCpuClusterMap;
>  
>  typedef struct VersalMap {
>      VersalCpuClusterMap apu;
> +    VersalCpuClusterMap rpu;
>  
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
>  
>      VersalSimplePeriphMap canfd[4];
> @@ -227,10 +230,31 @@ static const VersalMap VERSAL_MAP = {
>              .has_its = true,
>              .its = 0xf9020000,
>          },
>      },
>  
> +    .rpu = {
> +        .name = "rpu",
> +        .cpu_model = ARM_CPU_TYPE_NAME("cortex-r5f"),
> +        .num_cluster = 1,
> +        .num_core = 2,
> +        .qemu_cluster_id = 1,
> +        .mp_affinity = {
> +            .base = 0x100,
> +            .core_mask = 0xff,
> +            .core_shift = 0,
> +        },
> +        .start_powered_off = SPO_ALL,
> +        .dtb_expose = false,
> +        .gic = {
> +            .version = 2,
> +            .dist = 0xf9000000,
> +            .cpu_iface = 0xf9001000,
> +            .num_irq = 192,
> +        },
> +    },
> +
>      .uart[0] = { 0xff000000, 18 },
>      .uart[1] = { 0xff010000, 19 },
>      .num_uart = 2,
>  
>      .canfd[0] = { 0xff060000, 20 },
> @@ -809,39 +833,10 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
>          qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
>                           compatible, sizeof(compatible));
>      }
>  }
>  
> -static void versal_create_rpu_cpus(Versal *s)
> -{
> -    int i;
> -
> -    object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
> -                            TYPE_CPU_CLUSTER);
> -    qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
> -
> -    for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
> -        Object *obj;
> -
> -        object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
> -                                "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
> -                                XLNX_VERSAL_RCPU_TYPE);
> -        obj = OBJECT(&s->lpd.rpu.cpu[i]);
> -        object_property_set_bool(obj, "start-powered-off", true,
> -                                 &error_abort);
> -
> -        object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
> -        object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
> -                                &error_abort);
> -        object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
> -                                 &error_abort);
> -        qdev_realize(DEVICE(obj), NULL, &error_fatal);
> -    }
> -
> -    qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
> -}
> -
>  static void versal_create_uart(Versal *s,
>                                 const VersalSimplePeriphMap *map,
>                                 int chardev_idx)
>  {
>      DeviceState *dev;
> @@ -1637,11 +1632,11 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      qemu_fdt_setprop_cell(s->cfg.fdt, "/", "interrupt-parent", s->phandle.gic);
>      qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#size-cells", 0x2);
>      qemu_fdt_setprop_cell(s->cfg.fdt, "/", "#address-cells", 0x2);
>  
>      versal_create_cpu_cluster(s, &map->apu);
> -    versal_create_rpu_cpus(s);
> +    versal_create_cpu_cluster(s, &map->rpu);
>  
>      for (i = 0; i < map->num_uart; i++) {
>          versal_create_uart(s, &map->uart[i], i);
>      }
>  
> @@ -1687,12 +1682,10 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      /* Create the On Chip Memory (OCM).  */
>      memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
>                             MM_OCM_SIZE, &error_fatal);
>  
>      memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
> -    memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
> -                                        &s->lpd.rpu.mr_ps_alias, 0);
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
>  {
>      DeviceState *sdhci, *card;
> @@ -1794,14 +1787,11 @@ int versal_get_num_sdhci(VersalVersion version)
>  static void versal_base_init(Object *obj)
>  {
>      Versal *s = XLNX_VERSAL_BASE(obj);
>      size_t i, num_can;
>  
> -    memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
>      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
> -    memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
> -                             "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
>      s->intc = g_array_new(false, false, sizeof(DeviceState *));
>  
>      num_can = versal_get_map(s)->num_canfd;
>      s->cfg.canbus = g_new0(CanBusState *, num_can);
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 28/48] hw/arm/xlnx-versal: ocm: refactor creation
  2025-07-16  9:54 ` [PATCH 28/48] hw/arm/xlnx-versal: ocm: " Luc Michel
@ 2025-07-30 19:04   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:04 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:10AM +0200, Luc Michel wrote:
> Refactor the OCM creation using the VersalMap structure.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  4 ----
>  hw/arm/xlnx-versal.c         | 20 ++++++++++++++++----
>  2 files changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 62b8d234ecb..7be5a6ccf4d 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -46,14 +46,10 @@ struct Versal {
>      struct {
>          /* 4 ranges to access DDR.  */
>          MemoryRegion mr_ddr_ranges[4];
>      } noc;
>  
> -    struct {
> -        MemoryRegion mr_ocm;
> -    } lpd;
> -
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
>          uint32_t gic;
>      } phandle;
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 3905549b32e..f46c73ac8e7 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -71,10 +71,15 @@ FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
>  typedef struct VersalSimplePeriphMap {
>      uint64_t addr;
>      int irq;
>  } VersalSimplePeriphMap;
>  
> +typedef struct VersalMemMap {
> +    uint64_t addr;
> +    uint64_t size;
> +} VersalMemMap;
> +
>  typedef struct VersalGicMap {
>      int version;
>      uint64_t dist;
>      uint64_t redist;
>      uint64_t cpu_iface;
> @@ -108,10 +113,12 @@ typedef struct VersalCpuClusterMap {
>  
>      enum StartPoweredOffMode start_powered_off;
>  } VersalCpuClusterMap;
>  
>  typedef struct VersalMap {
> +    VersalMemMap ocm;
> +
>      VersalCpuClusterMap apu;
>      VersalCpuClusterMap rpu;
>  
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
> @@ -207,10 +214,15 @@ typedef struct VersalMap {
>          int irq_num;
>      } reserved;
>  } VersalMap;
>  
>  static const VersalMap VERSAL_MAP = {
> +    .ocm = {
> +        .addr = 0xfffc0000,
> +        .size = 0x40000,
> +    },
> +
>      .apu = {
>          .name = "apu",
>          .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
>          .num_cluster = 1,
>          .num_core = 2,
> @@ -1605,10 +1617,11 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>  
>  static void versal_realize(DeviceState *dev, Error **errp)
>  {
>      Versal *s = XLNX_VERSAL_BASE(dev);
>      DeviceState *slcr, *ospi;
> +    MemoryRegion *ocm;
>      Object *container;
>      const VersalMap *map = versal_get_map(s);
>      size_t i;
>  
>      if (s->cfg.fdt == NULL) {
> @@ -1678,14 +1691,13 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  
>      versal_map_ddr(s);
>      versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
> -    memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
> -                           MM_OCM_SIZE, &error_fatal);
> -
> -    memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
> +    ocm = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
> +    memory_region_add_subregion_overlap(&s->mr_ps, map->ocm.addr, ocm, 0);
>  }
>  
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
>  {
>      DeviceState *sdhci, *card;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 29/48] hw/arm/xlnx-versal: ddr: refactor creation
  2025-07-16  9:54 ` [PATCH 29/48] hw/arm/xlnx-versal: ddr: " Luc Michel
@ 2025-07-30 19:12   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:12 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:11AM +0200, Luc Michel wrote:
> Refactor the DDR aperture regions creation using the VersalMap
> structure. Device creation and FDT node creation are split into two
> functions because the later must happen during ARM virtual bootloader
> modify_dtb callback.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  7 +---
>  hw/arm/xlnx-versal-virt.c    | 79 +-----------------------------------
>  hw/arm/xlnx-versal.c         | 73 ++++++++++++++++++++++-----------
>  3 files changed, 53 insertions(+), 106 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 7be5a6ccf4d..a3bc967c352 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -41,15 +41,10 @@ struct Versal {
>  
>      /*< public >*/
>      GArray *intc;
>      MemoryRegion mr_ps;
>  
> -    struct {
> -        /* 4 ranges to access DDR.  */
> -        MemoryRegion mr_ddr_ranges[4];
> -    } noc;
> -
>      struct {
>          uint32_t clk_25mhz;
>          uint32_t clk_125mhz;
>          uint32_t gic;
>      } phandle;
> @@ -71,10 +66,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
>  {
>      g_assert(!qdev_is_realized(DEVICE(s)));
>      s->cfg.fdt = fdt;
>  }
>  
> +void versal_fdt_add_memory_nodes(Versal *s, uint64_t ram_size);
> +
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
>  void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_bbram_attach_drive(Versal *s, BlockBackend *blk);
>  void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>                                BlockBackend *blk);
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index cad345b98e0..7f40c197072 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -104,92 +104,17 @@ static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>          n++;
>      }
>      g_strfreev(node_path);
>  }
>  
> -static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
> -{
> -    /* Describes the various split DDR access regions.  */
> -    static const struct {
> -        uint64_t base;
> -        uint64_t size;
> -    } addr_ranges[] = {
> -        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
> -        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
> -        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
> -        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
> -    };
> -    uint64_t mem_reg_prop[8] = {0};
> -    uint64_t size = ram_size;
> -    Error *err = NULL;
> -    char *name;
> -    int i;
> -
> -    fdt_nop_memory_nodes(fdt, &err);
> -    if (err) {
> -        error_report_err(err);
> -        return;
> -    }
> -
> -    name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
> -    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
> -        uint64_t mapsize;
> -
> -        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
> -
> -        mem_reg_prop[i * 2] = addr_ranges[i].base;
> -        mem_reg_prop[i * 2 + 1] = mapsize;
> -        size -= mapsize;
> -    }
> -    qemu_fdt_add_subnode(fdt, name);
> -    qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
> -
> -    switch (i) {
> -    case 1:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1]);
> -        break;
> -    case 2:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3]);
> -        break;
> -    case 3:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3],
> -                                     2, mem_reg_prop[4],
> -                                     2, mem_reg_prop[5]);
> -        break;
> -    case 4:
> -        qemu_fdt_setprop_sized_cells(fdt, name, "reg",
> -                                     2, mem_reg_prop[0],
> -                                     2, mem_reg_prop[1],
> -                                     2, mem_reg_prop[2],
> -                                     2, mem_reg_prop[3],
> -                                     2, mem_reg_prop[4],
> -                                     2, mem_reg_prop[5],
> -                                     2, mem_reg_prop[6],
> -                                     2, mem_reg_prop[7]);
> -        break;
> -    default:
> -        g_assert_not_reached();
> -    }
> -    g_free(name);
> -}
> -
>  static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
>                                      void *fdt)
>  {
>      VersalVirt *s = container_of(binfo, VersalVirt, binfo);
>  
> -    fdt_add_memory_nodes(s, fdt, binfo->ram_size);
> +    fdt_nop_memory_nodes(s->fdt, &error_abort);
> +    versal_fdt_add_memory_nodes(&s->soc, binfo->ram_size);
>  }
>  
>  static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
>                                    int *fdt_size)
>  {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index f46c73ac8e7..bf680077e48 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -115,10 +115,15 @@ typedef struct VersalCpuClusterMap {
>  } VersalCpuClusterMap;
>  
>  typedef struct VersalMap {
>      VersalMemMap ocm;
>  
> +    struct VersalDDRMap {
> +        VersalMemMap chan[4];
> +        size_t num_chan;
> +    } ddr;
> +
>      VersalCpuClusterMap apu;
>      VersalCpuClusterMap rpu;
>  
>      VersalSimplePeriphMap uart[2];
>      size_t num_uart;
> @@ -219,10 +224,18 @@ static const VersalMap VERSAL_MAP = {
>      .ocm = {
>          .addr = 0xfffc0000,
>          .size = 0x40000,
>      },
>  
> +    .ddr = {
> +        .chan[0] = { .addr = 0x0, .size = 2 * GiB },
> +        .chan[1] = { .addr = 0x800000000ull, .size = 32 * GiB },
> +        .chan[2] = { .addr = 0xc00000000ull, .size = 256 * GiB },
> +        .chan[3] = { .addr = 0x10000000000ull, .size = 734 * GiB },
> +        .num_chan = 4,
> +    },
> +
>      .apu = {
>          .name = "apu",
>          .cpu_model = ARM_CPU_TYPE_NAME("cortex-a72"),
>          .num_cluster = 1,
>          .num_core = 2,
> @@ -1480,50 +1493,62 @@ static inline void versal_create_crl(Versal *s)
>                                  sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
>  
>      versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
>  }
>  
> -/* This takes the board allocated linear DDR memory and creates aliases
> +/*
> + * This takes the board allocated linear DDR memory and creates aliases
>   * for each split DDR range/aperture on the Versal address map.
>   */
> -static void versal_map_ddr(Versal *s)
> +static void versal_map_ddr(Versal *s, const struct VersalDDRMap *map)
>  {
>      uint64_t size = memory_region_size(s->cfg.mr_ddr);
> -    /* Describes the various split DDR access regions.  */
> -    static const struct {
> -        uint64_t base;
> -        uint64_t size;
> -    } addr_ranges[] = {
> -        { MM_TOP_DDR, MM_TOP_DDR_SIZE },
> -        { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
> -        { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
> -        { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
> -    };
>      uint64_t offset = 0;
>      int i;
>  
> -    assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
> -    for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
> -        char *name;
> +    for (i = 0; i < map->num_chan && size; i++) {
>          uint64_t mapsize;
> +        MemoryRegion *alias;
> +
> +        mapsize = MIN(size, map->chan[i].size);
>  
> -        mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
> -        name = g_strdup_printf("noc-ddr-range%d", i);
>          /* Create the MR alias.  */
> -        memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
> -                                 name, s->cfg.mr_ddr,
> -                                 offset, mapsize);
> +        alias = g_new(MemoryRegion, 1);
> +        memory_region_init_alias(alias, OBJECT(s), "noc-ddr-range",
> +                                 s->cfg.mr_ddr, offset, mapsize);
>  
>          /* Map it onto the NoC MR.  */
> -        memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
> -                                    &s->noc.mr_ddr_ranges[i]);
> +        memory_region_add_subregion(&s->mr_ps, map->chan[i].addr, alias);
>          offset += mapsize;
>          size -= mapsize;
> -        g_free(name);
>      }
>  }
>  
> +void versal_fdt_add_memory_nodes(Versal *s, uint64_t size)
> +{
> +    const struct VersalDDRMap *map = &versal_get_map(s)->ddr;
> +    g_autofree char *node;
> +    g_autofree uint64_t *reg;
> +    int i;
> +
> +    reg = g_new(uint64_t, map->num_chan * 2);
> +
> +    for (i = 0; i < map->num_chan && size; i++) {
> +        uint64_t mapsize;
> +
> +        mapsize = MIN(size, map->chan[i].size);
> +
> +        reg[i * 2] = cpu_to_be64(map->chan[i].addr);
> +        reg[i * 2 + 1] = cpu_to_be64(mapsize);
> +
> +        size -= mapsize;
> +    }
> +
> +    node = versal_fdt_add_subnode(s, "/memory", 0, "memory", sizeof("memory"));
> +    qemu_fdt_setprop(s->cfg.fdt, node, "reg", reg, sizeof(uint64_t) * i * 2);
> +}
> +
>  static void versal_unimp_area(Versal *s, const char *name,
>                                  MemoryRegion *mr,
>                                  hwaddr base, hwaddr size)
>  {
>      DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
> @@ -1687,11 +1712,11 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      versal_create_trng(s, &map->trng);
>      versal_create_rtc(s, &map->rtc);
>      versal_create_cfu(s, &map->cfu);
>      versal_create_crl(s);
>  
> -    versal_map_ddr(s);
> +    versal_map_ddr(s, &map->ddr);
>      versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
>      ocm = g_new(MemoryRegion, 1);
>      memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor
  2025-07-16  9:54 ` [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor Luc Michel
@ 2025-07-30 19:13   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:13 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:12AM +0200, Luc Michel wrote:
> Add the versal_get_num_cpu accessor to the Versal SoC to retrieve the
> number of CPUs in the SoC. Use it in the xlnx-versal-virt machine.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h | 1 +
>  hw/arm/xlnx-versal-virt.c    | 7 ++++---
>  hw/arm/xlnx-versal.c         | 8 ++++++++
>  3 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index a3bc967c352..ffa7801b30f 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -77,10 +77,11 @@ void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
>                                BlockBackend *blk);
>  
>  qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx);
>  hwaddr versal_get_reserved_mmio_addr(Versal *s);
>  
> +int versal_get_num_cpu(VersalVersion version);
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 7f40c197072..5e47a20922a 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -344,16 +344,17 @@ static void versal_virt_machine_finalize(Object *obj)
>  }
>  
>  static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
>  {
>      MachineClass *mc = MACHINE_CLASS(oc);
> +    int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
>  
>      mc->desc = "Xilinx Versal Virtual development board";
>      mc->init = versal_virt_init;
> -    mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
> -    mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
> -    mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
> +    mc->min_cpus = num_cpu;
> +    mc->max_cpus = num_cpu;
> +    mc->default_cpus = num_cpu;
>      mc->no_cdrom = true;
>      mc->auto_create_sdcard = true;
>      mc->default_ram_id = "ddr";
>      object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
>                                     versal_set_ospi_model);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index bf680077e48..5151822ad56 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -1805,10 +1805,18 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s)
>      const VersalMap *map = versal_get_map(s);
>  
>      return map->reserved.mmio_start;
>  }
>  
> +int versal_get_num_cpu(VersalVersion version)
> +{
> +    const VersalMap *map = VERSION_TO_MAP[version];
> +
> +    return map->apu.num_cluster * map->apu.num_core
> +        + map->rpu.num_cluster * map->rpu.num_core;
> +}
> +
>  int versal_get_num_can(VersalVersion version)
>  {
>      const VersalMap *map = VERSION_TO_MAP[version];
>  
>      return map->num_canfd;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives
  2025-07-16  9:54 ` [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives Luc Michel
@ 2025-07-30 19:14   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:14 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:13AM +0200, Luc Michel wrote:
> Drop unused include directives from xlnx-versal-crl.c
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/misc/xlnx-versal-crl.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index 08ff2fcc24f..f288545967a 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -1,18 +1,15 @@
>  /*
>   * QEMU model of the Clock-Reset-LPD (CRL).
>   *
> - * Copyright (c) 2022 Advanced Micro Devices, Inc.
> + * Copyright (c) 2022-2025 Advanced Micro Devices, Inc.
>   * SPDX-License-Identifier: GPL-2.0-or-later
>   *
>   * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
>   */
>  
>  #include "qemu/osdep.h"
> -#include "qapi/error.h"
> -#include "qemu/log.h"
> -#include "qemu/bitops.h"
>  #include "migration/vmstate.h"
>  #include "hw/qdev-properties.h"
>  #include "hw/sysbus.h"
>  #include "hw/irq.h"
>  #include "hw/register.h"
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes
  2025-07-16  9:54 ` [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes Luc Michel
@ 2025-07-30 19:23   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-30 19:23 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:14AM +0200, Luc Michel wrote:
> Split the TYPE_XLNX_VERSAL_CRL type into base and concrete classes. This
> is in preparation for the versal2 version of the CRL.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/misc/xlnx-versal-crl.h | 31 ++++++++++++++++++--
>  hw/misc/xlnx-versal-crl.c         | 48 +++++++++++++++++++------------
>  2 files changed, 58 insertions(+), 21 deletions(-)
> 
> diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
> index dba6d3585d1..2b39d203a67 100644
> --- a/include/hw/misc/xlnx-versal-crl.h
> +++ b/include/hw/misc/xlnx-versal-crl.h
> @@ -1,21 +1,27 @@
>  /*
>   * QEMU model of the Clock-Reset-LPD (CRL).
>   *
>   * Copyright (c) 2022 Xilinx Inc.
> + * Copyright (c) 2025 Advanced Micro Devices, Inc.
>   * SPDX-License-Identifier: GPL-2.0-or-later
>   *
>   * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>   */
>  #ifndef HW_MISC_XLNX_VERSAL_CRL_H
>  #define HW_MISC_XLNX_VERSAL_CRL_H
>  
>  #include "hw/sysbus.h"
>  #include "hw/register.h"
>  #include "target/arm/cpu-qom.h"
> +#include "hw/arm/xlnx-versal-version.h"
>  
> +#define TYPE_XLNX_VERSAL_CRL_BASE "xlnx-versal-crl-base"
>  #define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
> +
> +OBJECT_DECLARE_TYPE(XlnxVersalCRLBase, XlnxVersalCRLBaseClass,
> +                    XLNX_VERSAL_CRL_BASE)
>  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
>  
>  REG32(ERR_CTRL, 0x0)
>      FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
>  REG32(IR_STATUS, 0x4)
> @@ -214,22 +220,43 @@ REG32(PSM_RST_MODE, 0x370)
>  
>  #define CRL_R_MAX (R_PSM_RST_MODE + 1)
>  
>  #define RPU_MAX_CPU 2
>  
> -struct XlnxVersalCRL {
> +struct XlnxVersalCRLBase {
>      SysBusDevice parent_obj;
> +
> +    RegisterInfoArray *reg_array;
> +    uint32_t *regs;
> +};
> +
> +struct XlnxVersalCRLBaseClass {
> +    SysBusDeviceClass parent_class;
> +};
> +
> +struct XlnxVersalCRL {
> +    XlnxVersalCRLBase parent_obj;
>      qemu_irq irq;
>  
>      struct {
>          ARMCPU *cpu_r5[RPU_MAX_CPU];
>          DeviceState *adma[8];
>          DeviceState *uart[2];
>          DeviceState *gem[2];
>          DeviceState *usb;
>      } cfg;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[CRL_R_MAX];
>      RegisterInfo regs_info[CRL_R_MAX];
>  };
> +
> +static inline const char *xlnx_versal_crl_class_name(VersalVersion ver)
> +{
> +    switch (ver) {
> +    case VERSAL_VER_VERSAL:
> +        return TYPE_XLNX_VERSAL_CRL;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
>  #endif
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index f288545967a..be89e0da40d 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -296,21 +296,21 @@ static const RegisterAccessInfo crl_regs_info[] = {
>          .reset = 0x1,
>          .rsvd = 0xf8,
>      }
>  };
>  
> -static void crl_reset_enter(Object *obj, ResetType type)
> +static void versal_crl_reset_enter(Object *obj, ResetType type)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>      unsigned int i;
>  
>      for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
>          register_reset(&s->regs_info[i]);
>      }
>  }
>  
> -static void crl_reset_hold(Object *obj, ResetType type)
> +static void versal_crl_reset_hold(Object *obj, ResetType type)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>  
>      crl_update_irq(s);
>  }
> @@ -323,24 +323,26 @@ static const MemoryRegionOps crl_ops = {
>          .min_access_size = 4,
>          .max_access_size = 4,
>      },
>  };
>  
> -static void crl_init(Object *obj)
> +static void versal_crl_init(Object *obj)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
> +    XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
>      int i;
>  
> -    s->reg_array =
> +    xvcb->reg_array =
>          register_init_block32(DEVICE(obj), crl_regs_info,
>                                ARRAY_SIZE(crl_regs_info),
>                                s->regs_info, s->regs,
>                                &crl_ops,
>                                XLNX_VERSAL_CRL_ERR_DEBUG,
>                                CRL_R_MAX * 4);
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    xvcb->regs = s->regs;
> +    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  
>      for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
>          object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
>                                   (Object **)&s->cfg.cpu_r5[i],
> @@ -375,45 +377,53 @@ static void crl_init(Object *obj)
>                               OBJ_PROP_LINK_STRONG);
>  }
>  
>  static void crl_finalize(Object *obj)
>  {
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
> +    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
>      register_finalize_block(s->reg_array);
>  }
>  
> -static const VMStateDescription vmstate_crl = {
> +static const VMStateDescription vmstate_versal_crl = {
>      .name = TYPE_XLNX_VERSAL_CRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
>          VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
>          VMSTATE_END_OF_LIST(),
>      }
>  };
>  
> -static void crl_class_init(ObjectClass *klass, const void *data)
> +static void versal_crl_class_init(ObjectClass *klass, const void *data)
>  {
> -    ResettableClass *rc = RESETTABLE_CLASS(klass);
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
>  
> -    dc->vmsd = &vmstate_crl;
> -
> -    rc->phases.enter = crl_reset_enter;
> -    rc->phases.hold = crl_reset_hold;
> +    dc->vmsd = &vmstate_versal_crl;
> +    rc->phases.enter = versal_crl_reset_enter;
> +    rc->phases.hold = versal_crl_reset_hold;
>  }
>  
> -static const TypeInfo crl_info = {
> -    .name          = TYPE_XLNX_VERSAL_CRL,
> +static const TypeInfo crl_base_info = {
> +    .name          = TYPE_XLNX_VERSAL_CRL_BASE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
> -    .instance_size = sizeof(XlnxVersalCRL),
> -    .class_init    = crl_class_init,
> -    .instance_init = crl_init,
> +    .instance_size = sizeof(XlnxVersalCRLBase),
> +    .class_size    = sizeof(XlnxVersalCRLBaseClass),
>      .instance_finalize = crl_finalize,
> +    .abstract      = true,
> +};
> +
> +static const TypeInfo versal_crl_info = {
> +    .name          = TYPE_XLNX_VERSAL_CRL,
> +    .parent        = TYPE_XLNX_VERSAL_CRL_BASE,
> +    .instance_size = sizeof(XlnxVersalCRL),
> +    .instance_init = versal_crl_init,
> +    .class_init    = versal_crl_class_init,
>  };
>  
>  static void crl_register_types(void)
>  {
> -    type_register_static(&crl_info);
> +    type_register_static(&crl_base_info);
> +    type_register_static(&versal_crl_info);
>  }
>  
>  type_init(crl_register_types)
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic
  2025-07-16  9:54 ` [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic Luc Michel
@ 2025-07-31 13:23   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 13:23 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Luc,

On Wed, Jul 16, 2025 at 11:54:15AM +0200, Luc Michel wrote:
> Refactor the device reset logic to have a common register write callback
> for all the devices. This uses a decode function to map the register
> address to the actual peripheral to reset. This refactoring changes the
> CPU property name from cpu_r5[*] to rpu[*] to ease with the connections
> in the Versal SoC. It also fixes a bug where the gem device pointer
> was mapped to the usb link property.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
>  include/hw/misc/xlnx-versal-crl.h |   8 +-
>  hw/misc/xlnx-versal-crl.c         | 163 ++++++++++++++++--------------
>  2 files changed, 92 insertions(+), 79 deletions(-)
> 
> diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
> index 2b39d203a67..7e50a95ad3c 100644
> --- a/include/hw/misc/xlnx-versal-crl.h
> +++ b/include/hw/misc/xlnx-versal-crl.h
> @@ -218,33 +218,33 @@ REG32(PSM_RST_MODE, 0x370)
>      FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
>      FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
>  
>  #define CRL_R_MAX (R_PSM_RST_MODE + 1)
>  
> -#define RPU_MAX_CPU 2
> -
>  struct XlnxVersalCRLBase {
>      SysBusDevice parent_obj;
>  
>      RegisterInfoArray *reg_array;
>      uint32_t *regs;
>  };
>  
>  struct XlnxVersalCRLBaseClass {
>      SysBusDeviceClass parent_class;
> +
> +    DeviceState ** (*decode_periph_rst)(XlnxVersalCRLBase *s, hwaddr, size_t *);
>  };
>  
>  struct XlnxVersalCRL {
>      XlnxVersalCRLBase parent_obj;
>      qemu_irq irq;
>  
>      struct {
> -        ARMCPU *cpu_r5[RPU_MAX_CPU];
> +        DeviceState *rpu[2];
>          DeviceState *adma[8];
>          DeviceState *uart[2];
>          DeviceState *gem[2];
> -        DeviceState *usb;
> +        DeviceState *usb[1];
>      } cfg;
>  
>      uint32_t regs[CRL_R_MAX];
>      RegisterInfo regs_info[CRL_R_MAX];
>  };
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index be89e0da40d..115327cfcf4 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -53,94 +53,103 @@ static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
>      s->regs[R_IR_MASK] |= val;
>      crl_update_irq(s);
>      return 0;
>  }
>  
> -static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
> -                          bool rst_old, bool rst_new)
> +static DeviceState **versal_decode_periph_rst(XlnxVersalCRLBase *s,
> +                                             hwaddr addr, size_t *count)

One space is missing above but otherwise:

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

>  {
> -    device_cold_reset(dev);
> -}
> +    size_t idx;
> +    XlnxVersalCRL *xvc = XLNX_VERSAL_CRL(s);
>  
> -static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
> -                          bool rst_old, bool rst_new)
> -{
> -    if (rst_new) {
> -        arm_set_cpu_off(arm_cpu_mp_affinity(armcpu));
> -    } else {
> -        arm_set_cpu_on_and_reset(arm_cpu_mp_affinity(armcpu));
> -    }
> -}
> +    *count = 1;
>  
> -#define REGFIELD_RESET(type, s, reg, f, new_val, dev) {     \
> -    bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f);       \
> -    bool new_f = FIELD_EX32(new_val, reg, f);               \
> -                                                            \
> -    /* Detect edges.  */                                    \
> -    if (dev && old_f != new_f) {                            \
> -        crl_reset_ ## type(s, dev, old_f, new_f);           \
> -    }                                                       \
> -}
> +    switch (addr) {
> +    case A_RST_CPU_R5:
> +        return xvc->cfg.rpu;
>  
> -static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +    case A_RST_ADMA:
> +        /* A single register fans out to all DMA reset inputs */
> +        *count = ARRAY_SIZE(xvc->cfg.adma);
> +        return xvc->cfg.adma;
>  
> -    REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
> -    REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
> -    return val64;
> -}
> +    case A_RST_UART0 ... A_RST_UART1:
> +        idx = (addr - A_RST_UART0) / sizeof(uint32_t);
> +        return xvc->cfg.uart + idx;
>  
> -static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> -    int i;
> +    case A_RST_GEM0 ... A_RST_GEM1:
> +        idx = (addr - A_RST_GEM0) / sizeof(uint32_t);
> +        return xvc->cfg.gem + idx;
> +
> +    case A_RST_USB0:
> +        return xvc->cfg.usb;
>  
> -    /* A single register fans out to all ADMA reset inputs.  */
> -    for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
> -        REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
> +    default:
> +        /* invalid or unimplemented */
> +        return NULL;
>      }
> -    return val64;
>  }
>  
> -static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
> +static uint64_t crl_rst_cpu_prew(RegisterInfo *reg, uint64_t val64)
>  {
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
> +    XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
> +    DeviceState **dev;
> +    size_t i, count;
>  
> -    REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
> -    return val64;
> -}
> +    dev = xvcbc->decode_periph_rst(s, reg->access->addr, &count);
>  
> -static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +    for (i = 0; i < 2; i++) {
> +        bool prev, new;
> +        uint64_t aff;
>  
> -    REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
> -    return val64;
> -}
> +        prev = extract32(s->regs[reg->access->addr / 4], i, 1);
> +        new = extract32(val64, i, 1);
>  
> -static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +        if (prev == new) {
> +            continue;
> +        }
>  
> -    REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
> -    return val64;
> -}
> +        aff = arm_cpu_mp_affinity(ARM_CPU(dev[i]));
>  
> -static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +        if (new) {
> +            arm_set_cpu_off(aff);
> +        } else {
> +            arm_set_cpu_on_and_reset(aff);
> +        }
> +    }
>  
> -    REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
>      return val64;
>  }
>  
> -static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
> +static uint64_t crl_rst_dev_prew(RegisterInfo *reg, uint64_t val64)
>  {
> -    XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
> +    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
> +    XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
> +    DeviceState **dev;
> +    bool prev, new;
> +    size_t i, count;
> +
> +    dev = xvcbc->decode_periph_rst(s, reg->access->addr, &count);
> +
> +    if (dev == NULL) {
> +        return val64;
> +    }
> +
> +    prev = s->regs[reg->access->addr / 4] & 0x1;
> +    new = val64 & 0x1;
> +
> +    if (prev == new) {
> +        return val64;
> +    }
> +
> +    for (i = 0; i < count; i++) {
> +        if (dev[i]) {
> +            device_cold_reset(dev[i]);
> +        }
> +    }
>  
> -    REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
>      return val64;
>  }
>  
>  static const RegisterAccessInfo crl_regs_info[] = {
>      {   .name = "ERR_CTRL",  .addr = A_ERR_CTRL,
> @@ -242,31 +251,31 @@ static const RegisterAccessInfo crl_regs_info[] = {
>          .reset = 0x3c00,
>          .rsvd = 0xfdfc00f8,
>      },{ .name = "RST_CPU_R5",  .addr = A_RST_CPU_R5,
>          .reset = 0x17,
>          .rsvd = 0x8,
> -        .pre_write = crl_rst_r5_prew,
> +        .pre_write = crl_rst_cpu_prew,
>      },{ .name = "RST_ADMA",  .addr = A_RST_ADMA,
>          .reset = 0x1,
> -        .pre_write = crl_rst_adma_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_GEM0",  .addr = A_RST_GEM0,
>          .reset = 0x1,
> -        .pre_write = crl_rst_gem0_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_GEM1",  .addr = A_RST_GEM1,
>          .reset = 0x1,
> -        .pre_write = crl_rst_gem1_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_SPARE",  .addr = A_RST_SPARE,
>          .reset = 0x1,
>      },{ .name = "RST_USB0",  .addr = A_RST_USB0,
>          .reset = 0x1,
> -        .pre_write = crl_rst_usb_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_UART0",  .addr = A_RST_UART0,
>          .reset = 0x1,
> -        .pre_write = crl_rst_uart0_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_UART1",  .addr = A_RST_UART1,
>          .reset = 0x1,
> -        .pre_write = crl_rst_uart1_prew,
> +        .pre_write = crl_rst_dev_prew,
>      },{ .name = "RST_SPI0",  .addr = A_RST_SPI0,
>          .reset = 0x1,
>      },{ .name = "RST_SPI1",  .addr = A_RST_SPI1,
>          .reset = 0x1,
>      },{ .name = "RST_CAN0",  .addr = A_RST_CAN0,
> @@ -341,13 +350,13 @@ static void versal_crl_init(Object *obj)
>                                CRL_R_MAX * 4);
>      xvcb->regs = s->regs;
>      sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  
> -    for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
> -        object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
> -                                 (Object **)&s->cfg.cpu_r5[i],
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
> +        object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
> +                                 (Object **)&s->cfg.rpu[i],
>                                   qdev_prop_allow_set_link_before_realize,
>                                   OBJ_PROP_LINK_STRONG);
>      }
>  
>      for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
> @@ -369,14 +378,16 @@ static void versal_crl_init(Object *obj)
>                                   (Object **)&s->cfg.gem[i],
>                                   qdev_prop_allow_set_link_before_realize,
>                                   OBJ_PROP_LINK_STRONG);
>      }
>  
> -    object_property_add_link(obj, "usb", TYPE_DEVICE,
> -                             (Object **)&s->cfg.gem[i],
> -                             qdev_prop_allow_set_link_before_realize,
> -                             OBJ_PROP_LINK_STRONG);
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.usb); ++i) {
> +        object_property_add_link(obj, "usb[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.usb[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
>  }
>  
>  static void crl_finalize(Object *obj)
>  {
>      XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
> @@ -394,15 +405,17 @@ static const VMStateDescription vmstate_versal_crl = {
>  };
>  
>  static void versal_crl_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
>      ResettableClass *rc = RESETTABLE_CLASS(klass);
>  
>      dc->vmsd = &vmstate_versal_crl;
>      rc->phases.enter = versal_crl_reset_enter;
>      rc->phases.hold = versal_crl_reset_hold;
> +    xvcc->decode_periph_rst = versal_decode_periph_rst;
>  }
>  
>  static const TypeInfo crl_base_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL_BASE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices
  2025-07-16  9:54 ` [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices Luc Michel
@ 2025-07-31 13:26   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 13:26 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:16AM +0200, Luc Michel wrote:
> The CRL connects to various devices through link properties to be able
> to reset them. The connections were dropped during the SoC refactoring.
> Reintroduce them now.
> 
> Rely on the QOM tree to retrieve the devices to connect. The component
> parts of the device names are chosen to match the properties on the CRL.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 5151822ad56..796b4911a02 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -1473,21 +1473,50 @@ static void versal_create_cfu(Versal *s, const struct VersalCfuMap *map)
>      sysbus_realize_and_unref(sbd, &error_fatal);
>      memory_region_add_subregion(&s->mr_ps, map->cfu_sfr,
>                                  sysbus_mmio_get_region(sbd, 0));
>  }
>  
> +static inline void crl_connect_dev(Object *crl, Object *dev)
> +{
> +    const char *prop = object_get_canonical_path_component(dev);
> +
> +    /* The component part of the device path matches the CRL property name */
> +    object_property_set_link(crl, prop, dev, &error_abort);
> +}
> +
> +static inline void crl_connect_dev_by_name(Versal *s, Object *crl,
> +                                           const char *name, size_t num)
> +{
> +    size_t i;
> +
> +    for (i = 0; i < num; i++) {
> +        Object *dev = versal_get_child_idx(s, name, i);
> +
> +        crl_connect_dev(crl, dev);
> +    }
> +}
> +
>  static inline void versal_create_crl(Versal *s)
>  {
>      const VersalMap *map;
>      const char *crl_class;
>      DeviceState *dev;
> +    Object *obj;
>  
>      map = versal_get_map(s);
>  
>      crl_class = TYPE_XLNX_VERSAL_CRL;
>      dev = qdev_new(crl_class);
> -    object_property_add_child(OBJECT(s), "crl", OBJECT(dev));
> +    obj = OBJECT(dev);
> +    object_property_add_child(OBJECT(s), "crl", obj);
> +
> +    crl_connect_dev_by_name(s, obj, "rpu-cluster/rpu",
> +                            map->rpu.num_cluster * map->rpu.num_core);
> +    crl_connect_dev_by_name(s, obj, map->zdma[0].name, map->zdma[0].num_chan);
> +    crl_connect_dev_by_name(s, obj, "uart", map->num_uart);
> +    crl_connect_dev_by_name(s, obj, "gem", map->num_gem);
> +    crl_connect_dev_by_name(s, obj, "usb", map->num_usb);
>  
>      sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
>  
>      memory_region_add_subregion(&s->mr_ps, map->crl.addr,
>                                  sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices
  2025-07-16  9:54 ` [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices Luc Michel
@ 2025-07-31 13:29   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 13:29 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:17AM +0200, Luc Michel wrote:
> Use the bsa.h header for ARM timer and maintainance IRQ indices instead
> of redefining our owns.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  6 ------
>  hw/arm/xlnx-versal.c         | 28 +++++++++++++++++-----------
>  2 files changed, 17 insertions(+), 17 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index ffa7801b30f..3be9f0a5550 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -84,16 +84,10 @@ int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
>  /* Memory-map and IRQ definitions. Copied a subset from
>   * auto-generated files.  */
>  
> -#define VERSAL_GIC_MAINT_IRQ        9
> -#define VERSAL_TIMER_VIRT_IRQ       11
> -#define VERSAL_TIMER_S_EL1_IRQ      13
> -#define VERSAL_TIMER_NS_EL1_IRQ     14
> -#define VERSAL_TIMER_NS_EL2_IRQ     10
> -
>  #define VERSAL_CRL_IRQ             10
>  #define VERSAL_UART0_IRQ_0         18
>  #define VERSAL_UART1_IRQ_0         19
>  #define VERSAL_CANFD0_IRQ_0        20
>  #define VERSAL_CANFD1_IRQ_0        21
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 796b4911a02..c513d28c8d4 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -47,10 +47,11 @@
>  #include "hw/intc/arm_gicv3_its_common.h"
>  #include "hw/intc/arm_gic.h"
>  #include "hw/core/split-irq.h"
>  #include "target/arm/cpu.h"
>  #include "hw/cpu/cluster.h"
> +#include "hw/arm/bsa.h"
>  
>  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
>  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
>  #define GEM_REVISION        0x40070106
>  
> @@ -674,11 +675,12 @@ static DeviceState *versal_create_gic(Versal *s,
>          }
>  
>          qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
>          qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
>          qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
> -                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
> +                               GIC_FDT_IRQ_TYPE_PPI,
> +                               INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>          qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0);
>      }
>  
>      versal_create_gic_its(s, map, dev, mr, node);
> @@ -699,14 +701,14 @@ static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
>      /*
>       * Mapping from the output timer irq lines from the CPU to the
>       * GIC PPI inputs.
>       */
>      const int timer_irq[] = {
> -        [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
> -        [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
> -        [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
> -        [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
> +        [GTIMER_PHYS] = INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ),
> +        [GTIMER_VIRT] = INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ),
> +        [GTIMER_HYP]  = INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ),
> +        [GTIMER_SEC]  = INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ),
>      };
>  
>      has_gtimer = arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_GENERIC_TIMER);
>  
>      if (has_gtimer) {
> @@ -717,13 +719,13 @@ static void connect_gic_to_cpu(const VersalCpuClusterMap *map,
>          }
>      }
>  
>      if (map->gic.version == 3) {
>          qemu_irq maint_irq;
> +        int maint_idx = ppibase + INTID_TO_PPI(ARCH_GIC_MAINT_IRQ);
>  
> -        maint_irq = qdev_get_gpio_in(gic,
> -                                     ppibase + VERSAL_GIC_MAINT_IRQ);
> +        maint_irq = qdev_get_gpio_in(gic, maint_idx);
>          qdev_connect_gpio_out_named(cpu, "gicv3-maintenance-interrupt",
>                                      0, maint_irq);
>      }
>  
>      sysbus_connect_irq(sbd, idx, qdev_get_gpio_in(cpu, ARM_CPU_IRQ));
> @@ -845,17 +847,21 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
>  
>      has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
>      if (map->dtb_expose && has_gtimer) {
>          qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
>          qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
> -                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ,
> +                               GIC_FDT_IRQ_TYPE_PPI,
> +                               INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ),
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> -                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ,
> +                               GIC_FDT_IRQ_TYPE_PPI,
> +                               INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ),
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> -                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ,
> +                               GIC_FDT_IRQ_TYPE_PPI,
> +                               INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ),
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI,
> -                               GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ,
> +                               GIC_FDT_IRQ_TYPE_PPI,
> +                               INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ),
>                                 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>          qemu_fdt_setprop(s->cfg.fdt, "/timer", "compatible",
>                           compatible, sizeof(compatible));
>      }
>  }
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 36/48] hw/arm/xlnx-versal: tidy up
  2025-07-16  9:54 ` [PATCH 36/48] hw/arm/xlnx-versal: tidy up Luc Michel
@ 2025-07-31 20:14   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:14 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:18AM +0200, Luc Michel wrote:
> Remove now unused macros in xlnx-versal.[ch]. Those macros have been
> replaced by the VersalMap structure that serves as a central description
> for the SoC. The ones still in use in the versal_unimp function are
> inlined.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h | 204 -----------------------------------
>  hw/arm/xlnx-versal.c         |  28 ++---
>  2 files changed, 7 insertions(+), 225 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 3be9f0a5550..bdfab2a5426 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -21,22 +21,10 @@
>  #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
>  OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  
>  #define TYPE_XLNX_VERSAL "xlnx-versal"
>  
> -#define XLNX_VERSAL_NR_ACPUS   2
> -#define XLNX_VERSAL_NR_RCPUS   2
> -#define XLNX_VERSAL_NR_UARTS   2
> -#define XLNX_VERSAL_NR_GEMS    2
> -#define XLNX_VERSAL_NR_ADMAS   8
> -#define XLNX_VERSAL_NR_SDS     2
> -#define XLNX_VERSAL_NR_XRAM    4
> -#define XLNX_VERSAL_NR_IRQS    192
> -#define XLNX_VERSAL_NR_CANFD   2
> -#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
> -#define XLNX_VERSAL_NR_CFRAME  15
> -
>  struct Versal {
>      /*< private >*/
>      SysBusDevice parent_obj;
>  
>      /*< public >*/
> @@ -81,198 +69,6 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s);
>  
>  int versal_get_num_cpu(VersalVersion version);
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
> -/* Memory-map and IRQ definitions. Copied a subset from
> - * auto-generated files.  */
> -
> -#define VERSAL_CRL_IRQ             10
> -#define VERSAL_UART0_IRQ_0         18
> -#define VERSAL_UART1_IRQ_0         19
> -#define VERSAL_CANFD0_IRQ_0        20
> -#define VERSAL_CANFD1_IRQ_0        21
> -#define VERSAL_USB0_IRQ_0          22
> -#define VERSAL_GEM0_IRQ_0          56
> -#define VERSAL_GEM0_WAKE_IRQ_0     57
> -#define VERSAL_GEM1_IRQ_0          58
> -#define VERSAL_GEM1_WAKE_IRQ_0     59
> -#define VERSAL_ADMA_IRQ_0          60
> -#define VERSAL_XRAM_IRQ_0          79
> -#define VERSAL_CFU_IRQ_0           120
> -#define VERSAL_PMC_APB_IRQ         121
> -#define VERSAL_OSPI_IRQ            124
> -#define VERSAL_SD0_IRQ_0           126
> -#define VERSAL_EFUSE_IRQ           139
> -#define VERSAL_TRNG_IRQ            141
> -#define VERSAL_RTC_ALARM_IRQ       142
> -#define VERSAL_RTC_SECONDS_IRQ     143
> -
> -/* Architecturally reserved IRQs suitable for virtualization.  */
> -#define VERSAL_RSVD_IRQ_FIRST 111
> -#define VERSAL_RSVD_IRQ_LAST  118
> -
> -#define MM_TOP_RSVD                 0xa0000000U
> -#define MM_TOP_RSVD_SIZE            0x4000000
> -#define MM_GIC_APU_DIST_MAIN        0xf9000000U
> -#define MM_GIC_APU_DIST_MAIN_SIZE   0x10000
> -#define MM_GIC_APU_REDIST_0         0xf9080000U
> -#define MM_GIC_APU_REDIST_0_SIZE    0x80000
> -
> -#define MM_UART0                    0xff000000U
> -#define MM_UART0_SIZE               0x10000
> -#define MM_UART1                    0xff010000U
> -#define MM_UART1_SIZE               0x10000
> -
> -#define MM_CANFD0                   0xff060000U
> -#define MM_CANFD0_SIZE              0x10000
> -#define MM_CANFD1                   0xff070000U
> -#define MM_CANFD1_SIZE              0x10000
> -
> -#define MM_GEM0                     0xff0c0000U
> -#define MM_GEM0_SIZE                0x10000
> -#define MM_GEM1                     0xff0d0000U
> -#define MM_GEM1_SIZE                0x10000
> -
> -#define MM_ADMA_CH0                 0xffa80000U
> -#define MM_ADMA_CH0_SIZE            0x10000
> -
> -#define MM_OCM                      0xfffc0000U
> -#define MM_OCM_SIZE                 0x40000
> -
> -#define MM_XRAM                     0xfe800000
> -#define MM_XRAMC                    0xff8e0000
> -#define MM_XRAMC_SIZE               0x10000
> -
> -#define MM_USB2_CTRL_REGS           0xFF9D0000
> -#define MM_USB2_CTRL_REGS_SIZE      0x10000
> -
> -#define MM_USB_0                    0xFE200000
> -#define MM_USB_0_SIZE               0x10000
> -
> -#define MM_TOP_DDR                  0x0
> -#define MM_TOP_DDR_SIZE             0x80000000U
> -#define MM_TOP_DDR_2                0x800000000ULL
> -#define MM_TOP_DDR_2_SIZE           0x800000000ULL
> -#define MM_TOP_DDR_3                0xc000000000ULL
> -#define MM_TOP_DDR_3_SIZE           0x4000000000ULL
> -#define MM_TOP_DDR_4                0x10000000000ULL
> -#define MM_TOP_DDR_4_SIZE           0xb780000000ULL
> -
> -#define MM_PSM_START                0xffc80000U
> -#define MM_PSM_END                  0xffcf0000U
> -
> -#define MM_CRL                      0xff5e0000U
> -#define MM_CRL_SIZE                 0x300000
> -#define MM_IOU_SCNTR                0xff130000U
> -#define MM_IOU_SCNTR_SIZE           0x10000
> -#define MM_IOU_SCNTRS               0xff140000U
> -#define MM_IOU_SCNTRS_SIZE          0x10000
> -#define MM_FPD_CRF                  0xfd1a0000U
> -#define MM_FPD_CRF_SIZE             0x140000
> -#define MM_FPD_FPD_APU              0xfd5c0000
> -#define MM_FPD_FPD_APU_SIZE         0x100
> -
> -#define MM_PMC_PMC_IOU_SLCR         0xf1060000
> -#define MM_PMC_PMC_IOU_SLCR_SIZE    0x10000
> -
> -#define MM_PMC_OSPI                 0xf1010000
> -#define MM_PMC_OSPI_SIZE            0x10000
> -
> -#define MM_PMC_OSPI_DAC             0xc0000000
> -#define MM_PMC_OSPI_DAC_SIZE        0x20000000
> -
> -#define MM_PMC_OSPI_DMA_DST         0xf1011800
> -#define MM_PMC_OSPI_DMA_SRC         0xf1011000
> -
> -#define MM_PMC_SD0                  0xf1040000U
> -#define MM_PMC_SD0_SIZE             0x10000
> -#define MM_PMC_BBRAM_CTRL           0xf11f0000
> -#define MM_PMC_BBRAM_CTRL_SIZE      0x00050
> -#define MM_PMC_EFUSE_CTRL           0xf1240000
> -#define MM_PMC_EFUSE_CTRL_SIZE      0x00104
> -#define MM_PMC_EFUSE_CACHE          0xf1250000
> -#define MM_PMC_EFUSE_CACHE_SIZE     0x00C00
> -
> -#define MM_PMC_CFU_APB              0xf12b0000
> -#define MM_PMC_CFU_APB_SIZE         0x10000
> -#define MM_PMC_CFU_STREAM           0xf12c0000
> -#define MM_PMC_CFU_STREAM_SIZE      0x1000
> -#define MM_PMC_CFU_SFR              0xf12c1000
> -#define MM_PMC_CFU_SFR_SIZE         0x1000
> -#define MM_PMC_CFU_FDRO             0xf12c2000
> -#define MM_PMC_CFU_FDRO_SIZE        0x1000
> -#define MM_PMC_CFU_STREAM_2         0xf1f80000
> -#define MM_PMC_CFU_STREAM_2_SIZE    0x40000
> -
> -#define MM_PMC_CFRAME0_REG          0xf12d0000
> -#define MM_PMC_CFRAME0_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME0_FDRI         0xf12d1000
> -#define MM_PMC_CFRAME0_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME1_REG          0xf12d2000
> -#define MM_PMC_CFRAME1_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME1_FDRI         0xf12d3000
> -#define MM_PMC_CFRAME1_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME2_REG          0xf12d4000
> -#define MM_PMC_CFRAME2_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME2_FDRI         0xf12d5000
> -#define MM_PMC_CFRAME2_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME3_REG          0xf12d6000
> -#define MM_PMC_CFRAME3_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME3_FDRI         0xf12d7000
> -#define MM_PMC_CFRAME3_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME4_REG          0xf12d8000
> -#define MM_PMC_CFRAME4_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME4_FDRI         0xf12d9000
> -#define MM_PMC_CFRAME4_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME5_REG          0xf12da000
> -#define MM_PMC_CFRAME5_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME5_FDRI         0xf12db000
> -#define MM_PMC_CFRAME5_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME6_REG          0xf12dc000
> -#define MM_PMC_CFRAME6_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME6_FDRI         0xf12dd000
> -#define MM_PMC_CFRAME6_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME7_REG          0xf12de000
> -#define MM_PMC_CFRAME7_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME7_FDRI         0xf12df000
> -#define MM_PMC_CFRAME7_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME8_REG          0xf12e0000
> -#define MM_PMC_CFRAME8_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME8_FDRI         0xf12e1000
> -#define MM_PMC_CFRAME8_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME9_REG          0xf12e2000
> -#define MM_PMC_CFRAME9_REG_SIZE     0x1000
> -#define MM_PMC_CFRAME9_FDRI         0xf12e3000
> -#define MM_PMC_CFRAME9_FDRI_SIZE    0x1000
> -#define MM_PMC_CFRAME10_REG         0xf12e4000
> -#define MM_PMC_CFRAME10_REG_SIZE    0x1000
> -#define MM_PMC_CFRAME10_FDRI        0xf12e5000
> -#define MM_PMC_CFRAME10_FDRI_SIZE   0x1000
> -#define MM_PMC_CFRAME11_REG         0xf12e6000
> -#define MM_PMC_CFRAME11_REG_SIZE    0x1000
> -#define MM_PMC_CFRAME11_FDRI        0xf12e7000
> -#define MM_PMC_CFRAME11_FDRI_SIZE   0x1000
> -#define MM_PMC_CFRAME12_REG         0xf12e8000
> -#define MM_PMC_CFRAME12_REG_SIZE    0x1000
> -#define MM_PMC_CFRAME12_FDRI        0xf12e9000
> -#define MM_PMC_CFRAME12_FDRI_SIZE   0x1000
> -#define MM_PMC_CFRAME13_REG         0xf12ea000
> -#define MM_PMC_CFRAME13_REG_SIZE    0x1000
> -#define MM_PMC_CFRAME13_FDRI        0xf12eb000
> -#define MM_PMC_CFRAME13_FDRI_SIZE   0x1000
> -#define MM_PMC_CFRAME14_REG         0xf12ec000
> -#define MM_PMC_CFRAME14_REG_SIZE    0x1000
> -#define MM_PMC_CFRAME14_FDRI        0xf12ed000
> -#define MM_PMC_CFRAME14_FDRI_SIZE   0x1000
> -#define MM_PMC_CFRAME_BCAST_REG       0xf12ee000
> -#define MM_PMC_CFRAME_BCAST_REG_SIZE  0x1000
> -#define MM_PMC_CFRAME_BCAST_FDRI      0xf12ef000
> -#define MM_PMC_CFRAME_BCAST_FDRI_SIZE 0x1000
> -
> -#define MM_PMC_CRP                  0xf1260000U
> -#define MM_PMC_CRP_SIZE             0x10000
> -#define MM_PMC_RTC                  0xf12a0000
> -#define MM_PMC_RTC_SIZE             0x10000
> -#define MM_PMC_TRNG                 0xf1230000
> -#define MM_PMC_TRNG_SIZE            0x10000
>  #endif
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index c513d28c8d4..aef53876f26 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -16,11 +16,10 @@
>  #include "qobject/qlist.h"
>  #include "qemu/module.h"
>  #include "hw/sysbus.h"
>  #include "net/net.h"
>  #include "system/system.h"
> -#include "hw/arm/boot.h"
>  #include "hw/misc/unimp.h"
>  #include "hw/arm/xlnx-versal.h"
>  #include "qemu/log.h"
>  #include "target/arm/cpu-qom.h"
>  #include "target/arm/gtimer.h"
> @@ -49,17 +48,10 @@
>  #include "hw/core/split-irq.h"
>  #include "target/arm/cpu.h"
>  #include "hw/cpu/cluster.h"
>  #include "hw/arm/bsa.h"
>  
> -#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
> -#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
> -#define GEM_REVISION        0x40070106
> -
> -#define VERSAL_NUM_PMC_APB_IRQS 18
> -#define NUM_OSPI_IRQ_LINES 3
> -
>  /*
>   * IRQ descriptor to catch the following cases:
>   *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
>   */
>  FIELD(VERSAL_IRQ, IRQ, 0, 16)
> @@ -1361,11 +1353,11 @@ static DeviceState *versal_create_ospi(Versal *s,
>  
>      memory_region_add_subregion(&s->mr_ps, map->dac,
>                                  linear_mr);
>  
>      /* OSPI irq */
> -    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
> +    orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", 3,
>                              map->irq);
>  
>      sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
>      sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
>      sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
> @@ -1622,22 +1614,16 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
>  static void versal_unimp(Versal *s)
>  {
>      DeviceState *slcr;
>      qemu_irq gpio_in;
>  
> -    versal_unimp_area(s, "psm", &s->mr_ps,
> -                        MM_PSM_START, MM_PSM_END - MM_PSM_START);
> -    versal_unimp_area(s, "crf", &s->mr_ps,
> -                        MM_FPD_CRF, MM_FPD_CRF_SIZE);
> -    versal_unimp_area(s, "apu", &s->mr_ps,
> -                        MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE);
> -    versal_unimp_area(s, "crp", &s->mr_ps,
> -                        MM_PMC_CRP, MM_PMC_CRP_SIZE);
> -    versal_unimp_area(s, "iou-scntr", &s->mr_ps,
> -                        MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
> -    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
> -                        MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
> +    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
> +    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
> +    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
> +    versal_unimp_area(s, "crp", &s->mr_ps, 0xf1260000, 0x10000);
> +    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
> +    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, 0xff140000, 0x10000);
>  
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel,
>                              "sd-emmc-sel-dummy", 2);
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
>                              "qspi-ospi-mux-sel-dummy", 1);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version
  2025-07-16  9:54 ` [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version Luc Michel
@ 2025-07-31 20:19   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:19 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:19AM +0200, Luc Michel wrote:
> Add the versal2 version of the CRL device. For the implemented part, it
> is similar to the versal version but drives reset line of more devices.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal-version.h |   1 +
>  include/hw/misc/xlnx-versal-crl.h    | 329 ++++++++++++++++++++++
>  hw/misc/xlnx-versal-crl.c            | 392 +++++++++++++++++++++++++++
>  3 files changed, 722 insertions(+)
> 
> diff --git a/include/hw/arm/xlnx-versal-version.h b/include/hw/arm/xlnx-versal-version.h
> index 46eb165a2bd..1e8d31b3248 100644
> --- a/include/hw/arm/xlnx-versal-version.h
> +++ b/include/hw/arm/xlnx-versal-version.h
> @@ -8,8 +8,9 @@
>  #ifndef HW_ARM_XLNX_VERSAL_VERSION_H
>  #define HW_ARM_XLNX_VERSAL_VERSION_H
>  
>  typedef enum VersalVersion {
>      VERSAL_VER_VERSAL,
> +    VERSAL_VER_VERSAL2,
>  } VersalVersion;
>  
>  #endif
> diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
> index 7e50a95ad3c..f6b8694ebea 100644
> --- a/include/hw/misc/xlnx-versal-crl.h
> +++ b/include/hw/misc/xlnx-versal-crl.h
> @@ -15,14 +15,16 @@
>  #include "target/arm/cpu-qom.h"
>  #include "hw/arm/xlnx-versal-version.h"
>  
>  #define TYPE_XLNX_VERSAL_CRL_BASE "xlnx-versal-crl-base"
>  #define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
> +#define TYPE_XLNX_VERSAL2_CRL "xlnx-versal2-crl"
>  
>  OBJECT_DECLARE_TYPE(XlnxVersalCRLBase, XlnxVersalCRLBaseClass,
>                      XLNX_VERSAL_CRL_BASE)
>  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
> +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersal2CRL, XLNX_VERSAL2_CRL)
>  
>  REG32(ERR_CTRL, 0x0)
>      FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
>  REG32(IR_STATUS, 0x4)
>      FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
> @@ -218,10 +220,318 @@ REG32(PSM_RST_MODE, 0x370)
>      FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
>      FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
>  
>  #define CRL_R_MAX (R_PSM_RST_MODE + 1)
>  
> +REG32(VERSAL2_ERR_CTRL, 0x0)
> +REG32(VERSAL2_WPROT, 0x1c)
> +    FIELD(VERSAL2_WPROT, ACTIVE, 0, 1)
> +REG32(VERSAL2_RPLL_CTRL, 0x40)
> +    FIELD(VERSAL2_RPLL_CTRL, POST_SRC, 24, 3)
> +    FIELD(VERSAL2_RPLL_CTRL, PRE_SRC, 20, 3)
> +    FIELD(VERSAL2_RPLL_CTRL, CLKOUTDIV, 16, 2)
> +    FIELD(VERSAL2_RPLL_CTRL, FBDIV, 8, 8)
> +    FIELD(VERSAL2_RPLL_CTRL, BYPASS, 3, 1)
> +    FIELD(VERSAL2_RPLL_CTRL, RESET, 0, 1)
> +REG32(VERSAL2_RPLL_CFG, 0x44)
> +    FIELD(VERSAL2_RPLL_CFG, LOCK_DLY, 25, 7)
> +    FIELD(VERSAL2_RPLL_CFG, LOCK_CNT, 13, 10)
> +    FIELD(VERSAL2_RPLL_CFG, LFHF, 10, 2)
> +    FIELD(VERSAL2_RPLL_CFG, CP, 5, 4)
> +    FIELD(VERSAL2_RPLL_CFG, RES, 0, 4)
> +REG32(VERSAL2_FLXPLL_CTRL, 0x50)
> +    FIELD(VERSAL2_FLXPLL_CTRL, POST_SRC, 24, 3)
> +    FIELD(VERSAL2_FLXPLL_CTRL, PRE_SRC, 20, 3)
> +    FIELD(VERSAL2_FLXPLL_CTRL, CLKOUTDIV, 16, 2)
> +    FIELD(VERSAL2_FLXPLL_CTRL, FBDIV, 8, 8)
> +    FIELD(VERSAL2_FLXPLL_CTRL, BYPASS, 3, 1)
> +    FIELD(VERSAL2_FLXPLL_CTRL, RESET, 0, 1)
> +REG32(VERSAL2_FLXPLL_CFG, 0x54)
> +    FIELD(VERSAL2_FLXPLL_CFG, LOCK_DLY, 25, 7)
> +    FIELD(VERSAL2_FLXPLL_CFG, LOCK_CNT, 13, 10)
> +    FIELD(VERSAL2_FLXPLL_CFG, LFHF, 10, 2)
> +    FIELD(VERSAL2_FLXPLL_CFG, CP, 5, 4)
> +    FIELD(VERSAL2_FLXPLL_CFG, RES, 0, 4)
> +REG32(VERSAL2_PLL_STATUS, 0x60)
> +    FIELD(VERSAL2_PLL_STATUS, FLXPLL_STABLE, 3, 1)
> +    FIELD(VERSAL2_PLL_STATUS, RPLL_STABLE, 2, 1)
> +    FIELD(VERSAL2_PLL_STATUS, FLXPLL_LOCK, 1, 1)
> +    FIELD(VERSAL2_PLL_STATUS, RPLL_LOCK, 0, 1)
> +REG32(VERSAL2_RPLL_TO_XPD_CTRL, 0x100)
> +    FIELD(VERSAL2_RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
> +REG32(VERSAL2_LPX_TOP_SWITCH_CTRL, 0x104)
> +    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
> +    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_LPX_LSBUS_CLK_CTRL, 0x108)
> +    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_RPU_CLK_CTRL, 0x10c)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERE, 24, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERD, 23, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERC, 22, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERB, 21, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERA, 20, 1)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_RPU_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_OCM_CLK_CTRL, 0x120)
> +    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM3, 24, 1)
> +    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM2, 23, 1)
> +    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM1, 22, 1)
> +    FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM0, 21, 1)
> +REG32(VERSAL2_IOU_SWITCH_CLK_CTRL, 0x124)
> +    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_GEM0_REF_CTRL, 0x128)
> +    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_RX, 27, 1)
> +    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_TX, 26, 1)
> +    FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_GEM0_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_GEM0_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_GEM1_REF_CTRL, 0x12c)
> +    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_RX, 27, 1)
> +    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_TX, 26, 1)
> +    FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_GEM1_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_GEM1_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_GEM_TSU_REF_CLK_CTRL, 0x130)
> +    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_USB0_BUS_REF_CLK_CTRL, 0x134)
> +    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_USB1_BUS_REF_CLK_CTRL, 0x138)
> +    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_UART0_REF_CLK_CTRL, 0x13c)
> +    FIELD(VERSAL2_UART0_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_UART0_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_UART0_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_UART1_REF_CLK_CTRL, 0x140)
> +    FIELD(VERSAL2_UART1_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_UART1_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_UART1_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_SPI0_REF_CLK_CTRL, 0x144)
> +    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_SPI0_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_SPI1_REF_CLK_CTRL, 0x148)
> +    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_SPI1_REF_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_CAN0_REF_2X_CTRL, 0x14c)
> +    FIELD(VERSAL2_CAN0_REF_2X_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_CAN0_REF_2X_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_CAN0_REF_2X_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_CAN1_REF_2X_CTRL, 0x150)
> +    FIELD(VERSAL2_CAN1_REF_2X_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_CAN1_REF_2X_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_CAN1_REF_2X_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_CAN2_REF_2X_CTRL, 0x154)
> +    FIELD(VERSAL2_CAN2_REF_2X_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_CAN2_REF_2X_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_CAN2_REF_2X_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_CAN3_REF_2X_CTRL, 0x158)
> +    FIELD(VERSAL2_CAN3_REF_2X_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_CAN3_REF_2X_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_CAN3_REF_2X_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C0_REF_CTRL, 0x15c)
> +    FIELD(VERSAL2_I3C0_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C0_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C0_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C1_REF_CTRL, 0x160)
> +    FIELD(VERSAL2_I3C1_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C1_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C1_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C2_REF_CTRL, 0x164)
> +    FIELD(VERSAL2_I3C2_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C2_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C2_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C3_REF_CTRL, 0x168)
> +    FIELD(VERSAL2_I3C3_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C3_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C3_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C4_REF_CTRL, 0x16c)
> +    FIELD(VERSAL2_I3C4_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C4_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C4_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C5_REF_CTRL, 0x170)
> +    FIELD(VERSAL2_I3C5_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C5_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C5_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C6_REF_CTRL, 0x174)
> +    FIELD(VERSAL2_I3C6_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C6_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C6_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_I3C7_REF_CTRL, 0x178)
> +    FIELD(VERSAL2_I3C7_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_I3C7_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_I3C7_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_DBG_LPX_CTRL, 0x17c)
> +    FIELD(VERSAL2_DBG_LPX_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_DBG_LPX_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_DBG_LPX_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_TIMESTAMP_REF_CTRL, 0x180)
> +    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_SAFETY_CHK, 0x184)
> +REG32(VERSAL2_ASU_CLK_CTRL, 0x188)
> +    FIELD(VERSAL2_ASU_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_ASU_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_DBG_TSTMP_CLK_CTRL, 0x18c)
> +    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_MMI_TOPSW_CLK_CTRL, 0x190)
> +    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, CLKACT, 25, 1)
> +    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_WWDT_PLL_CLK_CTRL, 0x194)
> +    FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, DIVISOR0, 8, 10)
> +    FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, SRCSEL, 0, 3)
> +REG32(VERSAL2_RCLK_CTRL, 0x1a0)
> +    FIELD(VERSAL2_RCLK_CTRL, CLKACT, 8, 6)
> +    FIELD(VERSAL2_RCLK_CTRL, SELECT, 0, 6)
> +REG32(VERSAL2_RST_RPU_A, 0x310)
> +    FIELD(VERSAL2_RST_RPU_A, TOPRESET, 16, 1)
> +    FIELD(VERSAL2_RST_RPU_A, CORE1_POR, 9, 1)
> +    FIELD(VERSAL2_RST_RPU_A, CORE0_POR, 8, 1)
> +    FIELD(VERSAL2_RST_RPU_A, CORE1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_A, CORE0_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_B, 0x314)
> +    FIELD(VERSAL2_RST_RPU_B, TOPRESET, 16, 1)
> +    FIELD(VERSAL2_RST_RPU_B, CORE1_POR, 9, 1)
> +    FIELD(VERSAL2_RST_RPU_B, CORE0_POR, 8, 1)
> +    FIELD(VERSAL2_RST_RPU_B, CORE1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_B, CORE0_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_C, 0x318)
> +    FIELD(VERSAL2_RST_RPU_C, TOPRESET, 16, 1)
> +    FIELD(VERSAL2_RST_RPU_C, CORE1_POR, 9, 1)
> +    FIELD(VERSAL2_RST_RPU_C, CORE0_POR, 8, 1)
> +    FIELD(VERSAL2_RST_RPU_C, CORE1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_C, CORE0_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_D, 0x31c)
> +    FIELD(VERSAL2_RST_RPU_D, TOPRESET, 16, 1)
> +    FIELD(VERSAL2_RST_RPU_D, CORE1_POR, 9, 1)
> +    FIELD(VERSAL2_RST_RPU_D, CORE0_POR, 8, 1)
> +    FIELD(VERSAL2_RST_RPU_D, CORE1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_D, CORE0_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_E, 0x320)
> +    FIELD(VERSAL2_RST_RPU_E, TOPRESET, 16, 1)
> +    FIELD(VERSAL2_RST_RPU_E, CORE1_POR, 9, 1)
> +    FIELD(VERSAL2_RST_RPU_E, CORE0_POR, 8, 1)
> +    FIELD(VERSAL2_RST_RPU_E, CORE1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_E, CORE0_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_GD_0, 0x324)
> +    FIELD(VERSAL2_RST_RPU_GD_0, RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_GD_0, TOP_RESET, 0, 1)
> +REG32(VERSAL2_RST_RPU_GD_1, 0x328)
> +    FIELD(VERSAL2_RST_RPU_GD_1, RESET, 1, 1)
> +    FIELD(VERSAL2_RST_RPU_GD_1, TOP_RESET, 0, 1)
> +REG32(VERSAL2_RST_ASU_GD, 0x32c)
> +    FIELD(VERSAL2_RST_ASU_GD, RESET, 1, 1)
> +    FIELD(VERSAL2_RST_ASU_GD, TOP_RESET, 0, 1)
> +REG32(VERSAL2_RST_ADMA, 0x334)
> +    FIELD(VERSAL2_RST_ADMA, RESET, 0, 1)
> +REG32(VERSAL2_RST_SDMA, 0x338)
> +    FIELD(VERSAL2_RST_SDMA, RESET, 0, 1)
> +REG32(VERSAL2_RST_GEM0, 0x33c)
> +    FIELD(VERSAL2_RST_GEM0, RESET, 0, 1)
> +REG32(VERSAL2_RST_GEM1, 0x340)
> +    FIELD(VERSAL2_RST_GEM1, RESET, 0, 1)
> +REG32(VERSAL2_RST_USB0, 0x348)
> +    FIELD(VERSAL2_RST_USB0, RESET, 0, 1)
> +REG32(VERSAL2_RST_USB1, 0x34c)
> +    FIELD(VERSAL2_RST_USB1, RESET, 0, 1)
> +REG32(VERSAL2_RST_UART0, 0x350)
> +    FIELD(VERSAL2_RST_UART0, RESET, 0, 1)
> +REG32(VERSAL2_RST_UART1, 0x354)
> +    FIELD(VERSAL2_RST_UART1, RESET, 0, 1)
> +REG32(VERSAL2_RST_SPI0, 0x358)
> +    FIELD(VERSAL2_RST_SPI0, RESET, 0, 1)
> +REG32(VERSAL2_RST_SPI1, 0x35c)
> +    FIELD(VERSAL2_RST_SPI1, RESET, 0, 1)
> +REG32(VERSAL2_RST_CAN0, 0x360)
> +    FIELD(VERSAL2_RST_CAN0, RESET, 0, 1)
> +REG32(VERSAL2_RST_CAN1, 0x364)
> +    FIELD(VERSAL2_RST_CAN1, RESET, 0, 1)
> +REG32(VERSAL2_RST_CAN2, 0x368)
> +    FIELD(VERSAL2_RST_CAN2, RESET, 0, 1)
> +REG32(VERSAL2_RST_CAN3, 0x36c)
> +    FIELD(VERSAL2_RST_CAN3, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C0, 0x374)
> +    FIELD(VERSAL2_RST_I3C0, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C1, 0x378)
> +    FIELD(VERSAL2_RST_I3C1, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C2, 0x37c)
> +    FIELD(VERSAL2_RST_I3C2, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C3, 0x380)
> +    FIELD(VERSAL2_RST_I3C3, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C4, 0x384)
> +    FIELD(VERSAL2_RST_I3C4, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C5, 0x388)
> +    FIELD(VERSAL2_RST_I3C5, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C6, 0x38c)
> +    FIELD(VERSAL2_RST_I3C6, RESET, 0, 1)
> +REG32(VERSAL2_RST_I3C7, 0x390)
> +    FIELD(VERSAL2_RST_I3C7, RESET, 0, 1)
> +REG32(VERSAL2_RST_DBG_LPX, 0x398)
> +    FIELD(VERSAL2_RST_DBG_LPX, RESET_HSDP, 1, 1)
> +    FIELD(VERSAL2_RST_DBG_LPX, RESET, 0, 1)
> +REG32(VERSAL2_RST_GPIO, 0x39c)
> +    FIELD(VERSAL2_RST_GPIO, RESET, 0, 1)
> +REG32(VERSAL2_RST_TTC, 0x3a0)
> +    FIELD(VERSAL2_RST_TTC, TTC7_RESET, 7, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC6_RESET, 6, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC5_RESET, 5, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC4_RESET, 4, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC3_RESET, 3, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC2_RESET, 2, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC1_RESET, 1, 1)
> +    FIELD(VERSAL2_RST_TTC, TTC0_RESET, 0, 1)
> +REG32(VERSAL2_RST_TIMESTAMP, 0x3a4)
> +    FIELD(VERSAL2_RST_TIMESTAMP, RESET, 0, 1)
> +REG32(VERSAL2_RST_SWDT0, 0x3a8)
> +    FIELD(VERSAL2_RST_SWDT0, RESET, 0, 1)
> +REG32(VERSAL2_RST_SWDT1, 0x3ac)
> +    FIELD(VERSAL2_RST_SWDT1, RESET, 0, 1)
> +REG32(VERSAL2_RST_SWDT2, 0x3b0)
> +    FIELD(VERSAL2_RST_SWDT2, RESET, 0, 1)
> +REG32(VERSAL2_RST_SWDT3, 0x3b4)
> +    FIELD(VERSAL2_RST_SWDT3, RESET, 0, 1)
> +REG32(VERSAL2_RST_SWDT4, 0x3b8)
> +    FIELD(VERSAL2_RST_SWDT4, RESET, 0, 1)
> +REG32(VERSAL2_RST_IPI, 0x3bc)
> +    FIELD(VERSAL2_RST_IPI, RESET, 0, 1)
> +REG32(VERSAL2_RST_SYSMON, 0x3c0)
> +    FIELD(VERSAL2_RST_SYSMON, CFG_RST, 0, 1)
> +REG32(VERSAL2_ASU_MB_RST_MODE, 0x3c4)
> +    FIELD(VERSAL2_ASU_MB_RST_MODE, WAKEUP, 2, 1)
> +    FIELD(VERSAL2_ASU_MB_RST_MODE, RST_MODE, 0, 2)
> +REG32(VERSAL2_FPX_TOPSW_MUX_CTRL, 0x3c8)
> +    FIELD(VERSAL2_FPX_TOPSW_MUX_CTRL, SELECT, 0, 1)
> +REG32(VERSAL2_RST_FPX, 0x3d0)
> +    FIELD(VERSAL2_RST_FPX, SRST, 1, 1)
> +    FIELD(VERSAL2_RST_FPX, POR, 0, 1)
> +REG32(VERSAL2_RST_MMI, 0x3d4)
> +    FIELD(VERSAL2_RST_MMI, POR, 0, 1)
> +REG32(VERSAL2_RST_OCM, 0x3d8)
> +    FIELD(VERSAL2_RST_OCM, RESET_OCM3, 3, 1)
> +    FIELD(VERSAL2_RST_OCM, RESET_OCM2, 2, 1)
> +    FIELD(VERSAL2_RST_OCM, RESET_OCM1, 1, 1)
> +    FIELD(VERSAL2_RST_OCM, RESET_OCM0, 0, 1)
> +
> +#define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1)
> +
>  struct XlnxVersalCRLBase {
>      SysBusDevice parent_obj;
>  
>      RegisterInfoArray *reg_array;
>      uint32_t *regs;
> @@ -247,15 +557,34 @@ struct XlnxVersalCRL {
>  
>      uint32_t regs[CRL_R_MAX];
>      RegisterInfo regs_info[CRL_R_MAX];
>  };
>  
> +struct XlnxVersal2CRL {
> +    XlnxVersalCRLBase parent_obj;
> +
> +    struct {
> +        DeviceState *rpu[10];
> +        DeviceState *adma[8];
> +        DeviceState *sdma[8];
> +        DeviceState *uart[2];
> +        DeviceState *gem[2];
> +        DeviceState *usb[2];
> +        DeviceState *can[4];
> +    } cfg;
> +
> +    RegisterInfo regs_info[VERSAL2_CRL_R_MAX];
> +    uint32_t regs[VERSAL2_CRL_R_MAX];
> +};
> +
>  static inline const char *xlnx_versal_crl_class_name(VersalVersion ver)
>  {
>      switch (ver) {
>      case VERSAL_VER_VERSAL:
>          return TYPE_XLNX_VERSAL_CRL;
> +    case VERSAL_VER_VERSAL2:
> +        return TYPE_XLNX_VERSAL2_CRL;
>      default:
>          g_assert_not_reached();
>      }
>  }
>  
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index 115327cfcf4..367e42a30d3 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -87,10 +87,55 @@ static DeviceState **versal_decode_periph_rst(XlnxVersalCRLBase *s,
>          /* invalid or unimplemented */
>          return NULL;
>      }
>  }
>  
> +static DeviceState **versal2_decode_periph_rst(XlnxVersalCRLBase *s,
> +                                               hwaddr addr, size_t *count)
> +{
> +    size_t idx;
> +    XlnxVersal2CRL *xvc = XLNX_VERSAL2_CRL(s);
> +
> +    *count = 1;
> +
> +    switch (addr) {
> +    case A_VERSAL2_RST_RPU_A ... A_VERSAL2_RST_RPU_E:
> +        idx = (addr - A_VERSAL2_RST_RPU_A) / sizeof(uint32_t);
> +        idx *= 2; /* two RPUs per RST_RPU_x registers */
> +        return xvc->cfg.rpu + idx;
> +
> +    case A_VERSAL2_RST_ADMA:
> +        /* A single register fans out to all DMA reset inputs */
> +        *count = ARRAY_SIZE(xvc->cfg.adma);
> +        return xvc->cfg.adma;
> +
> +    case A_VERSAL2_RST_SDMA:
> +        *count = ARRAY_SIZE(xvc->cfg.sdma);
> +        return xvc->cfg.sdma;
> +
> +    case A_VERSAL2_RST_UART0 ... A_VERSAL2_RST_UART1:
> +        idx = (addr - A_VERSAL2_RST_UART0) / sizeof(uint32_t);
> +        return xvc->cfg.uart + idx;
> +
> +    case A_VERSAL2_RST_GEM0 ... A_VERSAL2_RST_GEM1:
> +        idx = (addr - A_VERSAL2_RST_GEM0) / sizeof(uint32_t);
> +        return xvc->cfg.gem + idx;
> +
> +    case A_VERSAL2_RST_USB0 ... A_VERSAL2_RST_USB1:
> +        idx = (addr - A_VERSAL2_RST_USB0) / sizeof(uint32_t);
> +        return xvc->cfg.usb + idx;
> +
> +    case A_VERSAL2_RST_CAN0 ... A_VERSAL2_RST_CAN3:
> +        idx = (addr - A_VERSAL2_RST_CAN0) / sizeof(uint32_t);
> +        return xvc->cfg.can + idx;
> +
> +    default:
> +        /* invalid or unimplemented */
> +        return NULL;
> +    }
> +}
> +
>  static uint64_t crl_rst_cpu_prew(RegisterInfo *reg, uint64_t val64)
>  {
>      XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(reg->opaque);
>      XlnxVersalCRLBaseClass *xvcbc = XLNX_VERSAL_CRL_BASE_GET_CLASS(s);
>      DeviceState **dev;
> @@ -305,20 +350,270 @@ static const RegisterAccessInfo crl_regs_info[] = {
>          .reset = 0x1,
>          .rsvd = 0xf8,
>      }
>  };
>  
> +static const RegisterAccessInfo versal2_crl_regs_info[] = {
> +    {   .name = "ERR_CTRL",  .addr = A_VERSAL2_ERR_CTRL,
> +        .reset = 0x1,
> +    },{ .name = "WPROT",  .addr = A_VERSAL2_WPROT,
> +    },{ .name = "RPLL_CTRL",  .addr = A_VERSAL2_RPLL_CTRL,
> +        .reset = 0x24809,
> +        .rsvd = 0xf88c00f6,
> +    },{ .name = "RPLL_CFG",  .addr = A_VERSAL2_RPLL_CFG,
> +        .reset = 0x7e5dcc6c,
> +        .rsvd = 0x1801210,
> +    },{ .name = "FLXPLL_CTRL",  .addr = A_VERSAL2_FLXPLL_CTRL,
> +        .reset = 0x24809,
> +        .rsvd = 0xf88c00f6,
> +    },{ .name = "FLXPLL_CFG",  .addr = A_VERSAL2_FLXPLL_CFG,
> +        .reset = 0x7e5dcc6c,
> +        .rsvd = 0x1801210,
> +    },{ .name = "PLL_STATUS",  .addr = A_VERSAL2_PLL_STATUS,
> +        .reset = 0xf,
> +        .rsvd = 0xf0,
> +        .ro = 0xf,
> +    },{ .name = "RPLL_TO_XPD_CTRL",  .addr = A_VERSAL2_RPLL_TO_XPD_CTRL,
> +        .reset = 0x2000100,
> +        .rsvd = 0xfdfc00ff,
> +    },{ .name = "LPX_TOP_SWITCH_CTRL",  .addr = A_VERSAL2_LPX_TOP_SWITCH_CTRL,
> +        .reset = 0xe000300,
> +        .rsvd = 0xf1fc00f8,
> +    },{ .name = "LPX_LSBUS_CLK_CTRL",  .addr = A_VERSAL2_LPX_LSBUS_CLK_CTRL,
> +        .reset = 0x2000800,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "RPU_CLK_CTRL",  .addr = A_VERSAL2_RPU_CLK_CTRL,
> +        .reset = 0x3f00300,
> +        .rsvd = 0xfc0c00f8,
> +    },{ .name = "OCM_CLK_CTRL",  .addr = A_VERSAL2_OCM_CLK_CTRL,
> +        .reset = 0x1e00000,
> +        .rsvd = 0xfe1fffff,
> +    },{ .name = "IOU_SWITCH_CLK_CTRL",  .addr = A_VERSAL2_IOU_SWITCH_CLK_CTRL,
> +        .reset = 0x2000500,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "GEM0_REF_CTRL",  .addr = A_VERSAL2_GEM0_REF_CTRL,
> +        .reset = 0xe000a00,
> +        .rsvd = 0xf1fc00f8,
> +    },{ .name = "GEM1_REF_CTRL",  .addr = A_VERSAL2_GEM1_REF_CTRL,
> +        .reset = 0xe000a00,
> +        .rsvd = 0xf1fc00f8,
> +    },{ .name = "GEM_TSU_REF_CLK_CTRL",  .addr = A_VERSAL2_GEM_TSU_REF_CLK_CTRL,
> +        .reset = 0x300,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "USB0_BUS_REF_CLK_CTRL",
> +        .addr = A_VERSAL2_USB0_BUS_REF_CLK_CTRL,
> +        .reset = 0x2001900,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "USB1_BUS_REF_CLK_CTRL",
> +        .addr = A_VERSAL2_USB1_BUS_REF_CLK_CTRL,
> +        .reset = 0x2001900,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "UART0_REF_CLK_CTRL",  .addr = A_VERSAL2_UART0_REF_CLK_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "UART1_REF_CLK_CTRL",  .addr = A_VERSAL2_UART1_REF_CLK_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "SPI0_REF_CLK_CTRL",  .addr = A_VERSAL2_SPI0_REF_CLK_CTRL,
> +        .reset = 0x600,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "SPI1_REF_CLK_CTRL",  .addr = A_VERSAL2_SPI1_REF_CLK_CTRL,
> +        .reset = 0x600,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "CAN0_REF_2X_CTRL",  .addr = A_VERSAL2_CAN0_REF_2X_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "CAN1_REF_2X_CTRL",  .addr = A_VERSAL2_CAN1_REF_2X_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "CAN2_REF_2X_CTRL",  .addr = A_VERSAL2_CAN2_REF_2X_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "CAN3_REF_2X_CTRL",  .addr = A_VERSAL2_CAN3_REF_2X_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C0_REF_CTRL",  .addr = A_VERSAL2_I3C0_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C1_REF_CTRL",  .addr = A_VERSAL2_I3C1_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C2_REF_CTRL",  .addr = A_VERSAL2_I3C2_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C3_REF_CTRL",  .addr = A_VERSAL2_I3C3_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C4_REF_CTRL",  .addr = A_VERSAL2_I3C4_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C5_REF_CTRL",  .addr = A_VERSAL2_I3C5_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C6_REF_CTRL",  .addr = A_VERSAL2_I3C6_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "I3C7_REF_CTRL",  .addr = A_VERSAL2_I3C7_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "DBG_LPX_CTRL",  .addr = A_VERSAL2_DBG_LPX_CTRL,
> +        .reset = 0x300,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "TIMESTAMP_REF_CTRL",  .addr = A_VERSAL2_TIMESTAMP_REF_CTRL,
> +        .reset = 0x2000c00,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "SAFETY_CHK",  .addr = A_VERSAL2_SAFETY_CHK,
> +    },{ .name = "ASU_CLK_CTRL",  .addr = A_VERSAL2_ASU_CLK_CTRL,
> +        .reset = 0x2000f04,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "DBG_TSTMP_CLK_CTRL",  .addr = A_VERSAL2_DBG_TSTMP_CLK_CTRL,
> +        .reset = 0x300,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "MMI_TOPSW_CLK_CTRL",  .addr = A_VERSAL2_MMI_TOPSW_CLK_CTRL,
> +        .reset = 0x2000300,
> +        .rsvd = 0xfdfc00f8,
> +    },{ .name = "WWDT_PLL_CLK_CTRL",  .addr = A_VERSAL2_WWDT_PLL_CLK_CTRL,
> +        .reset = 0xc00,
> +        .rsvd = 0xfffc00f8,
> +    },{ .name = "RCLK_CTRL",  .addr = A_VERSAL2_RCLK_CTRL,
> +        .rsvd = 0xc040,
> +    },{ .name = "RST_RPU_A",  .addr = A_VERSAL2_RST_RPU_A,
> +        .reset = 0x10303,
> +        .rsvd = 0xfffefcfc,
> +        .pre_write = crl_rst_cpu_prew,
> +    },{ .name = "RST_RPU_B",  .addr = A_VERSAL2_RST_RPU_B,
> +        .reset = 0x10303,
> +        .rsvd = 0xfffefcfc,
> +        .pre_write = crl_rst_cpu_prew,
> +    },{ .name = "RST_RPU_C",  .addr = A_VERSAL2_RST_RPU_C,
> +        .reset = 0x10303,
> +        .rsvd = 0xfffefcfc,
> +        .pre_write = crl_rst_cpu_prew,
> +    },{ .name = "RST_RPU_D",  .addr = A_VERSAL2_RST_RPU_D,
> +        .reset = 0x10303,
> +        .rsvd = 0xfffefcfc,
> +        .pre_write = crl_rst_cpu_prew,
> +    },{ .name = "RST_RPU_E",  .addr = A_VERSAL2_RST_RPU_E,
> +        .reset = 0x10303,
> +        .rsvd = 0xfffefcfc,
> +        .pre_write = crl_rst_cpu_prew,
> +    },{ .name = "RST_RPU_GD_0",  .addr = A_VERSAL2_RST_RPU_GD_0,
> +        .reset = 0x3,
> +    },{ .name = "RST_RPU_GD_1",  .addr = A_VERSAL2_RST_RPU_GD_1,
> +        .reset = 0x3,
> +    },{ .name = "RST_ASU_GD",  .addr = A_VERSAL2_RST_ASU_GD,
> +        .reset = 0x3,
> +    },{ .name = "RST_ADMA",  .addr = A_VERSAL2_RST_ADMA,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_SDMA",  .addr = A_VERSAL2_RST_SDMA,
> +        .pre_write = crl_rst_dev_prew,
> +        .reset = 0x1,
> +    },{ .name = "RST_GEM0",  .addr = A_VERSAL2_RST_GEM0,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_GEM1",  .addr = A_VERSAL2_RST_GEM1,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_USB0",  .addr = A_VERSAL2_RST_USB0,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_USB1",  .addr = A_VERSAL2_RST_USB1,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_UART0",  .addr = A_VERSAL2_RST_UART0,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_UART1",  .addr = A_VERSAL2_RST_UART1,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_SPI0",  .addr = A_VERSAL2_RST_SPI0,
> +        .reset = 0x1,
> +    },{ .name = "RST_SPI1",  .addr = A_VERSAL2_RST_SPI1,
> +        .reset = 0x1,
> +    },{ .name = "RST_CAN0",  .addr = A_VERSAL2_RST_CAN0,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_CAN1",  .addr = A_VERSAL2_RST_CAN1,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_CAN2",  .addr = A_VERSAL2_RST_CAN2,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_CAN3",  .addr = A_VERSAL2_RST_CAN3,
> +        .reset = 0x1,
> +        .pre_write = crl_rst_dev_prew,
> +    },{ .name = "RST_I3C0",  .addr = A_VERSAL2_RST_I3C0,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C1",  .addr = A_VERSAL2_RST_I3C1,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C2",  .addr = A_VERSAL2_RST_I3C2,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C3",  .addr = A_VERSAL2_RST_I3C3,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C4",  .addr = A_VERSAL2_RST_I3C4,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C5",  .addr = A_VERSAL2_RST_I3C5,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C6",  .addr = A_VERSAL2_RST_I3C6,
> +        .reset = 0x1,
> +    },{ .name = "RST_I3C7",  .addr = A_VERSAL2_RST_I3C7,
> +        .reset = 0x1,
> +    },{ .name = "RST_DBG_LPX",  .addr = A_VERSAL2_RST_DBG_LPX,
> +        .reset = 0x3,
> +        .rsvd = 0xfc,
> +    },{ .name = "RST_GPIO",  .addr = A_VERSAL2_RST_GPIO,
> +        .reset = 0x1,
> +    },{ .name = "RST_TTC",  .addr = A_VERSAL2_RST_TTC,
> +        .reset = 0xff,
> +    },{ .name = "RST_TIMESTAMP",  .addr = A_VERSAL2_RST_TIMESTAMP,
> +        .reset = 0x1,
> +    },{ .name = "RST_SWDT0",  .addr = A_VERSAL2_RST_SWDT0,
> +        .reset = 0x1,
> +    },{ .name = "RST_SWDT1",  .addr = A_VERSAL2_RST_SWDT1,
> +        .reset = 0x1,
> +    },{ .name = "RST_SWDT2",  .addr = A_VERSAL2_RST_SWDT2,
> +        .reset = 0x1,
> +    },{ .name = "RST_SWDT3",  .addr = A_VERSAL2_RST_SWDT3,
> +        .reset = 0x1,
> +    },{ .name = "RST_SWDT4",  .addr = A_VERSAL2_RST_SWDT4,
> +        .reset = 0x1,
> +    },{ .name = "RST_IPI",  .addr = A_VERSAL2_RST_IPI,
> +    },{ .name = "RST_SYSMON",  .addr = A_VERSAL2_RST_SYSMON,
> +    },{ .name = "ASU_MB_RST_MODE",  .addr = A_VERSAL2_ASU_MB_RST_MODE,
> +        .reset = 0x1,
> +        .rsvd = 0xf8,
> +    },{ .name = "FPX_TOPSW_MUX_CTRL",  .addr = A_VERSAL2_FPX_TOPSW_MUX_CTRL,
> +        .reset = 0x1,
> +    },{ .name = "RST_FPX",  .addr = A_VERSAL2_RST_FPX,
> +        .reset = 0x3,
> +    },{ .name = "RST_MMI",  .addr = A_VERSAL2_RST_MMI,
> +        .reset = 0x1,
> +    },{ .name = "RST_OCM",  .addr = A_VERSAL2_RST_OCM,
> +    }
> +};
> +
>  static void versal_crl_reset_enter(Object *obj, ResetType type)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>      unsigned int i;
>  
>      for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
>          register_reset(&s->regs_info[i]);
>      }
>  }
>  
> +static void versal2_crl_reset_enter(Object *obj, ResetType type)
> +{
> +    XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
> +    size_t i;
> +
> +    for (i = 0; i < VERSAL2_CRL_R_MAX; ++i) {
> +        register_reset(&s->regs_info[i]);
> +    }
> +}
> +
>  static void versal_crl_reset_hold(Object *obj, ResetType type)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>  
>      crl_update_irq(s);
> @@ -386,10 +681,77 @@ static void versal_crl_init(Object *obj)
>                                   qdev_prop_allow_set_link_before_realize,
>                                   OBJ_PROP_LINK_STRONG);
>      }
>  }
>  
> +static void versal2_crl_init(Object *obj)
> +{
> +    XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
> +    XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    size_t i;
> +
> +    xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
> +                                            ARRAY_SIZE(versal2_crl_regs_info),
> +                                            s->regs_info, s->regs,
> +                                            &crl_ops,
> +                                            XLNX_VERSAL_CRL_ERR_DEBUG,
> +                                            VERSAL2_CRL_R_MAX * 4);
> +    xvcb->regs = s->regs;
> +
> +    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
> +        object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
> +                                 (Object **)&s->cfg.rpu[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
> +        object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.adma[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.sdma); ++i) {
> +        object_property_add_link(obj, "sdma[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.sdma[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
> +        object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.uart[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
> +        object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.gem[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.usb); ++i) {
> +        object_property_add_link(obj, "usb[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.usb[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(s->cfg.can); ++i) {
> +        object_property_add_link(obj, "can[*]", TYPE_DEVICE,
> +                                 (Object **)&s->cfg.can[i],
> +                                 qdev_prop_allow_set_link_before_realize,
> +                                 OBJ_PROP_LINK_STRONG);
> +    }
> +}
> +
>  static void crl_finalize(Object *obj)
>  {
>      XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
>      register_finalize_block(s->reg_array);
>  }
> @@ -402,10 +764,20 @@ static const VMStateDescription vmstate_versal_crl = {
>          VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
>          VMSTATE_END_OF_LIST(),
>      }
>  };
>  
> +static const VMStateDescription vmstate_versal2_crl = {
> +    .name = TYPE_XLNX_VERSAL2_CRL,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (const VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(regs, XlnxVersal2CRL, VERSAL2_CRL_R_MAX),
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
>  static void versal_crl_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
>      ResettableClass *rc = RESETTABLE_CLASS(klass);
> @@ -414,10 +786,21 @@ static void versal_crl_class_init(ObjectClass *klass, const void *data)
>      rc->phases.enter = versal_crl_reset_enter;
>      rc->phases.hold = versal_crl_reset_hold;
>      xvcc->decode_periph_rst = versal_decode_periph_rst;
>  }
>  
> +static void versal2_crl_class_init(ObjectClass *klass, const void *data)
> +{
> +    XlnxVersalCRLBaseClass *xvcc = XLNX_VERSAL_CRL_BASE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_versal2_crl;
> +    rc->phases.enter = versal2_crl_reset_enter;
> +    xvcc->decode_periph_rst = versal2_decode_periph_rst;
> +}
> +
>  static const TypeInfo crl_base_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL_BASE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxVersalCRLBase),
>      .class_size    = sizeof(XlnxVersalCRLBaseClass),
> @@ -431,12 +814,21 @@ static const TypeInfo versal_crl_info = {
>      .instance_size = sizeof(XlnxVersalCRL),
>      .instance_init = versal_crl_init,
>      .class_init    = versal_crl_class_init,
>  };
>  
> +static const TypeInfo versal2_crl_info = {
> +    .name          = TYPE_XLNX_VERSAL2_CRL,
> +    .parent        = TYPE_XLNX_VERSAL_CRL_BASE,
> +    .instance_size = sizeof(XlnxVersal2CRL),
> +    .instance_init = versal2_crl_init,
> +    .class_init    = versal2_crl_class_init,
> +};
> +
>  static void crl_register_types(void)
>  {
>      type_register_static(&crl_base_info);
>      type_register_static(&versal_crl_info);
> +    type_register_static(&versal2_crl_info);
>  }
>  
>  type_init(crl_register_types)
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap
  2025-07-16  9:54 ` [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap Luc Michel
@ 2025-07-31 20:27   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:27 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Luc,

On Wed, Jul 16, 2025 at 11:54:20AM +0200, Luc Michel wrote:
> Add the per_cluster_gic switch to the VersalCpuClusterMap structure.
> When set, this indicates that a GIC instance should by created
> per-cluster instead of globaly for the whole RPU or APU. This is in

s/globaly/globally/

Otherwise:

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> preparation for versal2.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
>  hw/arm/xlnx-versal.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index aef53876f26..9d900fe3127 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -86,10 +86,15 @@ enum StartPoweredOffMode {
>      SPO_ALL,
>  };
>  
>  typedef struct VersalCpuClusterMap {
>      VersalGicMap gic;
> +    /*
> +     * true: one GIC per cluster.
> +     * false: one GIC for all CPUs
> +     */
> +    bool per_cluster_gic;
>  
>      const char *name;
>      const char *cpu_model;
>      size_t num_core;
>      size_t num_cluster;
> @@ -828,16 +833,22 @@ static void versal_create_cpu_cluster(Versal *s, const VersalCpuClusterMap *map)
>              DeviceState *cpu = versal_create_cpu(s, map, cluster, mr, i, j);
>  
>              cpus[i * map->num_core + j] = cpu;
>          }
>  
> +        if (map->per_cluster_gic) {
> +            versal_create_and_connect_gic(s, map, mr, &cpus[i * map->num_core],
> +                                          map->num_core);
> +        }
>      }
>  
>      qdev_realize_and_unref(cluster, NULL, &error_fatal);
>  
> -    versal_create_and_connect_gic(s, map, mr, cpus,
> -                                  map->num_cluster * map->num_core);
> +    if (!map->per_cluster_gic) {
> +        versal_create_and_connect_gic(s, map, mr, cpus,
> +                                      map->num_cluster * map->num_core);
> +    }
>  
>      has_gtimer = arm_feature(&ARM_CPU(cpus[0])->env, ARM_FEATURE_GENERIC_TIMER);
>      if (map->dtb_expose && has_gtimer) {
>          qemu_fdt_add_subnode(s->cfg.fdt, "/timer");
>          qemu_fdt_setprop_cells(s->cfg.fdt, "/timer", "interrupts",
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor
  2025-07-16  9:54 ` [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor Luc Michel
@ 2025-07-31 20:31   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:31 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:21AM +0200, Luc Michel wrote:
> Add the target field in the IRQ descriptor. This allows to target an IRQ
> to another IRQ controller than the GIC(s). Other supported targets are
> the PMC PPU1 CPU interrupt controller and the EAM (Error management)
> device. Those two devices are currently not implemented so IRQs
> targeting those will be left unconnected. This is in preparation for
> versal2.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal.c | 41 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 39 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 9d900fe3127..551671af425 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -50,18 +50,30 @@
>  #include "hw/cpu/cluster.h"
>  #include "hw/arm/bsa.h"
>  
>  /*
>   * IRQ descriptor to catch the following cases:
> + *   - An IRQ can either connect to the GICs, to the PPU1 intc, or the the EAM
>   *   - Multiple devices can connect to the same IRQ. They are OR'ed together.
>   */
>  FIELD(VERSAL_IRQ, IRQ, 0, 16)
> +FIELD(VERSAL_IRQ, TARGET, 16, 2)
>  FIELD(VERSAL_IRQ, ORED, 18, 1)
>  FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
>  
> +typedef enum VersalIrqTarget {
> +    IRQ_TARGET_GIC,
> +    IRQ_TARGET_PPU1,
> +    IRQ_TARGET_EAM,
> +} VersalIrqTarget;
> +
> +#define PPU1_IRQ(irq) ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
> +#define EAM_IRQ(irq) ((IRQ_TARGET_EAM << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
>  #define OR_IRQ(irq, or_idx) \
>      (R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
> +#define PPU1_OR_IRQ(irq, or_idx) \
> +    ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | OR_IRQ(irq, or_idx))
>  
>  typedef struct VersalSimplePeriphMap {
>      uint64_t addr;
>      int irq;
>  } VersalSimplePeriphMap;
> @@ -415,19 +427,27 @@ static qemu_irq versal_get_gic_irq(Versal *s, int irq_idx)
>   * Or gates are placed under the /soc/irq-or-gates QOM container.
>   */
>  static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
>                                            qemu_irq target_irq)
>  {
> +    static const char *TARGET_STR[] = {
> +        [IRQ_TARGET_GIC] = "gic",
> +        [IRQ_TARGET_PPU1] = "ppu1",
> +        [IRQ_TARGET_EAM] = "eam",
> +    };
> +
> +    VersalIrqTarget target;
>      Object *container = versal_get_child(s, "irq-or-gates");
>      DeviceState *dev;
>      g_autofree char *name;
>      int idx, or_idx;
>  
>      idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
>      or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> +    target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
>  
> -    name = g_strdup_printf("irq[%d]", idx);
> +    name = g_strdup_printf("%s-irq[%d]", TARGET_STR[target], idx);
>      dev = DEVICE(object_resolve_path_at(container, name));
>  
>      if (dev == NULL) {
>          dev = qdev_new(TYPE_OR_IRQ);
>          object_property_add_child(container, name, OBJECT(dev));
> @@ -439,16 +459,33 @@ static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
>      return qdev_get_gpio_in(dev, or_idx);
>  }
>  
>  static qemu_irq versal_get_irq(Versal *s, int irq_idx)
>  {
> +    VersalIrqTarget target;
>      qemu_irq irq;
>      bool ored;
>  
> +    target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
>      ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
>  
> -    irq = versal_get_gic_irq(s, irq_idx);
> +    switch (target) {
> +    case IRQ_TARGET_EAM:
> +        /* EAM not implemented */
> +        return NULL;
> +
> +    case IRQ_TARGET_PPU1:
> +        /* PPU1 CPU not implemented */
> +        return NULL;
> +
> +    case IRQ_TARGET_GIC:
> +        irq = versal_get_gic_irq(s, irq_idx);
> +        break;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
>  
>      if (ored) {
>          irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
>      }
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC
  2025-07-16  9:54 ` [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC Luc Michel
@ 2025-07-31 20:40   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:40 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:23AM +0200, Luc Michel wrote:
> Add the Versal Gen 2 (versal2) version of the Versal SoC family.
> This version embeds up to 8 Cortex-A78AE cores (split into 4 clusters)
> and 10 Cortex-R52 cores (split into 5 clusters). The similarities
> between versal and versal2 in term of architecture allow to reuse the
> VersalMap structure to almost fully describe the implemented parts of
> versal2.
> 
> The versal2 eFuse device differs quite a lot from the versal one and is
> left as future work.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/arm/xlnx-versal.h |  17 ++-
>  hw/arm/xlnx-versal.c         | 212 ++++++++++++++++++++++++++++++++---
>  2 files changed, 214 insertions(+), 15 deletions(-)
> 
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index bdfab2a5426..1d216b5dbf1 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -1,7 +1,7 @@
>  /*
> - * Model of the Xilinx Versal
> + * AMD/Xilinx Versal family SoC model.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
>   * Copyright (c) 2025 Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
> @@ -20,10 +20,11 @@
>  
>  #define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base"
>  OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE)
>  
>  #define TYPE_XLNX_VERSAL "xlnx-versal"
> +#define TYPE_XLNX_VERSAL2 "xlnx-versal2"
>  
>  struct Versal {
>      /*< private >*/
>      SysBusDevice parent_obj;
>  
> @@ -69,6 +70,20 @@ hwaddr versal_get_reserved_mmio_addr(Versal *s);
>  
>  int versal_get_num_cpu(VersalVersion version);
>  int versal_get_num_can(VersalVersion version);
>  int versal_get_num_sdhci(VersalVersion version);
>  
> +static inline const char *versal_get_class(VersalVersion version)
> +{
> +    switch (version) {
> +    case VERSAL_VER_VERSAL:
> +        return TYPE_XLNX_VERSAL;
> +
> +    case VERSAL_VER_VERSAL2:
> +        return TYPE_XLNX_VERSAL2;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
>  #endif
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 551671af425..52a68e356b0 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -1,7 +1,7 @@
>  /*
> - * Xilinx Versal SoC model.
> + * AMD/Xilinx Versal family SoC model.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
>   * Copyright (c) 2025 Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
> @@ -353,12 +353,133 @@ static const VersalMap VERSAL_MAP = {
>      .crl = { 0xff5e0000, 10 },
>  
>      .reserved = { 0xa0000000, 111, 8 },
>  };
>  
> +static const VersalMap VERSAL2_MAP = {
> +    .ocm = {
> +        .addr = 0xbbe00000,
> +        .size = 2 * MiB,
> +    },
> +
> +    .ddr = {
> +        .chan[0] = { .addr = 0x0, .size = 2046 * MiB },
> +        .chan[1] = { .addr = 0x800000000ull, .size = 32 * GiB },
> +        .chan[2] = { .addr = 0xc00000000ull, .size = 256 * GiB },
> +        .chan[3] = { .addr = 0x10000000000ull, .size = 734 * GiB },
> +        .num_chan = 4,
> +    },
> +
> +    .apu = {
> +        .name = "apu",
> +        .cpu_model = ARM_CPU_TYPE_NAME("cortex-a78ae"),
> +        .num_cluster = 4,
> +        .num_core = 2,
> +        .qemu_cluster_id = 0,
> +        .mp_affinity = {
> +            .base = 0x0, /* TODO: the MT bit should be set */
> +            .core_mask = 0xff,
> +            .core_shift = 8,
> +            .cluster_mask = 0xff,
> +            .cluster_shift = 16,
> +        },
> +        .start_powered_off = SPO_SECONDARIES,
> +        .dtb_expose = true,
> +        .gic = {
> +            .version = 3,
> +            .dist = 0xe2000000,
> +            .redist = 0xe2060000,
> +            .num_irq = 544,
> +            .has_its = true,
> +            .its = 0xe2040000,
> +        },
> +    },
> +
> +    .rpu = {
> +        .name = "rpu",
> +        .cpu_model = ARM_CPU_TYPE_NAME("cortex-r52"),
> +        .num_cluster = 5,
> +        .num_core = 2,
> +        .qemu_cluster_id = 1,
> +        .mp_affinity = {
> +            .base = 0x0,
> +            .core_mask = 0xff,
> +            .core_shift = 0,
> +            .cluster_mask = 0xff,
> +            .cluster_shift = 8,
> +        },
> +        .start_powered_off = SPO_ALL,
> +        .dtb_expose = false,
> +        .per_cluster_gic = true,
> +        .gic = {
> +            .version = 3,
> +            .dist = 0x0,
> +            .redist = 0x100000,
> +            .num_irq = 288,
> +        },
> +    },
> +
> +    .uart[0] = { 0xf1920000, 25 },
> +    .uart[1] = { 0xf1930000, 26 },
> +    .num_uart = 2,
> +
> +    .canfd[0] = { 0xf19e0000, 27 },
> +    .canfd[1] = { 0xf19f0000, 28 },
> +    .canfd[2] = { 0xf1a00000, 95 },
> +    .canfd[3] = { 0xf1a10000, 96 },
> +    .num_canfd = 4,
> +
> +    .gem[0] = { { 0xf1a60000, 39 }, 2, "rgmii-id", 1000 },
> +    .gem[1] = { { 0xf1a70000, 41 }, 2, "rgmii-id", 1000 },
> +    .gem[2] = { { 0xed920000, 164 }, 4, "usxgmii", 10000 }, /* MMI 10Gb GEM */
> +    .num_gem = 3,
> +
> +    .zdma[0] = { "adma", { 0xebd00000, 72 }, 8, 0x10000, 1 },
> +    .zdma[1] = { "sdma", { 0xebd80000, 112 }, 8, 0x10000, 1 },
> +    .num_zdma = 2,
> +
> +    .usb[0] = { .xhci = 0xf1b00000, .ctrl = 0xf1ee0000, .irq = 29 },
> +    .usb[1] = { .xhci = 0xf1c00000, .ctrl = 0xf1ef0000, .irq = 34 },
> +    .num_usb = 2,
> +
> +    .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 230 },
> +
> +    .ospi = {
> +        .ctrl = 0xf1010000,
> +        .dac = 0xc0000000, .dac_sz = 0x20000000,
> +        .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
> +        .irq = 216,
> +    },
> +
> +    .sdhci[0] = { 0xf1040000, 218 },
> +    .sdhci[1] = { 0xf1050000, 220 }, /* eMMC */
> +    .num_sdhci = 2,
> +
> +    .pmc_iou_slcr = { 0xf1060000, 222 },
> +    .bbram = { 0xf11f0000, PPU1_OR_IRQ(18, 0) },
> +    .crl = { 0xeb5e0000 },
> +    .trng = { 0xf1230000, 233 },
> +    .rtc = {
> +        { 0xf12a0000, PPU1_OR_IRQ(18, 1) },
> +        .alarm_irq = 200, .second_irq = 201
> +    },
> +
> +    .cfu = {
> +        .cframe_base = 0xf12d0000, .cframe_stride = 0x1000,
> +        .cframe_bcast_reg = 0xf12ee000, .cframe_bcast_fdri = 0xf12ef000,
> +        .cfu_apb = 0xf12b0000, .cfu_sfr = 0xf12c1000,
> +        .cfu_stream = 0xf12c0000, .cfu_stream_2 = 0xf1f80000,
> +        .cfu_fdro = 0xf12c2000,
> +        .cfu_apb_irq = 235, .cframe_irq = EAM_IRQ(7),
> +    },
> +
> +    .reserved = { 0xf5e00000, 270, 8 },
> +};
> +
>  static const VersalMap *VERSION_TO_MAP[] = {
>      [VERSAL_VER_VERSAL] = &VERSAL_MAP,
> +    [VERSAL_VER_VERSAL2] = &VERSAL2_MAP,
>  };
>  
>  static inline VersalVersion versal_get_version(Versal *s)
>  {
>      return XLNX_VERSAL_BASE_GET_CLASS(s)->version;
> @@ -1291,10 +1412,15 @@ static void versal_create_efuse(Versal *s,
>  {
>      DeviceState *bits;
>      DeviceState *ctrl;
>      DeviceState *cache;
>  
> +    if (versal_get_version(s) != VERSAL_VER_VERSAL) {
> +        /* TODO for versal2 */
> +        return;
> +    }
> +
>      ctrl = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CTRL);
>      cache = qdev_new(TYPE_XLNX_VERSAL_EFUSE_CACHE);
>      bits = qdev_new(TYPE_XLNX_EFUSE);
>  
>      qdev_prop_set_uint32(bits, "efuse-nr", 3);
> @@ -1542,34 +1668,47 @@ static inline void crl_connect_dev_by_name(Versal *s, Object *crl,
>  }
>  
>  static inline void versal_create_crl(Versal *s)
>  {
>      const VersalMap *map;
> +    VersalVersion ver;
>      const char *crl_class;
>      DeviceState *dev;
> +    size_t num_gem;
>      Object *obj;
>  
>      map = versal_get_map(s);
> +    ver = versal_get_version(s);
>  
> -    crl_class = TYPE_XLNX_VERSAL_CRL;
> +    crl_class = xlnx_versal_crl_class_name(ver);
>      dev = qdev_new(crl_class);
>      obj = OBJECT(dev);
>      object_property_add_child(OBJECT(s), "crl", obj);
>  
> +    /*
> +     * The 3rd GEM controller on versal2 is in the MMI subsystem.
> +     * Its reset line is not connected to the CRL. Consider only the first two
> +     * ones.
> +     */
> +    num_gem = ver == VERSAL_VER_VERSAL2 ? 2 : map->num_gem;
> +
>      crl_connect_dev_by_name(s, obj, "rpu-cluster/rpu",
>                              map->rpu.num_cluster * map->rpu.num_core);
>      crl_connect_dev_by_name(s, obj, map->zdma[0].name, map->zdma[0].num_chan);
>      crl_connect_dev_by_name(s, obj, "uart", map->num_uart);
> -    crl_connect_dev_by_name(s, obj, "gem", map->num_gem);
> +    crl_connect_dev_by_name(s, obj, "gem", num_gem);
>      crl_connect_dev_by_name(s, obj, "usb", map->num_usb);
>  
>      sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_abort);
>  
>      memory_region_add_subregion(&s->mr_ps, map->crl.addr,
>                                  sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
>  
> -    versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
> +    if (ver == VERSAL_VER_VERSAL) {
> +        /* CRL IRQ line has been removed in versal2 */
> +        versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), 0, map->crl.irq);
> +    }
>  }
>  
>  /*
>   * This takes the board allocated linear DDR memory and creates aliases
>   * for each split DDR range/aperture on the Versal address map.
> @@ -1657,21 +1796,16 @@ static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
>      qemu_log_mask(LOG_UNIMP,
>                    "PMC SLCR parity interrupt behaviour "
>                    "is not yet implemented\n");
>  }
>  
> -static void versal_unimp(Versal *s)
> +static void versal_unimp_common(Versal *s)
>  {
>      DeviceState *slcr;
>      qemu_irq gpio_in;
>  
> -    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
> -    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
> -    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
>      versal_unimp_area(s, "crp", &s->mr_ps, 0xf1260000, 0x10000);
> -    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
> -    versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, 0xff140000, 0x10000);
>  
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel,
>                              "sd-emmc-sel-dummy", 2);
>      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
>                              "qspi-ospi-mux-sel-dummy", 1);
> @@ -1690,10 +1824,29 @@ static void versal_unimp(Versal *s)
>  
>      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0);
>      qdev_connect_gpio_out_named(slcr, SYSBUS_DEVICE_GPIO_IRQ, 0, gpio_in);
>  }
>  
> +static void versal_unimp(Versal *s)
> +{
> +    versal_unimp_area(s, "psm", &s->mr_ps, 0xffc80000, 0x70000);
> +    versal_unimp_area(s, "crf", &s->mr_ps, 0xfd1a0000, 0x140000);
> +    versal_unimp_area(s, "apu", &s->mr_ps, 0xfd5c0000, 0x100);
> +    versal_unimp_area(s, "iou-scntr", &s->mr_ps, 0xff130000, 0x10000);
> +    versal_unimp_area(s, "iou-scntr-secure", &s->mr_ps, 0xff140000, 0x10000);
> +
> +    versal_unimp_common(s);
> +}
> +
> +static void versal2_unimp(Versal *s)
> +{
> +    versal_unimp_area(s, "fpd-systmr-ctrl", &s->mr_ps, 0xec920000, 0x1000);
> +    versal_unimp_area(s, "crf", &s->mr_ps, 0xec200000, 0x100000);
> +
> +    versal_unimp_common(s);
> +}
> +
>  static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>                                   unsigned int freq_hz)
>  {
>      uint32_t phandle;
>  
> @@ -1707,13 +1860,12 @@ static uint32_t fdt_add_clk_node(Versal *s, const char *name,
>      qemu_fdt_setprop(s->cfg.fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
>  
>      return phandle;
>  }
>  
> -static void versal_realize(DeviceState *dev, Error **errp)
> +static void versal_realize_common(Versal *s)
>  {
> -    Versal *s = XLNX_VERSAL_BASE(dev);
>      DeviceState *slcr, *ospi;
>      MemoryRegion *ocm;
>      Object *container;
>      const VersalMap *map = versal_get_map(s);
>      size_t i;
> @@ -1782,18 +1934,33 @@ static void versal_realize(DeviceState *dev, Error **errp)
>      versal_create_rtc(s, &map->rtc);
>      versal_create_cfu(s, &map->cfu);
>      versal_create_crl(s);
>  
>      versal_map_ddr(s, &map->ddr);
> -    versal_unimp(s);
>  
>      /* Create the On Chip Memory (OCM).  */
>      ocm = g_new(MemoryRegion, 1);
>      memory_region_init_ram(ocm, OBJECT(s), "ocm", map->ocm.size, &error_fatal);
>      memory_region_add_subregion_overlap(&s->mr_ps, map->ocm.addr, ocm, 0);
>  }
>  
> +static void versal_realize(DeviceState *dev, Error **errp)
> +{
> +    Versal *s = XLNX_VERSAL_BASE(dev);
> +
> +    versal_realize_common(s);
> +    versal_unimp(s);
> +}
> +
> +static void versal2_realize(DeviceState *dev, Error **errp)
> +{
> +    Versal *s = XLNX_VERSAL_BASE(dev);
> +
> +    versal_realize_common(s);
> +    versal2_unimp(s);
> +}
> +
>  void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk)
>  {
>      DeviceState *sdhci, *card;
>  
>      sdhci = DEVICE(versal_get_child_idx(s, "sdhci", sd_idx));
> @@ -1925,20 +2092,30 @@ static const Property versal_properties[] = {
>  
>  static void versal_base_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->realize = versal_realize;
>      device_class_set_props(dc, versal_properties);
>      /* No VMSD since we haven't got any top-level SoC state to save.  */
>  }
>  
>  static void versal_class_init(ObjectClass *klass, const void *data)
>  {
>      VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      vc->version = VERSAL_VER_VERSAL;
> +    dc->realize = versal_realize;
> +}
> +
> +static void versal2_class_init(ObjectClass *klass, const void *data)
> +{
> +    VersalClass *vc = XLNX_VERSAL_BASE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    vc->version = VERSAL_VER_VERSAL2;
> +    dc->realize = versal2_realize;
>  }
>  
>  static const TypeInfo versal_base_info = {
>      .name = TYPE_XLNX_VERSAL_BASE,
>      .parent = TYPE_SYS_BUS_DEVICE,
> @@ -1953,12 +2130,19 @@ static const TypeInfo versal_info = {
>      .name = TYPE_XLNX_VERSAL,
>      .parent = TYPE_XLNX_VERSAL_BASE,
>      .class_init = versal_class_init,
>  };
>  
> +static const TypeInfo versal2_info = {
> +    .name = TYPE_XLNX_VERSAL2,
> +    .parent = TYPE_XLNX_VERSAL_BASE,
> +    .class_init = versal2_class_init,
> +};
> +
>  static void versal_register_types(void)
>  {
>      type_register_static(&versal_base_info);
>      type_register_static(&versal_info);
> +    type_register_static(&versal2_info);
>  }
>  
>  type_init(versal_register_types);
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt
  2025-07-16  9:54 ` [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt Luc Michel
@ 2025-07-31 20:45   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 20:45 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:24AM +0200, Luc Michel wrote:
> To align with current branding and ensure coherency with the upcoming
> versal2 machine, rename the xlnx-versal-virt machine to amd-versal-virt.
> Keep an alias of the old name to the new one for command-line backward
> compatibility.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  docs/system/arm/xlnx-versal-virt.rst | 26 +++++++++++++++-----------
>  hw/arm/xlnx-versal-virt.c            | 11 +++++++----
>  2 files changed, 22 insertions(+), 15 deletions(-)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
> index c5f35f28e4f..2c63fbf519f 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -1,21 +1,25 @@
> -Xilinx Versal Virt (``xlnx-versal-virt``)
> -=========================================
> +AMD Versal Virt (``amd-versal-virt``)
> +=====================================
>  
> -Xilinx Versal is a family of heterogeneous multi-core SoCs
> +AMD Versal is a family of heterogeneous multi-core SoCs
>  (System on Chip) that combine traditional hardened CPUs and I/O
>  peripherals in a Processing System (PS) with runtime programmable
>  FPGA logic (PL) and an Artificial Intelligence Engine (AIE).
>  
> +QEMU implements the Versal Series variant of Versal SoCs, with the
> +``amd-versal-virt`` machine. The alias ``xlnx-versal-virt`` is kept for
> +backward compatibility.
> +
>  More details here:
> -https://www.xilinx.com/products/silicon-devices/acap/versal.html
> +https://www.amd.com/en/products/adaptive-socs-and-fpgas/versal.html
>  
>  The family of Versal SoCs share a single architecture but come in
>  different parts with different speed grades, amounts of PL and
>  other differences.
>  
> -The Xilinx Versal Virt board in QEMU is a model of a virtual board
> +The AMD Versal Virt board in QEMU is a model of a virtual board
>  (does not exist in reality) with a virtual Versal SoC without I/O
>  limitations. Currently, we support the following cores and devices:
>  
>  Implemented CPU cores:
>  
> @@ -72,11 +76,11 @@ A few examples:
>  
>  Direct Linux boot of a generic ARM64 upstream Linux kernel:
>  
>  .. code-block:: bash
>  
> -  $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
> +  $ qemu-system-aarch64 -M amd-versal-virt -m 2G \
>        -serial mon:stdio -display none \
>        -kernel arch/arm64/boot/Image \
>        -nic user -nic user \
>        -device virtio-rng-device,bus=virtio-mmio-bus.0 \
>        -drive if=none,index=0,file=hd0.qcow2,id=hd0,snapshot \
> @@ -85,11 +89,11 @@ Direct Linux boot of a generic ARM64 upstream Linux kernel:
>  
>  Direct Linux boot of PetaLinux 2019.2:
>  
>  .. code-block:: bash
>  
> -  $ qemu-system-aarch64  -M xlnx-versal-virt -m 2G \
> +  $ qemu-system-aarch64  -M amd-versal-virt -m 2G \
>        -serial mon:stdio -display none \
>        -kernel petalinux-v2019.2/Image \
>        -append "rdinit=/sbin/init console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8" \
>        -net nic,model=cadence_gem,netdev=net0 -netdev user,id=net0 \
>        -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
> @@ -98,11 +102,11 @@ Direct Linux boot of PetaLinux 2019.2:
>  Boot PetaLinux 2019.2 via ARM Trusted Firmware (2018.3 because the 2019.2
>  version of ATF tries to configure the CCI which we don't model) and U-boot:
>  
>  .. code-block:: bash
>  
> -  $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
> +  $ qemu-system-aarch64 -M amd-versal-virt -m 2G \
>        -serial stdio -display none \
>        -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
>        -device loader,file=petalinux-v2019.2/u-boot.elf \
>        -device loader,addr=0x20000000,file=petalinux-v2019.2/Image \
>        -nic user -nic user \
> @@ -123,11 +127,11 @@ Run the following at the U-Boot prompt:
>  
>  Boot Linux as DOM0 on Xen via U-Boot:
>  
>  .. code-block:: bash
>  
> -  $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
> +  $ qemu-system-aarch64 -M amd-versal-virt -m 4G \
>        -serial stdio -display none \
>        -device loader,file=petalinux-v2019.2/u-boot.elf,cpu-num=0 \
>        -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
>        -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
>        -nic user -nic user \
> @@ -151,11 +155,11 @@ Run the following at the U-Boot prompt:
>  
>  Boot Linux as Dom0 on Xen via ARM Trusted Firmware and U-Boot:
>  
>  .. code-block:: bash
>  
> -  $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
> +  $ qemu-system-aarch64 -M amd-versal-virt -m 4G \
>        -serial stdio -display none \
>        -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
>        -device loader,file=petalinux-v2019.2/u-boot.elf \
>        -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
>        -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
> @@ -225,11 +229,11 @@ To use a different index value, N, from default of 1, add:
>  
>    Thus, a file backend should be used with caution, and 'format=luks'
>    is highly recommended (albeit with usage complexity).
>  
>    Better yet, do not use actual product data when running guest image
> -  on this Xilinx Versal Virt board.
> +  on this AMD Versal Virt board.
>  
>  Using CANFDs for Versal Virt
>  """"""""""""""""""""""""""""
>  Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
>  implementation. Bus connection and socketCAN connection for each CAN module
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 5e47a20922a..daacbfb984e 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -1,7 +1,7 @@
>  /*
> - * Xilinx Versal Virtual board.
> + * AMD/Xilinx Versal Virtual board.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
>   * Copyright (c) 2025, Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
> @@ -24,11 +24,11 @@
>  #include "hw/arm/boot.h"
>  #include "target/arm/multiprocessing.h"
>  #include "qom/object.h"
>  #include "target/arm/cpu.h"
>  
> -#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
> +#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
>  OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
>  
>  #define XLNX_VERSAL_NUM_OSPI_FLASH 4
>  
>  struct VersalVirt {
> @@ -53,10 +53,11 @@ struct VersalVirt {
>  };
>  
>  static void fdt_create(VersalVirt *s)
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(s);
> +    const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
>  
>      s->fdt = create_device_tree(&s->fdt_size);
>      if (!s->fdt) {
>          error_report("create_device_tree() failed");
>          exit(1);
> @@ -70,11 +71,12 @@ static void fdt_create(VersalVirt *s)
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
>      qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
>      qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
> -    qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
> +    qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
> +                     sizeof(versal_compat));
>  }
>  
>  static void fdt_add_clk_node(VersalVirt *s, const char *name,
>                               unsigned int freq_hz, uint32_t phandle)
>  {
> @@ -346,11 +348,12 @@ static void versal_virt_machine_finalize(Object *obj)
>  static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
>  {
>      MachineClass *mc = MACHINE_CLASS(oc);
>      int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
>  
> -    mc->desc = "Xilinx Versal Virtual development board";
> +    mc->desc = "AMD Versal Virtual development board";
> +    mc->alias = "xlnx-versal-virt";
>      mc->init = versal_virt_init;
>      mc->min_cpus = num_cpu;
>      mc->max_cpus = num_cpu;
>      mc->default_cpus = num_cpu;
>      mc->no_cdrom = true;
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes
  2025-07-16  9:54 ` [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes Luc Michel
@ 2025-07-31 21:00   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:00 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Luc,

On Wed, Jul 16, 2025 at 11:54:25AM +0200, Luc Michel wrote:
> Split the xlnx-versal-virt machine type into a base abstract type and a
> concrete type. There is no functional change. This is in preparation for
> versal2 machine.

s/for versal2/for the versal2/ 

Otherwise:

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
>  hw/arm/xlnx-versal-virt.c | 74 +++++++++++++++++++++++++++------------
>  1 file changed, 52 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index daacbfb984e..9b20aef8b07 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -24,12 +24,15 @@
>  #include "hw/arm/boot.h"
>  #include "target/arm/multiprocessing.h"
>  #include "qom/object.h"
>  #include "target/arm/cpu.h"
>  
> +#define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
> +    MACHINE_TYPE_NAME("amd-versal-virt-base")
> +OBJECT_DECLARE_TYPE(VersalVirt, VersalVirtClass, XLNX_VERSAL_VIRT_BASE_MACHINE)
> +
>  #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
> -OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
>  
>  #define XLNX_VERSAL_NUM_OSPI_FLASH 4
>  
>  struct VersalVirt {
>      MachineState parent_obj;
> @@ -50,10 +53,16 @@ struct VersalVirt {
>          bool secure;
>          char *ospi_model;
>      } cfg;
>  };
>  
> +struct VersalVirtClass {
> +    MachineClass parent_class;
> +
> +    VersalVersion version;
> +};
> +
>  static void fdt_create(VersalVirt *s)
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(s);
>      const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
>  
> @@ -191,27 +200,28 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
>      versal_sdhci_plug_card(&s->soc, idx, blk);
>  }
>  
>  static char *versal_get_ospi_model(Object *obj, Error **errp)
>  {
> -    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
>  
>      return g_strdup(s->cfg.ospi_model);
>  }
>  
>  static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
>  {
> -    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
>  
>      g_free(s->cfg.ospi_model);
>      s->cfg.ospi_model = g_strdup(value);
>  }
>  
>  
>  static void versal_virt_init(MachineState *machine)
>  {
> -    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
> +    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(machine);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(machine);
>      int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
>      int i;
>  
>      /*
>       * If the user provides an Operating System to be loaded, we expect them
> @@ -239,15 +249,15 @@ static void versal_virt_init(MachineState *machine)
>      if (machine->kernel_filename) {
>          psci_conduit = QEMU_PSCI_CONDUIT_SMC;
>      }
>  
>      object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
> -                            TYPE_XLNX_VERSAL);
> +                            versal_get_class(vvc->version));
>      object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
>                               &error_abort);
>  
> -    for (i = 0; i < versal_get_num_can(VERSAL_VER_VERSAL); i++) {
> +    for (i = 0; i < versal_get_num_can(vvc->version); i++) {
>          g_autofree char *prop_name = g_strdup_printf("canbus%d", i);
>  
>          object_property_set_link(OBJECT(&s->soc), prop_name,
>                                   OBJECT(s->canbus[i]),
>                                   &error_abort);
> @@ -272,11 +282,11 @@ static void versal_virt_init(MachineState *machine)
>  
>      /* Attach efuse backend, if given */
>      efuse_attach_drive(s);
>  
>      /* Plug SD cards */
> -    for (i = 0; i < versal_get_num_sdhci(VERSAL_VER_VERSAL); i++) {
> +    for (i = 0; i < versal_get_num_sdhci(vvc->version); i++) {
>          sd_plug_card(s, i, drive_get(IF_SD, 0, i));
>      }
>  
>      s->binfo.ram_size = machine->ram_size;
>      s->binfo.loader_start = 0x0;
> @@ -316,14 +326,15 @@ static void versal_virt_init(MachineState *machine)
>      }
>  }
>  
>  static void versal_virt_machine_instance_init(Object *obj)
>  {
> -    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(s);
>      size_t i, num_can;
>  
> -    num_can = versal_get_num_can(VERSAL_VER_VERSAL);
> +    num_can = versal_get_num_can(vvc->version);
>      s->canbus = g_new0(CanBusState *, num_can);
>  
>      /*
>       * User can set canbusx properties to can-bus object and optionally connect
>       * to socketcan interface via command line.
> @@ -337,47 +348,66 @@ static void versal_virt_machine_instance_init(Object *obj)
>      }
>  }
>  
>  static void versal_virt_machine_finalize(Object *obj)
>  {
> -    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +    VersalVirt *s = XLNX_VERSAL_VIRT_BASE_MACHINE(obj);
>  
>      g_free(s->cfg.ospi_model);
>      g_free(s->canbus);
>  }
>  
> -static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
> +static void versal_virt_machine_class_init_common(ObjectClass *oc)
>  {
>      MachineClass *mc = MACHINE_CLASS(oc);
> -    int num_cpu = versal_get_num_cpu(VERSAL_VER_VERSAL);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(mc);
> +    int num_cpu = versal_get_num_cpu(vvc->version);
>  
> -    mc->desc = "AMD Versal Virtual development board";
> -    mc->alias = "xlnx-versal-virt";
> -    mc->init = versal_virt_init;
> -    mc->min_cpus = num_cpu;
> -    mc->max_cpus = num_cpu;
> -    mc->default_cpus = num_cpu;
>      mc->no_cdrom = true;
>      mc->auto_create_sdcard = true;
>      mc->default_ram_id = "ddr";
> +    mc->min_cpus = num_cpu;
> +    mc->max_cpus = num_cpu;
> +    mc->default_cpus = num_cpu;
> +    mc->init = versal_virt_init;
> +
>      object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
>                                     versal_set_ospi_model);
>      object_class_property_set_description(oc, "ospi-flash",
>                                            "Change the OSPI Flash model");
>  }
>  
> -static const TypeInfo versal_virt_machine_init_typeinfo = {
> -    .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
> +static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
> +{
> +    MachineClass *mc = MACHINE_CLASS(oc);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(oc);
> +
> +    mc->desc = "AMD Versal Virtual development board";
> +    mc->alias = "xlnx-versal-virt";
> +    vvc->version = VERSAL_VER_VERSAL;
> +
> +    versal_virt_machine_class_init_common(oc);
> +}
> +
> +static const TypeInfo versal_virt_base_machine_init_typeinfo = {
> +    .name       = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
>      .parent     = TYPE_MACHINE,
> -    .class_init = versal_virt_machine_class_init,
> +    .class_size = sizeof(VersalVirtClass),
>      .instance_init = versal_virt_machine_instance_init,
>      .instance_size = sizeof(VersalVirt),
>      .instance_finalize = versal_virt_machine_finalize,
> +    .abstract = true,
> +};
> +
> +static const TypeInfo versal_virt_machine_init_typeinfo = {
> +    .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
> +    .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
> +    .class_init = versal_virt_machine_class_init,
>  };
>  
>  static void versal_virt_machine_init_register_types(void)
>  {
> +    type_register_static(&versal_virt_base_machine_init_typeinfo);
>      type_register_static(&versal_virt_machine_init_typeinfo);
>  }
>  
>  type_init(versal_virt_machine_init_register_types)
> -
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up
  2025-07-16  9:54 ` [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up Luc Michel
@ 2025-07-31 21:00   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:00 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:26AM +0200, Luc Michel wrote:
> Remove now unused clock nodes. They have been replaced by the ones
> created in the SoC. Remove the unused cfg.secure VersalVirt field.
> Remove unecessary include directives.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/arm/xlnx-versal-virt.c | 24 ------------------------
>  1 file changed, 24 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 9b20aef8b07..154ed7332c3 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -17,14 +17,12 @@
>  #include "system/address-spaces.h"
>  #include "hw/block/flash.h"
>  #include "hw/boards.h"
>  #include "hw/sysbus.h"
>  #include "hw/arm/fdt.h"
> -#include "hw/qdev-properties.h"
>  #include "hw/arm/xlnx-versal.h"
>  #include "hw/arm/boot.h"
> -#include "target/arm/multiprocessing.h"
>  #include "qom/object.h"
>  #include "target/arm/cpu.h"
>  
>  #define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
>      MACHINE_TYPE_NAME("amd-versal-virt-base")
> @@ -39,20 +37,15 @@ struct VersalVirt {
>  
>      Versal soc;
>  
>      void *fdt;
>      int fdt_size;
> -    struct {
> -        uint32_t clk_125Mhz;
> -        uint32_t clk_25Mhz;
> -    } phandle;
>      struct arm_boot_info binfo;
>  
>      CanBusState **canbus;
>  
>      struct {
> -        bool secure;
>          char *ospi_model;
>      } cfg;
>  };
>  
>  struct VersalVirtClass {
> @@ -70,35 +63,20 @@ static void fdt_create(VersalVirt *s)
>      if (!s->fdt) {
>          error_report("create_device_tree() failed");
>          exit(1);
>      }
>  
> -    /* Allocate all phandles.  */
> -    s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
> -    s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
> -
>      /* Create /chosen node for load_dtb.  */
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
>      qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
>      qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
>      qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
>                       sizeof(versal_compat));
>  }
>  
> -static void fdt_add_clk_node(VersalVirt *s, const char *name,
> -                             unsigned int freq_hz, uint32_t phandle)
> -{
> -    qemu_fdt_add_subnode(s->fdt, name);
> -    qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
> -    qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
> -    qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
> -    qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
> -    qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
> -}
> -
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
>      char **node_path;
>      int n = 0;
> @@ -263,12 +241,10 @@ static void versal_virt_init(MachineState *machine)
>                                   &error_abort);
>      }
>  
>      fdt_create(s);
>      versal_set_fdt(&s->soc, s->fdt);
> -    fdt_add_clk_node(s, "/old-clk125", 125000000, s->phandle.clk_125Mhz);
> -    fdt_add_clk_node(s, "/old-clk25", 25000000, s->phandle.clk_25Mhz);
>  
>      sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
>      create_virtio_regions(s);
>  
>      /*
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices
  2025-07-16  9:54 ` [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices Luc Michel
@ 2025-07-31 21:01   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:01 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:27AM +0200, Luc Michel wrote:
> Update the list of supported devices in the Versal SoCs.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  docs/system/arm/xlnx-versal-virt.rst | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
> index 2c63fbf519f..94c8bacf61a 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -21,15 +21,15 @@ The AMD Versal Virt board in QEMU is a model of a virtual board
>  (does not exist in reality) with a virtual Versal SoC without I/O
>  limitations. Currently, we support the following cores and devices:
>  
>  Implemented CPU cores:
>  
> -- 2 ACPUs (ARM Cortex-A72)
> +- 2 ACPUs (ARM Cortex-A72) with their GICv3 and ITS
> +- 2 RCPUs (ARM Cortex-R5F) with their GICv2
>  
>  Implemented devices:
>  
> -- Interrupt controller (ARM GICv3)
>  - 2 UARTs (ARM PL011)
>  - An RTC (Versal built-in)
>  - 2 GEMs (Cadence MACB Ethernet MACs)
>  - 8 ADMA (Xilinx zDMA) channels
>  - 2 SD Controllers
> @@ -37,10 +37,13 @@ Implemented devices:
>  - XRAM (4MB of on chip Accelerator RAM)
>  - DDR memory
>  - BBRAM (36 bytes of Battery-backed RAM)
>  - eFUSE (3072 bytes of one-time field-programmable bit array)
>  - 2 CANFDs
> +- USB controller
> +- OSPI controller
> +- TRNG controller
>  
>  QEMU does not yet model any other devices, including the PL and the AI Engine.
>  
>  Other differences between the hardware and the QEMU model:
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb
  2025-07-16  9:54 ` [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb Luc Michel
@ 2025-07-31 21:02   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:02 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:28AM +0200, Luc Michel wrote:
> Add a note in the DTB section explaining how to dump the generated DTB
> using the dumpdtb machine option.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  docs/system/arm/xlnx-versal-virt.rst | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
> index 94c8bacf61a..5d7fa18592b 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -63,11 +63,17 @@ Users can load firmware or boot-loaders with the ``-device loader`` options.
>  
>  When loading an OS, QEMU generates a DTB and selects an appropriate address
>  where it gets loaded. This DTB will be passed to the kernel in register x0.
>  
>  If there's no ``-kernel`` option, we generate a DTB and place it at 0x1000
> -for boot-loaders or firmware to pick it up.
> +for boot-loaders or firmware to pick it up. To dump and observe the generated
> +DTB, one can use the ``dumpdtb`` machine option:
> +
> +.. code-block:: bash
> +
> +  $ qemu-system-aarch64 -M amd-versal-virt,dumpdtb=example.dtb -m 2G
> +
>  
>  If users want to provide their own DTB, they can use the ``-dtb`` option.
>  These DTBs will have their memory nodes modified to match QEMU's
>  selected ram_size option before they get passed to the kernel or FW.
>  
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine
  2025-07-16  9:54 ` [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine Luc Michel
@ 2025-07-31 21:08   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:08 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:29AM +0200, Luc Michel wrote:
> Add the Versal Gen 2 Virtual development machine embedding a
> versal2 SoC. This machine follows the same principle than the
> xlnx-versal-virt machine. It creates its own DTB and feeds it to the
> software payload. This way only implemented devices are exposed to the
> guest and the user does not need to provide a DTB.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  docs/system/arm/xlnx-versal-virt.rst | 49 ++++++++++++++++++++++++----
>  hw/arm/xlnx-versal-virt.c            | 37 +++++++++++++++++++--
>  2 files changed, 76 insertions(+), 10 deletions(-)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
> index 5d7fa18592b..af56b275413 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -1,16 +1,18 @@
> -AMD Versal Virt (``amd-versal-virt``)
> -=====================================
> +AMD Versal Virt (``amd-versal-virt``, ``amd-versal2-virt``)
> +===========================================================
>  
>  AMD Versal is a family of heterogeneous multi-core SoCs
>  (System on Chip) that combine traditional hardened CPUs and I/O
>  peripherals in a Processing System (PS) with runtime programmable
>  FPGA logic (PL) and an Artificial Intelligence Engine (AIE).
>  
> -QEMU implements the Versal Series variant of Versal SoCs, with the
> -``amd-versal-virt`` machine. The alias ``xlnx-versal-virt`` is kept for
> -backward compatibility.
> +QEMU implements two variants of Versal SoCs:
> +
> +- Versal (the ``amd-versal-virt`` machine, the alias ``xlnx-versal-virt`` is
> +  kept for backward compatibility)
> +- Versal Gen 2 (the ``amd-versal2-virt`` machine)
>  
>  More details here:
>  https://www.amd.com/en/products/adaptive-socs-and-fpgas/versal.html
>  
>  The family of Versal SoCs share a single architecture but come in
> @@ -19,10 +21,12 @@ other differences.
>  
>  The AMD Versal Virt board in QEMU is a model of a virtual board
>  (does not exist in reality) with a virtual Versal SoC without I/O
>  limitations. Currently, we support the following cores and devices:
>  
> +Versal
> +""""""
>  Implemented CPU cores:
>  
>  - 2 ACPUs (ARM Cortex-A72) with their GICv3 and ITS
>  - 2 RCPUs (ARM Cortex-R5F) with their GICv2
>  
> @@ -41,20 +45,42 @@ Implemented devices:
>  - 2 CANFDs
>  - USB controller
>  - OSPI controller
>  - TRNG controller
>  
> +Versal Gen 2
> +""""""""""""
> +Implemented CPU cores:
> +
> +- 8 ACPUs (ARM Cortex-A78AE) with their GICv3 and ITS
> +- 10 RCPUs (ARM Cortex-R52) with their GICv3 (one per cluster)
> +
> +Implemented devices:
> +
> +- 2 UARTs (ARM PL011)
> +- An RTC (Versal built-in)
> +- 3 GEMs (Cadence MACB Ethernet MACs)
> +- 8 ADMA (Xilinx zDMA) channels
> +- 2 SD Controllers
> +- OCM (256KB of On Chip Memory)
> +- DDR memory
> +- BBRAM (36 bytes of Battery-backed RAM)
> +- 2 CANFDs
> +- 2 USB controllers
> +- OSPI controller
> +- TRNG controller
> +
>  QEMU does not yet model any other devices, including the PL and the AI Engine.
>  
>  Other differences between the hardware and the QEMU model:
>  
>  - QEMU allows the amount of DDR memory provided to be specified with the
>    ``-m`` argument. If a DTB is provided on the command line then QEMU will
>    edit it to include suitable entries describing the Versal DDR memory ranges.
>  
> -- QEMU provides 8 virtio-mmio virtio transports; these start at
> -  address ``0xa0000000`` and have IRQs from 111 and upwards.
> +- QEMU provides 8 virtio-mmio virtio transports. They use reserved memory
> +  regions and IRQ pins to avoid conflicts with real SoC peripherals.
>  
>  Running
>  """""""
>  If the user provides an Operating System to be loaded, we expect users
>  to use the ``-kernel`` command line option.
> @@ -212,10 +238,15 @@ To use a different index value, N, from default of 0, add:
>  
>    -global driver=xlnx.bbram-ctrl,property=drive-index,value=N
>  
>  eFUSE File Backend
>  """"""""""""""""""
> +
> +.. note::
> +   The eFUSE device is not implemented in the Versal Gen 2 QEMU model
> +   yet.
> +
>  eFUSE can have an optional file backend, which must be a seekable
>  binary file with a size of 3072 bytes or larger. A file with all
>  binary 0s is a 'blank'.
>  
>  To add a file-backend for the eFUSE:
> @@ -269,5 +300,9 @@ To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
>  
>  .. code-block:: bash
>  
>      -object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
>      -object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
> +
> +.. note::
> +   Versal Gen 2 has 4 CAN controllers. ``canbus0`` to ``canbus3`` can
> +   be specified on the command line.
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 154ed7332c3..8cfb7d0c380 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -1,7 +1,7 @@
>  /*
> - * AMD/Xilinx Versal Virtual board.
> + * AMD/Xilinx Versal family Virtual board.
>   *
>   * Copyright (c) 2018 Xilinx Inc.
>   * Copyright (c) 2025, Advanced Micro Devices, Inc.
>   * Written by Edgar E. Iglesias
>   *
> @@ -27,10 +27,11 @@
>  #define TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE \
>      MACHINE_TYPE_NAME("amd-versal-virt-base")
>  OBJECT_DECLARE_TYPE(VersalVirt, VersalVirtClass, XLNX_VERSAL_VIRT_BASE_MACHINE)
>  
>  #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal-virt")
> +#define TYPE_XLNX_VERSAL2_VIRT_MACHINE MACHINE_TYPE_NAME("amd-versal2-virt")
>  
>  #define XLNX_VERSAL_NUM_OSPI_FLASH 4
>  
>  struct VersalVirt {
>      MachineState parent_obj;
> @@ -55,11 +56,13 @@ struct VersalVirtClass {
>  };
>  
>  static void fdt_create(VersalVirt *s)
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(s);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_GET_CLASS(s);
>      const char versal_compat[] = "amd-versal-virt\0xlnx-versal-virt";
> +    const char versal2_compat[] = "amd-versal2-virt";
>  
>      s->fdt = create_device_tree(&s->fdt_size);
>      if (!s->fdt) {
>          error_report("create_device_tree() failed");
>          exit(1);
> @@ -69,12 +72,22 @@ static void fdt_create(VersalVirt *s)
>      qemu_fdt_add_subnode(s->fdt, "/chosen");
>      qemu_fdt_add_subnode(s->fdt, "/aliases");
>  
>      /* Header */
>      qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
> -    qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
> -                     sizeof(versal_compat));
> +
> +    switch (vvc->version) {
> +    case VERSAL_VER_VERSAL:
> +        qemu_fdt_setprop(s->fdt, "/", "compatible", versal_compat,
> +                         sizeof(versal_compat));
> +        break;
> +
> +    case VERSAL_VER_VERSAL2:
> +        qemu_fdt_setprop(s->fdt, "/", "compatible", versal2_compat,
> +                         sizeof(versal2_compat));
> +        break;
> +    }
>  }
>  
>  static void fdt_nop_memory_nodes(void *fdt, Error **errp)
>  {
>      Error *err = NULL;
> @@ -362,10 +375,21 @@ static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
>      vvc->version = VERSAL_VER_VERSAL;
>  
>      versal_virt_machine_class_init_common(oc);
>  }
>  
> +static void versal2_virt_machine_class_init(ObjectClass *oc, const void *data)
> +{
> +    MachineClass *mc = MACHINE_CLASS(oc);
> +    VersalVirtClass *vvc = XLNX_VERSAL_VIRT_BASE_MACHINE_CLASS(oc);
> +
> +    mc->desc = "AMD Versal Gen 2 Virtual development board";
> +    vvc->version = VERSAL_VER_VERSAL2;
> +
> +    versal_virt_machine_class_init_common(oc);
> +}
> +
>  static const TypeInfo versal_virt_base_machine_init_typeinfo = {
>      .name       = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
>      .parent     = TYPE_MACHINE,
>      .class_size = sizeof(VersalVirtClass),
>      .instance_init = versal_virt_machine_instance_init,
> @@ -378,12 +402,19 @@ static const TypeInfo versal_virt_machine_init_typeinfo = {
>      .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
>      .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
>      .class_init = versal_virt_machine_class_init,
>  };
>  
> +static const TypeInfo versal2_virt_machine_init_typeinfo = {
> +    .name       = TYPE_XLNX_VERSAL2_VIRT_MACHINE,
> +    .parent     = TYPE_XLNX_VERSAL_VIRT_BASE_MACHINE,
> +    .class_init = versal2_virt_machine_class_init,
> +};
> +
>  static void versal_virt_machine_init_register_types(void)
>  {
>      type_register_static(&versal_virt_base_machine_init_typeinfo);
>      type_register_static(&versal_virt_machine_init_typeinfo);
> +    type_register_static(&versal2_virt_machine_init_typeinfo);
>  }
>  
>  type_init(versal_virt_machine_init_register_types)
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine
  2025-07-16  9:54 ` [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine Luc Michel
@ 2025-07-31 21:09   ` Francisco Iglesias
  0 siblings, 0 replies; 106+ messages in thread
From: Francisco Iglesias @ 2025-07-31 21:09 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, Jul 16, 2025 at 11:54:30AM +0200, Luc Michel wrote:
> Add a test for the amd-versal2-virt machine using the same command line,
> kernel, initrd than the ones used for amd-versal-virt.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  tests/functional/test_aarch64_xlnx_versal.py | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/tests/functional/test_aarch64_xlnx_versal.py b/tests/functional/test_aarch64_xlnx_versal.py
> index 4b9c49e5d64..f32d904ef7e 100755
> --- a/tests/functional/test_aarch64_xlnx_versal.py
> +++ b/tests/functional/test_aarch64_xlnx_versal.py
> @@ -18,12 +18,12 @@ class XlnxVersalVirtMachine(LinuxKernelTest):
>          ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/'
>           'installer-arm64/20101020ubuntu543.19/images/netboot/'
>           '/ubuntu-installer/arm64/initrd.gz'),
>          'e7a5e716b6f516d8be315c06e7331aaf16994fe4222e0e7cfb34bc015698929e')
>  
> -    def test_aarch64_xlnx_versal_virt(self):
> -        self.set_machine('xlnx-versal-virt')
> +    def common_aarch64_amd_versal_virt(self, machine):
> +        self.set_machine(machine)
>          kernel_path = self.ASSET_KERNEL.fetch()
>          initrd_path = self.ASSET_INITRD.fetch()
>  
>          self.vm.set_console()
>          self.vm.add_args('-m', '2G',
> @@ -31,7 +31,13 @@ def test_aarch64_xlnx_versal_virt(self):
>                           '-kernel', kernel_path,
>                           '-initrd', initrd_path)
>          self.vm.launch()
>          self.wait_for_console_pattern('Checked W+X mappings: passed')
>  
> +    def test_aarch64_amd_versal_virt(self):
> +        self.common_aarch64_amd_versal_virt('amd-versal-virt')
> +
> +    def test_aarch64_amd_versal2_virt(self):
> +        self.common_aarch64_amd_versal_virt('amd-versal2-virt')
> +
>  if __name__ == '__main__':
>      LinuxKernelTest.main()
> -- 
> 2.50.0
> 


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-07-16  9:53 ` [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs Luc Michel
  2025-07-29 13:42   ` Francisco Iglesias
@ 2025-08-04 12:24   ` Peter Maydell
  2025-08-18 13:30     ` Luc Michel
  1 sibling, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2025-08-04 12:24 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, 16 Jul 2025 at 10:55, Luc Michel <luc.michel@amd.com> wrote:
>
> Improve the IRQ index in the VersalMap structure to turn it into a
> descriptor:
>    - the lower 16 bits still represent the IRQ index
>    - bit 18 is used to indicate a shared IRQ connected to a OR gate
>    - bits 19 to 22 indicate the index on the OR gate.
>
> This allows to share an IRQ among multiple devices. An OR gate is
> created to connect the devices to the actual IRQ pin.


> +/*
> + * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
> + * used to return the corresponding or gate input IRQ. The or gate is created if
> + * not already existant.
> + *
> + * Or gates are placed under the /soc/irq-or-gates QOM container.
> + */
> +static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
> +                                          qemu_irq target_irq)
> +{
> +    Object *container = versal_get_child(s, "irq-or-gates");
> +    DeviceState *dev;
> +    g_autofree char *name;
> +    int idx, or_idx;
> +
> +    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> +    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> +
> +    name = g_strdup_printf("irq[%d]", idx);
> +    dev = DEVICE(object_resolve_path_at(container, name));
> +
> +    if (dev == NULL) {
> +        dev = qdev_new(TYPE_OR_IRQ);

Here we create a device...

> +        object_property_add_child(container, name, OBJECT(dev));
> +        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
> +        qdev_realize_and_unref(dev, NULL, &error_abort);
> +        qdev_connect_gpio_out(dev, 0, target_irq);
> +    }
> +
> +    return qdev_get_gpio_in(dev, or_idx);

...but then we don't save the pointer to it, so the only
thing still hanging onto it is the QOM tree.

If you want to change "embedded device struct" into
"allocate memory to create devices" that's fine, but the
SoC should still keep track of everything it's creating,
so that (at least in theory) it could clean it up on
unrealize.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property
  2025-07-16  9:54 ` [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property Luc Michel
@ 2025-08-04 12:33   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2025-08-04 12:33 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis,
	Frederic Konrad, Sai Pavan Boddu, Edgar E. Iglesias

On Wed, 16 Jul 2025 at 10:55, Luc Michel <luc.michel@amd.com> wrote:
>
> From: Francisco Iglesias <francisco.iglesias@xilinx.com>
>
> Introduce a 'first-cpu-index' property for specifying the first QEMU CPU
> connected to the GICv3. This makes it possible to have multiple instances
> of the GICv3 connected to different CPU clusters.
>
> Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  include/hw/intc/arm_gicv3_common.h | 1 +
>  hw/intc/arm_gicv3_common.c         | 3 ++-
>  hw/intc/arm_gicv3_cpuif.c          | 2 +-
>  3 files changed, 4 insertions(+), 2 deletions(-)

hw/intc/arm_gicv3_kvm.c also calls qemu_get_cpu(). You should
either update that also so it can handle first-cpu-index, or
else make kvm_arm_gicv3_realize() fail if it's non-zero.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU
  2025-07-16  9:54 ` [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU Luc Michel
@ 2025-08-04 12:44   ` Peter Maydell
  2025-08-04 18:44     ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2025-08-04 12:44 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, 16 Jul 2025 at 10:56, Luc Michel <luc.michel@amd.com> wrote:
>
> Add support for the ARM Cortex-A78AE CPU.



>  static const ARMCPUInfo aarch64_cpus[] = {
>      { .name = "cortex-a35",         .initfn = aarch64_a35_initfn },
>      { .name = "cortex-a55",         .initfn = aarch64_a55_initfn },
>      { .name = "cortex-a72",         .initfn = aarch64_a72_initfn },
>      { .name = "cortex-a76",         .initfn = aarch64_a76_initfn },
> +    { .name = "cortex-a78ae",       .initfn = aarch64_a78ae_initfn },

Do we really need to specifically call this the Cortex-A78AE ?
Is there anything we would model differently between this and
the Cortex-A78 ?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU
  2025-08-04 12:44   ` Peter Maydell
@ 2025-08-04 18:44     ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2025-08-04 18:44 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Mon, 4 Aug 2025 at 13:44, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Wed, 16 Jul 2025 at 10:56, Luc Michel <luc.michel@amd.com> wrote:
> >
> > Add support for the ARM Cortex-A78AE CPU.
>
>
>
> >  static const ARMCPUInfo aarch64_cpus[] = {
> >      { .name = "cortex-a35",         .initfn = aarch64_a35_initfn },
> >      { .name = "cortex-a55",         .initfn = aarch64_a55_initfn },
> >      { .name = "cortex-a72",         .initfn = aarch64_a72_initfn },
> >      { .name = "cortex-a76",         .initfn = aarch64_a76_initfn },
> > +    { .name = "cortex-a78ae",       .initfn = aarch64_a78ae_initfn },
>
> Do we really need to specifically call this the Cortex-A78AE ?
> Is there anything we would model differently between this and
> the Cortex-A78 ?

Looking a bit more closely at the TRMs, although they're quite
similar they're not identical -- for example the 78AE has
FEAT_FlagM (as advertised in ID_AA64ISAR0_EL1.TS) and the 78
does not. So we should keep this "cortex-a78ae" name, with
a comment something like "This is not quite the same as the
plain Cortex-A78; we don't currently model the latter".

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-04 12:24   ` Peter Maydell
@ 2025-08-18 13:30     ` Luc Michel
  2025-08-19 15:25       ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-08-18 13:30 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

Hi Peter,

On 13:24 Mon 04 Aug     , Peter Maydell wrote:
> On Wed, 16 Jul 2025 at 10:55, Luc Michel <luc.michel@amd.com> wrote:
> >
> > Improve the IRQ index in the VersalMap structure to turn it into a
> > descriptor:
> >    - the lower 16 bits still represent the IRQ index
> >    - bit 18 is used to indicate a shared IRQ connected to a OR gate
> >    - bits 19 to 22 indicate the index on the OR gate.
> >
> > This allows to share an IRQ among multiple devices. An OR gate is
> > created to connect the devices to the actual IRQ pin.
> 
> 
> > +/*
> > + * When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
> > + * used to return the corresponding or gate input IRQ. The or gate is created if
> > + * not already existant.
> > + *
> > + * Or gates are placed under the /soc/irq-or-gates QOM container.
> > + */
> > +static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
> > +                                          qemu_irq target_irq)
> > +{
> > +    Object *container = versal_get_child(s, "irq-or-gates");
> > +    DeviceState *dev;
> > +    g_autofree char *name;
> > +    int idx, or_idx;
> > +
> > +    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> > +    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> > +
> > +    name = g_strdup_printf("irq[%d]", idx);
> > +    dev = DEVICE(object_resolve_path_at(container, name));
> > +
> > +    if (dev == NULL) {
> > +        dev = qdev_new(TYPE_OR_IRQ);
> 
> Here we create a device...
> 
> > +        object_property_add_child(container, name, OBJECT(dev));
> > +        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
> > +        qdev_realize_and_unref(dev, NULL, &error_abort);
> > +        qdev_connect_gpio_out(dev, 0, target_irq);
> > +    }
> > +
> > +    return qdev_get_gpio_in(dev, or_idx);
> 
> ...but then we don't save the pointer to it, so the only
> thing still hanging onto it is the QOM tree.
> 
> If you want to change "embedded device struct" into
> "allocate memory to create devices" that's fine, but the
> SoC should still keep track of everything it's creating,
> so that (at least in theory) it could clean it up on
> unrealize.

I'm not sure I fully understand your point:

   - The OR gate device is parented to the "irq-or-gates" container,
     which is itself parented to the SoC. So finalizing (freeing) the
     SoC would trigger a cascade of free calls to the children,
     including those objects right?
   - Are you talking specifically about an unrealize call on the SoC
     object, without a subsequent free? I guess we don't expect to see
     such thing to happen in QEMU. The warning in the qdev_unrealize()
     documentation seems to go in that direction.

For reference, the QOM tree is as follows:

/machine (amd-versal-virt-machine)
  [...]
  /xlnx-versal (xlnx-versal)
    [...]
    /irq-or-gates (container)
      /gic-irq[121] (or-irq)
        /unnamed-gpio-in[0] (irq)
        /unnamed-gpio-in[10] (irq)
        /unnamed-gpio-in[11] (irq) 
        /unnamed-gpio-in[12] (irq)
        /unnamed-gpio-in[13] (irq) 
        /unnamed-gpio-in[14] (irq)
        /unnamed-gpio-in[15] (irq) 
        /unnamed-gpio-in[1] (irq)
        /unnamed-gpio-in[2] (irq)  
        /unnamed-gpio-in[3] (irq)
        /unnamed-gpio-in[4] (irq)
        /unnamed-gpio-in[5] (irq)
        /unnamed-gpio-in[6] (irq)
        /unnamed-gpio-in[7] (irq)
        /unnamed-gpio-in[8] (irq)
        /unnamed-gpio-in[9] (irq)
    [...]

Thanks

Luc


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-18 13:30     ` Luc Michel
@ 2025-08-19 15:25       ` Peter Maydell
  2025-08-20  7:18         ` Luc Michel
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2025-08-19 15:25 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Mon, 18 Aug 2025 at 14:30, Luc Michel <luc.michel@amd.com> wrote:
>
> Hi Peter,
>
> On 13:24 Mon 04 Aug     , Peter Maydell wrote:
> > On Wed, 16 Jul 2025 at 10:55, Luc Michel <luc.michel@amd.com> wrote:
> > >
> > > +static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
> > > +                                          qemu_irq target_irq)
> > > +{
> > > +    Object *container = versal_get_child(s, "irq-or-gates");
> > > +    DeviceState *dev;
> > > +    g_autofree char *name;
> > > +    int idx, or_idx;
> > > +
> > > +    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> > > +    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> > > +
> > > +    name = g_strdup_printf("irq[%d]", idx);
> > > +    dev = DEVICE(object_resolve_path_at(container, name));
> > > +
> > > +    if (dev == NULL) {
> > > +        dev = qdev_new(TYPE_OR_IRQ);
> >
> > Here we create a device...
> >
> > > +        object_property_add_child(container, name, OBJECT(dev));
> > > +        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
> > > +        qdev_realize_and_unref(dev, NULL, &error_abort);
> > > +        qdev_connect_gpio_out(dev, 0, target_irq);
> > > +    }
> > > +
> > > +    return qdev_get_gpio_in(dev, or_idx);
> >
> > ...but then we don't save the pointer to it, so the only
> > thing still hanging onto it is the QOM tree.
> >
> > If you want to change "embedded device struct" into
> > "allocate memory to create devices" that's fine, but the
> > SoC should still keep track of everything it's creating,
> > so that (at least in theory) it could clean it up on
> > unrealize.
>
> I'm not sure I fully understand your point:
>
>    - The OR gate device is parented to the "irq-or-gates" container,
>      which is itself parented to the SoC. So finalizing (freeing) the
>      SoC would trigger a cascade of free calls to the children,
>      including those objects right?

Ah, I hadn't noticed that we add the object as a QOM child
of the SoC here.

It does mean you can't ever get back to the OR gate object
except by walking the QOM tree, but I suppose that's OK.

It would be helpful if you could run "make check" under
the clang leak sanitizer with your patches added, to see
if it complains about anything. (Unfortunately it will
definitely complain about at least some pre-existing
leaks, I suspect.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-19 15:25       ` Peter Maydell
@ 2025-08-20  7:18         ` Luc Michel
  2025-08-21 13:55           ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-08-20  7:18 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On 16:25 Tue 19 Aug     , Peter Maydell wrote:
> On Mon, 18 Aug 2025 at 14:30, Luc Michel <luc.michel@amd.com> wrote:
> >
> > Hi Peter,
> >
> > On 13:24 Mon 04 Aug     , Peter Maydell wrote:
> > > On Wed, 16 Jul 2025 at 10:55, Luc Michel <luc.michel@amd.com> wrote:
> > > >
> > > > +static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
> > > > +                                          qemu_irq target_irq)
> > > > +{
> > > > +    Object *container = versal_get_child(s, "irq-or-gates");
> > > > +    DeviceState *dev;
> > > > +    g_autofree char *name;
> > > > +    int idx, or_idx;
> > > > +
> > > > +    idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
> > > > +    or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
> > > > +
> > > > +    name = g_strdup_printf("irq[%d]", idx);
> > > > +    dev = DEVICE(object_resolve_path_at(container, name));
> > > > +
> > > > +    if (dev == NULL) {
> > > > +        dev = qdev_new(TYPE_OR_IRQ);
> > >
> > > Here we create a device...
> > >
> > > > +        object_property_add_child(container, name, OBJECT(dev));
> > > > +        qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
> > > > +        qdev_realize_and_unref(dev, NULL, &error_abort);
> > > > +        qdev_connect_gpio_out(dev, 0, target_irq);
> > > > +    }
> > > > +
> > > > +    return qdev_get_gpio_in(dev, or_idx);
> > >
> > > ...but then we don't save the pointer to it, so the only
> > > thing still hanging onto it is the QOM tree.
> > >
> > > If you want to change "embedded device struct" into
> > > "allocate memory to create devices" that's fine, but the
> > > SoC should still keep track of everything it's creating,
> > > so that (at least in theory) it could clean it up on
> > > unrealize.
> >
> > I'm not sure I fully understand your point:
> >
> >    - The OR gate device is parented to the "irq-or-gates" container,
> >      which is itself parented to the SoC. So finalizing (freeing) the
> >      SoC would trigger a cascade of free calls to the children,
> >      including those objects right?
> 
> Ah, I hadn't noticed that we add the object as a QOM child
> of the SoC here.
> 
> It does mean you can't ever get back to the OR gate object
> except by walking the QOM tree, but I suppose that's OK.
> 
> It would be helpful if you could run "make check" under
> the clang leak sanitizer with your patches added, to see
> if it complains about anything. (Unfortunately it will
> definitely complain about at least some pre-existing
> leaks, I suspect.)
Yes I did that before sending my series and fixed all my leaks. As you
say there are some existing ones, mainly in the register API (IIRC it
does create an object that is not correctly parented).

I'll send v2 with your other remarks addressed then.

Thanks

Luc


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-20  7:18         ` Luc Michel
@ 2025-08-21 13:55           ` Peter Maydell
  2025-08-22 15:19             ` Luc Michel
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2025-08-21 13:55 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Wed, 20 Aug 2025 at 08:19, Luc Michel <luc.michel@amd.com> wrote:
> > It would be helpful if you could run "make check" under
> > the clang leak sanitizer with your patches added, to see
> > if it complains about anything. (Unfortunately it will
> > definitely complain about at least some pre-existing
> > leaks, I suspect.)
> Yes I did that before sending my series and fixed all my leaks. As you
> say there are some existing ones, mainly in the register API (IIRC it
> does create an object that is not correctly parented).

Yeah, register_init_block() seems to be broken in two ways:
 (1) it calls object_initialize() rather than
     object_initialize_child(), so the objects won't
     be automatically unreffed; but it doesn't manually
     unref them in register_finalize_block() either
 (2) the TYPE_REGISTER objects are a subclass of TYPE_DEVICE,
     but the code never calls realize on them. This means that
     if you fix point (1) then you trip the assert in
     qdev_assert_realized_properly_cb() which checks that
     every TYPE_DEVICE in the QOM tree was realized...

-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-21 13:55           ` Peter Maydell
@ 2025-08-22 15:19             ` Luc Michel
  2025-08-22 15:41               ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Luc Michel @ 2025-08-22 15:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On 14:55 Thu 21 Aug     , Peter Maydell wrote:
> On Wed, 20 Aug 2025 at 08:19, Luc Michel <luc.michel@amd.com> wrote:
> > > It would be helpful if you could run "make check" under
> > > the clang leak sanitizer with your patches added, to see
> > > if it complains about anything. (Unfortunately it will
> > > definitely complain about at least some pre-existing
> > > leaks, I suspect.)
> > Yes I did that before sending my series and fixed all my leaks. As you
> > say there are some existing ones, mainly in the register API (IIRC it
> > does create an object that is not correctly parented).
> 
> Yeah, register_init_block() seems to be broken in two ways:
>  (1) it calls object_initialize() rather than
>      object_initialize_child(), so the objects won't
>      be automatically unreffed; but it doesn't manually
>      unref them in register_finalize_block() either
>  (2) the TYPE_REGISTER objects are a subclass of TYPE_DEVICE,
>      but the code never calls realize on them. This means that
>      if you fix point (1) then you trip the assert in
>      qdev_assert_realized_properly_cb() which checks that
>      every TYPE_DEVICE in the QOM tree was realized...
> 

I'm willing to address this in a follow-up series.

Luc


^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs
  2025-08-22 15:19             ` Luc Michel
@ 2025-08-22 15:41               ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2025-08-22 15:41 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Frederic Konrad,
	Sai Pavan Boddu

On Fri, 22 Aug 2025 at 16:19, Luc Michel <luc.michel@amd.com> wrote:
>
> On 14:55 Thu 21 Aug     , Peter Maydell wrote:
> > On Wed, 20 Aug 2025 at 08:19, Luc Michel <luc.michel@amd.com> wrote:
> > > > It would be helpful if you could run "make check" under
> > > > the clang leak sanitizer with your patches added, to see
> > > > if it complains about anything. (Unfortunately it will
> > > > definitely complain about at least some pre-existing
> > > > leaks, I suspect.)
> > > Yes I did that before sending my series and fixed all my leaks. As you
> > > say there are some existing ones, mainly in the register API (IIRC it
> > > does create an object that is not correctly parented).
> >
> > Yeah, register_init_block() seems to be broken in two ways:
> >  (1) it calls object_initialize() rather than
> >      object_initialize_child(), so the objects won't
> >      be automatically unreffed; but it doesn't manually
> >      unref them in register_finalize_block() either
> >  (2) the TYPE_REGISTER objects are a subclass of TYPE_DEVICE,
> >      but the code never calls realize on them. This means that
> >      if you fix point (1) then you trip the assert in
> >      qdev_assert_realized_properly_cb() which checks that
> >      every TYPE_DEVICE in the QOM tree was realized...
> >
>
> I'm willing to address this in a follow-up series.

That would be great; the leaks have been around for ages, so
there's no huge rush about trying to fix them, and they're the
"object was going to stay around for the life of the simulation
anyway" kind of leak where the major reason to squash them is
just that they clutter up the output when you run ASAN...

The "need to realize the objects" part is a bit awkward, because
the current API assumes you can just call one function in your
instance_init, and I guess we'd need to turn this into "provide an
init and a realize", or else insist that you only call
register_init_block() in realize methods...

There's also basically the same problem in xlnx-versal-canfd.c
canfd_populate_regarray() which seems to be rolling its own
version of register_init_block(), and doing it with at least
one extra bug. (Maybe that could be refactored to use
register_init_block() ?)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 106+ messages in thread

end of thread, other threads:[~2025-08-22 15:42 UTC | newest]

Thread overview: 106+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-16  9:53 [PATCH 00/48] AMD Versal Gen 2 support Luc Michel
2025-07-16  9:53 ` [PATCH 01/48] hw/net/cadence_gem: fix register mask initialization Luc Michel
2025-07-24  8:30   ` Francisco Iglesias
2025-07-28  8:47   ` Boddu, Sai Pavan
2025-07-16  9:53 ` [PATCH 02/48] hw/arm/xlnx-versal: split the xlnx-versal type Luc Michel
2025-07-28 16:59   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 03/48] hw/arm/xlnx-versal: prepare for FDT creation Luc Michel
2025-07-28 17:13   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 04/48] hw/arm/xlnx-versal: uart: refactor creation Luc Michel
2025-07-28 17:29   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 05/48] hw/arm/xlnx-versal: canfd: " Luc Michel
2025-07-28 20:44   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 06/48] hw/arm/xlnx-versal: sdhci: " Luc Michel
2025-07-28 20:50   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 07/48] hw/arm/xlnx-versal: gem: " Luc Michel
2025-07-28 20:56   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 08/48] hw/arm/xlnx-versal: adma: " Luc Michel
2025-07-28 21:02   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 09/48] hw/arm/xlnx-versal: xram: " Luc Michel
2025-07-28 21:05   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 10/48] hw/arm/xlnx-versal: usb: " Luc Michel
2025-07-28 21:13   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 11/48] hw/arm/xlnx-versal: efuse: " Luc Michel
2025-07-29 13:25   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 12/48] hw/arm/xlnx-versal: ospi: " Luc Michel
2025-07-29 13:34   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 13/48] hw/arm/xlnx-versal: VersalMap: add support for OR'ed IRQs Luc Michel
2025-07-29 13:42   ` Francisco Iglesias
2025-08-04 12:24   ` Peter Maydell
2025-08-18 13:30     ` Luc Michel
2025-08-19 15:25       ` Peter Maydell
2025-08-20  7:18         ` Luc Michel
2025-08-21 13:55           ` Peter Maydell
2025-08-22 15:19             ` Luc Michel
2025-08-22 15:41               ` Peter Maydell
2025-07-16  9:53 ` [PATCH 14/48] hw/arm/xlnx-versal: PMC IOU SCLR: refactor creation Luc Michel
2025-07-29 19:41   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 15/48] hw/arm/xlnx-versal: bbram: " Luc Michel
2025-07-29 19:48   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 16/48] hw/arm/xlnx-versal: trng: " Luc Michel
2025-07-29 19:50   ` Francisco Iglesias
2025-07-16  9:53 ` [PATCH 17/48] hw/arm/xlnx-versal: rtc: " Luc Michel
2025-07-29 19:54   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 18/48] hw/arm/xlnx-versal: cfu: " Luc Michel
2025-07-29 19:58   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 19/48] hw/arm/xlnx-versal: crl: " Luc Michel
2025-07-29 20:00   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 20/48] hw/arm/xlnx-versal-virt: virtio: " Luc Michel
2025-07-29 20:04   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 21/48] hw/arm/xlnx-versal: refactor CPU cluster creation Luc Michel
2025-07-29 20:13   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 22/48] hw/arm/xlnx-versal: add the mp_affinity property to the CPU mapping Luc Michel
2025-07-29 20:15   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 23/48] hw/arm/xlnx-versal: instantiate the GIC ITS in the APU Luc Michel
2025-07-29 20:16   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 24/48] hw/intc/arm_gicv3: Introduce a 'first-cpu-index' property Luc Michel
2025-08-04 12:33   ` Peter Maydell
2025-07-16  9:54 ` [PATCH 25/48] hw/arm/xlnx-versal: add support for multiple GICs Luc Michel
2025-07-30 14:26   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 26/48] hw/arm/xlnx-versal: add support for GICv2 Luc Michel
2025-07-30 14:29   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 27/48] hw/arm/xlnx-versal: rpu: refactor creation Luc Michel
2025-07-30 19:03   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 28/48] hw/arm/xlnx-versal: ocm: " Luc Michel
2025-07-30 19:04   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 29/48] hw/arm/xlnx-versal: ddr: " Luc Michel
2025-07-30 19:12   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 30/48] hw/arm/xlnx-versal: add the versal_get_num_cpu accessor Luc Michel
2025-07-30 19:13   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 31/48] hw/misc/xlnx-versal-crl: remove unnecessary include directives Luc Michel
2025-07-30 19:14   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 32/48] hw/misc/xlnx-versal-crl: split into base/concrete classes Luc Michel
2025-07-30 19:23   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 33/48] hw/misc/xlnx-versal-crl: refactor device reset logic Luc Michel
2025-07-31 13:23   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 34/48] hw/arm/xlnx-versal: reconnect the CRL to the other devices Luc Michel
2025-07-31 13:26   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 35/48] hw/arm/xlnx-versal: use hw/arm/bsa.h for timer IRQ indices Luc Michel
2025-07-31 13:29   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 36/48] hw/arm/xlnx-versal: tidy up Luc Michel
2025-07-31 20:14   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 37/48] hw/misc/xlnx-versal-crl: add the versal2 version Luc Michel
2025-07-31 20:19   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 38/48] hw/arm/xlnx-versal: add a per_cluster_gic switch to VersalCpuClusterMap Luc Michel
2025-07-31 20:27   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 39/48] hw/arm/xlnx-versal: add the target field in IRQ descriptor Luc Michel
2025-07-31 20:31   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 40/48] target/arm/tcg/cpu64: add the cortex-a78ae CPU Luc Michel
2025-08-04 12:44   ` Peter Maydell
2025-08-04 18:44     ` Peter Maydell
2025-07-16  9:54 ` [PATCH 41/48] hw/arm/xlnx-versal: add versal2 SoC Luc Michel
2025-07-31 20:40   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 42/48] hw/arm/xlnx-versal-virt: rename the machine to amd-versal-virt Luc Michel
2025-07-31 20:45   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 43/48] hw/arm/xlnx-versal-virt: split into base/concrete classes Luc Michel
2025-07-31 21:00   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 44/48] hw/arm/xlnx-versal-virt: tidy up Luc Michel
2025-07-31 21:00   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 45/48] docs/system/arm/xlnx-versal-virt: update supported devices Luc Michel
2025-07-31 21:01   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 46/48] docs/system/arm/xlnx-versal-virt: add a note about dumpdtb Luc Michel
2025-07-31 21:02   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 47/48] hw/arm/xlnx-versal-virt: add the xlnx-versal2-virt machine Luc Michel
2025-07-31 21:08   ` Francisco Iglesias
2025-07-16  9:54 ` [PATCH 48/48] tests/functional/test_aarch64_xlnx_versal: test the versal2 machine Luc Michel
2025-07-31 21:09   ` Francisco Iglesias

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).