> -----Original Message-----
> From: Bernhard Beschow <[email protected]>
> Sent: 27 May 2026 02:43
> To: Gaurav Sharma <[email protected]>; [email protected]
> Cc: [email protected]; [email protected]; Philippe Mathieu-
> Daudé <[email protected]>
> Subject: [EXT] Re: [PATCHv1 3/7] hw/misc: Add SRC (System Reset Controller)
> to i.MX8MP
>
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
>
>
> Am 19. Mai 2026 17:56:31 UTC schrieb Gaurav Sharma
> <[email protected]>:
>
> Hi Gurav,
>
> >From: Bernhard Beschow <[email protected]>
> >
> >Add emulation of the i.MX8MP System Reset Controller (SRC).
> >The SRC manages reset control for various subsystems on the i.MX8MP SoC.
> >SRC registers are used to start/stop/poll the M7 core, hence needed for
> >AMP boot.
> >
> >Signed-off-by: Bernhard Beschow <[email protected]>
>
> Your SoB is missing here (since you already modified the code).
>
will add it in v2.
> >---
> > docs/system/arm/imx8m.rst | 1 +
> > hw/arm/Kconfig | 1 +
> > hw/arm/fsl-imx8mp.c | 10 +
> > hw/misc/Kconfig | 3 +
> > hw/misc/imx8mp_src.c | 431
> +++++++++++++++++++++++++++++++++++
> > hw/misc/meson.build | 1 +
> > hw/misc/trace-events | 5 +
> > include/hw/arm/fsl-imx8mp.h | 2 +
> > include/hw/misc/imx8mp_src.h | 32 +++
> > 9 files changed, 486 insertions(+)
> > create mode 100644 hw/misc/imx8mp_src.c create mode 100644
> >include/hw/misc/imx8mp_src.h
> >
> >diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst
> >index 1e110bc810..49c100c4b1 100644
> >--- a/docs/system/arm/imx8m.rst
> >+++ b/docs/system/arm/imx8m.rst
> >@@ -27,6 +27,7 @@ following devices:
> > * Clock Tree
> > * General Power Controller (GPC)
> > * General Purpose Register (GPR)
> >+ * System Reset Controller (SRC)
>
> I'd always (i.e. documentation, comments, device descriptions) omit the
> redundant abbreviations ("SRC" in this case), also in the other device models.
>
Okay. will make the change as part of v2.
> >
> > Boot options
> > ------------
> >diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
> >9e4b71264a..8e89e30c45 100644
> >--- a/hw/arm/Kconfig
> >+++ b/hw/arm/Kconfig
> >@@ -602,6 +602,7 @@ config FSL_IMX8MP
> > select FSL_IMX8MP_CCM
> > select FSL_IMX8MP_GPC
> > select FSL_IMX8MP_GPR
> >+ select FSL_IMX8MP_SRC
> > select IMX
> > select IMX_FEC
> > select IMX_I2C
> >diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index
> >c4aafbdc1c..168fcb0334 100644
> >--- a/hw/arm/fsl-imx8mp.c
> >+++ b/hw/arm/fsl-imx8mp.c
> >@@ -208,6 +208,8 @@ static void fsl_imx8mp_init(Object *obj)
> >
> > object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX8MP_GPR);
> >
> >+ object_initialize_child(obj, "src", &s->src, TYPE_IMX8MP_SRC);
> >+
> > for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
> > g_autofree char *name = g_strdup_printf("uart%d", i + 1);
> > object_initialize_child(obj, name, &s->uart[i],
> >TYPE_IMX_SERIAL); @@ -426,6 +428,13 @@ static void
> fsl_imx8mp_realize(DeviceState *dev, Error **errp)
> > qdev_get_gpio_in(gicdev, serial_table[i].irq));
> > }
> >
> >+ /* SRC */
> >+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->src), errp)) {
> >+ return;
> >+ }
> >+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0,
> >+ fsl_imx8mp_memmap[FSL_IMX8MP_SRC].addr);
> >+
> > /* GPC */
> > if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpc), errp)) {
> > return;
> >@@ -716,6 +725,7 @@ static void fsl_imx8mp_realize(DeviceState *dev,
> Error **errp)
> > case FSL_IMX8MP_PCIE_PHY1:
> > case FSL_IMX8MP_RAM:
> > case FSL_IMX8MP_SNVS_HP:
> >+ case FSL_IMX8MP_SRC:
> > case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
> > case FSL_IMX8MP_USB1 ... FSL_IMX8MP_USB2:
> > case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
> >diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index
> >7464788d82..185bd6f62a 100644
> >--- a/hw/misc/Kconfig
> >+++ b/hw/misc/Kconfig
> >@@ -107,6 +107,9 @@ config FSL_IMX8MP_GPC config FSL_IMX8MP_GPR
> > bool
> >
> >+config FSL_IMX8MP_SRC
> >+ bool
> >+
> > config STM32_RCC
> > bool
> >
> >diff --git a/hw/misc/imx8mp_src.c b/hw/misc/imx8mp_src.c new file mode
> >100644 index 0000000000..f339a7a088
> >--- /dev/null
> >+++ b/hw/misc/imx8mp_src.c
> >@@ -0,0 +1,431 @@
> >+/*
> >+ * i.MX 8M Plus System Reset Controller
> >+ *
> >+ * Copyright (c) 2025 Bernhard Beschow <[email protected]>
> >+ *
> >+ * SPDX-License-Identifier: GPL-2.0-or-later */
> >+
> >+#include "qemu/osdep.h"
> >+#include "hw/misc/imx8mp_src.h"
> >+#include "hw/core/cpu.h"
> >+#include "hw/core/qdev-properties.h"
> >+#include "hw/core/registerfields.h"
> >+#include "target/arm/arm-powerctl.h"
> >+#include "migration/vmstate.h"
> >+#include "qemu/bitops.h"
> >+#include "qemu/log.h"
> >+#include "qemu/main-loop.h"
> >+#include "trace.h"
> >+
> >+REG32(SRC_SCR, 0x0000)
> >+
> >+REG32(SRC_A53RCR0, 0x0004)
> >+ FIELD(SRC_A53RCR0, CORE_RESET3, 7, 1)
> >+ FIELD(SRC_A53RCR0, CORE_RESET2, 6, 1)
> >+ FIELD(SRC_A53RCR0, CORE_RESET1, 5, 1)
> >+ FIELD(SRC_A53RCR0, CORE_RESET0, 4, 1)
> >+
> >+REG32(SRC_A53RCR1, 0x0008)
> >+ FIELD(SRC_A53RCR1, CORE3_ENABLE, 3, 1)
> >+ FIELD(SRC_A53RCR1, CORE2_ENABLE, 2, 1)
> >+ FIELD(SRC_A53RCR1, CORE1_ENABLE, 1, 1)
> >+ FIELD(SRC_A53RCR1, CORE0_ENABLE, 0, 1)
>
> Let's omit the A53 handling for now since it interferes with -smp as Phil
> pointed out and since it isn't used with direct kernel boot. That is, we can
> remove the A53-related FIELDs for now, as well as the switch cases in
> fsl_imx8mp_src_write() and any code that would be rendered unused.
>
Okay. will clean it up.
> >+
> >+REG32(SRC_M7RCR, 0x000c)
> >+REG32(SRC_SUPERMIX_RCR, 0x0018)
> >+REG32(SRC_AUDIOMIX_RCR, 0x001c)
> >+REG32(SRC_USBPHY1_RCR, 0x0020)
> >+REG32(SRC_USBPHY2_RCR, 0x0024)
> >+REG32(SRC_MLMIX_RCR, 0x0028)
> >+REG32(SRC_PCIEPHY_RCR, 0x002c)
> >+REG32(SRC_HDMI_RCR, 0x0030)
> >+REG32(SRC_MEDIA_RCR, 0x0034)
> >+REG32(SRC_GPU2D_RCR, 0x0038)
> >+REG32(SRC_GPU3D_RCR, 0x003c)
> >+REG32(SRC_GPU_RCR, 0x0040)
> >+REG32(SRC_VPU_RCR, 0x0044)
> >+REG32(SRC_VPU_G1_RCR, 0x0048)
> >+REG32(SRC_VPU_G2_RCR, 0x004c)
> >+REG32(SRC_VPUVC8KE_RCR, 0x0050)
> >+REG32(SRC_NOC_RCR, 0x0054)
> >+REG32(SRC_SBMR1, 0x0058)
> >+REG32(SRC_SRSR, 0x005c)
> >+REG32(SRC_SISR, 0x0068)
> >+REG32(SRC_SIMR, 0x006c)
> >+
> >+REG32(SRC_SBMR2, 0x0070)
> >+ FIELD(SRC_SBMR2, IPP_BOOT_MODE, 24, 4)
> >+
> >+REG32(SRC_GPR1, 0x0074)
> >+REG32(SRC_GPR2, 0x0078)
> >+REG32(SRC_GPR3, 0x007c)
> >+REG32(SRC_GPR4, 0x0080)
> >+REG32(SRC_GPR5, 0x0084)
> >+REG32(SRC_GPR6, 0x0088)
> >+REG32(SRC_GPR7, 0x008c)
> >+REG32(SRC_GPR8, 0x0090)
> >+REG32(SRC_GPR9, 0x0094)
> >+REG32(SRC_GPR10, 0x0098)
> >+REG32(SRC_DDRC_RCR, 0x1000)
> >+REG32(SRC_HDMIPHY_RCR, 0x1008)
> >+REG32(SRC_MIPIPHY1_RCR, 0x100c)
> >+REG32(SRC_MIPIPHY2_RCR, 0x1010)
> >+REG32(SRC_HSIO_RCR, 0x1014)
> >+REG32(SRC_MEDIAISPDWP_RCR, 0x1018)
> >+
> >+static const char *fsl_imx8mp_src_reg_name(uint32_t reg) {
> >+ switch (reg) {
> >+ case R_SRC_SCR:
> >+ return " (SRC_SCR)";
> >+ case R_SRC_A53RCR0:
> >+ return " (SRC_A53RCR0)";
> >+ case R_SRC_A53RCR1:
> >+ return " (SRC_A53RCR1)";
> >+ case R_SRC_M7RCR:
> >+ return " (SRC_M7RCR)";
> >+ case R_SRC_SUPERMIX_RCR:
> >+ return " (SRC_SUPERMIX_RCR)";
> >+ case R_SRC_AUDIOMIX_RCR:
> >+ return " (SRC_AUDIOMIX_RCR)";
> >+ case R_SRC_USBPHY1_RCR:
> >+ return " (SRC_USBPHY1_RCR)";
> >+ case R_SRC_USBPHY2_RCR:
> >+ return " (SRC_USBPHY2_RCR)";
> >+ case R_SRC_MLMIX_RCR:
> >+ return " (SRC_MLMIX_RCR)";
> >+ case R_SRC_PCIEPHY_RCR:
> >+ return " (SRC_PCIEPHY_RCR)";
> >+ case R_SRC_HDMI_RCR:
> >+ return " (SRC_HDMI_RCR)";
> >+ case R_SRC_MEDIA_RCR:
> >+ return " (SRC_MEDIA_RCR)";
> >+ case R_SRC_GPU2D_RCR:
> >+ return " (SRC_GPU2D_RCR)";
> >+ case R_SRC_GPU3D_RCR:
> >+ return " (SRC_GPU3D_RCR)";
> >+ case R_SRC_GPU_RCR:
> >+ return " (SRC_GPU_RCR)";
> >+ case R_SRC_VPU_RCR:
> >+ return " (SRC_VPU_RCR)";
> >+ case R_SRC_VPU_G1_RCR:
> >+ return " (SRC_VPU_G1_RCR)";
> >+ case R_SRC_VPU_G2_RCR:
> >+ return " (SRC_VPU_G2_RCR)";
> >+ case R_SRC_VPUVC8KE_RCR:
> >+ return " (SRC_VPUVC8KE_RCR)";
> >+ case R_SRC_NOC_RCR:
> >+ return " (SRC_NOC_RCR)";
> >+ case R_SRC_SBMR1:
> >+ return " (SRC_SBMR1)";
> >+ case R_SRC_SRSR:
> >+ return " (SRC_SRSR)";
> >+ case R_SRC_SISR:
> >+ return " (SRC_SISR)";
> >+ case R_SRC_SIMR:
> >+ return " (SRC_SIMR)";
> >+ case R_SRC_SBMR2:
> >+ return " (SRC_SBMR2)";
> >+ case R_SRC_GPR1:
> >+ return " (SRC_GPR1)";
> >+ case R_SRC_GPR2:
> >+ return " (SRC_GPR2)";
> >+ case R_SRC_GPR3:
> >+ return " (SRC_GPR3)";
> >+ case R_SRC_GPR4:
> >+ return " (SRC_GPR4)";
> >+ case R_SRC_GPR5:
> >+ return " (SRC_GPR5)";
> >+ case R_SRC_GPR6:
> >+ return " (SRC_GPR6)";
> >+ case R_SRC_GPR7:
> >+ return " (SRC_GPR7)";
> >+ case R_SRC_GPR8:
> >+ return " (SRC_GPR8)";
> >+ case R_SRC_GPR9:
> >+ return " (SRC_GPR9)";
> >+ case R_SRC_GPR10:
> >+ return " (SRC_GPR10)";
> >+ case R_SRC_DDRC_RCR:
> >+ return " (SRC_DDRC_RCR)";
> >+ case R_SRC_HDMIPHY_RCR:
> >+ return " (SRC_HDMIPHY_RCR)";
> >+ case R_SRC_MIPIPHY1_RCR:
> >+ return " (SRC_MIPIPHY1_RCR)";
> >+ case R_SRC_MIPIPHY2_RCR:
> >+ return " (SRC_MIPIPHY2_RCR)";
> >+ case R_SRC_HSIO_RCR:
> >+ return " (SRC_HSIO_RCR)";
> >+ case R_SRC_MEDIAISPDWP_RCR:
> >+ return " (SRC_MEDIAISPDWP_RCR)";
> >+ default:
> >+ return " (reserved)";
> >+ }
> >+}
> >+
> >+static uint64_t fsl_imx8mp_src_read(void *opaque, hwaddr offset,
> >+ unsigned size) {
> >+ FslImx8mpSrcState *s = opaque;
> >+ const uint32_t reg = offset / 4;
> >+ uint32_t value = 0;
> >+
> >+ switch (reg) {
> >+ default:
> >+ if (reg < FSL_IMX8MP_SRC_NUM_REGS) {
> >+ value = s->regs[reg];
> >+ }
> >+ qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented register at
> offset 0x%"
> >+ HWADDR_PRIx "\n", TYPE_IMX8MP_SRC, __func__,
> >+ offset);
> >+ break;
> >+ }
> >+
> >+ trace_fsl_imx8mp_src_read(offset, fsl_imx8mp_src_reg_name(reg),
> >+ value);
> >+
> >+ return value;
> >+}
> >+
> >+/*
> >+ * The reset is asynchronous so we need to defer clearing the reset
> >+bit until
> >+ * the work is completed.
> >+ */
> >+
> >+struct FslImx8mpSrcResetInfo {
> >+ FslImx8mpSrcState *s;
> >+ int reset_bit;
> >+};
> >+
> >+
> >+static void imx8mp_src_reset(DeviceState *dev) {
> >+ FslImx8mpSrcState *s = IMX8MP_SRC(dev);
> >+
> >+ memset(s->regs, 0, sizeof(s->regs));
> >+
> >+ /* Primary A53 core enabled by default */
> >+ s->regs[R_SRC_A53RCR1] = BIT(0);
> >+
> >+ /*
> >+ * Default CM7 STOP state for Linux imx-rproc MMIO mode detection.
> >+ * Historically your minimal SRC-mmio stub seeded offset 0x0C with 0xA.
> >+ * In this model, offset 0x0C is R_SRC_M7RCR.
> >+ */
>
> I can't quite parse those comments. AI leftover?
>
> >+ s->regs[R_SRC_M7RCR] = 0x0000000A;
>
> The reset value in the datasheet is 0000_00A8h. In particular, why change the
> 8 to an A? AFAIU SW_M7C_RST is supposed to be set by the guest to trigger a
> core reset, and the bit clears itself once the reset process is finished.
>
Yes, this should be 0000_00A8h as mentioned in the reference manual of imx8mp.
I will rectify it as part of v2.
> >+
> >+ /* Boot mode field (kept from previous realize-time init) */
> >+ s->regs[R_SRC_SBMR2] = FIELD_DP32(s->regs[R_SRC_SBMR2],
> SRC_SBMR2,
> >+ IPP_BOOT_MODE, s->boot_mode);
>
> Let's not worry about the boot mode for now (see also below) and just
> remove this code for now.
>
Got it.
> >+}
> >+
> >+
> >+static void fsl_imx8mp_src_clear_reset_bit(CPUState *cpu,
> >+run_on_cpu_data data) {
> >+ struct FslImx8mpSrcResetInfo *ri = data.host_ptr;
> >+ FslImx8mpSrcState *s = ri->s;
> >+
> >+ assert(bql_locked());
> >+
> >+ s->regs[R_SRC_A53RCR0] = deposit32(s->regs[R_SRC_A53RCR0],
> >+ ri->reset_bit, 1, 0);
> >+
> trace_fsl_imx8mp_src_clear_reset_bit(fsl_imx8mp_src_reg_name(R_SRC_A53
> RCR0),
> >+ s->regs[R_SRC_A53RCR0]);
> >+
> >+ g_free(ri);
> >+}
> >+
> >+static void fsl_imx8mp_src_defer_clear_reset_bit(FslImx8mpSrcState *s,
> >+ int cpuid,
> >+ unsigned long
> >+reset_shift) {
> >+ struct FslImx8mpSrcResetInfo *ri;
> >+ CPUState *cpu = arm_get_cpu_by_id(cpuid);
> >+
> >+ if (!cpu) {
> >+ return;
> >+ }
> >+
> >+ ri = g_new(struct FslImx8mpSrcResetInfo, 1);
> >+ ri->s = s;
> >+ ri->reset_bit = reset_shift;
> >+
> >+ async_run_on_cpu(cpu, fsl_imx8mp_src_clear_reset_bit,
> >+ RUN_ON_CPU_HOST_PTR(ri)); }
> >+
> >+static void fsl_imx8mp_src_write(void *opaque, hwaddr offset, uint64_t
> value,
> >+ unsigned size) {
> >+ FslImx8mpSrcState *s = opaque;
> >+ const uint32_t reg = offset / 4;
> >+ unsigned long change_mask;
> >+
> >+ change_mask = s->regs[reg] ^ (uint32_t)value;
> >+
> >+ switch (reg) {
> >+ case R_SRC_A53RCR0:
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR0, CORE_RESET0)) {
> >+ arm_reset_cpu(0);
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 0,
> >+ R_SRC_A53RCR0_CORE_RESET0_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR0, CORE_RESET1)) {
> >+ arm_reset_cpu(1);
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 1,
> >+ R_SRC_A53RCR0_CORE_RESET1_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR0, CORE_RESET2)) {
> >+ arm_reset_cpu(2);
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 2,
> >+ R_SRC_A53RCR0_CORE_RESET2_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR0, CORE_RESET3)) {
> >+ arm_reset_cpu(3);
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 3,
> >+ R_SRC_A53RCR0_CORE_RESET3_SHIFT);
> >+ }
> >+ s->regs[reg] = value;
> >+ break;
> >+ case R_SRC_A53RCR1:
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR1, CORE3_ENABLE)) {
> >+ if (FIELD_EX32(value, SRC_A53RCR1, CORE3_ENABLE)) {
> >+ /* CORE 3 is brought up */
> >+ arm_set_cpu_on(3, s->regs[R_SRC_GPR8] << 2, 0, 3, true);
> >+ } else {
> >+ /* CORE 3 is shut down */
> >+ arm_set_cpu_off(3);
> >+ }
> >+ /* We clear the reset bit as the processor changed state */
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 3,
> R_SRC_A53RCR0_CORE_RESET3_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR1, CORE2_ENABLE)) {
> >+ if (FIELD_EX32(value, SRC_A53RCR1, CORE2_ENABLE)) {
> >+ /* CORE 2 is brought up */
> >+ arm_set_cpu_on(2, s->regs[R_SRC_GPR6] << 2, 0, 3, true);
> >+ } else {
> >+ /* CORE 2 is shut down */
> >+ arm_set_cpu_off(2);
> >+ }
> >+ /* We clear the reset bit as the processor changed state */
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 2,
> R_SRC_A53RCR0_CORE_RESET2_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR1, CORE1_ENABLE)) {
> >+ if (FIELD_EX32(value, SRC_A53RCR1, CORE1_ENABLE)) {
> >+ /* CORE 1 is brought up */
> >+ arm_set_cpu_on(1, s->regs[R_SRC_GPR4] << 2, 0, 3, true);
> >+ } else {
> >+ /* CORE 1 is shut down */
> >+ arm_set_cpu_off(1);
> >+ }
> >+ /* We clear the reset bit as the processor changed state */
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 1,
> R_SRC_A53RCR0_CORE_RESET1_SHIFT);
> >+ }
> >+ if (FIELD_EX32(change_mask, SRC_A53RCR1, CORE0_ENABLE)) {
> >+ if (FIELD_EX32(value, SRC_A53RCR1, CORE0_ENABLE)) {
> >+ /* CORE 1 is brought up */
> >+ arm_set_cpu_on(0, s->regs[R_SRC_GPR2] << 2, 0, 3, true);
> >+ } else {
> >+ /* CORE 1 is shut down */
> >+ arm_set_cpu_off(0);
> >+ }
> >+ /* We clear the reset bit as the processor changed state */
> >+ fsl_imx8mp_src_defer_clear_reset_bit(s, 0,
> R_SRC_A53RCR0_CORE_RESET0_SHIFT);
> >+ }
> >+ s->regs[reg] = value;
> >+ break;
> >+ default:
> >+ if (reg < FSL_IMX8MP_SRC_NUM_REGS) {
> >+ s->regs[reg] = value;
> >+ }
> >+ qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented register at
> offset 0x%"
> >+ HWADDR_PRIx "\n", TYPE_IMX8MP_SRC, __func__,
> >+ offset);
> >+ break;
> >+ }
> >+
> >+ trace_fsl_imx8mp_src_write(offset, fsl_imx8mp_src_reg_name(reg),
> >+value); }
> >+
> >+static const struct MemoryRegionOps imx8mp_src_ops = {
> >+ .read = fsl_imx8mp_src_read,
> >+ .write = fsl_imx8mp_src_write,
> >+ .endianness = DEVICE_LITTLE_ENDIAN,
> >+ .valid = {
> >+ /*
> >+ * Our device would not work correctly if the guest was doing
> >+ * unaligned access. This might not be a limitation on the real
> >+ * device but in practice there is no reason for a guest to access
> >+ * this device unaligned.
> >+ */
> >+ .min_access_size = 4,
> >+ .max_access_size = 4,
> >+ .unaligned = false,
> >+ },
> >+};
> >+
> >+void imx8mp_src_start_cpu(FslImx8mpSrcState *s, int cpuid) {
>
> This function is unused and should therefore be removed.
>
Okay. will clean it up as part of v2.
> >+ switch (cpuid) {
> >+ case 0:
> >+ arm_set_cpu_on(0, s->regs[R_SRC_GPR2] << 2, 0, 3, true);
> >+ break;
> >+ case 1:
> >+ arm_set_cpu_on(1, s->regs[R_SRC_GPR4] << 2, 0, 3, true);
> >+ break;
> >+ case 2:
> >+ arm_set_cpu_on(2, s->regs[R_SRC_GPR6] << 2, 0, 3, true);
> >+ break;
> >+ case 3:
> >+ arm_set_cpu_on(3, s->regs[R_SRC_GPR8] << 2, 0, 3, true);
> >+ break;
> >+ default:
> >+ g_assert_not_reached();
> >+ break;
> >+ }
> >+}
> >+
> >+static void imx8mp_src_realize(DeviceState *dev, Error **errp) {
> >+ FslImx8mpSrcState *s = IMX8MP_SRC(dev);
> >+
> >+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx8mp_src_ops, s,
> >+ TYPE_IMX8MP_SRC, 0x1000);
> >+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); }
> >+
> >+static const VMStateDescription imx8mp_src_vmstate = {
> >+ .name = TYPE_IMX8MP_SRC,
> >+ .version_id = 1,
> >+ .minimum_version_id = 1,
> >+ .fields = (const VMStateField[]) {
> >+ VMSTATE_UINT32_ARRAY(regs, FslImx8mpSrcState,
> FSL_IMX8MP_SRC_NUM_REGS),
> >+ VMSTATE_END_OF_LIST()
> >+ },
> >+};
> >+
> >+static const Property imx8mp_src_properties[] = {
> >+ DEFINE_PROP_UINT8("boot-mode", FslImx8mpSrcState, boot_mode, 0),
> >+};
>
> This property, and hence the boot_mode attribute, is neither used nor useful
> for now. Let's remove both.
>
Yes. will clean it up as part of v2.
> Best regards,
> Bernhard
>
> >+
> >+static void imx8mp_src_class_init(ObjectClass *klass, const void
> >+*data) {
> >+ DeviceClass *dc = DEVICE_CLASS(klass);
> >+
> >+ device_class_set_legacy_reset(dc, imx8mp_src_reset);
> >+ dc->realize = imx8mp_src_realize;
> >+ dc->vmsd = &imx8mp_src_vmstate;
> >+ device_class_set_props(dc, imx8mp_src_properties);
> >+ dc->desc = "i.MX 8M Plus System Reset Controller"; }
> >+
> >+static const TypeInfo imx8mp_src_types[] = {
> >+ {
> >+ .name = TYPE_IMX8MP_SRC,
> >+ .parent = TYPE_SYS_BUS_DEVICE,
> >+ .instance_size = sizeof(FslImx8mpSrcState),
> >+ .class_init = imx8mp_src_class_init,
> >+ },
> >+};
> >+
> >+DEFINE_TYPES(imx8mp_src_types)
> >diff --git a/hw/misc/meson.build b/hw/misc/meson.build index
> >67dd1a98e5..174aed40b6 100644
> >--- a/hw/misc/meson.build
> >+++ b/hw/misc/meson.build
> >@@ -61,6 +61,7 @@ system_ss.add(when:
> 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'
> > system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true:
> >files('imx8mp_ccm.c'))
> > system_ss.add(when: 'CONFIG_FSL_IMX8MP_GPC', if_true:
> >files('imx8mp_gpc.c'))
> > system_ss.add(when: 'CONFIG_FSL_IMX8MP_GPR', if_true:
> >files('imx8mp_gpr.c'))
> >+system_ss.add(when: 'CONFIG_FSL_IMX8MP_SRC', if_true:
> >+files('imx8mp_src.c'))
> > system_ss.add(when: 'CONFIG_IMX', if_true: files(
> > 'imx25_ccm.c',
> > 'imx31_ccm.c',
> >diff --git a/hw/misc/trace-events b/hw/misc/trace-events index
> >b88accc437..080e79787c 100644
> >--- a/hw/misc/trace-events
> >+++ b/hw/misc/trace-events
> >@@ -129,6 +129,11 @@ imx7_gpr_write(uint64_t offset, uint64_t value)
> >"addr 0x%08" PRIx64 "value 0x%08 imx7_snvs_read(uint64_t offset,
> uint64_t value, unsigned size) "i.MX SNVS read: offset 0x%08" PRIx64 " value
> 0x%08" PRIx64 " size %u"
> > imx7_snvs_write(uint64_t offset, uint64_t value, unsigned size) "i.MX SNVS
> write: offset 0x%08" PRIx64 " value 0x%08" PRIx64 " size %u"
> >
> >+# imx8mp_src.c
> >+fsl_imx8mp_src_read(uint64_t offset, const char *reg_name, uint32_t
> >+value) "[0x%" PRIx64 "%s] <- 0x%" PRIx32 fsl_imx8mp_src_write(uint64_t
> >+offset, const char *reg_name, uint64_t value) "[0x%" PRIx64 "%s] <-
> >+0x%" PRIx64 fsl_imx8mp_src_clear_reset_bit(const char *reg_name,
> >+uint32_t value) "reg[%s] <= 0x%" PRIx32
> >+
> > # mos6522.c
> > mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d"
> > mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta)
> >"latch=%d counter=0x%"PRIx64 " delta_next=0x%"PRIx64 diff --git
> >a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index
> >b3aca1f692..c6c133cc05 100644
> >--- a/include/hw/arm/fsl-imx8mp.h
> >+++ b/include/hw/arm/fsl-imx8mp.h
> >@@ -19,6 +19,7 @@
> > #include "hw/misc/imx8mp_ccm.h"
> > #include "hw/misc/imx8mp_gpc.h"
> > #include "hw/misc/imx8mp_gpr.h"
> >+#include "hw/misc/imx8mp_src.h"
> > #include "hw/net/imx_fec.h"
> > #include "hw/core/or-irq.h"
> > #include "hw/pci-host/designware.h"
> >@@ -64,6 +65,7 @@ struct FslImx8mpState {
> > IMX8MPAnalogState analog;
> > IMX7SNVSState snvs;
> > IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
> >+ FslImx8mpSrcState src;
> > IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
> > IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
> > IMXFECState enet;
> >diff --git a/include/hw/misc/imx8mp_src.h
> >b/include/hw/misc/imx8mp_src.h new file mode 100644 index
> >0000000000..9905d217b8
> >--- /dev/null
> >+++ b/include/hw/misc/imx8mp_src.h
> >@@ -0,0 +1,32 @@
> >+/*
> >+ * i.MX 8M Plus System Reset Controller
> >+ *
> >+ * Copyright (c) 2025 Bernhard Beschow <[email protected]>
> >+ *
> >+ * SPDX-License-Identifier: GPL-2.0-or-later */
> >+
> >+#ifndef FSL_IMX8MP_SRC_H
> >+#define FSL_IMX8MP_SRC_H
> >+
> >+#include "hw/core/sysbus.h"
> >+#include "system/memory.h"
> >+#include "qom/object.h"
> >+
> >+#define TYPE_IMX8MP_SRC "fsl-imx8mp-src"
> >+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpSrcState, IMX8MP_SRC)
> >+
> >+#define FSL_IMX8MP_SRC_NUM_REGS (0x100 / 4)
> >+
> >+struct FslImx8mpSrcState {
> >+ SysBusDevice parent_obj;
> >+
> >+ MemoryRegion iomem;
> >+
> >+ uint32_t regs[FSL_IMX8MP_SRC_NUM_REGS];
> >+ uint8_t boot_mode;
> >+};
> >+
> >+void imx8mp_src_start_cpu(FslImx8mpSrcState *s, int cpuid);
> >+
> >+#endif /* FSL_IMX8MP_SRC_H */