From: Bernhard Beschow <[email protected]> Add emulation of the i.MX8MP System Reset Controller. 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]> Signed-off-by: Gaurav Sharma <[email protected]> --- docs/system/arm/imx8m.rst | 5 +- hw/arm/Kconfig | 1 + hw/arm/fsl-imx8mp.c | 10 + hw/misc/Kconfig | 3 + hw/misc/imx8mp_src.c | 411 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/misc/trace-events | 5 + include/hw/arm/fsl-imx8mp.h | 2 + include/hw/misc/imx8mp_src.h | 52 +++++ 9 files changed, 488 insertions(+), 2 deletions(-) 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 7813469154..38f4e31443 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -26,8 +26,9 @@ following devices: * 6 General Purpose Timers * Secure Non-Volatile Storage (SNVS) including an RTC * Clock Tree - * General Power Controller (GPC) - * General Purpose Register (GPR) + * General Power Controller + * General Purpose Register + * System Reset Controller Boot options ------------ diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7b7378110c..2ab57b7c53 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -596,6 +596,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 0c61582a27..274b44794a 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); @@ -431,6 +433,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; @@ -750,6 +759,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 5c2945200e..d9e904ae2f 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..ee540d83a6 --- /dev/null +++ b/hw/misc/imx8mp_src.c @@ -0,0 +1,411 @@ +/* + * 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/misc/imx8mp_gpr.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/resettable.h" +#include "hw/core/registerfields.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "system/address-spaces.h" +#include "target/arm/arm-powerctl.h" +#include "target/arm/cpu.h" +#include "trace.h" + +REG32(SRC_SCR, 0x0000) + +REG32(SRC_A53RCR0, 0x0004) + +REG32(SRC_A53RCR1, 0x0008) + +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) + +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 uint32_t imx8mp_src_cm7_vbase(FslImx8mpSrcState *s) +{ + uint32_t gpr6 = s->gpr ? s->gpr->gpr[IOMUXC_GPR_GPR6] : 0; + uint32_t vbase = gpr6 & 0xffffff80; + + if (vbase == 0) { + uint32_t pc_le = 0, pc; + + address_space_read(&address_space_memory, + IMX8MP_ITCM_BASE + 4, + MEMTXATTRS_UNSPECIFIED, &pc_le, sizeof(pc_le)); + pc = le32_to_cpu(pc_le); + if (pc != 0 && pc != UINT32_MAX && (pc & 1)) { + vbase = 0; /* valid Thumb vector — boot from ITCM alias at 0x0 */ + } else { + vbase = s->cm7_vector_base; + } + } + return vbase; +} + +static void imx8mp_src_cm7_reset_run(CPUState *cpu, run_on_cpu_data data) +{ + FslImx8mpSrcState *s = data.host_ptr; + ARMCPU *m7 = ARM_CPU(cpu); + + m7->init_nsvtor = imx8mp_src_cm7_vbase(s); + arm_set_cpu_on_and_reset(arm_cpu_mp_affinity(m7)); +} + +static void imx8mp_src_cm7_off(CPUState *cpu, run_on_cpu_data data) +{ + arm_set_cpu_off(arm_cpu_mp_affinity(ARM_CPU(cpu))); +} + +static void imx8mp_src_cm7_reset_request(FslImx8mpSrcState *s) +{ + if (!s->cm7_cpu) { + return; + } + if (s->cm7_cpuwait) { + async_run_on_cpu(CPU(s->cm7_cpu), imx8mp_src_cm7_off, + RUN_ON_CPU_HOST_PTR(s)); + } else { + async_run_on_cpu(CPU(s->cm7_cpu), imx8mp_src_cm7_reset_run, + RUN_ON_CPU_HOST_PTR(s)); + } +} + +/* + * React to a CPUWAIT level change. + * level=1: CPUWAIT cleared (run); level=0: CPUWAIT set (halt). + */ +static void imx8mp_src_cm7_set_cpuwait(FslImx8mpSrcState *s, bool run) +{ + if (!s->cm7_cpu) { + return; + } + if (run) { + CPUState *cpu = CPU(s->cm7_cpu); + if (cpu->halted) { + async_run_on_cpu(cpu, imx8mp_src_cm7_reset_run, + RUN_ON_CPU_HOST_PTR(s)); + } + } else { + async_run_on_cpu(CPU(s->cm7_cpu), imx8mp_src_cm7_off, + RUN_ON_CPU_HOST_PTR(s)); + } +} + +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; + + if (reg < FSL_IMX8MP_SRC_NUM_REGS) { + value = s->regs[reg]; + } else { + qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX8MP_SRC, __func__, + offset); + } + + trace_fsl_imx8mp_src_read(offset, fsl_imx8mp_src_reg_name(reg), value); + + return value; +} + +static void fsl_imx8mp_src_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + FslImx8mpSrcState *s = opaque; + const uint32_t reg = offset / 4; + + if (reg >= FSL_IMX8MP_SRC_NUM_REGS) { + qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX8MP_SRC, __func__, + offset); + goto done; + } + + switch (reg) { + case R_SRC_M7RCR: { + uint32_t old_value = s->regs[reg]; + uint32_t new_value = (uint32_t)value; + uint32_t changed; + bool reset_pulse = false; + + /* + * SW_M7C_RST (bit1) is self-clearing on real HW: writing 1 triggers + * an M7 core-reset pulse and the bit reads back 0. + */ + if (new_value & SRC_M7RCR_SW_M7C_RST) { + reset_pulse = true; + new_value &= ~SRC_M7RCR_SW_M7C_RST; + } + + s->regs[reg] = new_value; + changed = old_value ^ new_value; + + if (reset_pulse) { + /* Self-clearing core-reset pulse -> reset (honoring CPUWAIT). */ + imx8mp_src_cm7_reset_request(s); + break; + } + + if (changed & SRC_M7RCR_SW_M7C_NON_SCLR_RST) { + bool held = new_value & SRC_M7RCR_SW_M7C_NON_SCLR_RST; + /* NON_SCLR latch: 1 = hold in reset (off); 0 = release. */ + if (held) { + if (s->cm7_cpu) { + async_run_on_cpu(CPU(s->cm7_cpu), imx8mp_src_cm7_off, + RUN_ON_CPU_HOST_PTR(s)); + } + } else { + imx8mp_src_cm7_reset_request(s); + } + } + break; + } + default: + s->regs[reg] = value; + break; + } + +done: + + 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, + }, +}; + +static void imx8mp_src_reset_enter(Object *obj, ResetType type) +{ + FslImx8mpSrcState *s = IMX8MP_SRC(obj); + FslImx8mpSrcClass *sc = IMX8MP_SRC_GET_CLASS(obj); + + if (sc->parent_phases.enter) { + sc->parent_phases.enter(obj, type); + } + + memset(s->regs, 0, sizeof(s->regs)); + + /* + * Default CM7 STOP state for Linux imx-rproc MMIO mode detection. + */ + s->regs[R_SRC_M7RCR] = 0x000000A8; +} + +static void imx8mp_src_cm7_cpuwait_handler(void *opaque, int n, int level) +{ + FslImx8mpSrcState *s = opaque; + + s->cm7_cpuwait = !level; + imx8mp_src_cm7_set_cpuwait(s, (bool)level); +} + +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); + qdev_init_gpio_in_named(dev, imx8mp_src_cm7_cpuwait_handler, "cm7-cpuwait", 1); +} + +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_UINT32("cm7-vector-base", FslImx8mpSrcState, cm7_vector_base, + 0x80000000), + DEFINE_PROP_LINK("cm7-cpu", FslImx8mpSrcState, cm7_cpu, + TYPE_ARM_CPU, ARMCPU *), + DEFINE_PROP_LINK("gpr", FslImx8mpSrcState, gpr, + TYPE_IMX8MP_GPR, IMX8MPGPRState *), +}; + +static void imx8mp_src_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + FslImx8mpSrcClass *sc = IMX8MP_SRC_CLASS(klass); + + resettable_class_set_parent_phases(rc, + imx8mp_src_reset_enter, + NULL, + NULL, + &sc->parent_phases); + 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_size = sizeof(FslImx8mpSrcClass), + .class_init = imx8mp_src_class_init, + }, +}; + +DEFINE_TYPES(imx8mp_src_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 5eda094d34..79954586e8 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -64,6 +64,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 6db4934dc5..6239200f37 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -131,6 +131,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 8f07b2a270..87c83c3f0e 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/flexcan.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" @@ -66,6 +67,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..d888410539 --- /dev/null +++ b/include/hw/misc/imx8mp_src.h @@ -0,0 +1,52 @@ +/* + * 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/resettable.h" +#include "hw/core/sysbus.h" +#include "system/memory.h" +#include "qom/object.h" +#include "target/arm/cpu-qom.h" + +typedef struct IMX8MPGPRState IMX8MPGPRState; + +#define TYPE_IMX8MP_SRC "fsl-imx8mp-src" +OBJECT_DECLARE_TYPE(FslImx8mpSrcState, FslImx8mpSrcClass, IMX8MP_SRC) + +struct FslImx8mpSrcClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +/* + * ITCM base in the A53/system-bus view. + * Used by SRC to probe for a valid M7 reset vector when GPR6 == 0. + */ +#define IMX8MP_ITCM_BASE 0x007E0000U + +#define FSL_IMX8MP_SRC_NUM_REGS (0x100 / 4) + +#define SRC_M7RCR_SW_M7C_NON_SCLR_RST (1u << 0) /* latching core reset */ +#define SRC_M7RCR_SW_M7C_RST (1u << 1) /* self-clearing pulse */ + +struct FslImx8mpSrcState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + + uint32_t regs[FSL_IMX8MP_SRC_NUM_REGS]; + + ARMCPU *cm7_cpu; + IMX8MPGPRState *gpr; + bool cm7_cpuwait; + uint32_t cm7_vector_base; +}; + +#endif /* FSL_IMX8MP_SRC_H */ -- 2.34.1
