[PATCH 2/4] imx9: bootaux: Support booting CM70, CM71 and CM33 sync cores

ye.li at oss.nxp.com ye.li at oss.nxp.com
Wed Jun 17 16:14:44 CEST 2026


From: Alice Guo <alice.guo at nxp.com>

Support booting CM70, CM71 and CM33 sync core image by bootaux command
on iMX95, iMX94 and iMX952. (iMX95 and iMX952 only supports CM70).

Each core uses different core id which is defined by SM and passed in
SIP call.
 - CM33:  0
 - CM70:  1
 - CM71:  7
 - CM33S: 8

Prior to run bootaux to start core, prepaux is needed before loading
image. Below is example for booting CM70 TCM image on iMX95.

    =>fatload mmc 1:1 0x90000000 rpmsg.bin
    =>prepaux 1
    =>cp.b 0x90000000 0x203c0000 ${filesize}
    =>bootaux 0 1

Signed-off-by: Alice Guo <alice.guo at nxp.com>
Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 arch/arm/include/asm/arch-imx9/imx-regs.h |  18 +++
 arch/arm/mach-imx/imx9/imx_bootaux.c      | 188 ++++++++++++++++++----
 arch/arm/mach-imx/imx9/scmi/soc.c         |  33 +++-
 include/imx_sip.h                         |   2 +
 4 files changed, 206 insertions(+), 35 deletions(-)

diff --git a/arch/arm/include/asm/arch-imx9/imx-regs.h b/arch/arm/include/asm/arch-imx9/imx-regs.h
index 47d6ae9b559..55f4f34e1bc 100644
--- a/arch/arm/include/asm/arch-imx9/imx-regs.h
+++ b/arch/arm/include/asm/arch-imx9/imx-regs.h
@@ -47,6 +47,16 @@
 #define SRC_MEDIA_RBASE		(SRC_IPS_BASE_ADDR + 0x2400)
 #define SRC_M33P_RBASE		(SRC_IPS_BASE_ADDR + 0x2800)
 
+#ifdef CONFIG_IMX94
+#define TCML_BASE_ADDR              (0x209C0000UL)
+#define TCML_BASE_MCORE_SEC_ADDR    (0x1FFC0000UL)
+#define TCML_BASE_MCORE_NSEC_ADDR   (0x0FFC0000UL)
+#define TCML_SIZE                   (0x40000U)
+#define TCMU_BASE_ADDR              (0x20A00000UL)
+#define TCMU_BASE_MCORE_SEC_ADDR    (0x30000000UL)
+#define TCMU_BASE_MCORE_NSEC_ADDR   (0x20000000UL)
+#define TCMU_SIZE                   (0x40000U)
+#else
 #define TCML_BASE_ADDR              (0x201E0000UL)
 #define TCML_BASE_MCORE_SEC_ADDR    (0x1FFE0000UL)
 #define TCML_BASE_MCORE_NSEC_ADDR   (0x0FFE0000UL)
@@ -55,6 +65,14 @@
 #define TCMU_BASE_MCORE_SEC_ADDR    (0x30000000UL)
 #define TCMU_BASE_MCORE_NSEC_ADDR   (0x20000000UL)
 #define TCMU_SIZE                   (0x20000U)
+#endif
+
+#define M7_TCML_BASE_ADDR           (0x20380000UL)
+#define M7_TCML_BASE_MCORE_ADDR     (0x0UL)
+#define M7_TCML_MAX_SIZE            (0x80000U) /* Could configure to 512KB TCML */
+#define M71_TCML_BASE_ADDR          (0x20280000UL)
+#define M71_TCML_BASE_MCORE_ADDR    (0x0UL)
+#define M71_TCML_MAX_SIZE           (0x80000U) /* Could configure to 512KB TCML */
 
 #define FLEXSPI_AHB_ADDR            (0x28000000UL)
 #define FLEXSPI_AHB_SIZE            (0x8000000UL)
diff --git a/arch/arm/mach-imx/imx9/imx_bootaux.c b/arch/arm/mach-imx/imx9/imx_bootaux.c
index d3494a9baa9..ce43f6bc3a8 100644
--- a/arch/arm/mach-imx/imx9/imx_bootaux.c
+++ b/arch/arm/mach-imx/imx9/imx_bootaux.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2022 NXP
+ * Copyright 2022, 2026 NXP
  */
 
 #include <command.h>
