[PATCH V2 23/30] imx: imx8: bootaux: Add i.MX8 M4 boot support

Peng Fan (OSS) peng.fan at oss.nxp.com
Thu Jun 15 12:09:20 CEST 2023


From: Ye Li <ye.li at nxp.com>

1. Implement bootaux for the M4 boot on i.MX8QM and QXP. Users need to download
   M4 image to any DDR address first. Then use the
   "bootaux <M4 download DDR address> [M4 core id]" to boot CM4_0
   or CM4_1, the default core id is 0 for CM4_0.

   Since current M4 only supports running in TCM. The bootaux will copy
   the M4 image from DDR to its TCML.

2. Implment bootaux for HIFI on QXP
   command: bootaux 0x81000000 1

Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 arch/arm/include/asm/mach-imx/sys_proto.h |   1 +
 arch/arm/mach-imx/Kconfig                 |   2 +-
 arch/arm/mach-imx/Makefile                |   5 +
 arch/arm/mach-imx/imx8/cpu.c              | 174 ++++++++++++++++++++++
 arch/arm/mach-imx/imx_bootaux.c           |  15 +-
 5 files changed, 192 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 85d9ca60b14..31ae179b211 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -236,6 +236,7 @@ void board_mem_get_layout(u64 *phys_sdram_1_start,
 			  u64 *phys_sdram_2_start,
 			  u64 *phys_sdram_2_size);
 
+int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data);
 int arch_auxiliary_core_check_up(u32 core_id);
 
 int board_mmc_get_env_dev(int devno);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 2cca89d4bb1..d94b5828d0d 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -31,7 +31,7 @@ config IMX_RDC
 
 config IMX_BOOTAUX
 	bool "Support boot auxiliary core"
-	depends on ARCH_MX7 || ARCH_MX6 || ARCH_VF610 || ARCH_IMX8M
+	depends on ARCH_MX7 || ARCH_MX6 || ARCH_VF610 || ARCH_IMX8 || ARCH_IMX8M
 	help
 	  bootaux [addr] to boot auxiliary core.
 
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 906f538259a..9023b99f21d 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -66,6 +66,11 @@ ifeq ($(SOC),$(filter $(SOC),vf610))
 obj-y += ddrmc-vf610.o
 obj-$(CONFIG_DDRMC_VF610_CALIBRATION) += ddrmc-vf610-calibration.o
 endif
+ifeq ($(SOC),$(filter $(SOC),imx8))
+ifneq ($(CONFIG_SPL_BUILD),y)
+obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o
+endif
+endif
 ifneq ($(CONFIG_SPL_BUILD),y)
 obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
 obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 2b34077438f..c62357044e0 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -26,6 +26,8 @@
 #include <asm/armv8/mmu.h>
 #include <asm/setup.h>
 #include <asm/mach-imx/boot_mode.h>
+#include <power-domain.h>
+#include <elf.h>
 #include <spl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -107,6 +109,178 @@ int arch_misc_init(void)
 }
 #endif
 
+#ifdef CONFIG_IMX_BOOTAUX
+
+#ifdef CONFIG_IMX8QM
+int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
+{
+	sc_rsrc_t core_rsrc, mu_rsrc;
+	sc_faddr_t tcml_addr;
+	u32 tcml_size = SZ_128K;
+	ulong addr;
+
+	switch (core_id) {
+	case 0:
+		core_rsrc = SC_R_M4_0_PID0;
+		tcml_addr = 0x34FE0000;
+		mu_rsrc = SC_R_M4_0_MU_1A;
+		break;
+	case 1:
+		core_rsrc = SC_R_M4_1_PID0;
+		tcml_addr = 0x38FE0000;
+		mu_rsrc = SC_R_M4_1_MU_1A;
+		break;
+	default:
+		printf("Not support this core boot up, ID:%u\n", core_id);
+		return -EINVAL;
+	}
+
+	addr = (sc_faddr_t)boot_private_data;
+
+	if (addr >= tcml_addr && addr <= tcml_addr + tcml_size) {
+		printf("Wrong image address 0x%lx, should not in TCML\n",
+		       addr);
+		return -EINVAL;
+	}
+
+	printf("Power on M4 and MU\n");
+
+	if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+		return -EIO;
+
+	if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+		return -EIO;
+
+	printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", addr, (ulong)tcml_addr);
+
+	if (addr != tcml_addr)
+		memcpy((void *)tcml_addr, (void *)addr, tcml_size);
+
+	printf("Start M4 %u\n", core_id);
+	if (sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr) != SC_ERR_NONE)
+		return -EIO;
+
+	printf("bootaux complete\n");
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_IMX8QXP
+int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
+{
+	sc_rsrc_t core_rsrc, mu_rsrc = SC_R_NONE;
+	sc_faddr_t aux_core_ram;
+	u32 size;
+	ulong addr;
+
+	switch (core_id) {
+	case 0:
+		core_rsrc = SC_R_M4_0_PID0;
+		aux_core_ram = 0x34FE0000;
+		mu_rsrc = SC_R_M4_0_MU_1A;
+		size = SZ_128K;
+		break;
+	case 1:
+		core_rsrc = SC_R_DSP;
+		aux_core_ram = 0x596f8000;
+		size = SZ_2K;
+		break;
+	default:
+		printf("Not support this core boot up, ID:%u\n", core_id);
+		return -EINVAL;
+	}
+
+	addr = (sc_faddr_t)boot_private_data;
+
+	if (addr >= aux_core_ram && addr <= aux_core_ram + size) {
+		printf("Wrong image address 0x%lx, should not in aux core ram\n",
+		       addr);
+		return -EINVAL;
+	}
+
+	printf("Power on aux core %d\n", core_id);
+
+	if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+		return -EIO;
+
+	if (mu_rsrc != SC_R_NONE) {
+		if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+			return -EIO;
+	}
+
+	if (core_id == 1) {
+		struct power_domain pd;
+
+		if (sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, true, false) != SC_ERR_NONE) {
+			printf("Error enable clock\n");
+			return -EIO;
+		}
+
+		if (!power_domain_lookup_name("audio_sai0", &pd)) {
+			if (power_domain_on(&pd)) {
+				printf("Error power on SAI0\n");
+				return -EIO;
+			}
+		}
+
+		if (!power_domain_lookup_name("audio_ocram", &pd)) {
+			if (power_domain_on(&pd)) {
+				printf("Error power on HIFI RAM\n");
+				return -EIO;
+			}
+		}
+	}
+
+	printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram);
+	if (core_id == 0) {
+		/* M4 use bin file */
+		memcpy((void *)aux_core_ram, (void *)addr, size);
+	} else {
+		/* HIFI use elf file */
+		if (!valid_elf_image(addr))
+			return -1;
+		addr = load_elf_image_shdr(addr);
+	}
+
+	printf("Start %s\n", core_id == 0 ? "M4" : "HIFI");
+
+	if (sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram) != SC_ERR_NONE)
+		return -EIO;
+
+	printf("bootaux complete\n");
+	return 0;
+}
+#endif
+
+int arch_auxiliary_core_check_up(u32 core_id)
+{
+	sc_rsrc_t core_rsrc;
+	sc_pm_power_mode_t power_mode;
+
+	switch (core_id) {
+	case 0:
+		core_rsrc = SC_R_M4_0_PID0;
+		break;
+#ifdef CONFIG_IMX8QM
+	case 1:
+		core_rsrc = SC_R_M4_1_PID0;
+		break;
+#endif
+	default:
+		printf("Not support this core, ID:%u\n", core_id);
+		return 0;
+	}
+
+	if (sc_pm_get_resource_power_mode(-1, core_rsrc, &power_mode) != SC_ERR_NONE)
+		return 0;
+
+	if (power_mode != SC_PM_PW_MODE_OFF)
+		return 1;
+
+	return 0;
+}
+#endif
+
 int print_bootinfo(void)
 {
 	enum boot_device bt_dev = get_boot_device();
diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c
index ab7a41fd11d..f7b14ca38d9 100644
--- a/arch/arm/mach-imx/imx_bootaux.c
+++ b/arch/arm/mach-imx/imx_bootaux.c
@@ -14,6 +14,7 @@
 #include <linux/compiler.h>
 #include <cpu_func.h>
 
+#ifndef CONFIG_IMX8
 /* Just to avoid build error */
 #if IS_ENABLED(CONFIG_IMX8M)
 #define SRC_M4C_NON_SCLR_RST_MASK	BIT(0)
@@ -158,7 +159,7 @@ int arch_auxiliary_core_check_up(u32 core_id)
 
 	return 1;
 }
-
+#endif
 /*
  * To i.MX6SX and i.MX7D, the image supported by bootaux needs
  * the reset vector at the head for the image, with SP and PC
@@ -177,11 +178,15 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc,
 {
 	ulong addr;
 	int ret, up;
+	u32 core = 0;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	up = arch_auxiliary_core_check_up(0);
+	if (argc > 2)
+		core = simple_strtoul(argv[2], NULL, 10);
+
+	up = arch_auxiliary_core_check_up(core);
 	if (up) {
 		printf("## Auxiliary core is already up\n");
 		return CMD_RET_SUCCESS;
@@ -192,7 +197,7 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc,
 	if (!addr)
 		return CMD_RET_FAILURE;
 
-	ret = arch_auxiliary_core_up(0, addr);
+	ret = arch_auxiliary_core_up(core, addr);
 	if (ret)
 		return CMD_RET_FAILURE;
 
@@ -202,5 +207,7 @@ static int do_bootaux(struct cmd_tbl *cmdtp, int flag, int argc,
 U_BOOT_CMD(
 	bootaux, CONFIG_SYS_MAXARGS, 1,	do_bootaux,
 	"Start auxiliary core",
-	""
+	"<address> [<core>]\n"
+	"   - start auxiliary core [<core>] (default 0),\n"
+	"     at address <address>\n"
 );
-- 
2.40.0



More information about the U-Boot mailing list