1/*
2 * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <asm_macros.S>
9#include <cpu_macros.S>
10#include <platform_def.h>
11#include <el3_common_macros.S>
12
13	.globl	plat_secondary_cold_boot_setup
14	.globl	platform_is_primary_cpu
15	.globl	plat_is_my_cpu_primary
16	.globl	plat_my_core_pos
17	.globl	plat_crash_console_init
18	.globl	plat_crash_console_putc
19	.globl  plat_crash_console_flush
20	.globl	platform_mem_init
21	.globl	plat_secondary_cpus_bl31_entry
22
23	.globl plat_get_my_entrypoint
24
25	/* -----------------------------------------------------
26	 * void plat_secondary_cold_boot_setup (void);
27	 *
28	 * This function performs any platform specific actions
29	 * needed for a secondary cpu after a cold reset e.g
30	 * mark the cpu's presence, mechanism to place it in a
31	 * holding pen etc.
32	 * -----------------------------------------------------
33	 */
34func plat_secondary_cold_boot_setup
35	/* Wait until the it gets reset signal from rstmgr gets populated */
36poll_mailbox:
37#if	PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
38	mov_imm x0, PLAT_SEC_ENTRY
39	cbz	x0, poll_mailbox
40	br      x0
41#else
42	wfi
43	mov_imm	x0, PLAT_SEC_ENTRY
44	ldr	x1, [x0]
45	mov_imm	x2, PLAT_CPUID_RELEASE
46	ldr	x3, [x2]
47	mrs	x4, mpidr_el1
48	and	x4, x4, #0xff
49	cmp	x3, x4
50	b.ne	poll_mailbox
51	br	x1
52#endif
53endfunc plat_secondary_cold_boot_setup
54
55#if	((PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10) || \
56	(PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX) || \
57	(PLATFORM_MODEL == PLAT_SOCFPGA_N5X))
58
59func platform_is_primary_cpu
60	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
61	cmp	x0, #PLAT_PRIMARY_CPU
62	cset	x0, eq
63	ret
64endfunc platform_is_primary_cpu
65
66#else
67
68func platform_is_primary_cpu
69	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
70	cmp x0, #(PLAT_PRIMARY_CPU_A76)
71	b.eq primary_cpu
72	cmp x0, #(PLAT_PRIMARY_CPU_A55)
73	b.eq primary_cpu
74primary_cpu:
75	cset	x0, eq
76	ret
77endfunc platform_is_primary_cpu
78
79#endif
80
81func plat_is_my_cpu_primary
82	mrs	x0, mpidr_el1
83	b   platform_is_primary_cpu
84endfunc plat_is_my_cpu_primary
85
86func plat_my_core_pos
87	mrs	x0, mpidr_el1
88	and	x1, x0, #MPIDR_CPU_MASK
89	and	x0, x0, #MPIDR_CLUSTER_MASK
90#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
91	add	x0, x1, x0, LSR #8
92#else
93	add	x0, x1, x0, LSR #6
94#endif
95	ret
96endfunc plat_my_core_pos
97
98func warm_reset_req
99#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
100	bl	plat_is_my_cpu_primary
101	cbnz	x0, warm_reset
102warm_reset:
103	mov_imm x1, PLAT_SEC_ENTRY
104	str	xzr, [x1]
105	mrs	x1, rmr_el3
106	orr	x1, x1, #0x02
107	msr	rmr_el3, x1
108	isb
109	dsb	sy
110#else
111	str	xzr, [x4]
112	bl	plat_is_my_cpu_primary
113	cbz	x0, cpu_in_wfi
114	mov_imm x1, PLAT_SEC_ENTRY
115	str	xzr, [x1]
116	mrs	x1, rmr_el3
117	orr	x1, x1, #0x02
118	msr	rmr_el3, x1
119	isb
120	dsb	sy
121cpu_in_wfi:
122	wfi
123	b	cpu_in_wfi
124#endif
125endfunc warm_reset_req
126
127/* TODO: Zephyr warm reset test */
128#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
129func plat_get_my_entrypoint
130	ldr	x4, =L2_RESET_DONE_REG
131	ldr	x5, [x4]
132	ldr	x1, =PLAT_L2_RESET_REQ
133	cmp	x1, x5
134	b.eq	zephyr_reset_req
135	mov_imm	x1, PLAT_SEC_ENTRY
136	ldr	x0, [x1]
137	ret
138zephyr_reset_req:
139	ldr	x0, =0x00
140	ret
141endfunc plat_get_my_entrypoint
142#else
143func plat_get_my_entrypoint
144	ldr	x4, =L2_RESET_DONE_REG
145	ldr	x5, [x4]
146	ldr	x1, =L2_RESET_DONE_STATUS
147	cmp	x1, x5
148	b.eq	warm_reset_req
149	mov_imm	x1, PLAT_SEC_ENTRY
150	ldr	x0, [x1]
151	ret
152endfunc plat_get_my_entrypoint
153#endif
154
155	/* ---------------------------------------------
156	 * int plat_crash_console_init(void)
157	 * Function to initialize the crash console
158	 * without a C Runtime to print crash report.
159	 * Clobber list : x0, x1, x2
160	 * ---------------------------------------------
161	 */
162func plat_crash_console_init
163	mov_imm	x0, CRASH_CONSOLE_BASE
164	mov_imm	x1, PLAT_UART_CLOCK
165	mov_imm	x2, PLAT_BAUDRATE
166	b	console_16550_core_init
167endfunc plat_crash_console_init
168
169	/* ---------------------------------------------
170	 * int plat_crash_console_putc(void)
171	 * Function to print a character on the crash
172	 * console without a C Runtime.
173	 * Clobber list : x1, x2
174	 * ---------------------------------------------
175	 */
176func plat_crash_console_putc
177	mov_imm x1, CRASH_CONSOLE_BASE
178	b	console_16550_core_putc
179endfunc plat_crash_console_putc
180
181func plat_crash_console_flush
182	mov_imm x0, CRASH_CONSOLE_BASE
183	b	console_16550_core_flush
184endfunc plat_crash_console_flush
185
186
187	/* --------------------------------------------------------
188	 * void platform_mem_init (void);
189	 *
190	 * Any memory init, relocation to be done before the
191	 * platform boots. Called very early in the boot process.
192	 * --------------------------------------------------------
193	 */
194func platform_mem_init
195	mov	x0, #0
196	ret
197endfunc platform_mem_init
198
199	/* --------------------------------------------------------
200	 * macro plat_secondary_cpus_bl31_entry;
201	 *
202	 * el3_entrypoint_common init param configuration.
203	 * Called very early in the secondary cores boot process.
204	 * --------------------------------------------------------
205	 */
206func plat_secondary_cpus_bl31_entry
207	el3_entrypoint_common                                   \
208		_init_sctlr=0                                   \
209		_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS  \
210		_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU      \
211		_init_memory=1                                  \
212		_init_c_runtime=1                               \
213		_exception_vectors=runtime_exceptions		\
214		_pie_fixup_size=BL31_LIMIT - BL31_BASE
215endfunc plat_secondary_cpus_bl31_entry
216