xref: /rk3399_ARM-atf/plat/intel/soc/common/aarch64/plat_helpers.S (revision 5cef096e4c7238b397ebd9661d61daecf6464283)
1/*
2 * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
4 * Copyright (c) 2024, Altera Corporation. All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#include <arch.h>
10#include <asm_macros.S>
11#include <cpu_macros.S>
12#include <platform_def.h>
13#include <el3_common_macros.S>
14
15	.globl	plat_secondary_cold_boot_setup
16	.globl	platform_is_primary_cpu
17	.globl	plat_is_my_cpu_primary
18	.globl	plat_my_core_pos
19	.globl	plat_crash_console_init
20	.globl	plat_crash_console_putc
21	.globl  plat_crash_console_flush
22	.globl	platform_mem_init
23	.globl	plat_secondary_cpus_bl31_entry
24
25	.globl plat_get_my_entrypoint
26
27	/* -----------------------------------------------------
28	 * void plat_secondary_cold_boot_setup (void);
29	 *
30	 * This function performs any platform specific actions
31	 * needed for a secondary cpu after a cold reset e.g
32	 * mark the cpu's presence, mechanism to place it in a
33	 * holding pen etc.
34	 * -----------------------------------------------------
35	 */
36func plat_secondary_cold_boot_setup
37	/* Wait until the it gets reset signal from rstmgr gets populated */
38poll_mailbox:
39#if	PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
40	mov_imm x0, PLAT_SEC_ENTRY
41	cbz	x0, poll_mailbox
42	br      x0
43#else
44	wfi
45	mov_imm	x0, PLAT_SEC_ENTRY
46	ldr	x1, [x0]
47	mov_imm	x2, PLAT_CPUID_RELEASE
48	ldr	x3, [x2]
49	mrs	x4, mpidr_el1
50	and	x4, x4, #0xff
51	cmp	x3, x4
52	b.ne	poll_mailbox
53	br	x1
54#endif
55endfunc plat_secondary_cold_boot_setup
56
57#if	((PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10) || \
58	(PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX) || \
59	(PLATFORM_MODEL == PLAT_SOCFPGA_N5X))
60
61func platform_is_primary_cpu
62	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
63	cmp	x0, #PLAT_PRIMARY_CPU
64	cset	x0, eq
65	ret
66endfunc platform_is_primary_cpu
67
68#else
69
70func platform_is_primary_cpu
71	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
72	cmp x0, #(PLAT_PRIMARY_CPU_A76)
73	b.eq primary_cpu
74	cmp x0, #(PLAT_PRIMARY_CPU_A55)
75	b.eq primary_cpu
76primary_cpu:
77	cset	x0, eq
78	ret
79endfunc platform_is_primary_cpu
80
81#endif
82
83func plat_is_my_cpu_primary
84	mrs	x0, mpidr_el1
85	b   platform_is_primary_cpu
86endfunc plat_is_my_cpu_primary
87
88func plat_my_core_pos
89	mrs	x0, mpidr_el1
90	and	x1, x0, #MPIDR_CPU_MASK
91	and	x0, x0, #MPIDR_CLUSTER_MASK
92#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
93	add	x0, x1, x0, LSR #8
94#else
95	add	x0, x1, x0, LSR #6
96#endif
97	ret
98endfunc plat_my_core_pos
99
100func warm_reset_req
101#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
102	/* Clear the markup before going for warm reset */
103	bic	x2, x2, #BS_REG_MAGIC_KEYS_MASK
104	/* Check if the address is 64 bit aligned or not */
105	ldr	x4, =L2_RESET_DONE_REG
106	tst	x4, #ALIGN_CHECK_64BIT_MASK
107	b.ne	unaligned_store
108	/* Device memory address is aligned, store the value directly */
109	str	x2, [x4]
110	b	continue_warm_reset
111
112	/* Unaligned store, use byte by byte method to store */
113unaligned_store:
114	strb	w2, [x4]
115	lsr	x2, x2, #8
116	add	x4, x4, #1
117	strb	w2, [x4]
118	lsr	x2, x2, #8
119	add	x4, x4, #1
120	strb	w2, [x4]
121	lsr	x2, x2, #8
122	add	x4, x4, #1
123	strb	w2, [x4]
124#else
125	/* Clear the markup before going for warm reset */
126	bic	x2, x2, #BS_REG_MAGIC_KEYS_MASK
127	str	x2, [x4]
128#endif
129
130continue_warm_reset:
131	bl	plat_is_my_cpu_primary
132	cbz	x0, cpu_in_wfi
133	mov_imm x1, PLAT_SEC_ENTRY
134	str	xzr, [x1]
135	mrs	x1, rmr_el3
136	orr	x1, x1, #0x02
137	msr	rmr_el3, x1
138	isb
139	dsb	sy
140cpu_in_wfi:
141	wfi
142	b	cpu_in_wfi
143endfunc warm_reset_req
144
145#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
146func plat_get_my_entrypoint
147	ldr	x4, =L2_RESET_DONE_REG
148
149	/* Check if the address is 64 bit aligned or not */
150	tst	x4, #ALIGN_CHECK_64BIT_MASK
151	b.ne	unaligned_load
152
153	/* Device memory address is aligned, load the value directly */
154	ldr	x1, [x4]
155	b	events_check
156
157	/*
158	 * It is unaligned device memory access. Read only LSB 32 bits
159	 * byte by byte and combine them to get the 32 bit value.
160	 */
161unaligned_load:
162	ldrb	w1, [x4]
163	ldrb	w2, [x4, #1]
164	ldrb	w3, [x4, #2]
165	ldrb	w4, [x4, #3]
166	orr	x1, x1, x2, lsl #8
167	orr	x1, x1, x3, lsl #16
168	orr	x1, x1, x4, lsl #24
169
170events_check:
171	/* Keep a backup of the boot scratch register contents */
172	mov	x2, x1
173
174	/* Mask and get the required bits */
175	and	x1, x1, #BS_REG_MAGIC_KEYS_MASK
176
177	/* Check for warm reset request */
178	ldr	x5, =L2_RESET_DONE_STATUS
179	cmp	x1, x5
180	b.eq	warm_reset_req
181
182	/* Check for SMP secondary cores boot request */
183	ldr	x5, =SMP_SEC_CORE_BOOT_REQ
184	cmp	x1, x5
185	b.eq	smp_request
186
187	/* Otherwise it is a cold reset request */
188	mov	x0, #0
189	ret
190
191smp_request:
192	/*
193	 * On the SMP boot request, return the address 'bl31_warm_entrypoint',
194	 * which is passed to 'psci_setup' routine as part of BL31
195	 * initialization.
196	 */
197	ldr	x1, =PLAT_SEC_ENTRY
198	ldr	x0, [x1]
199	ret
200endfunc plat_get_my_entrypoint
201#else
202func plat_get_my_entrypoint
203	ldr	x4, =L2_RESET_DONE_REG
204	ldr	x5, [x4]
205
206	/* Keep a backup of the boot scratch register contents */
207	mov	x2, x5
208
209	/* Mask and get only the required bits */
210	and	x5, x5, #BS_REG_MAGIC_KEYS_MASK
211
212	/* Check for warm reset request */
213	ldr	x1, =L2_RESET_DONE_STATUS
214	cmp	x1, x5
215	b.eq	warm_reset_req
216	mov_imm	x1, PLAT_SEC_ENTRY
217	ldr	x0, [x1]
218	ret
219endfunc plat_get_my_entrypoint
220#endif
221
222	/* ---------------------------------------------
223	 * int plat_crash_console_init(void)
224	 * Function to initialize the crash console
225	 * without a C Runtime to print crash report.
226	 * Clobber list : x0, x1, x2
227	 * ---------------------------------------------
228	 */
229func plat_crash_console_init
230	mov_imm	x0, CRASH_CONSOLE_BASE
231	mov_imm	x1, PLAT_UART_CLOCK
232	mov_imm	x2, PLAT_BAUDRATE
233	b	console_16550_core_init
234endfunc plat_crash_console_init
235
236	/* ---------------------------------------------
237	 * int plat_crash_console_putc(void)
238	 * Function to print a character on the crash
239	 * console without a C Runtime.
240	 * Clobber list : x1, x2
241	 * ---------------------------------------------
242	 */
243func plat_crash_console_putc
244	mov_imm x1, CRASH_CONSOLE_BASE
245	b	console_16550_core_putc
246endfunc plat_crash_console_putc
247
248func plat_crash_console_flush
249	mov_imm x0, CRASH_CONSOLE_BASE
250	b	console_16550_core_flush
251endfunc plat_crash_console_flush
252
253
254	/* --------------------------------------------------------
255	 * void platform_mem_init (void);
256	 *
257	 * Any memory init, relocation to be done before the
258	 * platform boots. Called very early in the boot process.
259	 * --------------------------------------------------------
260	 */
261func platform_mem_init
262	mov	x0, #0
263	ret
264endfunc platform_mem_init
265
266	/* --------------------------------------------------------
267	 * macro plat_secondary_cpus_bl31_entry;
268	 *
269	 * el3_entrypoint_common init param configuration.
270	 * Called very early in the secondary cores boot process.
271	 * --------------------------------------------------------
272	 */
273func plat_secondary_cpus_bl31_entry
274	el3_entrypoint_common                                   \
275		_init_sctlr=0                                   \
276		_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS  \
277		_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU      \
278		_init_memory=1                                  \
279		_init_c_runtime=1                               \
280		_exception_vectors=runtime_exceptions		\
281		_pie_fixup_size=BL31_LIMIT - BL31_BASE
282endfunc plat_secondary_cpus_bl31_entry
283