From nobody Sat Sep 26 20:02:57 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 1789905416698291.17045941405695; Sun, 20 Sep 2026 04:56:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8Y-0006MP-8l; Sun, 20 Sep 2026 07:55:14 -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 1x8G8T-0006Jb-JU; Sun, 20 Sep 2026 07:55:09 -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 1x8G8R-0001Zf-GT; Sun, 20 Sep 2026 07:55:09 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id EA52F1A0032; Sun, 20 Sep 2026 13:55:04 +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 B4ECD1A0034; Sun, 20 Sep 2026 13:55:04 +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 238CE18000BF; Sun, 20 Sep 2026 19:55:02 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 01/10] hw/misc: Add i.MX8MP GPC (General Power Controller) IP Date: Sun, 20 Sep 2026 17:24:49 +0530 Message-Id: <20260920115458.481605-2-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905418108158500 Content-Type: text/plain; charset="utf-8" Add a minimal emulation of the i.MX8MP General Power Controller 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 | 146 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 2 + include/hw/misc/imx8mp_gpc.h | 34 ++++++++ 8 files changed, 198 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 1bcb8255be..e9e970ce64 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -26,6 +26,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 eae06369b0..17450256db 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -594,6 +594,7 @@ config FSL_IMX8MP select CAN_FLEXCAN 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 bcd91739d9..ac7f9104f3 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); @@ -427,6 +429,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); @@ -720,6 +729,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) case FSL_IMX8MP_FLEXCAN1 ... FSL_IMX8MP_FLEXCAN2: 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 46e3c03cc8..c17275441c 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..9d8b93779d --- /dev/null +++ b/hw/misc/imx8mp_gpc.c @@ -0,0 +1,146 @@ +/* + * 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/core/resettable.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 ResettablePhases imx8mp_gpc_parent_phases; + +static void imx8mp_gpc_reset_enter(Object *obj, ResetType type) +{ + IMX8MPGPCState *s =3D IMX8MP_GPC(obj); + + if (imx8mp_gpc_parent_phases.enter) { + imx8mp_gpc_parent_phases.enter(obj, type); + } + + 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 void imx8mp_gpc_reset_hold(Object *obj, ResetType type) +{ + if (imx8mp_gpc_parent_phases.hold) { + imx8mp_gpc_parent_phases.hold(obj, type); + } +} + +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); + ResettableClass *rc =3D RESETTABLE_CLASS(oc); + + resettable_class_set_parent_phases(rc, + imx8mp_gpc_reset_enter, + imx8mp_gpc_reset_hold, + NULL, + &imx8mp_gpc_parent_phases); + + 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 9790afa104..ba9d586ec9 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -62,6 +62,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 2be3c51af5..daca290cdb 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/flexcan.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" @@ -56,6 +57,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 Sep 26 20:02:57 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 1789905406876200.37273442618414; Sun, 20 Sep 2026 04:56:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8W-0006LU-Mu; Sun, 20 Sep 2026 07:55:12 -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 1x8G8U-0006Ju-L8; Sun, 20 Sep 2026 07:55:10 -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 1x8G8S-0001Zv-8k; Sun, 20 Sep 2026 07:55:10 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id E26021A0028; Sun, 20 Sep 2026 13:55:06 +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 ABDB61A0003; Sun, 20 Sep 2026 13:55:06 +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 BCAA818000BA; Sun, 20 Sep 2026 19:55:04 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 02/10] hw/misc: Add GPR (General Purpose Register) IP to iMX8MP Date: Sun, 20 Sep 2026 17:24:50 +0530 Message-Id: <20260920115458.481605-3-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905408359158500 Content-Type: text/plain; charset="utf-8" Add IOMUXC General Purpose Registers IP and wire it into the i.MX8MP SoC mo= del. 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 | 155 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 2 + include/hw/misc/imx8mp_gpr.h | 62 ++++++++++++++ 8 files changed, 235 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 e9e970ce64..7813469154 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -27,6 +27,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 17450256db..7b7378110c 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -595,6 +595,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 ac7f9104f3..0c61582a27 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); @@ -436,6 +438,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); @@ -735,6 +744,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 c17275441c..5c2945200e 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..7e1f44e6bc --- /dev/null +++ b/hw/misc/imx8mp_gpr.c @@ -0,0 +1,155 @@ +/* + * 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 "hw/core/resettable.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_enter(Object *obj, ResetType type) +{ + IMX8MPGPRState *s =3D IMX8MP_GPR(obj); + IMX8MPGPRClass *gc =3D IMX8MP_GPR_GET_CLASS(obj); + + if (gc->parent_phases.enter) { + gc->parent_phases.enter(obj, type); + } + + 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; +} + +static void imx8mp_gpr_reset_hold(Object *obj, ResetType type) +{ + IMX8MPGPRState *s =3D IMX8MP_GPR(obj); + IMX8MPGPRClass *gc =3D IMX8MP_GPR_GET_CLASS(obj); + + if (gc->parent_phases.hold) { + gc->parent_phases.hold(obj, type); + } + + /* 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); + ResettableClass *rc =3D RESETTABLE_CLASS(oc); + IMX8MPGPRClass *gc =3D IMX8MP_GPR_CLASS(oc); + + resettable_class_set_parent_phases(rc, + imx8mp_gpr_reset_enter, + imx8mp_gpr_reset_hold, + NULL, + &gc->parent_phases); + + 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), + .class_size =3D sizeof(IMX8MPGPRClass), + .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 ba9d586ec9..5eda094d34 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -63,6 +63,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 daca290cdb..8f07b2a270 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/flexcan.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" @@ -58,6 +59,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..aa94692e8a --- /dev/null +++ b/include/hw/misc/imx8mp_gpr.h @@ -0,0 +1,62 @@ +/* + * 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/resettable.h" +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_IMX8MP_GPR "imx8mp.gpr" +OBJECT_DECLARE_TYPE(IMX8MPGPRState, IMX8MPGPRClass, IMX8MP_GPR) + +struct IMX8MPGPRClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +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 Sep 26 20:02:57 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 1789905354682840.3486652538695; Sun, 20 Sep 2026 04:55:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8d-0006WE-JA; Sun, 20 Sep 2026 07:55:19 -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 1x8G8X-0006Lx-DL; Sun, 20 Sep 2026 07:55:13 -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 1x8G8U-0001aR-8H; Sun, 20 Sep 2026 07:55:12 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id DA02F1A0036; Sun, 20 Sep 2026 13:55:08 +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 7984C1A002D; Sun, 20 Sep 2026 13:55:08 +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 62FD818000BF; Sun, 20 Sep 2026 19:55:06 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 03/10] hw/misc: Add SRC (System Reset Controller) to i.MX8MP Date: Sun, 20 Sep 2026 17:24:51 +0530 Message-Id: <20260920115458.481605-4-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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.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: 1789905359893158500 From: Bernhard Beschow 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 Signed-off-by: Gaurav Sharma --- 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 =20 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) =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); @@ -431,6 +433,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; @@ -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 =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..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 + * + * 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 =3D s->gpr ? s->gpr->gpr[IOMUXC_GPR_GPR6] : 0; + uint32_t vbase =3D gpr6 & 0xffffff80; + + if (vbase =3D=3D 0) { + uint32_t pc_le =3D 0, pc; + + address_space_read(&address_space_memory, + IMX8MP_ITCM_BASE + 4, + MEMTXATTRS_UNSPECIFIED, &pc_le, sizeof(pc_le)); + pc =3D le32_to_cpu(pc_le); + if (pc !=3D 0 && pc !=3D UINT32_MAX && (pc & 1)) { + vbase =3D 0; /* valid Thumb vector =E2=80=94 boot from ITCM al= ias at 0x0 */ + } else { + vbase =3D s->cm7_vector_base; + } + } + return vbase; +} + +static void imx8mp_src_cm7_reset_run(CPUState *cpu, run_on_cpu_data data) +{ + FslImx8mpSrcState *s =3D data.host_ptr; + ARMCPU *m7 =3D ARM_CPU(cpu); + + m7->init_nsvtor =3D 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=3D1: CPUWAIT cleared (run); level=3D0: CPUWAIT set (halt). + */ +static void imx8mp_src_cm7_set_cpuwait(FslImx8mpSrcState *s, bool run) +{ + if (!s->cm7_cpu) { + return; + } + if (run) { + CPUState *cpu =3D 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 =3D opaque; + const uint32_t reg =3D offset / 4; + uint32_t value =3D 0; + + if (reg < FSL_IMX8MP_SRC_NUM_REGS) { + value =3D 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 val= ue, + unsigned size) +{ + FslImx8mpSrcState *s =3D opaque; + const uint32_t reg =3D offset / 4; + + if (reg >=3D 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 =3D s->regs[reg]; + uint32_t new_value =3D (uint32_t)value; + uint32_t changed; + bool reset_pulse =3D false; + + /* + * SW_M7C_RST (bit1) is self-clearing on real HW: writing 1 trigge= rs + * an M7 core-reset pulse and the bit reads back 0. + */ + if (new_value & SRC_M7RCR_SW_M7C_RST) { + reset_pulse =3D true; + new_value &=3D ~SRC_M7RCR_SW_M7C_RST; + } + + s->regs[reg] =3D new_value; + changed =3D 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 =3D new_value & SRC_M7RCR_SW_M7C_NON_SCLR_RST; + /* NON_SCLR latch: 1 =3D hold in reset (off); 0 =3D 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] =3D value; + break; + } + +done: + + 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, + }, +}; + +static void imx8mp_src_reset_enter(Object *obj, ResetType type) +{ + FslImx8mpSrcState *s =3D IMX8MP_SRC(obj); + FslImx8mpSrcClass *sc =3D 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] =3D 0x000000A8; +} + +static void imx8mp_src_cm7_cpuwait_handler(void *opaque, int n, int level) +{ + FslImx8mpSrcState *s =3D opaque; + + s->cm7_cpuwait =3D !level; + imx8mp_src_cm7_set_cpuwait(s, (bool)level); +} + +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); + qdev_init_gpio_in_named(dev, imx8mp_src_cm7_cpuwait_handler, "cm7-cpuw= ait", 1); +} + +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_UINT32("cm7-vector-base", FslImx8mpSrcState, cm7_vector_ba= se, + 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 =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + FslImx8mpSrcClass *sc =3D IMX8MP_SRC_CLASS(klass); + + resettable_class_set_parent_phases(rc, + imx8mp_src_reset_enter, + NULL, + NULL, + &sc->parent_phases); + 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_size =3D sizeof(FslImx8mpSrcClass), + .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 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" =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 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 + * + * 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 =3D=3D 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 */ --=20 2.34.1 From nobody Sat Sep 26 20:02:57 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 1789905425798185.4820709996742; Sun, 20 Sep 2026 04:57:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8a-0006Qr-JP; Sun, 20 Sep 2026 07:55:16 -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 1x8G8Y-0006Mg-JZ; Sun, 20 Sep 2026 07:55:14 -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 1x8G8V-0001an-Ux; Sun, 20 Sep 2026 07:55:14 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 82DD41A0003; Sun, 20 Sep 2026 13:55:10 +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 2149A1A001A; Sun, 20 Sep 2026 13:55:10 +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 31BD918000BA; Sun, 20 Sep 2026 19:55:08 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 04/10] hw/misc: Add MU (Messaging Unit) IP to i.MX8MP device model Date: Sun, 20 Sep 2026 17:24:52 +0530 Message-Id: <20260920115458.481605-5-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905428319158500 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 | 328 ++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/fsl-imx8mp.h | 10 ++ include/hw/misc/imx8mp_mu.h | 53 ++++++ 8 files changed, 436 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 38f4e31443..cdf862a456 100644 --- a/docs/system/arm/imx8m.rst +++ b/docs/system/arm/imx8m.rst @@ -29,6 +29,7 @@ following devices: * General Power Controller * General Purpose Register * System Reset Controller + * Messaging Unit =20 Boot options ------------ diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 2ab57b7c53..d92239fd4e 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -597,6 +597,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 274b44794a..2d5b5f3870 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); @@ -500,6 +510,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 { @@ -754,6 +792,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 d9e904ae2f..1e3b14b2a9 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..adaaf26eca --- /dev/null +++ b/hw/misc/imx8mp_mu.c @@ -0,0 +1,328 @@ +/* + * 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 "hw/core/resettable.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 ResettablePhases imx8mp_mu_parent_phases; + +static void imx8mp_mu_reset_enter(Object *obj, ResetType type) +{ + IMX8MPMUState *s =3D IMX8MP_MU(obj); + + if (imx8mp_mu_parent_phases.enter) { + imx8mp_mu_parent_phases.enter(obj, type); + } + memset(s->mu, 0, sizeof(s->mu)); + + s->mu[MU_SR] =3D 0x00F00080; +} + +static void imx8mp_mu_reset_hold(Object *obj, ResetType type) +{ + IMX8MPMUState *s =3D IMX8MP_MU(obj); + if (imx8mp_mu_parent_phases.hold) { + imx8mp_mu_parent_phases.hold(obj, type); + } + + 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); + ResettableClass *rc =3D RESETTABLE_CLASS(oc); + + resettable_class_set_parent_phases(rc, + imx8mp_mu_reset_enter, + imx8mp_mu_reset_hold, + NULL, + &imx8mp_mu_parent_phases); + 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 79954586e8..e9c21f06bb 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -65,6 +65,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 87c83c3f0e..f9fb703816 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/flexcan.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" @@ -40,6 +41,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_CANS =3D 2, FSL_IMX8MP_NUM_CPUS =3D 4, @@ -48,12 +51,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 @@ -67,6 +76,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 Sep 26 20:02:57 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 1789905375099106.58072385615662; Sun, 20 Sep 2026 04:56:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8b-0006SD-L7; Sun, 20 Sep 2026 07:55:17 -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 1x8G8Z-0006NV-9l; Sun, 20 Sep 2026 07:55:15 -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 1x8G8X-0001ay-Kf; Sun, 20 Sep 2026 07:55:15 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 290DC1A0021; Sun, 20 Sep 2026 13:55:12 +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 E6DE31A0018; Sun, 20 Sep 2026 13:55:11 +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 CB4C318000BE; Sun, 20 Sep 2026 19:55:09 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCHv3 05/10] hw/misc: Extend i.MX8MP CCM with Cortex-M7 clock outputs Date: Sun, 20 Sep 2026 17:24:53 +0530 Message-Id: <20260920115458.481605-6-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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.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: 1789905377883158500 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 Reviewed-by: Bernhard Beschow --- 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 97d363e79d..41746e1eeb 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 Sep 26 20:02:57 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 1789905414920803.9915201409492; Sun, 20 Sep 2026 04:56:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8f-0006Wz-FE; Sun, 20 Sep 2026 07:55:21 -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 1x8G8c-0006Vi-H8; Sun, 20 Sep 2026 07:55:18 -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 1x8G8Z-0001bG-CT; Sun, 20 Sep 2026 07:55:18 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id E80D41A001A; Sun, 20 Sep 2026 13:55:13 +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 894B91A0018; Sun, 20 Sep 2026 13:55:13 +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 9AA7F180006C; Sun, 20 Sep 2026 19:55:11 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 06/10] hw/arm: Enable Cortex-M7 AMP boot on i.MX8MP Date: Sun, 20 Sep 2026 17:24:54 +0530 Message-Id: <20260920115458.481605-7-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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.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: 1789905416182158500 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. Signed-off-by: Gaurav Sharma --- docs/system/arm/imx8m.rst | 184 +++++++++++++++++++++++++++++++++++- hw/arm/fsl-imx8mp.c | 116 ++++++++++++++++++----- include/hw/arm/fsl-imx8mp.h | 10 +- 3 files changed, 286 insertions(+), 24 deletions(-) diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst index cdf862a456..95fd27ec5c 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 @@ -37,6 +38,187 @@ 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 Recipe (``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 + + +Prerequisites +~~~~~~~~~~~~~ + +To manually test Cortex-M7 firmware loading from Linux, the following +components are needed: + +1. Linux kernel configuration to enable i.MX remoteproc support. +2. ``imx8mp-evk-rpmsg.dtb`` - device tree that enables the Cortex-M7 remo= teproc node, reserves DDR memory regions + for the Cortex-M7 firmware, resource table,vrings and buffers. +3. A Cortex-M7 ELF firmware image linked to execute from DDR. + +NXP application note AN5317 describes the required remoteproc and reserved= -memory setup +for loading Cortex-M firmware from Linux. + + +Linux kernel configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The guest kernel needs remoteproc support. On official linux-imx kernels, = this support is enabled by default. +When using Buildroot, verify that the kernel configuration enables the rem= oteproc and rpmsg options needed by the +i.MX remoteproc driver, for example: + +.. code-block:: none + + CONFIG_REMOTEPROC=3Dy + CONFIG_IMX_REMOTEPROC=3Dy + CONFIG_RPMSG=3Dy + CONFIG_VIRTIO_RPMSG_BUS=3Dy + CONFIG_RPMSG_CHAR=3Dy + +Depending on the kernel version and configuration, some options may be sel= ected +automatically by the i.MX remoteproc driver. + + + +Device tree preparation +~~~~~~~~~~~~~~~~~~~~~~~ + +1. Refer to ``9.1 i.MX Linux rproc support`` of application note AN5317 to= add the + following nodes in ``imx8mp-evk-rpmsg.dts`` :- + + m7_ddr_alias + m7_itcm + m7_dtcm + +2. Modify the compatible string of ``imx8mp-cm7`` node from ``fsl,imx8mn-c= m7`` to ``fsl,imx8mp-cm7-mmio`` +3. Add the following properties to the ``imx8mp-cm7`` node :- + + ``syscon =3D <&src>;`` + ``fsl,iomuxc-gpr =3D <&gpr>;`` + + These references are needed by imx_rproc_mmio_detect_mode in i.MX remot= eproc driver + for M7 boot mode detection. + + + Build ``imx8mp-evk-rpmsg.dtb`` from the above dts changes. + + + +Building a Cortex-M7 ELF firmware +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A simple manual test is the MCUXpresso SDK UART polling example for the i.= MX8MP +EVK. It prints to a UART and is therefore easy to observe from QEMU. + +1. Follow this guide to set up MCUXpresso SDK for i.MX8MPEVK :- MCUXSDKIMX= 8MPGSUG[https://share.google/qD4D09FCkkydTurqp] +2. Build a DDR-linked Cortex-M7 ELF using the ARM GNU toolchain from the M= CUXpresso SDK:- + + +.. code-block:: bash + + $ cd ${MCUX_SDK}/boards/evkmimx8mp/driver_examples/uart/polling/armgcc + $ ./build_ddr_release.sh + +As a result, ``iuart_polling_cm7.elf`` will be generated in ``ddr_release= `` folder. + +Boot qemu i.MX8MP EVK machine with the updated linux kernel and ``imx8mp-e= vk-rpmsg.dtb`` + +3. Copy the ``iuart_polling_cm7.elf`` to ``/lib/firmware/`` path inside iM= X8MPEVK qemu emulation. + + +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 + + +Starting QEMU for Cortex-M7 remoteproc testing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Execute the following command to start i.MX8MPEVK emulation:- + +.. code-block:: bash + + $ qemu-system-aarch64 -M imx8mp-evk \ + -display none -serial null -serial stdio -serial null -serial /tmp/i= mx8mp-uart4 \ + -kernel Image \ + -dtb imx8mp-evk-rpmsg.dtb \ + -append "root=3D/dev/mmcblk2p2" \ + -drive file=3Dsdcard.img,if=3Dsd,bus=3D2,format=3Draw,id=3Dmmcblk2 + +2. On a new tab execute the following to open a console:- + +.. code-block:: bash + + $ screen /tmp/imx8mp-uart4 115200 + +3. Execute the following commands inside emulation to load the firmware el= f:- + +.. code-block:: bash + + $ echo iuart_polling_cm7.elf > /sys/class/remoteproc/remoteproc0/firmwa= re + $ echo start > /sys/class/remoteproc/remoteproc0/state + + +On the tab where the console is opened, you will observe the UART logs. Th= e characters +typed from the keyboard will echo on the console. + + +Note:- + +Only DDR-linked bare-metal ELF images are currently supported by QEMU +emulation. If the firmware is linked for a vector table base address other= than +``0x80000000``, configure the Cortex-M7 vector base using the SoC property +``cm7-vector-base``:- + +.. code-block:: bash + + -global fsl-imx8mp.cm7-vector-base=3D0x80000000 + +If this property is not provided, QEMU uses ``0x80000000`` by default. + + + Direct Linux Kernel Boot '''''''''''''''''''''''' =20 @@ -73,7 +255,7 @@ 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 \ -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 2d5b5f3870..cea8be7b71 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -12,6 +12,8 @@ #include "system/address-spaces.h" #include "hw/arm/bsa.h" #include "hw/arm/fsl-imx8mp.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/qdev-clock.h" #include "hw/misc/unimp.h" #include "hw/core/boards.h" #include "system/kvm.h" @@ -21,6 +23,9 @@ #include "target/arm/kvm_arm.h" #include "qapi/error.h" #include "qobject/qlist.h" +#include "target/arm/arm-powerctl.h" + +#define IMX8MP_NUM_A53 4 =20 static const struct { hwaddr addr; @@ -196,6 +201,8 @@ static void fsl_imx8mp_init(Object *obj) FslImx8mpState *s =3D FSL_IMX8MP(obj); int i; =20 + 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); @@ -282,21 +289,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) const char *cpu_type =3D ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53= "); int i; =20 - 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); - return; - } - - for (i =3D 0; i < ms->smp.cpus; i++) { + for (i =3D 0; i < IMX8MP_NUM_A53; i++) { g_autofree char *name =3D g_strdup_printf("cpu%d", i); object_initialize_child(OBJECT(dev), name, &s->cpu[i], cpu_type); } =20 /* CPUs */ - for (i =3D 0; i < ms->smp.cpus; i++) { + for (i =3D 0; i < IMX8MP_NUM_A53; i++) { /* On uniprocessor, the CBAR is set to 0 */ - if (ms->smp.cpus > 1 && + if (IMX8MP_NUM_A53 > 1 && object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) { object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar", fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST]= .addr, @@ -339,11 +340,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) QList *redist_region_count; bool pmu =3D object_property_get_bool(OBJECT(first_cpu), "pmu", NU= LL); =20 - qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus); + qdev_prop_set_uint32(gicdev, "num-cpu", IMX8MP_NUM_A53); qdev_prop_set_uint32(gicdev, "num-irq", FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL); redist_region_count =3D qlist_new(); - qlist_append_int(redist_region_count, ms->smp.cpus); + qlist_append_int(redist_region_count, IMX8MP_NUM_A53); qdev_prop_set_array(gicdev, "redist-region-count", redist_region_c= ount); object_property_set_link(OBJECT(&s->gic), "sysmem", OBJECT(get_system_memory()), &error_fatal= ); @@ -358,7 +359,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) * maintenance interrupt signal to the appropriate GIC PPI inputs,= and * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs. */ - for (i =3D 0; i < ms->smp.cpus; i++) { + for (i =3D 0; i < IMX8MP_NUM_A53; i++) { DeviceState *cpudev =3D DEVICE(&s->cpu[i]); int intidbase =3D FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL; qemu_irq irq; @@ -388,11 +389,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) =20 sysbus_connect_irq(gicsbd, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); - sysbus_connect_irq(gicsbd, i + ms->smp.cpus, + sysbus_connect_irq(gicsbd, i + IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); - sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus, + sysbus_connect_irq(gicsbd, i + 2 * IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); - sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus, + sysbus_connect_irq(gicsbd, i + 3 * IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); =20 if (kvm_enabled()) { @@ -443,13 +444,6 @@ 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; @@ -464,6 +458,49 @@ 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 + /* 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", 160); + qdev_prop_set_bit(cm7dev, "enable-bitband", false); + + /* 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; + } + + arm_set_cpu_off(arm_cpu_mp_affinity(s->cm7.cpu)); + } + + qdev_prop_set_uint32(DEVICE(&s->src), "cm7-vector-base", + s->cm7_vector_base); + object_property_set_link(OBJECT(&s->src), "cm7-cpu", + OBJECT(s->cm7.cpu), &error_abort); + object_property_set_link(OBJECT(&s->src), "gpr", + OBJECT(&s->gpr), &error_abort); + 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); + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpr), 0, + qdev_get_gpio_in_named(DEVICE(&s->src), + "cm7-cpuwait", 0)); + /* GPTs */ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2, &error_abort); @@ -777,6 +814,37 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].addr, &s->ocram); =20 + if (!memory_region_init_ram(&s->itcm, OBJECT(dev), "imx8mp.itcm", + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_ITCM].siz= e, + errp)) { + return; + } + memory_region_add_subregion(get_system_memory(), + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_ITCM].add= r, + &s->itcm); + + if (!memory_region_init_ram(&s->dtcm, OBJECT(dev), "imx8mp.dtcm", + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_DTCM].siz= e, + errp)) { + return; + } + memory_region_add_subregion(get_system_memory(), + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_DTCM].add= r, + &s->dtcm); + + /* M7-view aliases: ITCM@0x0, DTCM@0x20000000 */ + memory_region_init_alias(&s->itcm_alias, OBJECT(dev), "imx8mp.itcm-ali= as", + &s->itcm, 0, + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_ITCM].size); + memory_region_add_subregion_overlap(get_system_memory(), + 0x00000000, &s->itcm_alias, 1); + + memory_region_init_alias(&s->dtcm_alias, OBJECT(dev), "imx8mp.dtcm-ali= as", + &s->dtcm, 0, + fsl_imx8mp_memmap[FSL_IMX8MP_TCM_DTCM].size); + memory_region_add_subregion_overlap(get_system_memory(), + 0x20000000, &s->dtcm_alias, 1); + /* Unimplemented devices */ for (i =3D 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) { switch (i) { @@ -794,6 +862,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) case FSL_IMX8MP_IOMUXC_GPR: case FSL_IMX8MP_MU_1_A ... FSL_IMX8MP_MU_3_B: case FSL_IMX8MP_OCRAM: + case FSL_IMX8MP_TCM_ITCM: + case FSL_IMX8MP_TCM_DTCM: case FSL_IMX8MP_PCIE1: case FSL_IMX8MP_PCIE_PHY1: case FSL_IMX8MP_RAM: @@ -822,6 +892,8 @@ static const Property fsl_imx8mp_properties[] =3D { CanBusState *), DEFINE_PROP_LINK("canbus1", FslImx8mpState, canbus[1], TYPE_CAN_BUS, CanBusState *), + 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 f9fb703816..317e6a4576 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" @@ -67,6 +68,9 @@ struct FslImx8mpState { SysBusDevice parent_obj; =20 ARMCPU cpu[FSL_IMX8MP_NUM_CPUS]; + ARMv7MState cm7; + bool enable_cm7; + uint32_t cm7_vector_base; GICv3State gic; IMX8MPGPCState gpc; IMX8MPGPRState gpr; @@ -89,13 +93,17 @@ struct FslImx8mpState { FlexcanState flexcan[FSL_IMX8MP_NUM_CANS]; OrIRQState gpt5_gpt6_irq; MemoryRegion ocram; - + MemoryRegion itcm; + MemoryRegion dtcm; + MemoryRegion itcm_alias; + MemoryRegion dtcm_alias; uint32_t phy_num; bool phy_connected; =20 CanBusState *canbus[FSL_IMX8MP_NUM_CANS]; }; =20 + enum FslImx8mpMemoryRegions { FSL_IMX8MP_A53_DAP, FSL_IMX8MP_AIPS1_CONFIGURATION, --=20 2.34.1 From nobody Sat Sep 26 20:02:57 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 178990538939672.84138609099239; Sun, 20 Sep 2026 04:56:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8f-0006Wx-6v; Sun, 20 Sep 2026 07:55:21 -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 1x8G8c-0006Vl-OR; Sun, 20 Sep 2026 07:55:18 -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 1x8G8a-0001bh-S7; Sun, 20 Sep 2026 07:55:18 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 663701A002E; Sun, 20 Sep 2026 13:55:15 +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 2E9131A0018; Sun, 20 Sep 2026 13:55:15 +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 402BA18000BA; Sun, 20 Sep 2026 19:55:13 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 07/10] hw/arm: Rename FSL_IMX8MP_NUM_CPUS to FSL_IMX8MP_NUM_A53 Date: Sun, 20 Sep 2026 17:24:55 +0530 Message-Id: <20260920115458.481605-8-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905395939158500 Content-Type: text/plain; charset="utf-8" The Cortex-M7 is not an A53 and is not part of the cpu[] array. Rename the constant to make the A53-only scope explicit, introduce FSL_IMX8MP_NUM_M7 for the single Cortex-M7 core, and remove the redundant local IMX8MP_NUM_A53 define from fsl-imx8mp.c Signed-off-by: Gaurav Sharma --- hw/arm/fsl-imx8mp.c | 19 +++++++++---------- hw/arm/imx8mp-evk.c | 5 +++-- include/hw/arm/fsl-imx8mp.h | 5 +++-- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index cea8be7b71..e7dafa2403 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -25,7 +25,6 @@ #include "qobject/qlist.h" #include "target/arm/arm-powerctl.h" =20 -#define IMX8MP_NUM_A53 4 =20 static const struct { hwaddr addr; @@ -289,15 +288,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) const char *cpu_type =3D ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53= "); int i; =20 - for (i =3D 0; i < IMX8MP_NUM_A53; i++) { + for (i =3D 0; i < FSL_IMX8MP_NUM_A53; i++) { g_autofree char *name =3D g_strdup_printf("cpu%d", i); object_initialize_child(OBJECT(dev), name, &s->cpu[i], cpu_type); } =20 /* CPUs */ - for (i =3D 0; i < IMX8MP_NUM_A53; i++) { + for (i =3D 0; i < FSL_IMX8MP_NUM_A53; i++) { /* On uniprocessor, the CBAR is set to 0 */ - if (IMX8MP_NUM_A53 > 1 && + if (FSL_IMX8MP_NUM_A53 > 1 && object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) { object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar", fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST]= .addr, @@ -340,11 +339,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) QList *redist_region_count; bool pmu =3D object_property_get_bool(OBJECT(first_cpu), "pmu", NU= LL); =20 - qdev_prop_set_uint32(gicdev, "num-cpu", IMX8MP_NUM_A53); + qdev_prop_set_uint32(gicdev, "num-cpu", FSL_IMX8MP_NUM_A53); qdev_prop_set_uint32(gicdev, "num-irq", FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL); redist_region_count =3D qlist_new(); - qlist_append_int(redist_region_count, IMX8MP_NUM_A53); + qlist_append_int(redist_region_count, FSL_IMX8MP_NUM_A53); qdev_prop_set_array(gicdev, "redist-region-count", redist_region_c= ount); object_property_set_link(OBJECT(&s->gic), "sysmem", OBJECT(get_system_memory()), &error_fatal= ); @@ -359,7 +358,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) * maintenance interrupt signal to the appropriate GIC PPI inputs,= and * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs. */ - for (i =3D 0; i < IMX8MP_NUM_A53; i++) { + for (i =3D 0; i < FSL_IMX8MP_NUM_A53; i++) { DeviceState *cpudev =3D DEVICE(&s->cpu[i]); int intidbase =3D FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL; qemu_irq irq; @@ -389,11 +388,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) =20 sysbus_connect_irq(gicsbd, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); - sysbus_connect_irq(gicsbd, i + IMX8MP_NUM_A53, + sysbus_connect_irq(gicsbd, i + FSL_IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); - sysbus_connect_irq(gicsbd, i + 2 * IMX8MP_NUM_A53, + sysbus_connect_irq(gicsbd, i + 2 * FSL_IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); - sysbus_connect_irq(gicsbd, i + 3 * IMX8MP_NUM_A53, + sysbus_connect_irq(gicsbd, i + 3 * FSL_IMX8MP_NUM_A53, qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); =20 if (kvm_enabled()) { diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c index 3f376f86d9..432a146efd 100644 --- a/hw/arm/imx8mp-evk.c +++ b/hw/arm/imx8mp-evk.c @@ -147,8 +147,9 @@ static void imx8mp_evk_machine_class_init(ObjectClass *= oc, const void *data) =20 mc->desc =3D "NXP i.MX 8M Plus EVK Board"; mc->init =3D imx8mp_evk_init; - mc->default_cpus =3D 4; - mc->max_cpus =3D FSL_IMX8MP_NUM_CPUS; + mc->default_cpus =3D FSL_IMX8MP_NUM_A53 + FSL_IMX8MP_NUM_M7; + mc->min_cpus =3D FSL_IMX8MP_NUM_A53 + FSL_IMX8MP_NUM_M7; + mc->max_cpus =3D FSL_IMX8MP_NUM_A53 + FSL_IMX8MP_NUM_M7; mc->default_ram_id =3D "imx8mp-evk.ram"; mc->default_ram_size =3D 6 * GiB; mc->get_default_cpu_type =3D imx8mp_evk_get_default_cpu_type; diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index 317e6a4576..e8d84f82b5 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -46,7 +46,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP) =20 enum FslImx8mpConfiguration { FSL_IMX8MP_NUM_CANS =3D 2, - FSL_IMX8MP_NUM_CPUS =3D 4, + FSL_IMX8MP_NUM_A53 =3D 4, + FSL_IMX8MP_NUM_M7 =3D 1, FSL_IMX8MP_NUM_ECSPIS =3D 3, FSL_IMX8MP_NUM_GPIOS =3D 5, FSL_IMX8MP_NUM_GPTS =3D 6, @@ -67,7 +68,7 @@ typedef struct IMX8MPMUPair { struct FslImx8mpState { SysBusDevice parent_obj; =20 - ARMCPU cpu[FSL_IMX8MP_NUM_CPUS]; + ARMCPU cpu[FSL_IMX8MP_NUM_A53]; ARMv7MState cm7; bool enable_cm7; uint32_t cm7_vector_base; --=20 2.34.1 From nobody Sat Sep 26 20:02:57 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 1789905396843162.63549757932083; Sun, 20 Sep 2026 04:56:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8h-0006Yh-Kz; Sun, 20 Sep 2026 07:55:23 -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 1x8G8e-0006Wg-Ar; Sun, 20 Sep 2026 07:55:20 -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 1x8G8c-0001c3-Hm; Sun, 20 Sep 2026 07:55:19 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 0C9071A0029; Sun, 20 Sep 2026 13:55:17 +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 CB1831A0018; Sun, 20 Sep 2026 13:55:16 +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 D95B1180006C; Sun, 20 Sep 2026 19:55:14 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 08/10] MAINTAINERS: Merge MCIMX8MM-EVK and MCIMX8MP-EVK entries Date: Sun, 20 Sep 2026 17:24:56 +0530 Message-Id: <20260920115458.481605-9-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905397889158500 Content-Type: text/plain; charset="utf-8" Merge the separate MCIMX8MM-EVK and MCIMX8MP-EVK MAINTAINERS entries into a single combined entry covering both SoC families. Signed-off-by: Gaurav Sharma Reviewed-by: Bernhard Beschow --- MAINTAINERS | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6be9c5725b..7120784ec7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -933,29 +933,24 @@ F: hw/pci-host/designware.c F: include/hw/pci-host/designware.h F: docs/system/arm/mcimx7d-sabre.rst =20 -MCIMX8MM-EVK / iMX8MM +MCIMX8MP-EVK / MCIMX8MM-EVK +M: Bernhard Beschow M: Gaurav Sharma L: qemu-arm@nongnu.org S: Maintained F: hw/arm/fsl-imx8mm.c F: hw/arm/imx8mm-evk.c -F: include/hw/arm/fsl-imx8mm.h -F: docs/system/arm/imx8m.rst -F: tests/functional/aarch64/test_imx8mm_evk.py - -MCIMX8MP-EVK / i.MX8MP -M: Bernhard Beschow -L: qemu-arm@nongnu.org -S: Maintained F: hw/arm/imx8mp-evk.c F: hw/arm/fsl-imx8mp.c F: hw/misc/imx8mp_*.c F: hw/pci-host/fsl_imx8m_phy.c F: hw/rtc/rs5c372.c +F: include/hw/arm/fsl-imx8mm.h F: include/hw/arm/fsl-imx8mp.h F: include/hw/misc/imx8mp_*.h F: include/hw/pci-host/fsl_imx8m_phy.h F: docs/system/arm/imx8m.rst +F: tests/functional/aarch64/test_imx8mm_evk.py F: tests/functional/aarch64/test_imx8mp_evk.py F: tests/qtest/rs5c372-test.c =20 --=20 2.34.1 From nobody Sat Sep 26 20:02:57 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 1789905452947297.9363554950519; Sun, 20 Sep 2026 04:57:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8j-0006Zs-ET; Sun, 20 Sep 2026 07:55:25 -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 1x8G8g-0006Xc-Sh; Sun, 20 Sep 2026 07:55:23 -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 1x8G8e-0001cW-EP; Sun, 20 Sep 2026 07:55:22 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id A8360200018; Sun, 20 Sep 2026 13:55:18 +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 71896200008; Sun, 20 Sep 2026 13:55:18 +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 8089018000BE; Sun, 20 Sep 2026 19:55:16 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 09/10] hw/arm: Add IRQ splitter for i.MX8MP AMP interrupt routing Date: Sun, 20 Sep 2026 17:24:57 +0530 Message-Id: <20260920115458.481605-10-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905454093158500 Content-Type: text/plain; charset="utf-8" Wire all 160 SoC SPI interrupt lines through SplitIRQ splitters so that each interrupt is delivered to both the Cortex-A53 GICv3 and the Cortex-M7 NVIC simultaneously. As per i.MX8MP RM Table 7-2 the same interrupt lines are routed to both cores. Signed-off-by: Gaurav Sharma --- hw/arm/fsl-imx8mp.c | 59 +++++++++++++++++++++++++------------ include/hw/arm/fsl-imx8mp.h | 2 ++ 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index e7dafa2403..17733c7270 100644 --- a/hw/arm/fsl-imx8mp.c +++ b/hw/arm/fsl-imx8mp.c @@ -200,6 +200,12 @@ static void fsl_imx8mp_init(Object *obj) FslImx8mpState *s =3D FSL_IMX8MP(obj); int i; =20 + for (i =3D 0; i < FSL_IMX8MP_NUM_IRQS; i++) { + g_autofree char *name =3D g_strdup_printf("irq-splitter%d", i); + object_initialize_child(obj, name, &s->cpu_irq_splitter[i], + TYPE_SPLIT_IRQ); + } + object_initialize_child(obj, "cm7", &s->cm7, TYPE_ARMV7M); =20 object_initialize_child(obj, "gic", &s->gic, gicv3_class_name()); @@ -286,6 +292,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) FslImx8mpState *s =3D FSL_IMX8MP(dev); DeviceState *gicdev =3D DEVICE(&s->gic); const char *cpu_type =3D ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53= "); + qemu_irq spi_irq[FSL_IMX8MP_NUM_IRQS]; int i; =20 for (i =3D 0; i < FSL_IMX8MP_NUM_A53; i++) { @@ -407,6 +414,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) } } =20 + for (i =3D 0; i < FSL_IMX8MP_NUM_IRQS; i++) { + DeviceState *splitter =3D DEVICE(&s->cpu_irq_splitter[i]); + qdev_prop_set_uint16(splitter, "num-lines", 2); + qdev_realize(splitter, NULL, &error_abort); + spi_irq[i] =3D qdev_get_gpio_in(splitter, 0); + qdev_connect_gpio_out(splitter, 0, + qdev_get_gpio_in(gicdev, i)); + } + /* CCM */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) { return; @@ -440,7 +456,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].ad= dr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, - qdev_get_gpio_in(gicdev, serial_table[i].irq)); + spi_irq[serial_table[i].irq]); } =20 /* GPC */ @@ -482,6 +498,11 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error= **errp) } =20 arm_set_cpu_off(arm_cpu_mp_affinity(s->cm7.cpu)); + + for (i =3D 0; i < FSL_IMX8MP_NUM_IRQS; i++) { + qdev_connect_gpio_out(DEVICE(&s->cpu_irq_splitter[i]), 1, + qdev_get_gpio_in(DEVICE(&s->cm7), i)); + } } =20 qdev_prop_set_uint32(DEVICE(&s->src), "cm7-vector-base", @@ -508,7 +529,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) } =20 qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_GPT5_GPT6_IR= Q)); + spi_irq[FSL_IMX8MP_GPT5_GPT6_IRQ]); =20 for (i =3D 0; i < FSL_IMX8MP_NUM_GPTS; i++) { hwaddr gpt_addrs[FSL_IMX8MP_NUM_GPTS] =3D { @@ -537,7 +558,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) }; =20 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0, - qdev_get_gpio_in(gicdev, gpt_irqs[i])); + spi_irq[gpt_irqs[i]]); } else { int irq =3D i - FSL_IMX8MP_NUM_GPTS + 2; =20 @@ -572,7 +593,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) } =20 sysbus_connect_irq(SYS_BUS_DEVICE(&s->mu[0].a), 0, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_MU1_A_IRQ)); + spi_irq[FSL_IMX8MP_MU1_A_IRQ]); =20 /* I2Cs */ for (i =3D 0; i < FSL_IMX8MP_NUM_I2CS; i++) { @@ -594,7 +615,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, - qdev_get_gpio_in(gicdev, i2c_table[i].irq)); + spi_irq[i2c_table[i].irq]); } =20 /* GPIOs */ @@ -641,9 +662,9 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr= ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0, - qdev_get_gpio_in(gicdev, gpio_table[i].irq_low)= ); + spi_irq[gpio_table[i].irq_low]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1, - qdev_get_gpio_in(gicdev, gpio_table[i].irq_high= )); + spi_irq[gpio_table[i].irq_high]); } =20 /* USDHCs */ @@ -663,7 +684,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].ad= dr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, - qdev_get_gpio_in(gicdev, usdhc_table[i].irq)); + spi_irq[usdhc_table[i].irq]); } =20 /* USBs */ @@ -684,7 +705,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0, - qdev_get_gpio_in(gicdev, usb_table[i].irq)); + spi_irq[usb_table[i].irq]); } =20 /* ECSPIs */ @@ -704,7 +725,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, - qdev_get_gpio_in(gicdev, spi_table[i].irq)); + spi_irq[spi_table[i].irq]); } =20 /* ENET1 */ @@ -718,9 +739,9 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0, fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ)); + spi_irq[FSL_IMX8MP_ENET1_MAC_IRQ]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1, - qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IR= Q)); + spi_irq[FSL_IMX6_ENET1_MAC_1588_IRQ]); =20 /* SNVS */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) { @@ -748,7 +769,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) =20 sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, - qdev_get_gpio_in(gicdev, wdog_table[i].irq)); + spi_irq[wdog_table[i].irq]); } =20 /* PCIe */ @@ -759,15 +780,15 @@ static void fsl_imx8mp_realize(DeviceState *dev, Erro= r **errp) fsl_imx8mp_memmap[FSL_IMX8MP_PCIE1].addr); =20 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTA_IRQ)); + spi_irq[FSL_IMX8MP_PCI_INTA_IRQ]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTB_IRQ)); + spi_irq[FSL_IMX8MP_PCI_INTB_IRQ]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTC_IRQ)); + spi_irq[FSL_IMX8MP_PCI_INTC_IRQ]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTD_IRQ)); + spi_irq[FSL_IMX8MP_PCI_INTD_IRQ]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, - qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_MSI_IRQ)); + spi_irq[FSL_IMX8MP_PCI_MSI_IRQ]); =20 if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) { return; @@ -800,7 +821,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error = **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->flexcan[i]), 0, flexcan_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->flexcan[i]), 0, - qdev_get_gpio_in(gicdev, flexcan_table[i].irq)); + spi_irq[flexcan_table[i].irq]); } =20 /* On-Chip RAM */ diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index e8d84f82b5..1685938a0b 100644 --- a/include/hw/arm/fsl-imx8mp.h +++ b/include/hw/arm/fsl-imx8mp.h @@ -25,6 +25,7 @@ #include "hw/net/flexcan.h" #include "hw/net/imx_fec.h" #include "hw/core/or-irq.h" +#include "hw/core/split-irq.h" #include "hw/pci-host/designware.h" #include "hw/pci-host/fsl_imx8m_phy.h" #include "hw/sd/sdhci.h" @@ -93,6 +94,7 @@ struct FslImx8mpState { FslImx8mPciePhyState pcie_phy; FlexcanState flexcan[FSL_IMX8MP_NUM_CANS]; OrIRQState gpt5_gpt6_irq; + SplitIRQ cpu_irq_splitter[FSL_IMX8MP_NUM_IRQS]; MemoryRegion ocram; MemoryRegion itcm; MemoryRegion dtcm; --=20 2.34.1 From nobody Sat Sep 26 20:02:57 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 1789905432303338.89379623432694; Sun, 20 Sep 2026 04:57:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x8G8j-0006a7-JX; Sun, 20 Sep 2026 07:55:25 -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 1x8G8i-0006Yw-1q; Sun, 20 Sep 2026 07:55:24 -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 1x8G8g-0001cu-2h; Sun, 20 Sep 2026 07:55:23 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 578AB200027; Sun, 20 Sep 2026 13:55:20 +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 21A4B200020; Sun, 20 Sep 2026 13:55:20 +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 273CB180006C; Sun, 20 Sep 2026 19:55:18 +0800 (+08) From: Gaurav Sharma To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, pbonzini@redhat.com, peter.maydell@linaro.org, shentey@gmail.com, pierrick.bouvier@oss.qualcomm.com, Gaurav Sharma Subject: [PATCHv3 10/10] tests/functional: Fix i.MX8MP EVK SMP configuration Date: Sun, 20 Sep 2026 17:24:58 +0530 Message-Id: <20260920115458.481605-11-gaurav.sharma_7@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260920115458.481605-1-gaurav.sharma_7@nxp.com> References: <20260920115458.481605-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: 1789905434107158500 Content-Type: text/plain; charset="utf-8" Remove the explicit '-smp 4' argument from the functional test. The SMP CPU count is now fixed internally via mc->default_cpus and no longer needs to be specified by the caller. Signed-off-by: Gaurav Sharma --- tests/functional/aarch64/test_imx8mp_evk.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/aarch64/test_imx8mp_evk.py b/tests/functional= /aarch64/test_imx8mp_evk.py index 99ddcdef83..6046c573d5 100755 --- a/tests/functional/aarch64/test_imx8mp_evk.py +++ b/tests/functional/aarch64/test_imx8mp_evk.py @@ -53,7 +53,6 @@ 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', '-kernel', self.kernel_path, '-initrd', self.initrd_path, '-dtb', self.dtb_path, --=20 2.34.1