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