All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wadim Mueller <wafgo01@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, "Peter Maydell" <peter.maydell@linaro.org>,
	"Philippe Mathieu-Daudé" <philmd@mailo.com>,
	"Bin Meng" <bmeng.cn@gmail.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Fabiano Rosas" <farosas@suse.de>,
	"Wadim Mueller" <wafgo01@gmail.com>
Subject: [RFC PATCH v2 13/14] hw/arm: add the am64-virt machine
Date: Thu, 20 Aug 2026 14:48:13 +0200	[thread overview]
Message-ID: <20260820124824.618671-14-wafgo01@gmail.com> (raw)
In-Reply-To: <20260820124824.618671-1-wafgo01@gmail.com>

Add a board around the AM64x SoC model. Besides the SoC it wires up a
PL011 pair, a PL031 RTC, PL061 GPIO, CFI flash, a GPEX PCIe host bridge
and an SD card, so that it is usable both for direct kernel boot and for
running the full TI boot chain from a .wic image via -bios.

A generated device tree matching the machine is added under pc-bios/dtb
for convenience, together with documentation and a MAINTAINERS entry.

Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
 MAINTAINERS                |  22 +++
 docs/system/arm/am64.rst   |  74 ++++++++
 docs/system/target-arm.rst |   1 +
 hw/arm/Kconfig             |   9 +
 hw/arm/am64-virt.c         | 347 +++++++++++++++++++++++++++++++++++++
 hw/arm/meson.build         |   1 +
 pc-bios/dtb/am64-virt.dtb  | Bin 0 -> 6116 bytes
 pc-bios/dtb/am64-virt.dts  | 292 +++++++++++++++++++++++++++++++
 8 files changed, 746 insertions(+)
 create mode 100644 docs/system/arm/am64.rst
 create mode 100644 hw/arm/am64-virt.c
 create mode 100644 pc-bios/dtb/am64-virt.dtb
 create mode 100644 pc-bios/dtb/am64-virt.dts

diff --git a/MAINTAINERS b/MAINTAINERS
index b51f5c3e60..dd0a3ee66a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1266,6 +1266,28 @@ F: hw/arm/msf2-som.c
 F: docs/system/arm/emcraft-sf2.rst
 F: tests/functional/arm/test_emcraft_sf2.py
 
