* [PATCH v2 1/8] hw/arm/allwinner-h618: Add Allwinner H618 SoC emulation
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 2/8] hw/arm/orangepi-zero2w: Add Orange Pi Zero 2W machine Khai Do
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
The Allwinner H618 is a 64-bit quad-core Cortex-A53 SoC. This commit
adds baseline SoC emulation including:
- 4x Cortex-A53 cores with PSCI conduit for SMP
- ARM GICv2 interrupt controller and generic timer PPI connections
- SRAM A1, SRAM A2, and 16550 UART0/1 controllers
- Unimplemented memory regions for non-critical peripherals
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
MAINTAINERS | 7 +
hw/arm/Kconfig | 7 +
hw/arm/allwinner-h618.c | 224 ++++++++++++++++++++++++++++++++
hw/arm/meson.build | 1 +
include/hw/arm/allwinner-h618.h | 57 ++++++++
5 files changed, 296 insertions(+)
create mode 100644 hw/arm/allwinner-h618.c
create mode 100644 include/hw/arm/allwinner-h618.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 70e9fed776..68f1c31d60 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -779,6 +779,13 @@ F: hw/arm/orangepi.c
F: docs/system/arm/orangepi.rst
F: tests/functional/arm/test_orangepi.py
+Allwinner-h618
+M: Khai Do <dovankhai97@gmail.com>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/*/allwinner-h618*
+F: include/hw/*/allwinner-h618*
+
ARM PrimeCell and CMSDK devices
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index e9f796f718..616beae7bf 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -333,6 +333,13 @@ config ALLWINNER_R40
select USB_EHCI_SYSBUS
select SD
+config ALLWINNER_H618
+ bool
+ default y if TCG && AARCH64
+ select SERIAL_MM
+ select ARM_GIC
+ select UNIMP
+
config MAX78000_SOC
bool
select ARM_V7M
diff --git a/hw/arm/allwinner-h618.c b/hw/arm/allwinner-h618.c
new file mode 100644
index 0000000000..59e0196fc6
--- /dev/null
+++ b/hw/arm/allwinner-h618.c
@@ -0,0 +1,224 @@
+/*
+ * Allwinner H618 System on Chip emulation
+ *
+ * Copyright (C) 2026 Khai Do <dovankhai97@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+#include "hw/core/qdev.h"
+#include "hw/core/sysbus.h"
+#include "hw/char/serial-mm.h"
+#include "hw/misc/unimp.h"
+#include "system/system.h"
+#include "system/address-spaces.h"
+#include "hw/arm/allwinner-h618.h"
+#include "target/arm/cpu-qom.h"
+#include "target/arm/gtimer.h"
+
+/* Memory map */
+const hwaddr allwinner_h618_memmap[] = {
+ [AW_H618_DEV_SRAM_A1] = 0x00020000,
+ [AW_H618_DEV_SRAM_A2] = 0x00100000,
+ [AW_H618_DEV_GIC_DIST] = 0x03021000,
+ [AW_H618_DEV_GIC_CPU] = 0x03022000,
+ [AW_H618_DEV_GIC_HYP] = 0x03024000,
+ [AW_H618_DEV_GIC_VCPU] = 0x03026000,
+ [AW_H618_DEV_UART0] = 0x05000000,
+ [AW_H618_DEV_UART1] = 0x05000400,
+ [AW_H618_DEV_UART2] = 0x05000800,
+ [AW_H618_DEV_UART3] = 0x05000c00,
+ [AW_H618_DEV_SDRAM] = 0x40000000,
+};
+
+/* List of unimplemented devices */
+static const struct AwH618Unimplemented {
+ const char *device_name;
+ hwaddr base;
+ hwaddr size;
+} unimplemented[] = {
+ { "ccu", 0x03001000, 4 * KiB },
+ { "dma", 0x03002000, 4 * KiB },
+ { "sid", 0x03006000, 4 * KiB },
+ { "smc", 0x03007000, 4 * KiB },
+ { "timer", 0x03009000, 4 * KiB },
+ { "pwm", 0x0300a000, 4 * KiB },
+ { "pio", 0x0300b000, 4 * KiB },
+ { "mmc0", 0x04020000, 4 * KiB },
+ { "mmc1", 0x04021000, 4 * KiB },
+ { "mmc2", 0x04022000, 4 * KiB },
+ { "rtc", 0x07000000, 4 * KiB },
+ { "prcm", 0x07010000, 4 * KiB },
+ { "r_pio", 0x07022000, 4 * KiB },
+ { "r_uart", 0x07080000, 4 * KiB },
+};
+
+/* Interrupt mapping */
+enum {
+ AW_H618_GIC_PPI_MAINT = 9,
+ AW_H618_GIC_PPI_HYPTIMER = 10,
+ AW_H618_GIC_PPI_VIRTTIMER = 11,
+ AW_H618_GIC_PPI_SECTIMER = 13,
+ AW_H618_GIC_PPI_PHYSTIMER = 14
+};
+
+enum {
+ AW_H618_GIC_SPI_UART0 = 0,
+ AW_H618_GIC_SPI_UART1 = 1,
+ AW_H618_GIC_SPI_UART2 = 2,
+ AW_H618_GIC_SPI_UART3 = 3,
+};
+
+enum {
+ AW_H618_GIC_NUM_SPI = 128
+};
+
+static void allwinner_h618_init(Object *obj)
+{
+ AwH618State *s = AW_H618(obj);
+ int i;
+
+ s->memmap = allwinner_h618_memmap;
+
+ for (i = 0; i < AW_H618_NUM_CPUS; i++) {
+ object_initialize_child(obj, "cpu[*]", &s->cpus[i],
+ ARM_CPU_TYPE_NAME("cortex-a53"));
+ }
+
+ object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
+}
+
+static void allwinner_h618_realize(DeviceState *dev, Error **errp)
+{
+ AwH618State *s = AW_H618(dev);
+ unsigned int i;
+
+ /* CPUs */
+ for (i = 0; i < AW_H618_NUM_CPUS; i++) {
+ /* Disable secondary CPUs until brought up by firmware/kernel */
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
+ i > 0);
+
+ /*
+ * Enable PSCI emulation with SMC calls so secondary CPUs
+ * can be brought up.
+ */
+ qdev_prop_set_uint32(DEVICE(&s->cpus[i]), "psci-conduit",
+ QEMU_PSCI_CONDUIT_SMC);
+
+ /* Mark realized */
+ qdev_realize(DEVICE(&s->cpus[i]), NULL, &error_fatal);
+ }
+
+ /* Generic Interrupt Controller */
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_H618_GIC_NUM_SPI +
+ GIC_INTERNAL);
+ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_H618_NUM_CPUS);
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
+ sysbus_realize(SYS_BUS_DEVICE(&s->gic), &error_fatal);
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0,
+ s->memmap[AW_H618_DEV_GIC_DIST]);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1,
+ s->memmap[AW_H618_DEV_GIC_CPU]);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2,
+ s->memmap[AW_H618_DEV_GIC_VCPU]);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3,
+ s->memmap[AW_H618_DEV_GIC_HYP]);
+
+ /* Connect GIC outputs to CPU interrupt inputs and CPU timer to GIC PPI */
+ for (i = 0; i < AW_H618_NUM_CPUS; i++) {
+ DeviceState *cpudev = DEVICE(&s->cpus[i]);
+ int ppibase = AW_H618_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
+ int irq;
+ /*
+ * Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs used for this board.
+ */
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = AW_H618_GIC_PPI_PHYSTIMER,
+ [GTIMER_VIRT] = AW_H618_GIC_PPI_VIRTTIMER,
+ [GTIMER_HYP] = AW_H618_GIC_PPI_HYPTIMER,
+ [GTIMER_SEC] = AW_H618_GIC_PPI_SECTIMER,
+ };
+
+ /* Connect CPU timer outputs to GIC PPI inputs */
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_connect_gpio_out(cpudev, irq,
+ qdev_get_gpio_in(DEVICE(&s->gic),
+ ppibase + timer_irq[irq]));
+ }
+
+ /* Connect GIC outputs to CPU interrupt inputs */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_H618_NUM_CPUS,
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_H618_NUM_CPUS),
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_H618_NUM_CPUS),
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+
+ /* GIC maintenance signal */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_H618_NUM_CPUS),
+ qdev_get_gpio_in(DEVICE(&s->gic),
+ ppibase + AW_H618_GIC_PPI_MAINT));
+ }
+
+ /* SRAM */
+ memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
+ 64 * KiB, &error_abort);
+ memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
+ 48 * KiB, &error_abort);
+ memory_region_add_subregion(get_system_memory(),
+ s->memmap[AW_H618_DEV_SRAM_A1], &s->sram_a1);
+ memory_region_add_subregion(get_system_memory(),
+ s->memmap[AW_H618_DEV_SRAM_A2], &s->sram_a2);
+
+ /* UART0 */
+ serial_mm_init(get_system_memory(), s->memmap[AW_H618_DEV_UART0], 2,
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H618_GIC_SPI_UART0),
+ 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+ /* UART1 */
+ serial_mm_init(get_system_memory(), s->memmap[AW_H618_DEV_UART1], 2,
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H618_GIC_SPI_UART1),
+ 115200, serial_hd(1), DEVICE_LITTLE_ENDIAN);
+
+ /* Unimplemented devices */
+ for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
+ create_unimplemented_device(unimplemented[i].device_name,
+ unimplemented[i].base,
+ unimplemented[i].size);
+ }
+}
+
+static void allwinner_h618_class_init(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = allwinner_h618_realize;
+ /* Reason: uses serial_hd() in realize function */
+ dc->user_creatable = false;
+}
+
+static const TypeInfo allwinner_h618_type_info = {
+ .name = TYPE_AW_H618,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(AwH618State),
+ .instance_init = allwinner_h618_init,
+ .class_init = allwinner_h618_class_init,
+};
+
+static void allwinner_h618_register_types(void)
+{
+ type_register_static(&allwinner_h618_type_info);
+}
+
+type_init(allwinner_h618_register_types)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index bcc068de04..42ed065b17 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -24,6 +24,7 @@ arm_common_ss.add(when: 'CONFIG_OMAP', if_true: files('omap1.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 'bananapi_m2u.c'))
+arm_common_ss.add(when: 'CONFIG_ALLWINNER_H618', if_true: files('allwinner-h618.c'))
arm_common_ss.add(when: 'CONFIG_MAX78000_SOC', if_true: files('max78000_soc.c'))
arm_common_ss.add(when: 'CONFIG_RASPI', if_true: files(
'bcm2836.c',
diff --git a/include/hw/arm/allwinner-h618.h b/include/hw/arm/allwinner-h618.h
new file mode 100644
index 0000000000..e1b7162759
--- /dev/null
+++ b/include/hw/arm/allwinner-h618.h
@@ -0,0 +1,57 @@
+/*
+ * Allwinner H618 System on Chip emulation
+ *
+ * Copyright (C) 2026 Khai Do <dovankhai97@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_ARM_ALLWINNER_H618_H
+#define HW_ARM_ALLWINNER_H618_H
+
+#include "qom/object.h"
+#include "hw/intc/arm_gic.h"
+#include "target/arm/cpu.h"
+
+/**
+ * Allwinner H618 device list
+ */
+enum {
+ AW_H618_DEV_SRAM_A1,
+ AW_H618_DEV_SRAM_A2,
+ AW_H618_DEV_GIC_DIST,
+ AW_H618_DEV_GIC_CPU,
+ AW_H618_DEV_GIC_HYP,
+ AW_H618_DEV_GIC_VCPU,
+ AW_H618_DEV_UART0,
+ AW_H618_DEV_UART1,
+ AW_H618_DEV_UART2,
+ AW_H618_DEV_UART3,
+ AW_H618_DEV_SDRAM
+};
+
+/** Total number of CPU cores in the H618 SoC */
+#define AW_H618_NUM_CPUS (4)
+
+/** Object type for the Allwinner H618 SoC */
+#define TYPE_AW_H618 "allwinner-h618"
+
+/** Convert input object to Allwinner H618 state object */
+OBJECT_DECLARE_SIMPLE_TYPE(AwH618State, AW_H618)
+
+/**
+ * Allwinner H618 object
+ */
+struct AwH618State {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ ARMCPU cpus[AW_H618_NUM_CPUS];
+ const hwaddr *memmap;
+ GICState gic;
+ MemoryRegion sram_a1;
+ MemoryRegion sram_a2;
+};
+
+#endif /* HW_ARM_ALLWINNER_H618_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 2/8] hw/arm/orangepi-zero2w: Add Orange Pi Zero 2W machine
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
2026-11-09 11:35 ` [PATCH v2 1/8] hw/arm/allwinner-h618: Add Allwinner H618 SoC emulation Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 3/8] hw/misc/allwinner-sid: Separate ALLWINNER_SID config symbol Khai Do
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
The Orange Pi Zero 2W is a single-board computer powered by the
Allwinner H618 SoC. This commit adds machine emulation with:
- Allwinner H618 SoC instance
- 1 GiB default system SDRAM at 0x40000000
- Kernel and firmware loading via arm_load_kernel
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
MAINTAINERS | 1 +
hw/arm/meson.build | 2 +-
hw/arm/orangepi-zero2w.c | 77 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 hw/arm/orangepi-zero2w.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 68f1c31d60..d5f60db054 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -785,6 +785,7 @@ L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/allwinner-h618*
F: include/hw/*/allwinner-h618*
+F: hw/arm/orangepi-zero2w.c
ARM PrimeCell and CMSDK devices
M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 42ed065b17..947ee2c7b4 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -24,7 +24,7 @@ arm_common_ss.add(when: 'CONFIG_OMAP', if_true: files('omap1.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
arm_common_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 'bananapi_m2u.c'))
-arm_common_ss.add(when: 'CONFIG_ALLWINNER_H618', if_true: files('allwinner-h618.c'))
+arm_common_ss.add(when: 'CONFIG_ALLWINNER_H618', if_true: files('allwinner-h618.c', 'orangepi-zero2w.c'))
arm_common_ss.add(when: 'CONFIG_MAX78000_SOC', if_true: files('max78000_soc.c'))
arm_common_ss.add(when: 'CONFIG_RASPI', if_true: files(
'bcm2836.c',
diff --git a/hw/arm/orangepi-zero2w.c b/hw/arm/orangepi-zero2w.c
new file mode 100644
index 0000000000..fe87a98efc
--- /dev/null
+++ b/hw/arm/orangepi-zero2w.c
@@ -0,0 +1,77 @@
+/*
+ * Orange Pi Zero 2W machine emulation
+ *
+ * Copyright (C) 2026 Khai Do <dovankhai97@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "system/address-spaces.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/core/boards.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/arm/allwinner-h618.h"
+#include "hw/arm/boot.h"
+
+#define TYPE_ORANGEPI_ZERO2W_MACHINE MACHINE_TYPE_NAME("orangepi-zero2w")
+OBJECT_DECLARE_SIMPLE_TYPE(OrangePiZero2WMachineState, ORANGEPI_ZERO2W_MACHINE)
+
+struct OrangePiZero2WMachineState {
+ MachineState parent;
+
+ struct arm_boot_info bootinfo;
+};
+
+static void orangepi_zero2w_init(MachineState *machine)
+{
+ OrangePiZero2WMachineState *opms = ORANGEPI_ZERO2W_MACHINE(machine);
+ AwH618State *h618;
+
+ /* BIOS is not supported by this board */
+ if (machine->firmware) {
+ error_report("BIOS not supported for this machine");
+ exit(1);
+ }
+
+ h618 = AW_H618(object_new(TYPE_AW_H618));
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(h618));
+ object_unref(OBJECT(h618));
+
+ /* Mark H618 object realized */
+ qdev_realize(DEVICE(h618), NULL, &error_abort);
+
+ /* SDRAM */
+ memory_region_add_subregion(get_system_memory(),
+ h618->memmap[AW_H618_DEV_SDRAM],
+ machine->ram);
+
+ opms->bootinfo.loader_start = h618->memmap[AW_H618_DEV_SDRAM];
+ opms->bootinfo.ram_size = machine->ram_size;
+ opms->bootinfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
+ arm_load_kernel(&h618->cpus[0], machine, &opms->bootinfo);
+}
+
+static void orangepi_zero2w_machine_init(MachineClass *mc)
+{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a53"),
+ NULL
+ };
+
+ mc->desc = "Orange Pi Zero 2W (Cortex-A53)";
+ mc->init = orangepi_zero2w_init;
+ mc->min_cpus = AW_H618_NUM_CPUS;
+ mc->max_cpus = AW_H618_NUM_CPUS;
+ mc->default_cpus = AW_H618_NUM_CPUS;
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
+ mc->valid_cpu_types = valid_cpu_types;
+ mc->default_ram_size = 1 * GiB;
+ mc->default_ram_id = "orangepi-zero2w.ram";
+}
+
+DEFINE_MACHINE_EXTENDED("orangepi-zero2w", MACHINE, OrangePiZero2WMachineState,
+ orangepi_zero2w_machine_init, false, false,
+ NULL)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 3/8] hw/misc/allwinner-sid: Separate ALLWINNER_SID config symbol
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
2026-11-09 11:35 ` [PATCH v2 1/8] hw/arm/allwinner-h618: Add Allwinner H618 SoC emulation Khai Do
2026-11-09 11:35 ` [PATCH v2 2/8] hw/arm/orangepi-zero2w: Add Orange Pi Zero 2W machine Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 4/8] hw/misc/allwinner-sid: Support configurable eFuse capacity up to 512 bytes Khai Do
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Introduce a dedicated CONFIG_ALLWINNER_SID Kconfig symbol and select
it from CONFIG_ALLWINNER_H3 so the SID controller can be reused by
other Allwinner SoCs.
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/arm/Kconfig | 1 +
hw/misc/Kconfig | 3 +++
hw/misc/meson.build | 2 +-
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 616beae7bf..21480e277d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -309,6 +309,7 @@ config ALLWINNER_H3
select ALLWINNER_SUN8I_EMAC
select ALLWINNER_I2C
select ALLWINNER_WDT
+ select ALLWINNER_SID
select SERIAL_MM
select ARM_TIMER
select ARM_GIC
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 685b7ff1e7..1639978874 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -268,6 +268,9 @@ config LASI
config ALLWINNER_SRAMC
bool
+config ALLWINNER_SID
+ bool
+
config ALLWINNER_A10_CCM
bool
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index fc3800baec..059d4c01a1 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -55,7 +55,7 @@ system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
-system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
+system_ss.add(when: 'CONFIG_ALLWINNER_SID', if_true: files('allwinner-sid.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-ccu.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-dramc.c'))
system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 4/8] hw/misc/allwinner-sid: Support configurable eFuse capacity up to 512 bytes
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
` (2 preceding siblings ...)
2026-11-09 11:35 ` [PATCH v2 3/8] hw/misc/allwinner-sid: Separate ALLWINNER_SID config symbol Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 5/8] hw/arm/allwinner-h618: Connect Allwinner SID controller Khai Do
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Allwinner SoCs provide different eFuse capacities: older SoCs have
16 to 256 bytes, while newer 64-bit SoCs (e.g. H618) provide up to 512
bytes of eFuse storage.
Add a "size" property (defaulting to 16 bytes for backward compatibility)
and an internal storage buffer up to 512 bytes (AW_SID_SIZE_MAX).
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/misc/allwinner-sid.c | 12 ++++++++++--
include/hw/misc/allwinner-sid.h | 8 ++++++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/hw/misc/allwinner-sid.c b/hw/misc/allwinner-sid.c
index b5f827d4bd..afe5132c93 100644
--- a/hw/misc/allwinner-sid.c
+++ b/hw/misc/allwinner-sid.c
@@ -79,10 +79,15 @@ static void allwinner_sid_write(void *opaque, hwaddr offset,
if ((s->control & REG_PRCTL_OP_LOCK) &&
(s->control & REG_PRCTL_WRITE)) {
- uint32_t id = s->control >> 16;
+ uint32_t id = extract32(s->control, 16, 9);
if (id <= sizeof(QemuUUID) - sizeof(s->rdkey)) {
s->rdkey = ldl_be_p(&s->identifier.data[id]);
+ } else if (s->size >= sizeof(s->rdkey) &&
+ id <= s->size - sizeof(s->rdkey)) {
+ s->rdkey = ldl_be_p(&s->storage[id]);
+ } else {
+ s->rdkey = 0;
}
}
s->control &= ~REG_PRCTL_WRITE;
@@ -129,16 +134,19 @@ static void allwinner_sid_init(Object *obj)
static const Property allwinner_sid_properties[] = {
DEFINE_PROP_UUID_NODEFAULT("identifier", AwSidState, identifier),
+ DEFINE_PROP_UINT32("size", AwSidState, size, sizeof(QemuUUID)),
};
static const VMStateDescription allwinner_sid_vmstate = {
.name = "allwinner-sid",
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(control, AwSidState),
VMSTATE_UINT32(rdkey, AwSidState),
VMSTATE_UINT8_ARRAY_V(identifier.data, AwSidState, sizeof(QemuUUID), 1),
+ VMSTATE_UINT32_V(size, AwSidState, 2),
+ VMSTATE_UINT8_ARRAY_V(storage, AwSidState, AW_SID_SIZE_MAX, 2),
VMSTATE_END_OF_LIST()
}
};
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
index cfa22a4d7f..da8c235c5d 100644
--- a/include/hw/misc/allwinner-sid.h
+++ b/include/hw/misc/allwinner-sid.h
@@ -24,6 +24,9 @@
#include "hw/core/sysbus.h"
#include "qemu/uuid.h"
+/** Maximum eFuse storage size supported */
+#define AW_SID_SIZE_MAX (512)
+
/**
* Object model
* @{
@@ -54,6 +57,11 @@ struct AwSidState {
/** Stores the emulated device identifier */
QemuUUID identifier;
+ /** Size of eFuse storage */
+ uint32_t size;
+
+ /** eFuse storage buffer */
+ uint8_t storage[AW_SID_SIZE_MAX];
};
#endif /* HW_MISC_ALLWINNER_SID_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 5/8] hw/arm/allwinner-h618: Connect Allwinner SID controller
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
` (3 preceding siblings ...)
2026-11-09 11:35 ` [PATCH v2 4/8] hw/misc/allwinner-sid: Support configurable eFuse capacity up to 512 bytes Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 6/8] hw/sd/allwinner-sdhost: Separate ALLWINNER_SDHOST config symbol Khai Do
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Wire up the Allwinner Security ID (SID) eFuse controller into the
H618 SoC model:
- Map SID MMIO registers at 0x03006000 with 256 bytes capacity
- Remove sid from unimplemented peripheral list
- Configure default fixed SID identifier in Orange Pi Zero 2W machine
- Select ALLWINNER_SID in Kconfig
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/arm/Kconfig | 1 +
hw/arm/allwinner-h618.c | 11 ++++++++++-
hw/arm/orangepi-zero2w.c | 8 ++++++++
include/hw/arm/allwinner-h618.h | 3 +++
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 21480e277d..a1c09272fd 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -339,6 +339,7 @@ config ALLWINNER_H618
default y if TCG && AARCH64
select SERIAL_MM
select ARM_GIC
+ select ALLWINNER_SID
select UNIMP
config MAX78000_SOC
diff --git a/hw/arm/allwinner-h618.c b/hw/arm/allwinner-h618.c
index 59e0196fc6..19e9c3f0a3 100644
--- a/hw/arm/allwinner-h618.c
+++ b/hw/arm/allwinner-h618.c
@@ -29,6 +29,7 @@ const hwaddr allwinner_h618_memmap[] = {
[AW_H618_DEV_GIC_CPU] = 0x03022000,
[AW_H618_DEV_GIC_HYP] = 0x03024000,
[AW_H618_DEV_GIC_VCPU] = 0x03026000,
+ [AW_H618_DEV_SID] = 0x03006000,
[AW_H618_DEV_UART0] = 0x05000000,
[AW_H618_DEV_UART1] = 0x05000400,
[AW_H618_DEV_UART2] = 0x05000800,
@@ -44,7 +45,6 @@ static const struct AwH618Unimplemented {
} unimplemented[] = {
{ "ccu", 0x03001000, 4 * KiB },
{ "dma", 0x03002000, 4 * KiB },
- { "sid", 0x03006000, 4 * KiB },
{ "smc", 0x03007000, 4 * KiB },
{ "timer", 0x03009000, 4 * KiB },
{ "pwm", 0x0300a000, 4 * KiB },
@@ -91,6 +91,10 @@ static void allwinner_h618_init(Object *obj)
}
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
+
+ object_initialize_child(obj, "sid", &s->sid, TYPE_AW_SID);
+ object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
+ "identifier");
}
static void allwinner_h618_realize(DeviceState *dev, Error **errp)
@@ -172,6 +176,11 @@ static void allwinner_h618_realize(DeviceState *dev, Error **errp)
ppibase + AW_H618_GIC_PPI_MAINT));
}
+ /* Security Identifier */
+ qdev_prop_set_uint32(DEVICE(&s->sid), "size", 256);
+ sysbus_realize(SYS_BUS_DEVICE(&s->sid), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H618_DEV_SID]);
+
/* SRAM */
memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
64 * KiB, &error_abort);
diff --git a/hw/arm/orangepi-zero2w.c b/hw/arm/orangepi-zero2w.c
index fe87a98efc..1cc9ad7ba6 100644
--- a/hw/arm/orangepi-zero2w.c
+++ b/hw/arm/orangepi-zero2w.c
@@ -40,6 +40,14 @@ static void orangepi_zero2w_init(MachineState *machine)
object_property_add_child(OBJECT(machine), "soc", OBJECT(h618));
object_unref(OBJECT(h618));
+ /* Setup SID properties. Currently using a default fixed SID identifier. */
+ if (qemu_uuid_is_null(&h618->sid.identifier)) {
+ qdev_prop_set_string(DEVICE(h618), "identifier",
+ "03006180-1111-2222-3333-000044556677");
+ } else if (ldl_be_p(&h618->sid.identifier.data[0]) != 0x03006180) {
+ warn_report("Security Identifier value does not include H618 prefix");
+ }
+
/* Mark H618 object realized */
qdev_realize(DEVICE(h618), NULL, &error_abort);
diff --git a/include/hw/arm/allwinner-h618.h b/include/hw/arm/allwinner-h618.h
index e1b7162759..d4c3d19725 100644
--- a/include/hw/arm/allwinner-h618.h
+++ b/include/hw/arm/allwinner-h618.h
@@ -11,6 +11,7 @@
#include "qom/object.h"
#include "hw/intc/arm_gic.h"
+#include "hw/misc/allwinner-sid.h"
#include "target/arm/cpu.h"
/**
@@ -23,6 +24,7 @@ enum {
AW_H618_DEV_GIC_CPU,
AW_H618_DEV_GIC_HYP,
AW_H618_DEV_GIC_VCPU,
+ AW_H618_DEV_SID,
AW_H618_DEV_UART0,
AW_H618_DEV_UART1,
AW_H618_DEV_UART2,
@@ -50,6 +52,7 @@ struct AwH618State {
ARMCPU cpus[AW_H618_NUM_CPUS];
const hwaddr *memmap;
GICState gic;
+ AwSidState sid;
MemoryRegion sram_a1;
MemoryRegion sram_a2;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 6/8] hw/sd/allwinner-sdhost: Separate ALLWINNER_SDHOST config symbol
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
` (4 preceding siblings ...)
2026-11-09 11:35 ` [PATCH v2 5/8] hw/arm/allwinner-h618: Connect Allwinner SID controller Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 7/8] hw/arm/allwinner-h618: Connect Allwinner SD/MMC host controller 0 Khai Do
2026-11-09 11:35 ` [PATCH v2 8/8] hw/arm/orangepi-zero2w: Wire up SD card and support firmware loading Khai Do
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Introduce a dedicated Kconfig symbol ALLWINNER_SDHOST for the Allwinner
SD/MMC host controller. Previously it was conditionally built only when
CONFIG_ALLWINNER_H3 was enabled.
Select ALLWINNER_SDHOST in ALLWINNER_H3.
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/arm/Kconfig | 1 +
hw/sd/Kconfig | 4 ++++
hw/sd/meson.build | 2 +-
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index a1c09272fd..18c45bc9e4 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -310,6 +310,7 @@ config ALLWINNER_H3
select ALLWINNER_I2C
select ALLWINNER_WDT
select ALLWINNER_SID
+ select ALLWINNER_SDHOST
select SERIAL_MM
select ARM_TIMER
select ARM_GIC
diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig
index c69bf24f8d..5078fd4fab 100644
--- a/hw/sd/Kconfig
+++ b/hw/sd/Kconfig
@@ -1,3 +1,7 @@
+config ALLWINNER_SDHOST
+ bool
+ select SD
+
config PL181
bool
select SD
diff --git a/hw/sd/meson.build b/hw/sd/meson.build
index ebf09e30a4..d15baaaf12 100644
--- a/hw/sd/meson.build
+++ b/hw/sd/meson.build
@@ -7,7 +7,7 @@ system_ss.add(when: 'CONFIG_SSI_SD', if_true: files('ssi-sd.c'))
system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_mmc.c'))
system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c'))
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
-system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
+system_ss.add(when: 'CONFIG_ALLWINNER_SDHOST', if_true: files('allwinner-sdhost.c'))
system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c'))
system_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))
system_ss.add(when: 'CONFIG_AXIADO_SDHCI', if_true: files('axiado_sdhci.c'))
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 7/8] hw/arm/allwinner-h618: Connect Allwinner SD/MMC host controller 0
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
` (5 preceding siblings ...)
2026-11-09 11:35 ` [PATCH v2 6/8] hw/sd/allwinner-sdhost: Separate ALLWINNER_SDHOST config symbol Khai Do
@ 2026-11-09 11:35 ` Khai Do
2026-11-09 11:35 ` [PATCH v2 8/8] hw/arm/orangepi-zero2w: Wire up SD card and support firmware loading Khai Do
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Wire up the Allwinner SD/MMC host controller 0 (SMHC0) into the
Allwinner H618 SoC model:
- Map MMC0 MMIO registers at 0x04020000
- Connect GIC interrupt SPI 35 (AW_H618_GIC_SPI_MMC0)
- Remove mmc0 from unimplemented peripheral list
- Alias "sd-bus" property from mmc0
- Select ALLWINNER_SDHOST in ALLWINNER_H618 Kconfig
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/arm/Kconfig | 1 +
hw/arm/allwinner-h618.c | 16 +++++++++++++++-
include/hw/arm/allwinner-h618.h | 3 +++
3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 18c45bc9e4..655047fc47 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -341,6 +341,7 @@ config ALLWINNER_H618
select SERIAL_MM
select ARM_GIC
select ALLWINNER_SID
+ select ALLWINNER_SDHOST
select UNIMP
config MAX78000_SOC
diff --git a/hw/arm/allwinner-h618.c b/hw/arm/allwinner-h618.c
index 19e9c3f0a3..9083e478d5 100644
--- a/hw/arm/allwinner-h618.c
+++ b/hw/arm/allwinner-h618.c
@@ -29,6 +29,7 @@ const hwaddr allwinner_h618_memmap[] = {
[AW_H618_DEV_GIC_CPU] = 0x03022000,
[AW_H618_DEV_GIC_HYP] = 0x03024000,
[AW_H618_DEV_GIC_VCPU] = 0x03026000,
+ [AW_H618_DEV_MMC0] = 0x04020000,
[AW_H618_DEV_SID] = 0x03006000,
[AW_H618_DEV_UART0] = 0x05000000,
[AW_H618_DEV_UART1] = 0x05000400,
@@ -49,7 +50,6 @@ static const struct AwH618Unimplemented {
{ "timer", 0x03009000, 4 * KiB },
{ "pwm", 0x0300a000, 4 * KiB },
{ "pio", 0x0300b000, 4 * KiB },
- { "mmc0", 0x04020000, 4 * KiB },
{ "mmc1", 0x04021000, 4 * KiB },
{ "mmc2", 0x04022000, 4 * KiB },
{ "rtc", 0x07000000, 4 * KiB },
@@ -72,6 +72,7 @@ enum {
AW_H618_GIC_SPI_UART1 = 1,
AW_H618_GIC_SPI_UART2 = 2,
AW_H618_GIC_SPI_UART3 = 3,
+ AW_H618_GIC_SPI_MMC0 = 35,
};
enum {
@@ -95,6 +96,8 @@ static void allwinner_h618_init(Object *obj)
object_initialize_child(obj, "sid", &s->sid, TYPE_AW_SID);
object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
"identifier");
+
+ object_initialize_child(obj, "mmc0", &s->mmc0, TYPE_AW_SDHOST_SUN50I_A64);
}
static void allwinner_h618_realize(DeviceState *dev, Error **errp)
@@ -181,6 +184,17 @@ static void allwinner_h618_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->sid), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H618_DEV_SID]);
+ /* SD/MMC 0 */
+ object_property_set_link(OBJECT(&s->mmc0), "dma-memory",
+ OBJECT(get_system_memory()), &error_fatal);
+ sysbus_realize(SYS_BUS_DEVICE(&s->mmc0), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H618_DEV_MMC0]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0,
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H618_GIC_SPI_MMC0));
+
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
+ "sd-bus");
+
/* SRAM */
memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
64 * KiB, &error_abort);
diff --git a/include/hw/arm/allwinner-h618.h b/include/hw/arm/allwinner-h618.h
index d4c3d19725..ea2ec205c8 100644
--- a/include/hw/arm/allwinner-h618.h
+++ b/include/hw/arm/allwinner-h618.h
@@ -12,6 +12,7 @@
#include "qom/object.h"
#include "hw/intc/arm_gic.h"
#include "hw/misc/allwinner-sid.h"
+#include "hw/sd/allwinner-sdhost.h"
#include "target/arm/cpu.h"
/**
@@ -24,6 +25,7 @@ enum {
AW_H618_DEV_GIC_CPU,
AW_H618_DEV_GIC_HYP,
AW_H618_DEV_GIC_VCPU,
+ AW_H618_DEV_MMC0,
AW_H618_DEV_SID,
AW_H618_DEV_UART0,
AW_H618_DEV_UART1,
@@ -53,6 +55,7 @@ struct AwH618State {
const hwaddr *memmap;
GICState gic;
AwSidState sid;
+ AwSdHostState mmc0;
MemoryRegion sram_a1;
MemoryRegion sram_a2;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 8/8] hw/arm/orangepi-zero2w: Wire up SD card and support firmware loading
2026-11-09 11:35 [PATCH v2 0/8] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
` (6 preceding siblings ...)
2026-11-09 11:35 ` [PATCH v2 7/8] hw/arm/allwinner-h618: Connect Allwinner SD/MMC host controller 0 Khai Do
@ 2026-11-09 11:35 ` Khai Do
7 siblings, 0 replies; 9+ messages in thread
From: Khai Do @ 2026-11-09 11:35 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, pbonzini, strahinja.p.jankovic, Khai Do
Connect the SD card block backend to the H618 "sd-bus", allowing
booting from MicroSD card images via `-drive if=sd,format=raw,file=...`.
In addition, support loading raw firmware binaries (such as EDK2 UEFI or
U-Boot) at 0x40080000 via the `-bios` command-line option.
Signed-off-by: Khai Do <dovankhai97@gmail.com>
---
hw/arm/orangepi-zero2w.c | 41 ++++++++++++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 6 deletions(-)
diff --git a/hw/arm/orangepi-zero2w.c b/hw/arm/orangepi-zero2w.c
index 1cc9ad7ba6..5b0e64cff4 100644
--- a/hw/arm/orangepi-zero2w.c
+++ b/hw/arm/orangepi-zero2w.c
@@ -13,8 +13,12 @@
#include "qemu/error-report.h"
#include "hw/core/boards.h"
#include "hw/core/qdev-properties.h"
+#include "hw/core/qdev-properties-system.h"
#include "hw/arm/allwinner-h618.h"
#include "hw/arm/boot.h"
+#include "hw/core/loader.h"
+#include "hw/sd/sd.h"
+#include "system/blockdev.h"
#define TYPE_ORANGEPI_ZERO2W_MACHINE MACHINE_TYPE_NAME("orangepi-zero2w")
OBJECT_DECLARE_SIMPLE_TYPE(OrangePiZero2WMachineState, ORANGEPI_ZERO2W_MACHINE)
@@ -29,12 +33,10 @@ static void orangepi_zero2w_init(MachineState *machine)
{
OrangePiZero2WMachineState *opms = ORANGEPI_ZERO2W_MACHINE(machine);
AwH618State *h618;
-
- /* BIOS is not supported by this board */
- if (machine->firmware) {
- error_report("BIOS not supported for this machine");
- exit(1);
- }
+ DriveInfo *di;
+ BlockBackend *blk;
+ BusState *bus;
+ DeviceState *carddev;
h618 = AW_H618(object_new(TYPE_AW_H618));
object_property_add_child(OBJECT(machine), "soc", OBJECT(h618));
@@ -51,6 +53,15 @@ static void orangepi_zero2w_init(MachineState *machine)
/* Mark H618 object realized */
qdev_realize(DEVICE(h618), NULL, &error_abort);
+ /* Retrieve SD bus and plug in SD card */
+ di = drive_get(IF_SD, 0, 0);
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
+ bus = qdev_get_child_bus(DEVICE(h618), "sd-bus");
+
+ carddev = qdev_new(TYPE_SD_CARD);
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
+
/* SDRAM */
memory_region_add_subregion(get_system_memory(),
h618->memmap[AW_H618_DEV_SDRAM],
@@ -59,6 +70,24 @@ static void orangepi_zero2w_init(MachineState *machine)
opms->bootinfo.loader_start = h618->memmap[AW_H618_DEV_SDRAM];
opms->bootinfo.ram_size = machine->ram_size;
opms->bootinfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
+
+ /* Load firmware if specified (-bios) */
+ if (machine->firmware) {
+ hwaddr firmware_addr = 0x40080000;
+ int r;
+
+ r = load_image_targphys(machine->firmware, firmware_addr,
+ machine->ram_size -
+ (firmware_addr - 0x40000000), NULL);
+ if (r < 0) {
+ error_report("Failed to load firmware from %s", machine->firmware);
+ exit(1);
+ }
+
+ opms->bootinfo.entry = firmware_addr;
+ opms->bootinfo.firmware_loaded = true;
+ }
+
arm_load_kernel(&h618->cpus[0], machine, &opms->bootinfo);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread