1 /* 2 * Copyright (C) 2016 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <asm/mach-imx/sys_proto.h> 10 #include <command.h> 11 #include <imx_sip.h> 12 #include <linux/compiler.h> 13 14 int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) 15 { 16 ulong stack, pc; 17 18 if (!boot_private_data) 19 return -EINVAL; 20 21 stack = *(ulong *)boot_private_data; 22 pc = *(ulong *)(boot_private_data + 4); 23 24 /* Set the stack and pc to M4 bootROM */ 25 writel(stack, M4_BOOTROM_BASE_ADDR); 26 writel(pc, M4_BOOTROM_BASE_ADDR + 4); 27 28 /* Enable M4 */ 29 #ifdef CONFIG_MX8M 30 call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0); 31 #else 32 clrsetbits_le32(SRC_BASE_ADDR + SRC_M4_REG_OFFSET, 33 SRC_M4C_NON_SCLR_RST_MASK, SRC_M4_ENABLE_MASK); 34 #endif 35 36 return 0; 37 } 38 39 int arch_auxiliary_core_check_up(u32 core_id) 40 { 41 #ifdef CONFIG_MX8M 42 return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0); 43 #else 44 unsigned int val; 45 46 val = readl(SRC_BASE_ADDR + SRC_M4_REG_OFFSET); 47 48 if (val & SRC_M4C_NON_SCLR_RST_MASK) 49 return 0; /* assert in reset */ 50 51 return 1; 52 #endif 53 } 54 55 /* 56 * To i.MX6SX and i.MX7D, the image supported by bootaux needs 57 * the reset vector at the head for the image, with SP and PC 58 * as the first two words. 59 * 60 * Per the cortex-M reference manual, the reset vector of M4 needs 61 * to exist at 0x0 (TCMUL). The PC and SP are the first two addresses 62 * of that vector. So to boot M4, the A core must build the M4's reset 63 * vector with getting the PC and SP from image and filling them to 64 * TCMUL. When M4 is kicked, it will load the PC and SP by itself. 65 * The TCMUL is mapped to (M4_BOOTROM_BASE_ADDR) at A core side for 66 * accessing the M4 TCMUL. 67 */ 68 static int do_bootaux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 69 { 70 ulong addr; 71 int ret, up; 72 73 if (argc < 2) 74 return CMD_RET_USAGE; 75 76 up = arch_auxiliary_core_check_up(0); 77 if (up) { 78 printf("## Auxiliary core is already up\n"); 79 return CMD_RET_SUCCESS; 80 } 81 82 addr = simple_strtoul(argv[1], NULL, 16); 83 84 printf("## Starting auxiliary core at 0x%08lX ...\n", addr); 85 86 ret = arch_auxiliary_core_up(0, addr); 87 if (ret) 88 return CMD_RET_FAILURE; 89 90 return CMD_RET_SUCCESS; 91 } 92 93 U_BOOT_CMD( 94 bootaux, CONFIG_SYS_MAXARGS, 1, do_bootaux, 95 "Start auxiliary core", 96 "" 97 ); 98