+TI AM64x / K3
+M: Wadim Mueller <wafgo01@gmail.com>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/am64-virt.c
+F: hw/arm/ti-am64x.c
+F: hw/arm/k3-bootrom*.c
+F: hw/char/ti-am64-uart.c
+F: hw/misc/ti-*.c
+F: hw/timer/ti-k3-dmtimer.c
+F: include/hw/arm/ti-am64x.h
+F: include/hw/arm/k3-bootrom.h
+F: include/hw/char/ti-am64-uart.h
+F: include/hw/misc/ti-*.h
+F: include/hw/timer/ti-k3-dmtimer.h
+F: pc-bios/dtb/am64-virt.dt[sb]
+F: tests/functional/aarch64/test_am64_bootrom.py
+F: tests/qtest/am64-*.c
+F: tests/qtest/ti-am64-i2c-test.c
+F: tests/unit/test-k3-bootrom.c
+F: docs/system/arm/am64.rst
+
 ASPEED BMCs
 M: Cédric Le Goater <clg@kaod.org>
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/docs/system/arm/am64.rst b/docs/system/arm/am64.rst
new file mode 100644
index 0000000000..cc2483b839
--- /dev/null
+++ b/docs/system/arm/am64.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+.. Copyright (c) 2026 CMBLU Energy AG
+
+Texas Instruments AM64x (``am64-virt``)
+======================================
+
+The ``am64-virt`` machine models a board built around the Texas Instruments
+AM64x (AM6442) Sitara SoC. The AM64x is a heterogeneous multi-core device;
+the model implements enough of it to run the stock TI boot chain
+(ROM boot -> R5 SPL -> TF-A/OP-TEE -> U-Boot -> Linux).
+
+Implemented CPU cores
+---------------------
+
+* Cortex-A53 cluster (2 cores, GICv3)
+* Cortex-R5F ``MCU_R5FSS0_CORE0`` boot core
+* Cortex-M4F ``MCU_M4FSS0_CORE0``
+
+Only one R5F core is modelled today; ``max_cpus`` reserves room for the
+remaining R5F cores of both clusters.
+
+Implemented devices
+-------------------
+
+* GICv3 (GIC-500) at the real AM64x addresses
+* MCU and MAIN domain UARTs (8250-compatible)
+* TI mailbox (IPC) blocks
+* TI secure proxy and the DMSC (TI-SCI system controller firmware) model
+* RAT (region address translation) for the R5F/M4F views of the memory map
+* CTRL_MMR (including the DEVSTAT boot pins), GTC, DDRSS, SDHCI PHY and TRNG
+* K3 DMTimer
+* SDHCI controllers (MMC1/eMMC and MMC2/SD)
+* OMAP-style MAIN I2C0 (no slaves; attach them with -device)
+* OCSRAM, DDR and a small set of virtio/PCIe/PL011/PL031/PL061 conveniences
+
+Boot modes
+----------
+
+Direct kernel boot::
+
+  qemu-system-aarch64 -M am64-virt -nographic \
+      -kernel Image -append "console=ttyAMA0" \
+      -dtb pc-bios/dtb/am64-virt.dtb
+
+ROM boot from a TI combined boot image (``tiboot3.bin``). The image is parsed
+the way the on-chip boot ROM does (X.509 certificate with the TI boot
+extension, followed by the individual components), the SYSFW component is
+handed to the DMSC model and the R5 SPL is started at the certified entry
+point::
+
+  qemu-system-aarch64 -M am64-virt -nographic \
+      -bios tiboot3.bin \
+      -drive if=sd,format=raw,file=core-image.wic
+
+Boot only the M4F core::
+
+  qemu-system-aarch64 -M am64-virt -M m4boot-cpu=0 -kernel m4-firmware.elf
+
+Machine options
+---------------
+
+``m4boot-cpu``
+  Set to ``0`` to hold the A53 and R5F cores in reset and boot only the M4F
+  core. Mutually exclusive with ``-bios``.
+
+Caveats
+-------
+
+Migration is not supported: the new device models have no VMState yet.
+
+Because the SoC realizes M4F and R5F vCPUs in addition to the A53s, every
+core needs a TCG context slot inside ``smp.max_cpus``. The machine therefore
+defaults to the full vCPU budget; if you pass ``-smp`` explicitly you must
+size ``maxcpus`` accordingly, for example ``-smp cpus=2,maxcpus=7``.
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index e34492402f..2fd41111e4 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -71,6 +71,7 @@ Board-specific documentation
 .. toctree::
    :maxdepth: 1
 
+   arm/am64
    arm/max78000
    arm/integratorcp
    arm/mps2
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 2172fc803b..3802170287 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -38,6 +38,15 @@ config ARM_VIRT
     select ACPI_HMAT
     select WDT_SBSA
 
+config AM64_VIRT
+    bool
+    default y
+    depends on TCG && ARM
+    select AT24C  # I2C EEPROMs can be attached with -device
+    select TI_AM64X
+    select TI_DMSC
+    select TI_SEC_PROXY
+
 config CUBIEBOARD
     bool
     default y