@@ -16,11 +16,16 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define CORE_CM33	0
+#define CORE_CM7	1
+#define CORE_CM71	7
+#define CORE_CM33S	8
+
 int arch_auxiliary_core_check_up(u32 core_id)
 {
 	struct arm_smccc_res res;
 
-	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STARTED, 0, 0,
+	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STARTED, 0, core_id,
 		      0, 0, 0, 0, &res);
 
 	return res.a0;
@@ -32,7 +37,7 @@ int arch_auxiliary_core_down(u32 core_id)
 
 	printf("## Stopping auxiliary core\n");
 
-	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STOP, 0, 0,
+	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_STOP, 0, core_id,
 		      0, 0, 0, 0, &res);
 
 	return 0;
@@ -42,17 +47,48 @@ int arch_auxiliary_core_up(u32 core_id, ulong addr)
 {
 	struct arm_smccc_res res;
 
-	if (!addr)
-		return -EINVAL;
-
 	printf("## Starting auxiliary core addr = 0x%08lX...\n", addr);
 
-	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_START, addr, 0,
+	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_START, addr, core_id,
+		      0, 0, 0, 0, &res);
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_SCMI_FIRMWARE)
+int arch_auxiliary_core_prepare(u32 core_id)
+{
+	struct arm_smccc_res res;
+
+	printf("## Preparing auxiliary core: %d\n", core_id);
+
+	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_PREP, 0, core_id,
+		      0, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
+int arch_auxiliary_core_prepared(u32 core_id)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_MCU_PREPED, 0, core_id,
 		      0, 0, 0, 0, &res);
 
+	return res.a0;
+}
+#else
+int arch_auxiliary_core_prepare(u32 core_id)
+{
 	return 0;
 }
 
+bool arch_auxiliary_core_prepared(u32 core_id)
+{
+	return true;
+}
+#endif
+
 static inline bool check_in_ddr(ulong addr)
 {
 	int i;
@@ -69,26 +105,42 @@ static inline bool check_in_ddr(ulong addr)
 	return false;
 }
 
-static inline bool check_in_tcm(ulong addr, bool mcore_view)
+static inline bool check_in_tcm(u32 core_id, ulong addr, bool mcore_view)
 {
 	if (mcore_view) {
-		if ((addr >= TCML_BASE_MCORE_SEC_ADDR &&
-		     addr < TCML_BASE_MCORE_SEC_ADDR + TCML_SIZE) ||
-		    (addr >= TCMU_BASE_MCORE_SEC_ADDR &&
-		     addr < TCMU_BASE_MCORE_SEC_ADDR + TCMU_SIZE))
-			return true;
-
-		if ((addr >= TCML_BASE_MCORE_NSEC_ADDR &&
-		     addr < TCML_BASE_MCORE_NSEC_ADDR + TCML_SIZE) ||
-		    (addr >= TCMU_BASE_MCORE_NSEC_ADDR &&
-		     addr < TCMU_BASE_MCORE_NSEC_ADDR + TCMU_SIZE))
-			return true;
+		if (core_id == CORE_CM33 || core_id == CORE_CM33S) {
+			if ((addr >= TCML_BASE_MCORE_SEC_ADDR &&
+			     addr < TCML_BASE_MCORE_SEC_ADDR + TCML_SIZE) ||
+			    (addr >= TCMU_BASE_MCORE_SEC_ADDR &&
+			     addr < TCMU_BASE_MCORE_SEC_ADDR + TCMU_SIZE))
+				return true;
+
+			if ((addr >= TCML_BASE_MCORE_NSEC_ADDR &&
+			     addr < TCML_BASE_MCORE_NSEC_ADDR + TCML_SIZE) ||
+			    (addr >= TCMU_BASE_MCORE_NSEC_ADDR &&
+			     addr < TCMU_BASE_MCORE_NSEC_ADDR + TCMU_SIZE))
+				return true;
+		} else if (core_id == CORE_CM7 || core_id == CORE_CM71) {
+			if (addr >= M7_TCML_BASE_MCORE_ADDR &&
+			    addr < M7_TCML_BASE_MCORE_ADDR + M7_TCML_MAX_SIZE)
+				return true;
+		}
 	} else {
-		if ((addr >= TCML_BASE_ADDR &&
-		     addr < TCML_BASE_ADDR + TCML_SIZE) ||
-		    (addr >= TCMU_BASE_ADDR &&
-		     addr < TCMU_BASE_ADDR + TCMU_SIZE))
-			return true;
+		if (core_id == CORE_CM33 || core_id == CORE_CM33S) {
+			if ((addr >= TCML_BASE_ADDR &&
+			     addr < TCML_BASE_ADDR + TCML_SIZE) ||
+			    (addr >= TCMU_BASE_ADDR &&
+			     addr < TCMU_BASE_ADDR + TCMU_SIZE))
+				return true;
+		} else if (core_id == CORE_CM7) {
+			if (addr >= M7_TCML_BASE_ADDR &&
+			    addr < M7_TCML_BASE_ADDR + M7_TCML_MAX_SIZE)
+				return true;
+		} else if (core_id == CORE_CM71) {
+			if (addr >= M71_TCML_BASE_ADDR &&
+			    addr < M71_TCML_BASE_ADDR + M7_TCML_MAX_SIZE)
+				return true;
+		}
 	}
 	return false;
 }
