xref: /openbmc/u-boot/arch/arm/cpu/armv8/start.S (revision 6b29a395)
1/*
2 * (C) Copyright 2013
3 * David Feng <fenghua@phytium.com.cn>
4 *
5 * SPDX-License-Identifier:	GPL-2.0+
6 */
7
8#include <asm-offsets.h>
9#include <config.h>
10#include <linux/linkage.h>
11#include <asm/macro.h>
12#include <asm/armv8/mmu.h>
13
14/*************************************************************************
15 *
16 * Startup Code (reset vector)
17 *
18 *************************************************************************/
19
20.globl	_start
21_start:
22	b	reset
23
24#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
25/*
26 * Various SoCs need something special and SoC-specific up front in
27 * order to boot, allow them to set that in their boot0.h file and then
28 * use it here.
29 */
30#include <asm/arch/boot0.h>
31ARM_SOC_BOOT0_HOOK
32#endif
33
34	.align 3
35
36.globl	_TEXT_BASE
37_TEXT_BASE:
38	.quad	CONFIG_SYS_TEXT_BASE
39
40/*
41 * These are defined in the linker script.
42 */
43.globl	_end_ofs
44_end_ofs:
45	.quad	_end - _start
46
47.globl	_bss_start_ofs
48_bss_start_ofs:
49	.quad	__bss_start - _start
50
51.globl	_bss_end_ofs
52_bss_end_ofs:
53	.quad	__bss_end - _start
54
55reset:
56	/* Allow the board to save important registers */
57	b	save_boot_params
58.globl	save_boot_params_ret
59save_boot_params_ret:
60
61#ifdef CONFIG_SYS_RESET_SCTRL
62	bl reset_sctrl
63#endif
64	/*
65	 * Could be EL3/EL2/EL1, Initial State:
66	 * Little Endian, MMU Disabled, i/dCache Disabled
67	 */
68	adr	x0, vectors
69	switch_el x1, 3f, 2f, 1f
703:	msr	vbar_el3, x0
71	mrs	x0, scr_el3
72	orr	x0, x0, #0xf			/* SCR_EL3.NS|IRQ|FIQ|EA */
73	msr	scr_el3, x0
74	msr	cptr_el3, xzr			/* Enable FP/SIMD */
75#ifdef COUNTER_FREQUENCY
76	ldr	x0, =COUNTER_FREQUENCY
77	msr	cntfrq_el0, x0			/* Initialize CNTFRQ */
78#endif
79	b	0f
802:	msr	vbar_el2, x0
81	mov	x0, #0x33ff
82	msr	cptr_el2, x0			/* Enable FP/SIMD */
83	b	0f
841:	msr	vbar_el1, x0
85	mov	x0, #3 << 20
86	msr	cpacr_el1, x0			/* Enable FP/SIMD */
870:
88
89	/* Apply ARM core specific erratas */
90	bl	apply_core_errata
91
92	/*
93	 * Cache/BPB/TLB Invalidate
94	 * i-cache is invalidated before enabled in icache_enable()
95	 * tlb is invalidated before mmu is enabled in dcache_enable()
96	 * d-cache is invalidated before enabled in dcache_enable()
97	 */
98
99	/* Processor specific initialization */
100	bl	lowlevel_init
101
102#if CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE)
103	branch_if_master x0, x1, master_cpu
104	b	spin_table_secondary_jump
105	/* never return */
106#elif defined(CONFIG_ARMV8_MULTIENTRY)
107	branch_if_master x0, x1, master_cpu
108
109	/*
110	 * Slave CPUs
111	 */
112slave_cpu:
113	wfe
114	ldr	x1, =CPU_RELEASE_ADDR
115	ldr	x0, [x1]
116	cbz	x0, slave_cpu
117	br	x0			/* branch to the given address */
118#endif /* CONFIG_ARMV8_MULTIENTRY */
119master_cpu:
120	bl	_main
121
122#ifdef CONFIG_SYS_RESET_SCTRL
123reset_sctrl:
124	switch_el x1, 3f, 2f, 1f
1253:
126	mrs	x0, sctlr_el3
127	b	0f
1282:
129	mrs	x0, sctlr_el2
130	b	0f
1311:
132	mrs	x0, sctlr_el1
133
1340:
135	ldr	x1, =0xfdfffffa
136	and	x0, x0, x1
137
138	switch_el x1, 6f, 5f, 4f
1396:
140	msr	sctlr_el3, x0
141	b	7f
1425:
143	msr	sctlr_el2, x0
144	b	7f
1454:
146	msr	sctlr_el1, x0
147
1487:
149	dsb	sy
150	isb
151	b	__asm_invalidate_tlb_all
152	ret
153#endif
154
155/*-----------------------------------------------------------------------*/
156
157WEAK(apply_core_errata)
158
159	mov	x29, lr			/* Save LR */
160	/* For now, we support Cortex-A57 specific errata only */
161
162	/* Check if we are running on a Cortex-A57 core */
163	branch_if_a57_core x0, apply_a57_core_errata
1640:
165	mov	lr, x29			/* Restore LR */
166	ret
167
168apply_a57_core_errata:
169
170#ifdef CONFIG_ARM_ERRATA_828024
171	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
172	/* Disable non-allocate hint of w-b-n-a memory type */
173	orr	x0, x0, #1 << 49
174	/* Disable write streaming no L1-allocate threshold */
175	orr	x0, x0, #3 << 25
176	/* Disable write streaming no-allocate threshold */
177	orr	x0, x0, #3 << 27
178	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
179#endif
180
181#ifdef CONFIG_ARM_ERRATA_826974
182	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
183	/* Disable speculative load execution ahead of a DMB */
184	orr	x0, x0, #1 << 59
185	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
186#endif
187
188#ifdef CONFIG_ARM_ERRATA_833471
189	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
190	/* FPSCR write flush.
191	 * Note that in some cases where a flush is unnecessary this
192	    could impact performance. */
193	orr	x0, x0, #1 << 38
194	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
195#endif
196
197#ifdef CONFIG_ARM_ERRATA_829520
198	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
199	/* Disable Indirect Predictor bit will prevent this erratum
200	    from occurring
201	 * Note that in some cases where a flush is unnecessary this
202	    could impact performance. */
203	orr	x0, x0, #1 << 4
204	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
205#endif
206
207#ifdef CONFIG_ARM_ERRATA_833069
208	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
209	/* Disable Enable Invalidates of BTB bit */
210	and	x0, x0, #0xE
211	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
212#endif
213	b 0b
214ENDPROC(apply_core_errata)
215
216/*-----------------------------------------------------------------------*/
217
218WEAK(lowlevel_init)
219	mov	x29, lr			/* Save LR */
220
221#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
222	branch_if_slave x0, 1f
223	ldr	x0, =GICD_BASE
224	bl	gic_init_secure
2251:
226#if defined(CONFIG_GICV3)
227	ldr	x0, =GICR_BASE
228	bl	gic_init_secure_percpu
229#elif defined(CONFIG_GICV2)
230	ldr	x0, =GICD_BASE
231	ldr	x1, =GICC_BASE
232	bl	gic_init_secure_percpu
233#endif
234#endif
235
236#ifdef CONFIG_ARMV8_MULTIENTRY
237	branch_if_master x0, x1, 2f
238
239	/*
240	 * Slave should wait for master clearing spin table.
241	 * This sync prevent salves observing incorrect
242	 * value of spin table and jumping to wrong place.
243	 */
244#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
245#ifdef CONFIG_GICV2
246	ldr	x0, =GICC_BASE
247#endif
248	bl	gic_wait_for_interrupt
249#endif
250
251	/*
252	 * All slaves will enter EL2 and optionally EL1.
253	 */
254	adr	x3, lowlevel_in_el2
255	ldr	x4, =ES_TO_AARCH64
256	bl	armv8_switch_to_el2
257
258lowlevel_in_el2:
259#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
260	adr	x3, lowlevel_in_el1
261	ldr	x4, =ES_TO_AARCH64
262	bl	armv8_switch_to_el1
263
264lowlevel_in_el1:
265#endif
266
267#endif /* CONFIG_ARMV8_MULTIENTRY */
268
2692:
270	mov	lr, x29			/* Restore LR */
271	ret
272ENDPROC(lowlevel_init)
273
274WEAK(smp_kick_all_cpus)
275	/* Kick secondary cpus up by SGI 0 interrupt */
276#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
277	ldr	x0, =GICD_BASE
278	b	gic_kick_secondary_cpus
279#endif
280	ret
281ENDPROC(smp_kick_all_cpus)
282
283/*-----------------------------------------------------------------------*/
284
285ENTRY(c_runtime_cpu_setup)
286	/* Relocate vBAR */
287	adr	x0, vectors
288	switch_el x1, 3f, 2f, 1f
2893:	msr	vbar_el3, x0
290	b	0f
2912:	msr	vbar_el2, x0
292	b	0f
2931:	msr	vbar_el1, x0
2940:
295
296	ret
297ENDPROC(c_runtime_cpu_setup)
298
299WEAK(save_boot_params)
300	b	save_boot_params_ret	/* back to my caller */
301ENDPROC(save_boot_params)
302