diff --git a/hw/arm/am64-virt.c b/hw/arm/am64-virt.c
new file mode 100644
index 0000000000..e78c73a347
--- /dev/null
+++ b/hw/arm/am64-virt.c
@@ -0,0 +1,347 @@
+/*
+ * AM64 virt machine model
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/core/boards.h"
+#include "hw/core/sysbus.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/machines-qom.h"
+#include "hw/char/pl011.h"
+#include "hw/block/flash.h"
+#include "hw/rtc/pl031.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/pci/pci.h"
+#include "hw/arm/ti-am64x.h"
+#include "hw/arm/k3-bootrom.h"
+#include "hw/core/qdev-clock.h"
+#include "hw/sd/sd.h"
+#include "system/address-spaces.h"
+#include "system/system.h"
+#include "system/blockdev.h"
+#include "qemu/error-report.h"
+#include "chardev/char.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/visitor.h"
+
+#define AM64_VIRT_DRAM_BASE 0x80000000ULL
+#define AM64_VIRT_UART0_BASE 0x09000000ULL
+#define AM64_VIRT_UART1_BASE 0x09040000ULL
+#define AM64_VIRT_UART0_IRQ 1
+#define AM64_VIRT_UART1_IRQ 8
+#define AM64_VIRT_RTC_BASE 0x09010000ULL
+#define AM64_VIRT_RTC_IRQ 2
+#define AM64_VIRT_GPIO_BASE 0x09030000ULL
+#define AM64_VIRT_GPIO_IRQ 7
+#define AM64_VIRT_FLASH_BASE 0x050000000ULL
+#define AM64_VIRT_FLASH_SIZE 0x08000000ULL
+#define AM64_VIRT_FLASH_SECTOR_SIZE (256 * KiB)
+#define AM64_VIRT_PCIE_MMIO_BASE 0x68000000ULL
+#define AM64_VIRT_PCIE_MMIO_SIZE 0x08000000ULL
+#define AM64_VIRT_PCIE_PIO_BASE 0x3EFF0000ULL
+#define AM64_VIRT_PCIE_PIO_SIZE 0x00010000ULL
+#define AM64_VIRT_PCIE_ECAM_BASE 0x0D000000ULL
+#define AM64_VIRT_PCIE_ECAM_SIZE 0x02000000ULL
+#define AM64_VIRT_PCIE_IRQ_BASE 3
+
+#define SYSCLK_FRQ 168000000ULL
+
+typedef struct AM64VirtMachineState {
+    MachineState parent_obj;
+    TIAM64xState *soc;
+    struct arm_boot_info bootinfo;
+    int32_t m4boot_cpu;
+} AM64VirtMachineState;
+
+#define TYPE_AM64_VIRT_MACHINE MACHINE_TYPE_NAME("am64-virt")
+OBJECT_DECLARE_SIMPLE_TYPE(AM64VirtMachineState, AM64_VIRT_MACHINE)
+
+static void am64_virt_get_m4boot_cpu(Object *obj, Visitor *v,
+                                     const char *name, void *opaque,
+                                     Error **errp)
+{
+    AM64VirtMachineState *ams = AM64_VIRT_MACHINE(obj);
+    int32_t value = ams->m4boot_cpu;
+
+    visit_type_int32(v, name, &value, errp);
+}
+
+static void am64_virt_set_m4boot_cpu(Object *obj, Visitor *v,
+                                     const char *name, void *opaque,
+                                     Error **errp)
+{
+    AM64VirtMachineState *ams = AM64_VIRT_MACHINE(obj);
+    int32_t value;
+
+    if (!visit_type_int32(v, name, &value, errp)) {
+        return;
+    }
+    if (value != -1 && value != 0) {
+        error_setg(errp, "am64-virt: m4boot_cpu must be -1 or 0");
+        return;
+    }
+    ams->m4boot_cpu = value;
+}
+
+static void am64_virt_machine_instance_init(Object *obj)
+{
+    AM64VirtMachineState *ams = AM64_VIRT_MACHINE(obj);
+
+    ams->m4boot_cpu = -1;
+    object_property_add_alias(obj, "m4boot_cpu", obj, "m4boot-cpu");
+}
+
+static void am64_virt_create_uart(hwaddr base, int irq, Chardev *chr,
+                                  DeviceState *gic)
+{
+    DeviceState *dev = qdev_new(TYPE_PL011);
+    SysBusDevice *s = SYS_BUS_DEVICE(dev);
+    MemoryRegion *sysmem = get_system_memory();
+
+    qdev_prop_set_chr(dev, "chardev", chr);
+    sysbus_realize_and_unref(s, &error_fatal);
+    memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(s, 0));
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(gic, irq));
+}
+
+static void am64_virt_create_pcie(const AM64VirtMachineState *ams,
+                                  DeviceState *gic)
+{
+    DeviceState *dev = qdev_new(TYPE_GPEX_HOST);
+    PCIHostState *pci;
+    MemoryRegion *mmio_alias;
+    MemoryRegion *ecam_alias;
+    MemoryRegion *mmio_reg;
+    MemoryRegion *ecam_reg;
+    int i;
+
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    ecam_alias = g_new0(MemoryRegion, 1);
+    ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
+                             ecam_reg, 0, AM64_VIRT_PCIE_ECAM_SIZE);
+    memory_region_add_subregion(get_system_memory(),
+                                AM64_VIRT_PCIE_ECAM_BASE, ecam_alias);
+
+    mmio_alias = g_new0(MemoryRegion, 1);
+    mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+    memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
+                             mmio_reg, AM64_VIRT_PCIE_MMIO_BASE,
+                             AM64_VIRT_PCIE_MMIO_SIZE);
+    memory_region_add_subregion(get_system_memory(),
+                                AM64_VIRT_PCIE_MMIO_BASE, mmio_alias);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, AM64_VIRT_PCIE_PIO_BASE);
+
+    for (i = 0; i < PCI_NUM_PINS; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
+                           qdev_get_gpio_in(gic,
+                                            AM64_VIRT_PCIE_IRQ_BASE + i));
+        gpex_set_irq_num(GPEX_HOST(dev), i, AM64_VIRT_PCIE_IRQ_BASE + i);
+    }
+
+    pci = PCI_HOST_BRIDGE(dev);
+    pci_init_nic_devices(pci->bus, MACHINE_GET_CLASS(ams)->default_nic);
+}
+
+static void am64_virt_create_rtc(hwaddr base, int irq, DeviceState *gic)
+{
+    sysbus_create_simple(TYPE_PL031, base, qdev_get_gpio_in(gic, irq));
+}
+
+static void am64_virt_create_gpio(hwaddr base, int irq, DeviceState *gic)
+{
+    sysbus_create_simple("pl061", base, qdev_get_gpio_in(gic, irq));
+}
+
+static void am64_virt_create_flash(void)
+{
+    DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
+
+    qdev_prop_set_uint32(dev, "num-blocks",
+                         AM64_VIRT_FLASH_SIZE / AM64_VIRT_FLASH_SECTOR_SIZE);
+    qdev_prop_set_uint64(dev, "sector-length", AM64_VIRT_FLASH_SECTOR_SIZE);
+    qdev_prop_set_uint8(dev, "width", 4);
+    qdev_prop_set_uint8(dev, "device-width", 2);
+    qdev_prop_set_bit(dev, "big-endian", false);
+    qdev_prop_set_uint16(dev, "id0", 0x89);
+    qdev_prop_set_uint16(dev, "id1", 0x18);
+    qdev_prop_set_uint16(dev, "id2", 0x00);
+    qdev_prop_set_uint16(dev, "id3", 0x00);
+    qdev_prop_set_string(dev, "name", "am64-virt.flash0");
+
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, AM64_VIRT_FLASH_BASE);
+}
+
+static void am64_virt_init(MachineState *machine)
+{
+    AM64VirtMachineState *ams = AM64_VIRT_MACHINE(machine);
+    DeviceState *soc = qdev_new(TYPE_TI_AM64X);
+    DeviceState *gic;
+    Clock *sysclk = clock_new(OBJECT(machine), "SYSCLK");
+    Chardev *mcu_chardev;
+    uint8_t a53_cpus = MIN(machine->smp.cpus, TI_AM64X_A53_NUM);
+    DriveInfo *sd_di = drive_get(IF_SD, 0, 0);
+
+    /*
+     * The SoC has M4 and R5F vCPUs beyond the A53s. Since TCG allocates
+     * context slots from smp.max_cpus at accelerator init, fail before realize.
+     */
+    if (machine->smp.max_cpus < a53_cpus + 2) {
+        error_report("am64-virt: -smp maxcpus=%d is too small for %d A53 "
+                     "+ M4 + R5F vCPUs; raise maxcpus (e.g. "
+                     "-smp cpus=2,maxcpus=7) or omit -smp",
+                     machine->smp.max_cpus, a53_cpus);
+        exit(1);
+    }
+
+    clock_set_hz(sysclk, SYSCLK_FRQ);
+    qdev_prop_set_uint8(soc, "a53-cpus", a53_cpus);
+    qdev_prop_set_uint64(soc, "ram-base", AM64_VIRT_DRAM_BASE);
+    qdev_prop_set_uint64(soc, "ram-size", machine->ram_size);
+    qdev_connect_clock_in(soc, "sysclk", sysclk);
+    mcu_chardev = qemu_chr_find("uart0");
+    if (mcu_chardev) {
+        qdev_prop_set_chr(DEVICE(&TI_AM64X(soc)->mcu_uart[0]),
+                          "chardev", mcu_chardev);
+    }
+    if (ams->m4boot_cpu >= 0) {
+        if (ams->m4boot_cpu != 0) {
+            error_report("am64-virt: m4boot_cpu only supports value 0");
+            exit(1);
+        }
+        qdev_prop_set_bit(soc, "a53-start-powered-off", true);
+        qdev_prop_set_bit(soc, "m4-start-powered-off", false);
+    }
+
+    if (machine->firmware && ams->m4boot_cpu >= 0) {
+        error_report("am64-virt: -bios and m4boot-cpu are mutually "
+                     "exclusive");
+        exit(1);
+    }
+    if (machine->firmware && machine->kernel_filename) {
+        /*
+         * ROM boot consumes -bios via k3_bootrom_load() and never calls
+         * arm_load_kernel(), therefore reject a silently ignored -kernel.
+         */
+        error_report("am64-virt: -bios and -kernel are mutually exclusive");
+        exit(1);
+    }
+    if (machine->firmware) {
+        /* ROM boot starts only R5F boot core. */
+        qdev_prop_set_bit(soc, "a53-start-powered-off", true);
+        qdev_prop_set_bit(soc, "m4-start-powered-off", true);
+        qdev_prop_set_bit(soc, "r5-start-powered-off", false);
+        qdev_prop_set_chr(DEVICE(&TI_AM64X(soc)->main_uart0),
+                          "chardev", serial_hd(0));
+        if (sd_di) {
+            /*
+             * DEVSTAT primary bootmode MMC (0x8), SD port: describe MMC2
+             * (sdhci[1]) FS-mode boot, not MMC1 raw mode.
+             */
+            qdev_prop_set_uint32(DEVICE(&TI_AM64X(soc)->ctrlmmr), "devstat",
+                                 0x240);
+        }
+    }
+
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(soc), &error_fatal);
+    ams->soc = TI_AM64X(soc);
+    gic = DEVICE(&ams->soc->gic);
+
+    if (sd_di) {
+        DeviceState *card = qdev_new(TYPE_SD_CARD);
+
+        qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(sd_di),
+                                &error_fatal);
+        qdev_realize_and_unref(card,
+                               qdev_get_child_bus(DEVICE(&ams->soc->sdhci[1]),
+                                                  "sd-bus"),
+                               &error_fatal);
+    }
+
+    memory_region_add_subregion(get_system_memory(), AM64_VIRT_DRAM_BASE,
+                                machine->ram);
+
+    am64_virt_create_uart(AM64_VIRT_UART0_BASE, AM64_VIRT_UART0_IRQ,
+                          machine->firmware ? serial_hd(1) : serial_hd(0),
+                          gic);
+    am64_virt_create_uart(AM64_VIRT_UART1_BASE, AM64_VIRT_UART1_IRQ,
+                          machine->firmware ? serial_hd(2) : serial_hd(1),
+                          gic);
+    am64_virt_create_rtc(AM64_VIRT_RTC_BASE, AM64_VIRT_RTC_IRQ, gic);
+    am64_virt_create_gpio(AM64_VIRT_GPIO_BASE, AM64_VIRT_GPIO_IRQ, gic);
+    am64_virt_create_flash();
+    am64_virt_create_pcie(ams, gic);
+
+    memset(&ams->bootinfo, 0, sizeof(ams->bootinfo));
+    ams->bootinfo.ram_size = machine->ram_size;
+    ams->bootinfo.loader_start = AM64_VIRT_DRAM_BASE;
+    ams->bootinfo.board_id = -1;
+    ams->bootinfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
+    g_assert(qemu_get_cpu(0));
+    if (machine->firmware) {
+        g_autofree char *fn =
+            qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
+
+        k3_bootrom_load(ams->soc, fn ? fn : machine->firmware,
+                        &error_fatal);
+    } else if (ams->m4boot_cpu < 0) {
+        arm_load_kernel(ARM_CPU(qemu_get_cpu(0)), machine, &ams->bootinfo);
+    }
+}
+
+static void am64_virt_machine_class_init(ObjectClass *oc, const void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "AM64 virt machine";
+    mc->init = am64_virt_init;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
+    mc->default_nic = "virtio-net-pci";
+    mc->default_ram_id = "am64-virt.ram";
+    /*
+     * Real AM64x has four R5F cores plus one M4 beyond the A53 cluster.
+     * Reserve max_cpus headroom for the not yet modeled R5F cores.
+     */
+    mc->max_cpus = TI_AM64X_A53_NUM + 4 + 1; /* 4 R5F cores, 1 M4 */
+    /*
+     * Default to the full heterogeneous vCPU budget, so plain invocations
+     * have enough TCG slots for A53, R5F and M4 cores.
+     */
+    mc->default_cpus = mc->max_cpus;
+    mc->default_ram_size = 2 * GiB;
+
+    object_class_property_add(oc, "m4boot-cpu", "int32",
+                              am64_virt_get_m4boot_cpu,
+                              am64_virt_set_m4boot_cpu,
+                              NULL, NULL);
+    object_class_property_set_description(oc, "m4boot-cpu",
+                                          "Set to 0 to boot only the M4 core");
+}
+
+static const TypeInfo am64_virt_machine_info = {
+    .name = TYPE_AM64_VIRT_MACHINE,
+    .parent = TYPE_MACHINE,
+    .instance_size = sizeof(AM64VirtMachineState),
+    .instance_init = am64_virt_machine_instance_init,
+    .class_init = am64_virt_machine_class_init,
+    .interfaces = arm_aarch64_machine_interfaces,
+};
+
+static void am64_virt_machine_init_register_types(void)
+{
+    type_register_static(&am64_virt_machine_info);
+}
+
+type_init(am64_virt_machine_init_register_types)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 139692dd11..cb6e881d01 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -112,6 +112,7 @@ arm_common_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c'))
 arm_common_ss.add(when: 'CONFIG_TI_AM64X', if_true: files('ti-am64x.c'))
 arm_common_ss.add(when: 'CONFIG_TI_AM64X', if_true: files('k3-bootrom-parse.c'))
 arm_common_ss.add(when: 'CONFIG_TI_AM64X', if_true: files('k3-bootrom.c'))