@@ -102,7 +154,7 @@ static inline bool check_in_flexspi(ulong addr)
 }
 
 #if IS_ENABLED(CONFIG_AHAB_BOOT)
-static int authenticate_auxcore_container(ulong addr, ulong *entry)
+static int authenticate_auxcore_container(u32 core_id, ulong addr, ulong *entry)
 {
 	struct container_hdr *phdr;
 	int i, ret = 0;
@@ -115,7 +167,8 @@ static int authenticate_auxcore_container(ulong addr, ulong *entry)
 		return -EINVAL;
 	}
 
-	if (!check_in_ddr(addr) && !check_in_tcm(addr, false) && !check_in_flexspi(addr)) {
+	if (!check_in_ddr(addr) && !check_in_tcm(core_id, addr, false) &&
+	    !check_in_flexspi(addr)) {
 		printf("Error: Container's address is invalid\n");
 		return -EINVAL;
 	}
@@ -148,7 +201,7 @@ static int authenticate_auxcore_container(ulong addr, ulong *entry)
 					    i * sizeof(struct boot_img_t));
 
 		/* Check Core ID of M core */
-		if ((img->meta & 0xff) != 0) {
+		if ((img->meta & 0xff) != core_id) {
 			printf("Error: Wrong Image core ID, meta = 0x%x\n", img->meta);
 			ret = -EFAULT;
 			break;
@@ -164,7 +217,8 @@ static int authenticate_auxcore_container(ulong addr, ulong *entry)
 				break;
 			}
 		} else {
-			if (!check_in_ddr(img->dst) && !check_in_tcm(img->dst, false)) {
+			if (!check_in_ddr(img->dst) &&
+			    !check_in_tcm(core_id, img->dst, false)) {
 				printf("Error: Invalid Image[%u] load address 0x%llx\n",
 				       i, img->dst);
 				ret = -EFAULT;
@@ -218,6 +272,12 @@ static int do_bootaux_cntr(struct cmd_tbl *cmdtp, int flag, int argc,
 		return CMD_RET_SUCCESS;
 	}
 
+	up = arch_auxiliary_core_prepared(core);
+	if (!up) {
+		printf("## Not prepared, run 'prepaux [coreid]' first\n");
+		return CMD_RET_FAILURE;
+	}
+
 	addr = simple_strtoul(argv[1], NULL, 16);
 
 	if (!addr)
@@ -225,13 +285,13 @@ static int do_bootaux_cntr(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	printf("Authenticate auxcore container at 0x%lx\n", addr);
 
-	ret = authenticate_auxcore_container(addr, &entry);
+	ret = authenticate_auxcore_container(core, addr, &entry);
 	if (ret) {
 		printf("Authenticate container failed %d\n", ret);
 		return CMD_RET_FAILURE;
 	}
 
-	if (!check_in_ddr(entry) && !check_in_tcm(entry, true) &&
+	if (!check_in_ddr(entry) && !check_in_tcm(core, entry, true) &&
 	    !check_in_flexspi(entry)) {
 		printf("Error: Image's entry 0x%lx is invalid\n", entry);
 		return CMD_RET_FAILURE;
@@ -281,12 +341,20 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc,
 		return CMD_RET_SUCCESS;
 	}
 
+	up = arch_auxiliary_core_prepared(core);
+	if (!up) {
+		printf("## Not prepared, run 'prepaux [coreid]' first\n");
+		return CMD_RET_FAILURE;
+	}
+
 	addr = simple_strtoul(argv[1], NULL, 16);
 
-	if (!addr)
+	if ((core != CORE_CM7 && core != CORE_CM71) && !addr) {
+		printf("Invalid address 0x%lx for core: %d\n", addr, core);
 		return CMD_RET_FAILURE;
+	}
 
-	if (!check_in_ddr(addr) && !check_in_tcm(addr, true) && !check_in_flexspi(addr)) {
+	if (!check_in_ddr(addr) && !check_in_tcm(core, addr, true) && !check_in_flexspi(addr)) {
 		printf("Error: Image's address 0x%lx is invalid\n", addr);
 		printf("     Address should be memory from M core view,\n"
 			   "     For example: 0x1ffe0000 for TCML in secure\n");
@@ -305,14 +373,21 @@ static int do_stopaux(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
 	int ret, up;
+	u32 core = 0;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	if (argc > 2)
+		core = simple_strtoul(argv[2], NULL, 10);
 
-	up = arch_auxiliary_core_check_up(0);
+	up = arch_auxiliary_core_check_up(core);
 	if (!up) {
 		printf("## Auxiliary core is already down\n");
 		return CMD_RET_SUCCESS;
 	}
 
-	ret = arch_auxiliary_core_down(0);
+	ret = arch_auxiliary_core_down(core);
 	if (ret)
 		return CMD_RET_FAILURE;
 
@@ -325,6 +400,41 @@ U_BOOT_CMD(
 	"<address> [<core>]\n"
 	"   - start auxiliary core [<core>] (default 0),\n"
 	"     at address <address>\n"
+	"     <core>:\n"
+	"         0 - CM33\n"
+	"         1 - CM70\n"
+	"         7 - CM71\n"
+	"         8 - CM33 Sync\n"
+);
+
+static int do_prepaux(struct cmd_tbl *cmdtp, int flag, int argc,
+		      char *const argv[])
+{
+	int ret;
+	u32 core = 0;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	core = simple_strtoul(argv[1], NULL, 10);
+
+	ret = arch_auxiliary_core_prepare(core);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+	prepaux, CONFIG_SYS_MAXARGS, 1,	do_prepaux,
+	"prepare auxiliary core",
+	"[<core>]\n"
+	"   - prep auxiliary core [<core>] (default 0),\n"
+	"     <core>:\n"
+	"         0 - CM33\n"
+	"         1 - CM70\n"
+	"         7 - CM71\n"
+	"         8 - CM33 Sync\n"
 );
 
 #if IS_ENABLED(CONFIG_AHAB_BOOT)
@@ -334,6 +444,11 @@ U_BOOT_CMD(
 	"<container_address> [<core>]\n"
 	"   - start auxiliary core [<core>] (default 0),\n"
 	"     with signed container image at address <address> in A core view\n"
+	"     <core>:\n"
+	"         0 - CM33\n"
+	"         1 - CM70\n"
+	"         7 - CM71\n"
+	"         8 - CM33 Sync\n"
 );
 #else
 U_BOOT_CMD(
@@ -342,5 +457,10 @@ U_BOOT_CMD(
 	"<address> [<core>]\n"
 	"   - start auxiliary core [<core>] (default 0),\n"
 	"     at address <address> of auxiliary core view\n"
+	"     <core>:\n"
+	"         0 - CM33\n"
+	"         1 - CM70\n"
+	"         7 - CM71\n"
+	"         8 - CM33 Sync\n"
 );
 #endif
diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c
index 3f71f0ee6e9..372dfc5518e 100644
--- a/arch/arm/mach-imx/imx9/scmi/soc.c
+++ b/arch/arm/mach-imx/imx9/scmi/soc.c
@@ -247,7 +247,38 @@ static struct mm_region imx9_mem_map[] = {
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
-	}, {
+	},
+#if IS_ENABLED(CONFIG_IMX94)
+	{
+		/* M71 TCM */
+		.virt = 0x202c0000UL,
+		.phys = 0x202c0000UL,
+		.size = 0x80000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{
+		/* M33S TCM */
+		.virt = 0x209c0000UL,
+		.phys = 0x209c0000UL,
+		.size = 0x80000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	/* 644K netc ocram for rpmsg buffer */
+	{
+		/* M33S NETC OCRAM */
+		.virt = 0x20800000UL,
+		.phys = 0x20800000UL,
+		.size = 0xa1000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#endif
+	{
 		/* OCRAM */
 		.virt = 0x20480000UL,
 		.phys = 0x20480000UL,
diff --git a/include/imx_sip.h b/include/imx_sip.h
index 8a5ca34f393..478cbd3fdaf 100644
--- a/include/imx_sip.h
+++ b/include/imx_sip.h
@@ -16,5 +16,7 @@
 #define IMX_SIP_SRC_MCU_START	0x00
 #define IMX_SIP_SRC_MCU_STARTED	0x01
 #define	IMX_SIP_SRC_MCU_STOP	0x02
+#define	IMX_SIP_SRC_MCU_PREP		0x04
+#define	IMX_SIP_SRC_MCU_PREPED		0x05
 
 #endif
-- 
2.34.1



More information about the U-Boot mailing list