From: Khai Do <dovankhai97@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, peter.maydell@linaro.org,
pbonzini@redhat.com, strahinja.p.jankovic@gmail.com,
Khai Do <dovankhai97@gmail.com>
Subject: [PATCH 1/5] hw/arm/allwinner-h618: Add Allwinner H618 SoC emulation
Date: Sat, 31 Oct 2026 21:51:43 +0700 [thread overview]
Message-ID: <20261031145147.32683-2-dovankhai97@gmail.com> (raw)
In-Reply-To: <20261031145147.32683-1-dovankhai97@gmail.com>
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
next prev parent reply other threads:[~2026-10-31 14:58 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 14:51 [PATCH 0/5] hw/arm: Add Allwinner H618 SoC and Orange Pi Zero 2W machine Khai Do
2026-10-31 14:51 ` Khai Do [this message]
2026-10-31 14:51 ` [PATCH 2/5] hw/arm/orangepi-zero2w: Add " Khai Do
2026-10-31 14:51 ` [PATCH 3/5] hw/misc/allwinner-sid: Separate ALLWINNER_SID config symbol Khai Do
2026-10-31 14:51 ` [PATCH 4/5] hw/misc/allwinner-sid: Support configurable eFuse capacity up to 512 bytes Khai Do
2026-10-31 14:51 ` [PATCH 5/5] hw/arm/allwinner-h618: Connect Allwinner SID controller Khai Do
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=20261031145147.32683-2-dovankhai97@gmail.com \
--to=dovankhai97@gmail.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=strahinja.p.jankovic@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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.