xref: /openbmc/u-boot/arch/arm/mach-imx/imx_bootaux.c (revision 522e035441ca04d99de2fc13b614ad896691e9c9)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2552a848eSStefano Babic /*
3552a848eSStefano Babic  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4552a848eSStefano Babic  */
5552a848eSStefano Babic 
6552a848eSStefano Babic #include <common.h>
78cf22313SPeng Fan #include <asm/io.h>
8ecd7ab56SPeng Fan #include <asm/mach-imx/sys_proto.h>
9552a848eSStefano Babic #include <command.h>
10ecd7ab56SPeng Fan #include <imx_sip.h>
1120b9f2eaSTom Rini #include <linux/compiler.h>
12552a848eSStefano Babic 
arch_auxiliary_core_up(u32 core_id,ulong boot_private_data)138cf22313SPeng Fan int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
14552a848eSStefano Babic {
158cf22313SPeng Fan 	ulong stack, pc;
168cf22313SPeng Fan 
178cf22313SPeng Fan 	if (!boot_private_data)
188cf22313SPeng Fan 		return -EINVAL;
198cf22313SPeng Fan 
2068e7410fSGary Bisson 	stack = *(u32 *)boot_private_data;
2168e7410fSGary Bisson 	pc = *(u32 *)(boot_private_data + 4);
228cf22313SPeng Fan 
238cf22313SPeng Fan 	/* Set the stack and pc to M4 bootROM */
248cf22313SPeng Fan 	writel(stack, M4_BOOTROM_BASE_ADDR);
258cf22313SPeng Fan 	writel(pc, M4_BOOTROM_BASE_ADDR + 4);
268cf22313SPeng Fan 
278cf22313SPeng Fan 	/* Enable M4 */
28*cd357ad1SPeng Fan #ifdef CONFIG_IMX8M
29ecd7ab56SPeng Fan 	call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0);
30ecd7ab56SPeng Fan #else
318cf22313SPeng Fan 	clrsetbits_le32(SRC_BASE_ADDR + SRC_M4_REG_OFFSET,
328cf22313SPeng Fan 			SRC_M4C_NON_SCLR_RST_MASK, SRC_M4_ENABLE_MASK);
33ecd7ab56SPeng Fan #endif
348cf22313SPeng Fan 
358cf22313SPeng Fan 	return 0;
36552a848eSStefano Babic }
37552a848eSStefano Babic 
arch_auxiliary_core_check_up(u32 core_id)388cf22313SPeng Fan int arch_auxiliary_core_check_up(u32 core_id)
39552a848eSStefano Babic {
40*cd357ad1SPeng Fan #ifdef CONFIG_IMX8M
41ecd7ab56SPeng Fan 	return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0);
42ecd7ab56SPeng Fan #else
438cf22313SPeng Fan 	unsigned int val;
448cf22313SPeng Fan 
458cf22313SPeng Fan 	val = readl(SRC_BASE_ADDR + SRC_M4_REG_OFFSET);
468cf22313SPeng Fan 
478cf22313SPeng Fan 	if (val & SRC_M4C_NON_SCLR_RST_MASK)
488cf22313SPeng Fan 		return 0;  /* assert in reset */
498cf22313SPeng Fan 
508cf22313SPeng Fan 	return 1;
51ecd7ab56SPeng Fan #endif
52552a848eSStefano Babic }
53552a848eSStefano Babic 
54552a848eSStefano Babic /*
55552a848eSStefano Babic  * To i.MX6SX and i.MX7D, the image supported by bootaux needs
56552a848eSStefano Babic  * the reset vector at the head for the image, with SP and PC
57552a848eSStefano Babic  * as the first two words.
58552a848eSStefano Babic  *
59552a848eSStefano Babic  * Per the cortex-M reference manual, the reset vector of M4 needs
60552a848eSStefano Babic  * to exist at 0x0 (TCMUL). The PC and SP are the first two addresses
61552a848eSStefano Babic  * of that vector.  So to boot M4, the A core must build the M4's reset
62552a848eSStefano Babic  * vector with getting the PC and SP from image and filling them to
63552a848eSStefano Babic  * TCMUL. When M4 is kicked, it will load the PC and SP by itself.
64552a848eSStefano Babic  * The TCMUL is mapped to (M4_BOOTROM_BASE_ADDR) at A core side for
65552a848eSStefano Babic  * accessing the M4 TCMUL.
66552a848eSStefano Babic  */
do_bootaux(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])6720b9f2eaSTom Rini static int do_bootaux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
68552a848eSStefano Babic {
69552a848eSStefano Babic 	ulong addr;
70552a848eSStefano Babic 	int ret, up;
71552a848eSStefano Babic 
72552a848eSStefano Babic 	if (argc < 2)
73552a848eSStefano Babic 		return CMD_RET_USAGE;
74552a848eSStefano Babic 
75552a848eSStefano Babic 	up = arch_auxiliary_core_check_up(0);
76552a848eSStefano Babic 	if (up) {
77552a848eSStefano Babic 		printf("## Auxiliary core is already up\n");
78552a848eSStefano Babic 		return CMD_RET_SUCCESS;
79552a848eSStefano Babic 	}
80552a848eSStefano Babic 
81552a848eSStefano Babic 	addr = simple_strtoul(argv[1], NULL, 16);
82552a848eSStefano Babic 
83552a848eSStefano Babic 	printf("## Starting auxiliary core at 0x%08lX ...\n", addr);
84552a848eSStefano Babic 
85552a848eSStefano Babic 	ret = arch_auxiliary_core_up(0, addr);
86552a848eSStefano Babic 	if (ret)
87552a848eSStefano Babic 		return CMD_RET_FAILURE;
88552a848eSStefano Babic 
89552a848eSStefano Babic 	return CMD_RET_SUCCESS;
90552a848eSStefano Babic }
91552a848eSStefano Babic 
92552a848eSStefano Babic U_BOOT_CMD(
93552a848eSStefano Babic 	bootaux, CONFIG_SYS_MAXARGS, 1,	do_bootaux,
94552a848eSStefano Babic 	"Start auxiliary core",
95552a848eSStefano Babic 	""
96552a848eSStefano Babic );
97