+arm_common_ss.add(when: 'CONFIG_AM64_VIRT', if_true: files('am64-virt.c'))
 
 arm_common_ss.add(when: ['CONFIG_AXIADO_SOC', 'TARGET_AARCH64'], if_true: files(
   'ax3000-soc.c'))
diff --git a/pc-bios/dtb/am64-virt.dtb b/pc-bios/dtb/am64-virt.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..b9cf2dd0b494ade59cd8cd4e4dc7b4d1434f7724
GIT binary patch
literal 6116
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
Hr5XMU#<@8L

literal 0
HcmV?d00001

diff --git a/pc-bios/dtb/am64-virt.dts b/pc-bios/dtb/am64-virt.dts
new file mode 100644
index 0000000000..09ab555c2e
--- /dev/null
+++ b/pc-bios/dtb/am64-virt.dts
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ */
+/dts-v1/;
+
+/ {
+	interrupt-parent = <0x8003>;
+	dma-coherent;
+	model = "linux,dummy-virt";
+	#size-cells = <0x02>;
+	#address-cells = <0x02>;
+	compatible = "linux,dummy-virt";
+
+	reserved-memory {
+		#address-cells = <0x02>;
+		#size-cells = <0x02>;
+		ranges;
+
+		m4f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+			phandle = <0x05>;
+		};
+
+		m4f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+			phandle = <0x06>;
+		};
+	};
+
+	psci {
+		migrate = <0xc4000005>;
+		cpu_on = <0xc4000003>;
+		cpu_off = <0x84000002>;
+		cpu_suspend = <0xc4000001>;
+		method = "hvc";
+		compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+	};
+
+	memory@80000000 {
+		reg = <0x00 0x80000000 0x00 0x40000000>;
+		device_type = "memory";
+	};
+
+	bus@48000000 {
+		bootph-all;
+		compatible = "simple-bus";
+		#address-cells = <0x02>;
+		#size-cells = <0x02>;
+		dma-ranges;
+		ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x6400000>;
+		ti,sci-dev-id = <0x19>;
+
+		mailbox@4d000000 {
+			bootph-all;
+			compatible = "ti,am654-secure-proxy";
+			#mbox-cells = <0x01>;
+			reg-names = "target_data", "rt", "scfg";
+			reg = <0x00 0x4d000000 0x00 0x80000 0x00 0x4a600000 0x00 0x80000 0x00 0x4a400000 0x00 0x80000>;
+			interrupt-names = "rx_012";
+			interrupts = <0x00 0x22 0x04>;
+			phandle = <0x07>;
+		};
+	};
+
+	platform-bus@c000000 {
+		interrupt-parent = <0x8003>;
+		ranges;
+		#address-cells = <0x02>;
+		#size-cells = <0x02>;
+		compatible = "qemu,platform", "simple-bus";
+
+		mailbox@29060000 {
+			compatible = "ti,am64-mailbox";
+			reg = <0x00 0x29060000 0x00 0x200>;
+			interrupts = <0x00 0x4c 0x04>;
+			#mbox-cells = <0x01>;
+			ti,mbox-num-users = <0x04>;
+			ti,mbox-num-fifos = <0x10>;
+			status = "okay";
+			phandle = <0x03>;
+
+			mbox-m4-0 {
+				ti,mbox-rx = <0x00 0x00 0x02>;
+				ti,mbox-tx = <0x01 0x00 0x02>;
+				phandle = <0x04>;
+			};
+		};
+
+		m4fss@5000000 {
+			compatible = "ti,am64-m4fss";
+			reg = <0x00 0x5000000 0x00 0x30000 0x00 0x5040000 0x00 0x10000>;
+			reg-names = "iram", "dram";
+			resets = <0x01 0x09 0x01>;
+			firmware-name = "am64-mcu-m4f0_0-fw";
+			ti,sci = <0x02>;
+			ti,sci-dev-id = <0x09>;
+			ti,sci-proc-ids = <0x18 0xff>;
+			mboxes = <0x03 0x04>;
+			memory-region = <0x05 0x06>;
+			status = "okay";
+		};
+
+		system-controller@44043000 {
+			bootph-all;
+			compatible = "ti,k2g-sci";
+			ti,host-id = <0x0c>;
+			mbox-names = "rx", "tx";
+			mboxes = <0x07 0x0c 0x07 0x0d>;
+			reg-names = "debug_messages";
+			reg = <0x00 0x44043000 0x00 0xfe0>;
+			phandle = <0x02>;
+
+			power-controller {
+				bootph-all;
+				compatible = "ti,sci-pm-domain";
+				#power-domain-cells = <0x02>;
+			};
+
+			clock-controller {
+				bootph-all;
+				compatible = "ti,k2g-sci-clk";
+				#clock-cells = <0x02>;
+			};
+
+			reset-controller {
+				bootph-all;
+				compatible = "ti,sci-reset";
+				#reset-cells = <0x02>;
+				phandle = <0x01>;
+			};
+		};
+	};
+
+	fw-cfg@9020000 {
+		dma-coherent;
+		reg = <0x00 0x9020000 0x00 0x18>;
+		compatible = "qemu,fw-cfg-mmio";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		poweroff {
+			gpios = <0x8005 0x03 0x00>;
+			linux,code = <0x74>;
+			label = "GPIO Key Poweroff";
+		};
+	};
+
+	pl061@9030000 {
+		phandle = <0x8005>;
+		clock-names = "apb_pclk";
+		clocks = <0x8000>;
+		interrupts = <0x00 0x07 0x04>;
+		gpio-controller;
+		#gpio-cells = <0x02>;
+		compatible = "arm,pl061", "arm,primecell";
+		reg = <0x00 0x9030000 0x00 0x1000>;
+	};
+
+	pcie@d000000 {
+		interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
+		interrupt-map = <0x00 0x00 0x00 0x01 0x8003 0x00 0x00 0x00 0x03 0x04 0x00 0x00 0x00 0x02 0x8003 0x00 0x00 0x00 0x04 0x04 0x00 0x00 0x00 0x03 0x8003 0x00 0x00 0x00 0x05 0x04 0x00 0x00 0x00 0x04 0x8003 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x01 0x8003 0x00 0x00 0x00 0x04 0x04 0x800 0x00 0x00 0x02 0x8003 0x00 0x00 0x00 0x05 0x04 0x800 0x00 0x00 0x03 0x8003 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x04 0x8003 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x01 0x8003 0x00 0x00 0x00 0x05 0x04 0x1000 0x00 0x00 0x02 0x8003 0x00 0x00 0x00 0x06 0x04 0x1000 0x00 0x00 0x03 0x8003 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x04 0x8003 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x01 0x8003 0x00 0x00 0x00 0x06 0x04 0x1800 0x00 0x00 0x02 0x8003 0x00 0x00 0x00 0x03 0x04 0x1800 0x00 0x00 0x03 0x8003 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x04 0x8003 0x00 0x00 0x00 0x05 0x04>;
+		#interrupt-cells = <0x01>;
+		ranges = <0x1000000 0x00 0x00 0x00 0x3eff0000 0x00 0x10000 0x2000000 0x00 0x68000000 0x00 0x68000000 0x00 0x08000000>;
+		reg = <0x00 0x0d000000 0x00 0x02000000>;
+		dma-coherent;
+		bus-range = <0x00 0x1f>;
+		linux,pci-domain = <0x00>;
+		#size-cells = <0x02>;
+		#address-cells = <0x03>;
+		device_type = "pci";
+		compatible = "pci-host-ecam-generic";
+	};
+
+	pl031@9010000 {
+		clock-names = "apb_pclk";
+		clocks = <0x8000>;
+		interrupts = <0x00 0x02 0x04>;
+		reg = <0x00 0x9010000 0x00 0x1000>;
+		compatible = "arm,pl031", "arm,primecell";
+	};
+
+	pl011@9000000 {
+		clock-names = "uartclk", "apb_pclk";
+		clocks = <0x8000 0x8000>;
+		interrupts = <0x00 0x01 0x04>;
+		reg = <0x00 0x9000000 0x00 0x1000>;
+		compatible = "arm,pl011", "arm,primecell";
+	};
+
+	pl011@9040000 {
+		clock-names = "uartclk", "apb_pclk";
+		clocks = <0x8000 0x8000>;
+		interrupts = <0x00 0x08 0x04>;
+		reg = <0x00 0x9040000 0x00 0x1000>;
+		compatible = "arm,pl011", "arm,primecell";
+	};
+
+	pmu {
+		interrupts = <0x01 0x07 0x304>;
+		compatible = "arm,armv8-pmuv3";
+	};
+
+	intc@1800000 {
+		phandle = <0x8003>;
+		reg = <0x00 0x1800000 0x00 0x10000
+		       0x00 0x1840000 0x00 0x40000>;
+		compatible = "arm,gic-v3";
+		ranges;
+		#size-cells = <0x02>;
+		#address-cells = <0x02>;
+		interrupt-controller;
+		#interrupt-cells = <0x03>;
+	};
+
+
+	flash@50000000 {
+		bank-width = <0x04>;
+		reg = <0x00 0x50000000 0x00 0x8000000>;
+		compatible = "cfi-flash";
+	};
+	cpus {
+		#size-cells = <0x00>;
+		#address-cells = <0x01>;
+
+		cpu-map {
+
+			socket0 {
+
+				cluster0 {
+
+					core0 {
+						cpu = <0x8002>;
+					};
+
+					core1 {
+						cpu = <0x8001>;
+					};
+				};
+			};
+		};
+
+		cpu@0 {
+			phandle = <0x8002>;
+			reg = <0x00>;
+			enable-method = "psci";
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+		};
+
+		cpu@1 {
+			phandle = <0x8001>;
+			reg = <0x01>;
+			enable-method = "psci";
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+		};
+	};
+
+	timer {
+		interrupts = <0x01 0x0d 0x304 0x01 0x0e 0x304 0x01 0x0b 0x304 0x01 0x0a 0x304>;
+		always-on;
+		compatible = "arm,armv8-timer", "arm,armv7-timer";
+	};
+
+	apb-pclk {
+		phandle = <0x8000>;
+		clock-output-names = "clk24mhz";
+		clock-frequency = <0x16e3600>;
+		#clock-cells = <0x00>;
+		compatible = "fixed-clock";
+	};
+
+	aliases {
+		serial0 = "/pl011@9000000";
+		serial1 = "/pl011@9040000";
+	};
+
+	chosen {
+		bootargs = "root=/dev/vda rw  mem=2048M console=ttyS2 console=ttyAMA0 swiotlb=0 audit=0";
+		stdout-path = "/pl011@9000000";
+		rng-seed = <0x2b2313e6 0x69289174 0x3e2a0676 0xe5dcc1a8 0xc1e04c16 0x988a8076 0x6e26a8c8 0x2a273f53>;
+		kaslr-seed = <0x10fd45dd 0xbe924a75>;
+	};
+};
-- 
2.43.0



  parent reply	other threads:[~2026-08-20 12:50 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20 12:48 [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 01/14] hw/i2c/omap_i2c: add a dedicated CONFIG_OMAP_I2C symbol Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 02/14] hw/i2c/omap_i2c: implement soft reset and NACK reporting Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 03/14] hw/sd/sdhci: complete non-interrupt ADMA descriptor chains in one pass Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 04/14] hw/char: add TI AM64x UART model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 05/14] hw/timer: add TI K3 DMTimer model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 06/14] hw/misc: add TI K3 CTRL_MMR, GTC, DDRSS, SDHCI PHY and TRNG models Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 07/14] hw/misc: add TI RAT (region address translation) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 08/14] hw/misc: add TI mailbox (IPC) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 09/14] hw/misc: add TI K3 secure proxy model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 10/14] hw/misc: add TI DMSC (TI-SCI system controller) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 11/14] hw/arm: add TI K3 combined boot image parser Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 12/14] hw/arm: add TI AM64x SoC model Wadim Mueller
2026-08-20 12:48 ` Wadim Mueller [this message]
2026-08-20 12:48 ` [RFC PATCH v2 14/14] tests: add AM64x unit, qtest and functional tests Wadim Mueller

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260820124824.618671-14-wafgo01@gmail.com \
    --to=wafgo01@gmail.com \
    --cc=bmeng.cn@gmail.com \
    --cc=farosas@suse.de \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@mailo.com \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.