From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213517463529.3161015965042; Tue, 19 May 2026 10:58:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgm-0008PP-6c; Tue, 19 May 2026 13:57:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOga-0008Mw-6x for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:57 -0400 Received: from inva020.nxp.com ([92.121.34.13]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgR-0002g8-MS for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:51 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 88D4B1A3C01; Tue, 19 May 2026 19:56:40 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 404A51A2703; Tue, 19 May 2026 19:56:40 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 1AFF81800093; Wed, 20 May 2026 01:56:39 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 1/7] hw/misc: Add i.MX8MP GPC (General Power Controller) IP Date: Tue, 19 May 2026 23:26:29 +0530 Message-Id: <20260519175635.3245229-2-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.13; envelope-from=gaurav.sharma_7@nxp.com; helo=inva020.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213519830154100 Content-Type: text/plain; charset="utf-8" Add a minimal emulation of the i.MX8MP General Power Controller (GPC) and wire it into the i.MX8MP SoC model. The GPC manages power domains and clock-gating behavior for cores on the i.= MX8MP SoC. This is needed to support AMP boot of the Cortex-M7 core from Linux. Signed-off-by: Gaurav Sharma --- docs/system/arm/imx8m.rst | 1 + hw/arm/Kconfig | 1 + hw/arm/fsl-imx8mp.c | 10 +++ hw/misc/Kconfig | 3 + hw/misc/imx8mp_gpc.c | 124 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 2 + include/hw/misc/imx8mp_gpc.h | 34 ++++++++++ 8 files changed, 176 insertions(+) create mode 100644 hw/misc/imx8mp_gpc.c create mode 100644 include/hw/misc/imx8mp_gpc.h diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst index afbc33b2f4..00325c2413 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -25,6 +25,7 @@ following devices: * 6 General Purpose Timers * Secure Non-Volatile Storage (SNVS) including an RTC * Clock Tree + * General Power Controller (GPC) =20 Boot options ------------ diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 5b198402d5..83293ff8a7 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -600,6 +600,7 @@ config FSL_IMX8MP select ARM_GIC select FSL_IMX8MP_ANALOG select FSL_IMX8MP_CCM + select FSL_IMX8MP_GPC select IMX select IMX_FEC select IMX_I2C diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index 7c03ed3c34..d68d816bf1 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -204,6 +204,8 @@ static void fsl_imx8mp_init(Object *obj) =20 object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS); =20 + object_initialize_child(obj, "gpc", &s->gpc, TYPE_IMX8MP_GPC); + for (i =3D 0; i < FSL_IMX8MP_NUM_UARTS; i++) { g_autofree char *name =3D g_strdup_printf("uart%d", i + 1); object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL); @@ -422,6 +424,13 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) qdev_get_gpio_in(gicdev, serial_table[i].irq)); } =20 + /* GPC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpc), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpc), 0, + fsl_imx8mp_memmap[FSL_IMX8MP_GPC].addr); + /* GPTs */ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2, &error_abort); @@ -686,6 +695,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) case FSL_IMX8MP_CCM: case FSL_IMX8MP_GIC_DIST: case FSL_IMX8MP_GIC_REDIST: + case FSL_IMX8MP_GPC: case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5: case FSL_IMX8MP_GPT1 ... FSL_IMX8MP_GPT6: case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3: diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 99bdf09219..e707a40f8c 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -101,6 +101,9 @@ config FSL_IMX8MP_ANALOG config FSL_IMX8MP_CCM bool =20 +config FSL_IMX8MP_GPC + bool + config STM32_RCC bool =20 diff --git a/hw/misc/imx8mp_gpc.c b/hw/misc/imx8mp_gpc.c new file mode 100644 index 0000000000..bbe29d33e8 --- /dev/null +++ b/hw/misc/imx8mp_gpc.c @@ -0,0 +1,124 @@ +/* + * i.MX 8M Plus GPC(General Power Controller) + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "qemu/osdep.h" +#include "hw/misc/imx8mp_gpc.h" +#include "migration/vmstate.h" + +#define IMX8MP_GPC_ACK_BIT31 0x80000000u + +#define IMX8MP_GPC_STAT_BUSY_BIT (1u << 5) + +static uint64_t imx8mp_gpc_read(void *opaque, hwaddr offset, unsigned size) +{ + IMX8MPGPCState *s =3D opaque; + uint32_t idx =3D offset >> 2; + + if (size !=3D 4 || (offset & 3) || offset >=3D IMX8MP_GPC_MMIO_SIZE) { + return 0; + } + + /* + * CM7 firmware polls GPC+0xD8 and loops while bit5 is 1. + * Emulate "ready" by forcing bit5 low on reads. + */ + if (idx =3D=3D IMX8MP_GPC_PU_PGC_SW_PUP_REQ) { + return s->regs[idx] & ~IMX8MP_GPC_STAT_BUSY_BIT; + } + + return s->regs[idx]; +} + +static void imx8mp_gpc_write(void *opaque, hwaddr offset, uint64_t value, = unsigned size) +{ + IMX8MPGPCState *s =3D opaque; + uint32_t idx =3D offset >> 2; + + if (size !=3D 4 || (offset & 3) || offset >=3D IMX8MP_GPC_MMIO_SIZE) { + return; + } + + /* + * CM7 firmware sets bit15 in GPC+0x190 and then polls until the value + * becomes negative (bit31 set). Emulate the hardware ACK by forcing + * bit31 high on writes to this register. + */ + if (idx =3D=3D IMX8MP_GPC_POLL_REG) { + s->regs[idx] =3D ((uint32_t)value) | IMX8MP_GPC_ACK_BIT31; + } else { + s->regs[idx] =3D (uint32_t)value; + } + +} + +static const MemoryRegionOps imx8mp_gpc_ops =3D { + .read =3D imx8mp_gpc_read, + .write =3D imx8mp_gpc_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static void imx8mp_gpc_reset(DeviceState *dev) +{ + IMX8MPGPCState *s =3D IMX8MP_GPC(dev); + memset(s->regs, 0, sizeof(s->regs)); + + /* + * Unblock CM7 firmware polling loop: return a negative value at 0x190. + * Any value with bit31 set works. + */ + s->regs[IMX8MP_GPC_POLL_REG] =3D IMX8MP_GPC_ACK_BIT31; + + /* Default "ready" for the earlier poll at 0xD8: ensure busy bit is cl= ear */ + s->regs[IMX8MP_GPC_PU_PGC_SW_PUP_REQ] =3D 0x00000000; + +} + +static const VMStateDescription imx8mp_gpc_vmstate =3D { + .name =3D TYPE_IMX8MP_GPC, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, IMX8MPGPCState, IMX8MP_GPC_MMIO_SIZE / = 4), + VMSTATE_END_OF_LIST() + }, +}; + +static void imx8mp_gpc_init(Object *obj) +{ + IMX8MPGPCState *s =3D IMX8MP_GPC(obj); + memory_region_init_io(&s->iomem, obj, &imx8mp_gpc_ops, s, + TYPE_IMX8MP_GPC, IMX8MP_GPC_MMIO_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void imx8mp_gpc_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + device_class_set_legacy_reset(dc, imx8mp_gpc_reset); + dc->vmsd =3D &imx8mp_gpc_vmstate; + dc->desc =3D "i.MX8MP GPC(General Power Controller)"; +} + +static const TypeInfo imx8mp_gpc_info[] =3D { + { + .name =3D TYPE_IMX8MP_GPC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(IMX8MPGPCState), + .instance_init =3D imx8mp_gpc_init, + .class_init =3D imx8mp_gpc_class_init, + } +}; + +DEFINE_TYPES(imx8mp_gpc_info); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index fa6a961ac9..512a539c6a 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -59,6 +59,7 @@ system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('e= ccmemctl.c')) system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', '= exynos4210_clk.c', 'exynos4210_rng.c')) system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_ana= log.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_IMX', if_true: files( 'imx25_ccm.c', 'imx31_ccm.c', diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index 3b6183ed1d..51630cfd3b 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -17,6 +17,7 @@ #include "hw/misc/imx7_snvs.h" #include "hw/misc/imx8mp_analog.h" #include "hw/misc/imx8mp_ccm.h" +#include "hw/misc/imx8mp_gpc.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" #include "hw/pci-host/designware.h" @@ -54,6 +55,7 @@ struct FslImx8mpState { =20 ARMCPU cpu[FSL_IMX8MP_NUM_CPUS]; GICv3State gic; + IMX8MPGPCState gpc; IMXGPTState gpt[FSL_IMX8MP_NUM_GPTS]; IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS]; IMX8MPCCMState ccm; diff --git a/include/hw/misc/imx8mp_gpc.h b/include/hw/misc/imx8mp_gpc.h new file mode 100644 index 0000000000..49a040e0c9 --- /dev/null +++ b/include/hw/misc/imx8mp_gpc.h @@ -0,0 +1,34 @@ +/* + * i.MX 8M Plus GPC(General Power Controller) + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef IMX8MP_GPC_H +#define IMX8MP_GPC_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define IMX8MP_GPC_MMIO_SIZE 0x1000 + +#define TYPE_IMX8MP_GPC "imx8mp.gpc" + +OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPGPCState, IMX8MP_GPC) + +enum IMX8MPGPCRegisters { + IMX8MP_GPC_PU_PGC_SW_PUP_REQ =3D 0x0D8 / 4, + IMX8MP_GPC_POLL_REG =3D 0x190 / 4, +}; + +struct IMX8MPGPCState { + SysBusDevice parent_obj; + MemoryRegion iomem; + uint32_t regs[IMX8MP_GPC_MMIO_SIZE / 4]; +}; + +#endif /* IMX8MP_GPC_H */ --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213511618816.9557996403432; Tue, 19 May 2026 10:58:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgj-0008OF-SC; Tue, 19 May 2026 13:57:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgV-0008M5-Qs for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:53 -0400 Received: from inva021.nxp.com ([92.121.34.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgR-0002gU-L4 for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:51 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 021C3203C16; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id AEBA1203C14; Tue, 19 May 2026 19:56:40 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7B06E180026F; Wed, 20 May 2026 01:56:39 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 2/7] hw/misc: Add GPR (General Purpose Register) IP to iMX8MP Date: Tue, 19 May 2026 23:26:30 +0530 Message-Id: <20260519175635.3245229-3-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.21; envelope-from=gaurav.sharma_7@nxp.com; helo=inva021.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213513488158500 Content-Type: text/plain; charset="utf-8" Add IOMUXC General Purpose Registers (GPR) IP and wire it into the i.MX8MP = SoC model. The GPR block provides system-level configuration registers on the i.MX8MP = SoC. It provides general purpose control bits and Cortex-M7 CPUWAIT gate needed = for AMP boot Signed-off-by: Gaurav Sharma --- docs/system/arm/imx8m.rst | 1 + hw/arm/Kconfig | 1 + hw/arm/fsl-imx8mp.c | 10 +++ hw/misc/Kconfig | 3 + hw/misc/imx8mp_gpr.c | 129 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 2 + include/hw/misc/imx8mp_gpr.h | 56 +++++++++++++++ 8 files changed, 203 insertions(+) create mode 100644 hw/misc/imx8mp_gpr.c create mode 100644 include/hw/misc/imx8mp_gpr.h diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst index 00325c2413..1e110bc810 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -26,6 +26,7 @@ following devices: * Secure Non-Volatile Storage (SNVS) including an RTC * Clock Tree * General Power Controller (GPC) + * General Purpose Register (GPR) =20 Boot options ------------ diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 83293ff8a7..9e4b71264a 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -601,6 +601,7 @@ config FSL_IMX8MP select FSL_IMX8MP_ANALOG select FSL_IMX8MP_CCM select FSL_IMX8MP_GPC + select FSL_IMX8MP_GPR select IMX select IMX_FEC select IMX_I2C diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index d68d816bf1..c4aafbdc1c 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -206,6 +206,8 @@ static void fsl_imx8mp_init(Object *obj) =20 object_initialize_child(obj, "gpc", &s->gpc, TYPE_IMX8MP_GPC); =20 + object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX8MP_GPR); + for (i =3D 0; i < FSL_IMX8MP_NUM_UARTS; i++) { g_autofree char *name =3D 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) sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpc), 0, fsl_imx8mp_memmap[FSL_IMX8MP_GPC].addr); =20 + /* GPR */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpr), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, + fsl_imx8mp_memmap[FSL_IMX8MP_IOMUXC_GPR].addr); + /* GPTs */ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2, &error_abort); @@ -701,6 +710,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3: case FSL_IMX8MP_ENET1: case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6: + case FSL_IMX8MP_IOMUXC_GPR: case FSL_IMX8MP_OCRAM: case FSL_IMX8MP_PCIE1: case FSL_IMX8MP_PCIE_PHY1: diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index e707a40f8c..7464788d82 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -104,6 +104,9 @@ config FSL_IMX8MP_CCM config FSL_IMX8MP_GPC bool =20 +config FSL_IMX8MP_GPR + bool + config STM32_RCC bool =20 diff --git a/hw/misc/imx8mp_gpr.c b/hw/misc/imx8mp_gpr.c new file mode 100644 index 0000000000..04d11cc1f9 --- /dev/null +++ b/hw/misc/imx8mp_gpr.c @@ -0,0 +1,129 @@ +/* + * i.MX 8M Plus IOMUXC GPR + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/imx8mp_gpr.h" +#include "hw/core/irq.h" +#include "migration/vmstate.h" + +#define IMX8MP_GPR22_OFF 0x58 +#define IMX8MP_GPR22_CM7_CPUWAIT_BIT (1u << 0) + +static inline void imx8mp_gpr_update_cm7_run(IMX8MPGPRState *s, uint32_t g= pr22) +{ + /* CPUWAIT=3D0 =3D> run, CPUWAIT=3D1 =3D> stop */ + bool run =3D ((gpr22 & IMX8MP_GPR22_CM7_CPUWAIT_BIT) =3D=3D 0); + qemu_set_irq(s->cm7_run_irq, run); +} + +static uint64_t imx8mp_gpr_read(void *opaque, hwaddr offset, unsigned size) +{ + IMX8MPGPRState *s =3D opaque; + + return s->gpr[offset >> 2]; +} + +static void imx8mp_gpr_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + IMX8MPGPRState *s =3D opaque; + + s->gpr[offset >> 2] =3D (uint32_t)value; + + /* Watch GPR22 bit0 (CM7_CPUWAIT) transitions */ + if (offset =3D=3D IMX8MP_GPR22_OFF) { + imx8mp_gpr_update_cm7_run(s, s->gpr[IMX8MP_GPR22_OFF >> 2]); + } + +} + +static const MemoryRegionOps imx8mp_gpr_ops =3D { + .read =3D imx8mp_gpr_read, + .write =3D imx8mp_gpr_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static void imx8mp_gpr_reset(DeviceState *dev) +{ + IMX8MPGPRState *s =3D IMX8MP_GPR(dev); + memset(s->gpr, 0, sizeof(s->gpr)); + + s->gpr[IOMUXC_GPR_GPR0] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR1] =3D 0x00010000; + s->gpr[IOMUXC_GPR_GPR2] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR3] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR4] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR5] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR6] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR7] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR8] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR9] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR10] =3D 0x00000008; + s->gpr[IOMUXC_GPR_GPR11] =3D 0x00000200; + s->gpr[IOMUXC_GPR_GPR12] =3D 0x00004000; + s->gpr[IOMUXC_GPR_GPR13] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR14] =3D 0x03494000; + s->gpr[IOMUXC_GPR_GPR15] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR16] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR17] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR18] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR19] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR20] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR21] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR22] =3D 0x00000001; + s->gpr[IOMUXC_GPR_GPR23] =3D 0x00000000; + s->gpr[IOMUXC_GPR_GPR24] =3D 0x00000000; + + /* Drive cm7_run_irq output to match reset value of CPUWAIT */ + imx8mp_gpr_update_cm7_run(s, s->gpr[IMX8MP_GPR22_OFF >> 2]); +} + +static const VMStateDescription imx8mp_gpr_vmstate =3D { + .name =3D TYPE_IMX8MP_GPR, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(gpr, IMX8MPGPRState, IOMUXC_GPR_MAX), + VMSTATE_END_OF_LIST() + }, +}; + +static void imx8mp_gpr_init(Object *obj) +{ + IMX8MPGPRState *s =3D IMX8MP_GPR(obj); + memory_region_init_io(&s->mmio, obj, &imx8mp_gpr_ops, s, + TYPE_IMX8MP_GPR, sizeof(s->gpr)); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->cm7_run_irq); +} + +static void imx8mp_gpr_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + device_class_set_legacy_reset(dc, imx8mp_gpr_reset); + dc->vmsd =3D &imx8mp_gpr_vmstate; + dc->desc =3D "i.MX8MP IOMUXC GPR"; +} + +static const TypeInfo imx8mp_gpr_info[] =3D { + { + .name =3D TYPE_IMX8MP_GPR, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(IMX8MPGPRState), + .instance_init =3D imx8mp_gpr_init, + .class_init =3D imx8mp_gpr_class_init, + } +}; + +DEFINE_TYPES(imx8mp_gpr_info); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 512a539c6a..67dd1a98e5 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -60,6 +60,7 @@ system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exy= nos4210_pmu.c', 'exynos system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_ana= log.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_IMX', if_true: files( 'imx25_ccm.c', 'imx31_ccm.c', diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index 51630cfd3b..b3aca1f692 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -18,6 +18,7 @@ #include "hw/misc/imx8mp_analog.h" #include "hw/misc/imx8mp_ccm.h" #include "hw/misc/imx8mp_gpc.h" +#include "hw/misc/imx8mp_gpr.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" #include "hw/pci-host/designware.h" @@ -56,6 +57,7 @@ struct FslImx8mpState { ARMCPU cpu[FSL_IMX8MP_NUM_CPUS]; GICv3State gic; IMX8MPGPCState gpc; + IMX8MPGPRState gpr; IMXGPTState gpt[FSL_IMX8MP_NUM_GPTS]; IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS]; IMX8MPCCMState ccm; diff --git a/include/hw/misc/imx8mp_gpr.h b/include/hw/misc/imx8mp_gpr.h new file mode 100644 index 0000000000..4a0c7d8583 --- /dev/null +++ b/include/hw/misc/imx8mp_gpr.h @@ -0,0 +1,56 @@ +/* + * i.MX 8M Plus IOMUXC GPR + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef IMX8MP_GPR_H +#define IMX8MP_GPR_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_IMX8MP_GPR "imx8mp.gpr" +OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPGPRState, IMX8MP_GPR) + +enum IMX8MPGPRRegisters { + IOMUXC_GPR_GPR0 =3D 0x000 / 4, + IOMUXC_GPR_GPR1 =3D 0x004 / 4, + IOMUXC_GPR_GPR2 =3D 0x008 / 4, + IOMUXC_GPR_GPR3 =3D 0x00C / 4, + IOMUXC_GPR_GPR4 =3D 0x010 / 4, + IOMUXC_GPR_GPR5 =3D 0x014 / 4, + IOMUXC_GPR_GPR6 =3D 0x018 / 4, + IOMUXC_GPR_GPR7 =3D 0x01C / 4, + IOMUXC_GPR_GPR8 =3D 0x020 / 4, + IOMUXC_GPR_GPR9 =3D 0x024 / 4, + IOMUXC_GPR_GPR10 =3D 0x028 / 4, + IOMUXC_GPR_GPR11 =3D 0x02C / 4, + IOMUXC_GPR_GPR12 =3D 0x030 / 4, + IOMUXC_GPR_GPR13 =3D 0x034 / 4, + IOMUXC_GPR_GPR14 =3D 0x038 / 4, + IOMUXC_GPR_GPR15 =3D 0x03C / 4, + IOMUXC_GPR_GPR16 =3D 0x040 / 4, + IOMUXC_GPR_GPR17 =3D 0x044 / 4, + IOMUXC_GPR_GPR18 =3D 0x048 / 4, + IOMUXC_GPR_GPR19 =3D 0x04C / 4, + IOMUXC_GPR_GPR20 =3D 0x050 / 4, + IOMUXC_GPR_GPR21 =3D 0x054 / 4, + IOMUXC_GPR_GPR22 =3D 0x058 / 4, + IOMUXC_GPR_GPR23 =3D 0x05C / 4, + IOMUXC_GPR_GPR24 =3D 0x060 / 4, + IOMUXC_GPR_MAX, +}; + +struct IMX8MPGPRState { + SysBusDevice parent_obj; + MemoryRegion mmio; + qemu_irq cm7_run_irq; + uint32_t gpr[IOMUXC_GPR_MAX]; +}; + +#endif /* IMX8MP_GPR_H */ --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213454353294.92755011303257; Tue, 19 May 2026 10:57:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgg-0008NR-Lr; Tue, 19 May 2026 13:57:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgU-0008Lx-K3 for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:51 -0400 Received: from inva021.nxp.com ([92.121.34.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgP-0002gC-Fj for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:50 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 2488B203C14; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 96591202769; Tue, 19 May 2026 19:56:40 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id E7AE718002FB; Wed, 20 May 2026 01:56:39 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com Subject: [PATCHv1 3/7] hw/misc: Add SRC (System Reset Controller) to i.MX8MP Date: Tue, 19 May 2026 23:26:31 +0530 Message-Id: <20260519175635.3245229-4-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.21; envelope-from=gaurav.sharma_7@nxp.com; helo=inva021.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213457142154100 Content-Type: text/plain; charset="utf-8" From: Bernhard Beschow 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 --- 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) =20 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) =20 object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX8MP_GPR); =20 + object_initialize_child(obj, "src", &s->src, TYPE_IMX8MP_SRC); + for (i =3D 0; i < FSL_IMX8MP_NUM_UARTS; i++) { g_autofree char *name =3D 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)); } =20 + /* 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 =20 +config FSL_IMX8MP_SRC + bool + config STM32_RCC bool =20 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 + * + * 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) + +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 =3D opaque; + const uint32_t reg =3D offset / 4; + uint32_t value =3D 0; + + switch (reg) { + default: + if (reg < FSL_IMX8MP_SRC_NUM_REGS) { + value =3D 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 un= til + * the work is completed. + */ + +struct FslImx8mpSrcResetInfo { + FslImx8mpSrcState *s; + int reset_bit; +}; + + +static void imx8mp_src_reset(DeviceState *dev) +{ + FslImx8mpSrcState *s =3D IMX8MP_SRC(dev); + + memset(s->regs, 0, sizeof(s->regs)); + + /* Primary A53 core enabled by default */ + s->regs[R_SRC_A53RCR1] =3D 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. + */ + s->regs[R_SRC_M7RCR] =3D 0x0000000A; + + /* Boot mode field (kept from previous realize-time init) */ + s->regs[R_SRC_SBMR2] =3D FIELD_DP32(s->regs[R_SRC_SBMR2], SRC_SBMR2, + IPP_BOOT_MODE, s->boot_mode); +} + + +static void fsl_imx8mp_src_clear_reset_bit(CPUState *cpu, run_on_cpu_data = data) +{ + struct FslImx8mpSrcResetInfo *ri =3D data.host_ptr; + FslImx8mpSrcState *s =3D ri->s; + + assert(bql_locked()); + + s->regs[R_SRC_A53RCR0] =3D 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_shif= t) +{ + struct FslImx8mpSrcResetInfo *ri; + CPUState *cpu =3D arm_get_cpu_by_id(cpuid); + + if (!cpu) { + return; + } + + ri =3D g_new(struct FslImx8mpSrcResetInfo, 1); + ri->s =3D s; + ri->reset_bit =3D 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 val= ue, + unsigned size) +{ + FslImx8mpSrcState *s =3D opaque; + const uint32_t reg =3D offset / 4; + unsigned long change_mask; + + change_mask =3D 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] =3D 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] =3D value; + break; + default: + if (reg < FSL_IMX8MP_SRC_NUM_REGS) { + s->regs[reg] =3D 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 =3D { + .read =3D fsl_imx8mp_src_read, + .write =3D fsl_imx8mp_src_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + /* + * 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 =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +void imx8mp_src_start_cpu(FslImx8mpSrcState *s, int cpuid) +{ + 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 =3D 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 =3D { + .name =3D TYPE_IMX8MP_SRC, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, FslImx8mpSrcState, FSL_IMX8MP_SRC_NUM_R= EGS), + VMSTATE_END_OF_LIST() + }, +}; + +static const Property imx8mp_src_properties[] =3D { + DEFINE_PROP_UINT8("boot-mode", FslImx8mpSrcState, boot_mode, 0), +}; + +static void imx8mp_src_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, imx8mp_src_reset); + dc->realize =3D imx8mp_src_realize; + dc->vmsd =3D &imx8mp_src_vmstate; + device_class_set_props(dc, imx8mp_src_properties); + dc->desc =3D "i.MX 8M Plus System Reset Controller"; +} + +static const TypeInfo imx8mp_src_types[] =3D { + { + .name =3D TYPE_IMX8MP_SRC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(FslImx8mpSrcState), + .class_init =3D 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" =20 +# 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] <=3D 0x%" PRIx32 + # mos6522.c mos6522_set_counter(int index, unsigned int val) "T%d.counter=3D%d" mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch= =3D%d counter=3D0x%"PRIx64 " delta_next=3D0x%"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 + * + * 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 */ --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213496769278.23785736861964; Tue, 19 May 2026 10:58:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgk-0008Ov-LE; Tue, 19 May 2026 13:57:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOga-0008Mt-5A for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:57 -0400 Received: from inva020.nxp.com ([92.121.34.13]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgR-0002gF-L5 for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:55 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 47F5D1A4432; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 010B91A2703; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 52B02180217B; Wed, 20 May 2026 01:56:40 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 4/7] hw/misc: Add MU (Messaging Unit) IP to i.MX8MP device model Date: Tue, 19 May 2026 23:26:32 +0530 Message-Id: <20260519175635.3245229-5-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.13; envelope-from=gaurav.sharma_7@nxp.com; helo=inva020.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213497197158500 Content-Type: text/plain; charset="utf-8" Add emulation of the Messaging Unit and wire it into the i.MX8MP SoC model. The MU provides inter-processor communication between the Cortex-A53 and Cortex-M7 cores on the i.MX8MP SoC. It is used by the Linux remoteproc framework as a mailbox for lifecycle management and message passing with the Cortex-M7 in an AMP configuration. Signed-off-by: Gaurav Sharma --- docs/system/arm/imx8m.rst | 1 + hw/arm/Kconfig | 1 + hw/arm/fsl-imx8mp.c | 39 +++++ hw/misc/Kconfig | 3 + hw/misc/imx8mp_mu.c | 308 ++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 10 ++ include/hw/misc/imx8mp_mu.h | 53 +++++++ 8 files changed, 416 insertions(+) create mode 100644 hw/misc/imx8mp_mu.c create mode 100644 include/hw/misc/imx8mp_mu.h diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst index 49c100c4b1..c482bf180f 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -28,6 +28,7 @@ following devices: * General Power Controller (GPC) * General Purpose Register (GPR) * System Reset Controller (SRC) + * Messaging Unit (MU) =20 Boot options ------------ diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 8e89e30c45..977e6a8e49 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -603,6 +603,7 @@ config FSL_IMX8MP select FSL_IMX8MP_GPC select FSL_IMX8MP_GPR select FSL_IMX8MP_SRC + select FSL_IMX8MP_MU select IMX select IMX_FEC select IMX_I2C diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index 168fcb0334..eec83deced 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -210,6 +210,16 @@ static void fsl_imx8mp_init(Object *obj) =20 object_initialize_child(obj, "src", &s->src, TYPE_IMX8MP_SRC); =20 + /* + * MU instances: MU_1..MU_3, each with A/B endpoints + */ + for (i =3D 0; i < FSL_IMX8MP_NUM_MU; i++) { + g_autofree char *name_a =3D g_strdup_printf("mu%d_a", i + 1); + g_autofree char *name_b =3D g_strdup_printf("mu%d_b", i + 1); + object_initialize_child(obj, name_a, &s->mu[i].a, TYPE_IMX8MP_MU); + object_initialize_child(obj, name_b, &s->mu[i].b, TYPE_IMX8MP_MU); + } + for (i =3D 0; i < FSL_IMX8MP_NUM_UARTS; i++) { g_autofree char *name =3D g_strdup_printf("uart%d", i + 1); object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL); @@ -495,6 +505,34 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) } } =20 + /* MU */ + static const int mu_mmio_map[FSL_IMX8MP_NUM_MU][2] =3D { + [0] =3D { FSL_IMX8MP_MU_1_A, FSL_IMX8MP_MU_1_B }, + [1] =3D { FSL_IMX8MP_MU_2_A, FSL_IMX8MP_MU_2_B }, + [2] =3D { FSL_IMX8MP_MU_3_A, FSL_IMX8MP_MU_3_B }, + }; + + for (i =3D 0; i < FSL_IMX8MP_NUM_MU; i++) { + hwaddr addr_a =3D fsl_imx8mp_memmap[mu_mmio_map[i][0]].addr; + hwaddr addr_b =3D fsl_imx8mp_memmap[mu_mmio_map[i][1]].addr; + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mu[i].a), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mu[i].a), 0, addr_a); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mu[i].b), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mu[i].b), 0, addr_b); + + s->mu[i].a.peer =3D &s->mu[i].b; + s->mu[i].b.peer =3D &s->mu[i].a; + } + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->mu[0].a), 0, + qdev_get_gpio_in(gicdev, FSL_IMX8MP_MU1_A_IRQ)); + /* I2Cs */ for (i =3D 0; i < FSL_IMX8MP_NUM_I2CS; i++) { struct { @@ -720,6 +758,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) case FSL_IMX8MP_ENET1: case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6: case FSL_IMX8MP_IOMUXC_GPR: + case FSL_IMX8MP_MU_1_A ... FSL_IMX8MP_MU_3_B: case FSL_IMX8MP_OCRAM: case FSL_IMX8MP_PCIE1: case FSL_IMX8MP_PCIE_PHY1: diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 185bd6f62a..144a3f7d67 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -110,6 +110,9 @@ config FSL_IMX8MP_GPR config FSL_IMX8MP_SRC bool =20 +config FSL_IMX8MP_MU + bool + config STM32_RCC bool =20 diff --git a/hw/misc/imx8mp_mu.c b/hw/misc/imx8mp_mu.c new file mode 100644 index 0000000000..f03cb07e22 --- /dev/null +++ b/hw/misc/imx8mp_mu.c @@ -0,0 +1,308 @@ +/* + * NXP i.MX Messaging Unit (MU) + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "qemu/osdep.h" +#include "qemu/log.h" + +#include "hw/misc/imx8mp_mu.h" +#include "hw/core/irq.h" +#include "hw/core/qdev-properties.h" +#include "migration/vmstate.h" + + +#define MU_SR_RFn_V1(x) (1u << (24 + (3 - (x)))) +#define MU_SR_TEn_V1(x) (1u << (20 + (3 - (x)))) +#define MU_SR_GIPn_V1(x) (1u << (28 + (3 - (x)))) +#define MU_CR_RIEn_V1(x) (1u << (24 + (3 - (x)))) +#define MU_CR_TIEn_V1(x) (1u << (20 + (3 - (x)))) +#define MU_CR_GIEn_V1(x) (1u << (28 + (3 - (x)))) +#define MU_CR_GIRn_V1(x) (1u << (16 + (3 - (x)))) + + +static inline IMX8MPMUState *imx8mp_mu_peer(IMX8MPMUState *s) +{ + return s->peer; +} + +static void imx8mp_mu_update_irq(IMX8MPMUState *s) +{ + + bool pending =3D false; + uint32_t sr =3D s->mu[MU_SR]; + uint32_t cr =3D s->mu[MU_CR]; + + for (int i =3D 0; i < 4; i++) { + /* TX done interrupt (TEn + TIEn) */ + if ((sr & MU_SR_TEn_V1(i)) && (cr & MU_CR_TIEn_V1(i))) { + pending =3D true; + break; + } + + /* RX data interrupt (RFn + RIEn) */ + if ((sr & MU_SR_RFn_V1(i)) && (cr & MU_CR_RIEn_V1(i))) { + pending =3D true; + break; + } + + /* Doorbell interrupt (GIPn + GIEn) - keep for completeness */ + if ((sr & MU_SR_GIPn_V1(i)) && (cr & MU_CR_GIEn_V1(i))) { + pending =3D true; + break; + } + } + qemu_set_irq(s->irq, pending); +} + +static uint64_t imx8mp_mu_read(void *opaque, hwaddr offset, unsigned size) +{ + IMX8MPMUState *s =3D opaque; + + if (size !=3D 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: invalid read size %u @0x%" HWADDR_PRIx "= \n", + size, offset); + return 0; + } + + if (offset & 3) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: unaligned read @0x%" + HWADDR_PRIx "\n", offset); + return 0; + } + + if (offset < MU_RR0) { + unsigned tr =3D offset >> 2; + if (s->strict_access) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: strict: read from TR%u" + " @0x%" HWADDR_PRIx "\n", tr, offset); + return 0; + } + return s->mu[MU_TR0 + tr]; + } + + if (offset >=3D MU_RR0 && offset < MU_SR) { + unsigned rr =3D (offset - MU_RR0) >> 2; + uint32_t v =3D s->mu[MU_RR0 + rr]; + IMX8MPMUState *p =3D imx8mp_mu_peer(s); + + if (s->strict_access && !(s->mu[MU_SR] & MU_SR_RFn_V1(rr))) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: strict: read from empty RR%u" + " @0x%" HWADDR_PRIx "\n", rr, offset); + return 0; + } + + if (s->mu[MU_SR] & MU_SR_RFn_V1(rr)) { + s->mu[MU_SR] &=3D ~MU_SR_RFn_V1(rr); + if (p) { + p->mu[MU_SR] |=3D MU_SR_TEn_V1(rr); + imx8mp_mu_update_irq(p); + } + } + imx8mp_mu_update_irq(s); + return v; + } + + switch (offset) { + case MU_SR: + return s->mu[MU_SR]; + case MU_CR: + return s->mu[MU_CR]; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: bad read @0x%" HWADDR_PRIx "\n", offset); + return 0; + } +} + +static void imx8mp_mu_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + IMX8MPMUState *s =3D opaque; + + if (size !=3D 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: invalid write size %u @0x%" HWADDR_PRIx = "\n", + size, offset); + return; + } + + if (offset & 3) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: unaligned write @0x%" + HWADDR_PRIx "\n", offset); + return; + } + + /* TR0..TR3 */ + if (offset < MU_RR0) { + unsigned tr =3D offset >> 2; + uint32_t v =3D (uint32_t)value; + IMX8MPMUState *p =3D imx8mp_mu_peer(s); + + if (s->strict_access && !(s->mu[MU_SR] & MU_SR_TEn_V1(tr))) { + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: strict: write to non-empty" + " TR%u @0x%" HWADDR_PRIx "\n", + tr, offset); + return; + } + + s->mu[MU_TR0 + tr] =3D v; + + /* + * Writing TR consumes local TX-empty (TE=3D0) and delivers the wo= rd + * into peer RR while setting peer RX-full (RF=3D1). + * + */ + s->mu[MU_SR] &=3D ~MU_SR_TEn_V1(tr); /* TE=3D0 */ + if (p) { + p->mu[MU_RR0 + tr] =3D v; + p->mu[MU_SR] |=3D MU_SR_RFn_V1(tr); /* RF=3D1 */ + imx8mp_mu_update_irq(p); + } + + imx8mp_mu_update_irq(s); + return; + } + + /* RR are read-only from this side */ + if (offset >=3D MU_RR0 && offset < MU_SR) { + unsigned rr =3D (offset - MU_RR0) >> 2; + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: write to RR%d ignored\n", rr); + return; + } + + switch (offset) { + case MU_CR: { + uint32_t v =3D (uint32_t)value; + IMX8MPMUState *p =3D imx8mp_mu_peer(s); + uint32_t gir_mask =3D 0; + + for (int i =3D 0; i < 4; i++) { + gir_mask |=3D MU_CR_GIRn_V1(i); + } + + if (p) { + for (int i =3D 0; i < 4; i++) { + if (v & MU_CR_GIRn_V1(i)) { + /* Set peer doorbell pending */ + p->mu[MU_SR] |=3D MU_SR_GIPn_V1(i); + } + } + imx8mp_mu_update_irq(p); + } + + /* + * Model GIRn as write-to-trigger (self-clearing) and keep other CR + * bits latched. + */ + v &=3D ~gir_mask; + + s->mu[MU_CR] =3D v; + imx8mp_mu_update_irq(s); + return; + } + + case MU_SR:{ + + /* Write-1-to-clear for doorbell bits */ + uint32_t v =3D (uint32_t)value; + for (int i =3D 0; i < 4; i++) { + if (v & MU_SR_GIPn_V1(i)) { + s->mu[MU_SR] &=3D ~MU_SR_GIPn_V1(i); + } + } + imx8mp_mu_update_irq(s); + return; + } + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "imx8mp_mu: bad write @0x%" HWADDR_PRIx + " =3D 0x%08" PRIx64 "\n", offset, value); + return; + } +} + +static void imx8mp_mu_reset(DeviceState *dev) +{ + IMX8MPMUState *s =3D IMX8MP_MU(dev); + memset(s->mu, 0, sizeof(s->mu)); + + s->mu[MU_SR] =3D 0x00F00080; + + imx8mp_mu_update_irq(s); +} + +static const MemoryRegionOps imx8mp_mu_ops =3D { + .read =3D imx8mp_mu_read, + .write =3D imx8mp_mu_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false, + }, +}; + +static const VMStateDescription imx8mp_mu_vmstate =3D { + .name =3D TYPE_IMX8MP_MU, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(mu, IMX8MPMUState, MU_MAX), + VMSTATE_END_OF_LIST() + }, +}; + +static void imx8mp_mu_init(Object *obj) +{ + IMX8MPMUState *s =3D IMX8MP_MU(obj); + SysBusDevice *sd =3D SYS_BUS_DEVICE(obj); + + /* Default to strict hardware-like access semantics. */ + s->strict_access =3D true; + + memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_MU, + IMX8MP_MU_MMIO_SIZE); + + /* Implemented subset as an IO subregion at offset 0 */ + memory_region_init_io(&s->mmio.regs, obj, &imx8mp_mu_ops, s, + TYPE_IMX8MP_MU ".regs", sizeof(s->mu)); + memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.regs); + + sysbus_init_mmio(sd, &s->mmio.container); + sysbus_init_irq(sd, &s->irq); +} + +static void imx8mp_mu_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + device_class_set_legacy_reset(dc, imx8mp_mu_reset); + dc->vmsd =3D &imx8mp_mu_vmstate; + dc->desc =3D "i.MX 8M Plus Messaging Unit"; +} + +static const TypeInfo imx8mp_mu_type_info[] =3D { + { + .name =3D TYPE_IMX8MP_MU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(IMX8MPMUState), + .instance_init =3D imx8mp_mu_init, + .class_init =3D imx8mp_mu_class_init, + } +}; + +DEFINE_TYPES(imx8mp_mu_type_info); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 174aed40b6..43b5696865 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -62,6 +62,7 @@ system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: fil= es('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_FSL_IMX8MP_MU', if_true: files('imx8mp_mu.c')) system_ss.add(when: 'CONFIG_IMX', if_true: files( 'imx25_ccm.c', 'imx31_ccm.c', diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index c6c133cc05..94d198b932 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -20,6 +20,7 @@ #include "hw/misc/imx8mp_gpc.h" #include "hw/misc/imx8mp_gpr.h" #include "hw/misc/imx8mp_src.h" +#include "hw/misc/imx8mp_mu.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" #include "hw/pci-host/designware.h" @@ -39,6 +40,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP) #define FSL_IMX8MP_RAM_START 0x40000000 #define FSL_IMX8MP_RAM_SIZE_MAX (8 * GiB) =20 +#define FSL_IMX8MP_MU1_A_IRQ 88 + enum FslImx8mpConfiguration { FSL_IMX8MP_NUM_CPUS =3D 4, FSL_IMX8MP_NUM_ECSPIS =3D 3, @@ -46,12 +49,18 @@ enum FslImx8mpConfiguration { FSL_IMX8MP_NUM_GPTS =3D 6, FSL_IMX8MP_NUM_I2CS =3D 6, FSL_IMX8MP_NUM_IRQS =3D 160, + FSL_IMX8MP_NUM_MU =3D 3, FSL_IMX8MP_NUM_UARTS =3D 4, FSL_IMX8MP_NUM_USBS =3D 2, FSL_IMX8MP_NUM_USDHCS =3D 3, FSL_IMX8MP_NUM_WDTS =3D 3, }; =20 +typedef struct IMX8MPMUPair { + IMX8MPMUState a; + IMX8MPMUState b; +} IMX8MPMUPair; + struct FslImx8mpState { SysBusDevice parent_obj; =20 @@ -65,6 +74,7 @@ struct FslImx8mpState { IMX8MPAnalogState analog; IMX7SNVSState snvs; IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS]; + IMX8MPMUPair mu[FSL_IMX8MP_NUM_MU]; FslImx8mpSrcState src; IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS]; IMXSerialState uart[FSL_IMX8MP_NUM_UARTS]; diff --git a/include/hw/misc/imx8mp_mu.h b/include/hw/misc/imx8mp_mu.h new file mode 100644 index 0000000000..4801708402 --- /dev/null +++ b/include/hw/misc/imx8mp_mu.h @@ -0,0 +1,53 @@ +/* + * NXP i.MX 8M Plus Messaging Unit (MU) + * + * Copyright (c) 2026, NXP Semiconductors + * Author: Gaurav Sharma + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef IMX8MP_MU_H +#define IMX8MP_MU_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define IMX8MP_MU_MMIO_SIZE 0x10000 + +enum IMX8MPMURegisters { + MU_TR0 =3D 0x000 / 4, + MU_TR1 =3D 0x004 / 4, + MU_TR2 =3D 0x008 / 4, + MU_TR3 =3D 0x00C / 4, + MU_RR0 =3D 0x010 / 4, + MU_RR1 =3D 0x014 / 4, + MU_RR2 =3D 0x018 / 4, + MU_RR3 =3D 0x01C / 4, + MU_SR =3D 0x020 / 4, + MU_CR =3D 0x024 / 4, + MU_MAX, +}; + +#define TYPE_IMX8MP_MU "imx8mp-mu" +OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPMUState, IMX8MP_MU) + +typedef struct IMX8MPMUState { + SysBusDevice parent_obj; + + struct { + MemoryRegion container; + MemoryRegion regs; + } mmio; + + qemu_irq irq; + + struct IMX8MPMUState *peer; + uint32_t mu[MU_MAX]; + + bool strict_access; + +} IMX8MPMUState; + +#endif /* IMX8MP_MU_H */ --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213463393296.5991638345763; Tue, 19 May 2026 10:57:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgh-0008Nx-VW; Tue, 19 May 2026 13:57:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOga-0008Mv-6f for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:57 -0400 Received: from inva020.nxp.com ([92.121.34.13]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgT-0002gw-M2 for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:52 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 267721A2703; Tue, 19 May 2026 19:56:42 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id D3A641A531A; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id B17081800093; Wed, 20 May 2026 01:56:40 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 5/7] hw/misc: Extend i.MX8MP CCM with Cortex-M7 clock outputs Date: Tue, 19 May 2026 23:26:33 +0530 Message-Id: <20260519175635.3245229-6-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.13; envelope-from=gaurav.sharma_7@nxp.com; helo=inva020.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213466821154100 Content-Type: text/plain; charset="utf-8" Add cm7_cpuclk (24 MHz) and cm7_refclk (32.768 kHz) clock outputs to the i.MX8MP CCM. These are required by the ARMv7M model to boot the Cortex-M7 core in an AMP configuration. Signed-off-by: Gaurav Sharma Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/misc/imx8mp_ccm.c | 9 +++++++++ include/hw/misc/imx8mp_ccm.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c index 911911ed86..5530c924b5 100644 --- a/hw/misc/imx8mp_ccm.c +++ b/hw/misc/imx8mp_ccm.c @@ -12,17 +12,24 @@ #include "qemu/log.h" =20 #include "hw/misc/imx8mp_ccm.h" +#include "hw/core/qdev-clock.h" #include "migration/vmstate.h" =20 #include "trace.h" =20 #define CKIH_FREQ 16000000 /* 16MHz crystal input */ =20 +#define IMX8MP_CM7_CPUCLK_HZ 24000000ULL /* osc_24m */ +#define IMX8MP_CM7_REFCLK_HZ 32768ULL /* osc_32k */ + static void imx8mp_ccm_reset(DeviceState *dev) { IMX8MPCCMState *s =3D IMX8MP_CCM(dev); =20 memset(s->ccm, 0, sizeof(s->ccm)); + + clock_set_hz(s->cm7_cpuclk, IMX8MP_CM7_CPUCLK_HZ); + clock_set_hz(s->cm7_refclk, IMX8MP_CM7_REFCLK_HZ); } =20 #define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t)) @@ -88,6 +95,8 @@ static void imx8mp_ccm_init(Object *obj) SysBusDevice *sd =3D SYS_BUS_DEVICE(obj); IMX8MPCCMState *s =3D IMX8MP_CCM(obj); =20 + s->cm7_cpuclk =3D qdev_init_clock_out(DEVICE(obj), "cm7_cpuclk"); + s->cm7_refclk =3D qdev_init_clock_out(DEVICE(obj), "cm7_refclk"); memory_region_init_io(&s->iomem, obj, &imx8mp_set_clr_tog_ops, diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h index 685c8582ff..c6ede6928c 100644 --- a/include/hw/misc/imx8mp_ccm.h +++ b/include/hw/misc/imx8mp_ccm.h @@ -9,6 +9,7 @@ #ifndef IMX8MP_CCM_H #define IMX8MP_CCM_H =20 +#include "hw/core/clock.h" #include "hw/misc/imx_ccm.h" #include "qom/object.h" =20 @@ -25,6 +26,8 @@ struct IMX8MPCCMState { MemoryRegion iomem; =20 uint32_t ccm[CCM_MAX]; + Clock *cm7_cpuclk; + Clock *cm7_refclk; }; =20 #endif /* IMX8MP_CCM_H */ --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213454524511.81789460497475; Tue, 19 May 2026 10:57:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgj-0008OD-MC; Tue, 19 May 2026 13:57:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOga-0008Mu-6x for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:57 -0400 Received: from inva021.nxp.com ([92.121.34.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgR-0002gl-MT for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:52 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 11462203C19; Tue, 19 May 2026 19:56:42 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id BE359202769; Tue, 19 May 2026 19:56:41 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 1BC22180026F; Wed, 20 May 2026 01:56:41 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 6/7] hw/arm: Enable Cortex-M7 AMP boot on i.MX8MP Date: Tue, 19 May 2026 23:26:34 +0530 Message-Id: <20260519175635.3245229-7-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.21; envelope-from=gaurav.sharma_7@nxp.com; helo=inva021.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213458742154100 Configure the i.MX8MP to boot the Cortex-M7 core alongside the Cortex-A53 cores in an Asymmetric Multiprocessing (AMP) configuration. The M7 firmware can be loaded and started from Linux running on the A53 cores via the remoteproc framework. CM7 boot is made optional. A GPR IRQ is connected to a cpuwait handler. The handler translates the CPUWAIT into STOP and RUN.It follows the classic Cortex-M boot sequence: initial SP and reset vector taken from the vector table. Signed-off-by: Gaurav Sharma --- docs/system/arm/imx8m.rst | 86 +++++++++++++++++++++- hw/arm/fsl-imx8mp.c | 143 ++++++++++++++++++++++++++++++++++++ include/hw/arm/fsl-imx8mp.h | 13 +++- 3 files changed, 240 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst index c482bf180f..d6729cbcc6 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -12,6 +12,7 @@ The ``imx8mp-evk`` and ``imx8mm-evk`` machines implement = the following devices: =20 * Up to 4 Cortex-A53 cores + * 1 Cortex-M7 core (``imx8mp-evk`` only) * Generic Interrupt Controller (GICv3) * 4 UARTs * 3 USDHC Storage Controllers @@ -36,6 +37,88 @@ Boot options The ``imx8mp-evk`` and ``imx8mm-evk`` machines can start a Linux kernel directly using the standard ``-kernel`` functionality. =20 +Asymmetric Multiprocessing (AMP) Boot (``imx8mp-evk`` only) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``imx8mp-evk`` machine includes a Cortex-M7 core alongside the +Cortex-A53 cores, enabling Asymmetric Multiprocessing (AMP). The M7 +firmware can be loaded from Linux using the remoteproc framework. + +There are 2 control paths for Cortex-M7 on iMX8MP:- +1. Firmware-mediated (via SMC/ATF) +2. MMIO driven path (via SRC and GPR access) + +``fsl,imx8mp-cm7-mmio`` exists specifically to select the MMIO path and av= oid dependence on firmware interfaces that aren=E2=80=99t guaranteed in qem= u. +This mode uses the SRC syscon block and the IOMUXC GPR for start/stop cont= rol. + +Memory carveouts for resource table, vrings need to be specified in the ``= imx8mp-evk-rpmsg.dts``. +Follow this application note to make the necessary changes - https://www.n= xp.com/docs/en/application-note/AN5317.pdf + +When Linux boots CM7 via remoteproc, the typical flow is: + +1. Linux booted with imx8mp-evk-rpmsg.dtb +2. Linux loads the CM7 ELF into a reserved DDR region +3. Linux toggles the CM7 start/stop control (SRC/GPR CPUWAIT, etc.) +4. CM7 starts executing from that DDR entry + + +If you build a Cortex-M7 bare-metal firmware elf that is linked for a vect= or +table base address other than the default 0x80000000, configure the CM7 ve= ctor base via the SoC property +``cm7-vector-base``. + +Note:-Currently only DDR-linked bare-metal binaries are supported in qemu = emulation. + +This can be set using a global property: + +.. code-block:: bash + + -global fsl-imx8mp.cm7-vector-base=3D0x80000000 + +In the absence of the above global property in qemu invocation, by default= 0x80000000 will be used. + + +To run the i.MX 8M Plus model with the Cortex-M7 core enabled(4x A53 + 1x = M7), start QEMU with + +.. code-block:: bash + + -smp 4,maxcpus=3D5 -global fsl-imx8mp.enable-cm7=3Don + + +Serial ports (UARTs) +'''''''''''''''''''' + +The i.MX 8M Plus EVK model provides four UARTs. QEMU connects each UART to= a +host character backend using the ``-serial`` option. This option can be us= ed +multiple times to create and wire multiple serial ports. + +The ``-serial`` options are positional: + +* the 1st ``-serial ...`` maps to ``serial0`` (UART1) +* the 2nd ``-serial ...`` maps to ``serial1`` (UART2) +* the 3rd ``-serial ...`` maps to ``serial2`` (UART3) +* the 4th ``-serial ...`` maps to ``serial3`` (UART4) + +Example usage:- To enable serial console for the official M7 mcuxpresso sd= k driver example - driver_examples/uart/polling which uses UART4, use:- + +.. code-block:: bash + + -serial null -serial stdio -serial null -serial pty:/tmp/imx8mp-uart4 + +This will create a symlink /tmp/imx8mp-uart4 pointed to the allocated PTY.= On a different tab the console for UART4 can be opened using the following= :- + +.. code-block:: bash + + $ screen /tmp/imx8mp-uart4 115200 + + +Once Linux is running, the M7 firmware can be loaded and started via the r= emoteproc interface: + +.. code-block:: bash + + # echo .elf > /sys/class/remoteproc/remoteproc0/firmware + # echo start > /sys/class/remoteproc/remoteproc0/state + + Direct Linux Kernel Boot '''''''''''''''''''''''' =20 @@ -72,7 +155,8 @@ For i.MX 8M Plus EVK: .. code-block:: bash =20 $ qemu-system-aarch64 -M imx8mp-evk \ - -display none -serial null -serial stdio \ + -display none -serial null -serial stdio -serial null -serial /tmp/i= mx8mp-uart4 \ + -smp 4,maxcpus=3D5 -global fsl-imx8mp.enable-cm7=3Don \ -kernel Image \ -dtb imx8mp-evk.dtb \ -append "root=3D/dev/mmcblk2p2" \ diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index eec83deced..a5066c3ae2 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -196,6 +196,10 @@ static void fsl_imx8mp_init(Object *obj) FslImx8mpState *s =3D FSL_IMX8MP(obj); int i; =20 + s->cm7_booted =3D false; + + object_initialize_child(obj, "cm7", &s->cm7, TYPE_ARMV7M); + object_initialize_child(obj, "gic", &s->gic, gicv3_class_name()); =20 object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM); @@ -269,6 +273,93 @@ static void fsl_imx8mp_init(Object *obj) TYPE_FSL_IMX8M_PCIE_PHY); } =20 +static inline void imx8mp_cm7_halt(CPUState *m7cs) +{ + cpu_interrupt(m7cs, CPU_INTERRUPT_HALT); + m7cs->halted =3D 1; + qemu_cpu_kick(m7cs); +} + +static inline void imx8mp_cm7_resume(CPUState *m7cs) +{ + /* Clear HALT interrupt (from STOP) and resume */ + cpu_reset_interrupt(m7cs, CPU_INTERRUPT_HALT); + m7cs->halted =3D 0; + m7cs->stopped =3D 0; + cpu_resume(m7cs); + cpu_interrupt(m7cs, CPU_INTERRUPT_EXITTB); + qemu_cpu_kick(m7cs); +} + +static void imx8mp_cm7_ctrl_apply(CPUState *cpu, run_on_cpu_data data) +{ + struct CM7CtlReq *r =3D data.host_ptr; + FslImx8mpState *s =3D r->s; + ARMCPU *m7 =3D s->cm7.cpu; + CPUState *m7cs =3D CPU(m7); + + if (!r->run) { + /* STOP: halt the M7 */ + imx8mp_cm7_halt(m7cs); + goto out; + } + + /* + * RUN: + * CPUWAIT is modeled as a run/stop gate. On first RUN, boot from vect= or + * table. Subsequent RUN resumes execution without resetting CM7 state. + */ + if (s->cm7_booted) { + imx8mp_cm7_resume(m7cs); + goto out; + } + + uint32_t msp_le =3D 0, pc_le =3D 0; + uint32_t msp, pc; + hwaddr vbase =3D s->cm7_vector_base; + + address_space_read(&address_space_memory, vbase, + MEMTXATTRS_UNSPECIFIED, &msp_le, sizeof(msp_le)); + address_space_read(&address_space_memory, vbase + 4, + MEMTXATTRS_UNSPECIFIED, &pc_le, sizeof(pc_le)); + msp =3D le32_to_cpu(msp_le); + pc =3D le32_to_cpu(pc_le); + + + /* Clear Thumb indicator bit (bit0) */ + pc &=3D ~1u; + + cpu_reset(m7cs); + + /* Set SP (R13) and PC (R15). Cortex-M uses Thumb */ + m7->env.regs[13] =3D msp; + m7->env.regs[15] =3D pc; + m7->env.thumb =3D 1; + + imx8mp_cm7_resume(m7cs); + + s->cm7_booted =3D true; +out: + g_free(r); +}; + +static void imx8mp_cm7_cpuwait_handler(void *opaque, int n, int level) +{ + FslImx8mpState *s =3D opaque; + (void)n; + + if (!s->cm7.cpu) { + return; + } + + struct CM7CtlReq *r =3D g_new0(struct CM7CtlReq, 1); + r->s =3D s; + r->run =3D !!level; + + async_run_on_cpu(CPU(s->cm7.cpu), imx8mp_cm7_ctrl_apply, + RUN_ON_CPU_HOST_PTR(r)); +} + static void fsl_imx8mp_realize(DeviceState *dev, Error **errp) { MachineState *ms =3D MACHINE(qdev_get_machine()); @@ -277,6 +368,23 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) const char *cpu_type =3D ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53= "); int i; =20 + if (!s->enable_cm7) { + object_unparent(OBJECT(&s->cm7)); + } else { + /* + * When CM7 is enabled we need one additional vCPU + * slot. If the user does not specify maxcpus=3D, + * QEMU defaults maxcpus to the current -smp count. + */ + unsigned int need =3D ms->smp.cpus + 1; + if (ms->smp.max_cpus < need) { + error_setg(errp, + "CM7 enabled requires -smp %u,maxcpus=3D%u (one ext= ra vCPU slot for CM7)", + ms->smp.cpus, need); + return; + } + } + if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) { error_setg(errp, "%s: Only %d CPUs are supported (%d requested)", TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus); @@ -459,6 +567,38 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, fsl_imx8mp_memmap[FSL_IMX8MP_IOMUXC_GPR].addr); =20 + if (s->enable_cm7) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpr), 0, + qemu_allocate_irq(imx8mp_cm7_cpuwait_handler, s, 0)); + + /* Realize Cortex-M7 subsystem */ + DeviceState *cm7dev =3D DEVICE(&s->cm7); + DeviceState *ccmdev =3D DEVICE(&s->ccm); + qdev_prop_set_string(cm7dev, "cpu-type", + ARM_CPU_TYPE_NAME("cortex-m7")); + qdev_prop_set_uint32(cm7dev, "num-irq", 64); + qdev_prop_set_bit(cm7dev, "enable-bitband", true); + + /* CM7 vector table base (configurable) */ + qdev_prop_set_uint32(cm7dev, "init-nsvtor", s->cm7_vector_base); + + /* Connect CM7 clocks from CCM exported outputs */ + qdev_connect_clock_in(cm7dev, "cpuclk", + qdev_get_clock_out(ccmdev, "cm7_cpuclk")); + qdev_connect_clock_in(cm7dev, "refclk", + qdev_get_clock_out(ccmdev, "cm7_refclk")); + object_property_set_link(OBJECT(&s->cm7), "memory", + OBJECT(get_system_memory()), &error_abort= ); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cm7), errp)) { + return; + } + + CPUState *m7cs =3D CPU(s->cm7.cpu); + cpu_interrupt(m7cs, CPU_INTERRUPT_HALT); + m7cs->halted =3D 1; + } + /* GPTs */ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2, &error_abort); @@ -784,6 +924,9 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) static const Property fsl_imx8mp_properties[] =3D { DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0), DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, = true), + DEFINE_PROP_BOOL("enable-cm7", FslImx8mpState, enable_cm7, false), + DEFINE_PROP_UINT32("cm7-vector-base", FslImx8mpState, + cm7_vector_base, 0x80000000), }; =20 static void fsl_imx8mp_class_init(ObjectClass *oc, const void *data) diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index 94d198b932..335e4beb6c 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -10,6 +10,7 @@ #define FSL_IMX8MP_H =20 #include "target/arm/cpu.h" +#include "hw/arm/armv7m.h" #include "hw/char/imx_serial.h" #include "hw/gpio/imx_gpio.h" #include "hw/i2c/imx_i2c.h" @@ -30,6 +31,7 @@ #include "hw/timer/imx_gpt.h" #include "hw/usb/hcd-dwc3.h" #include "hw/watchdog/wdt_imx2.h" +#include "hw/core/qdev-clock.h" #include "hw/core/sysbus.h" #include "qom/object.h" #include "qemu/units.h" @@ -43,7 +45,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP) #define FSL_IMX8MP_MU1_A_IRQ 88 =20 enum FslImx8mpConfiguration { - FSL_IMX8MP_NUM_CPUS =3D 4, + FSL_IMX8MP_NUM_CPUS =3D 5, FSL_IMX8MP_NUM_ECSPIS =3D 3, FSL_IMX8MP_NUM_GPIOS =3D 5, FSL_IMX8MP_NUM_GPTS =3D 6, @@ -65,6 +67,10 @@ struct FslImx8mpState { SysBusDevice parent_obj; =20 ARMCPU cpu[FSL_IMX8MP_NUM_CPUS]; + ARMv7MState cm7; + bool enable_cm7; + bool cm7_booted; + uint32_t cm7_vector_base; GICv3State gic; IMX8MPGPCState gpc; IMX8MPGPRState gpr; @@ -91,6 +97,11 @@ struct FslImx8mpState { bool phy_connected; }; =20 +struct CM7CtlReq { + FslImx8mpState *s; + bool run; +}; + enum FslImx8mpMemoryRegions { FSL_IMX8MP_A53_DAP, FSL_IMX8MP_AIPS1_CONFIGURATION, --=20 2.34.1 From nobody Sat May 30 18:38:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=nxp.com Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779213458097235.00266522409322; Tue, 19 May 2026 10:57:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPOgl-0008PK-TA; Tue, 19 May 2026 13:57:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgV-0008M8-Qz for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:53 -0400 Received: from inva021.nxp.com ([92.121.34.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPOgR-0002hd-OW for qemu-devel@nongnu.org; Tue, 19 May 2026 13:56:51 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 79FA5203C12; Tue, 19 May 2026 19:56:42 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 337F8202769; Tue, 19 May 2026 19:56:42 +0200 (CEST) Received: from lsv031015.swis.in-blr01.nxp.com (lsv031015.swis.in-blr01.nxp.com [10.12.177.77]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7A5FE1802161; Wed, 20 May 2026 01:56:41 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, Gaurav Sharma Subject: [PATCHv1 7/7] tests/functional: Enable Cortex-M7 boot in i.MX8MP EVK functional test Date: Tue, 19 May 2026 23:26:35 +0530 Message-Id: <20260519175635.3245229-8-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> References: <20260519175635.3245229-1-gaurav.sharma_7@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: ClamAV using ClamSMTP Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=92.121.34.21; envelope-from=gaurav.sharma_7@nxp.com; helo=inva021.nxp.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1779213462606154100 Content-Type: text/plain; charset="utf-8" Update the i.MX8MP EVK functional test to enable the Cortex-M7 core by setting maxcpus=3D5 and enabling the fsl-imx8mp.enable-cm7 property The i.MX8MP SoC model makes the Cortex-M7 optional and disabled by default. Signed-off-by: Gaurav Sharma --- tests/functional/aarch64/test_imx8mp_evk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/aarch64/test_imx8mp_evk.py b/tests/functional= /aarch64/test_imx8mp_evk.py index 99ddcdef83..175bfb5b3e 100755 --- a/tests/functional/aarch64/test_imx8mp_evk.py +++ b/tests/functional/aarch64/test_imx8mp_evk.py @@ -53,7 +53,8 @@ def test_aarch64_imx8mp_evk_usdhc(self): self.set_machine('imx8mp-evk') self.vm.set_console(console_index=3D1) self.vm.add_args('-m', '2G', - '-smp', '4', + '-smp', '4,maxcpus=3D5', + '-global', 'fsl-imx8mp.enable-cm7=3Don', '-kernel', self.kernel_path, '-initrd', self.initrd_path, '-dtb', self.dtb_path, --=20 2.34.1