99d126660d8a29bddb25882924cf4d9ba9d491f1
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * (C) Copyright 2013
4  * David Feng <fenghua@phytium.com.cn>
5  */
6
7 #include <asm-offsets.h>
8 #include <config.h>
9 #include <linux/linkage.h>
10 #include <asm/macro.h>
11 #include <asm/armv8/mmu.h>
12
13 /*************************************************************************
14  *
15  * Startup Code (reset vector)
16  *
17  *************************************************************************/
18
19 .globl  _start
20 _start:
21 #if defined(CONFIG_LINUX_KERNEL_IMAGE_HEADER)
22 #include <asm/boot0-linux-kernel-header.h>
23 #elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
24 /*
25  * Various SoCs need something special and SoC-specific up front in
26  * order to boot, allow them to set that in their boot0.h file and then
27  * use it here.
28  */
29 #include <asm/arch/boot0.h>
30 #else
31         b       reset
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
55 reset:
56         /* Allow the board to save important registers */
57         b       save_boot_params
58 .globl  save_boot_params_ret
59 save_boot_params_ret:
60
61 #if CONFIG_POSITION_INDEPENDENT
62         /*
63          * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
64          * executed at a different address than it was linked at.
65          */
66 pie_fixup:
67         adr     x0, _start              /* x0 <- Runtime value of _start */
68         ldr     x1, _TEXT_BASE          /* x1 <- Linked value of _start */
69         sub     x9, x0, x1              /* x9 <- Run-vs-link offset */
70         adr     x2, __rel_dyn_start     /* x2 <- Runtime &__rel_dyn_start */
71         adr     x3, __rel_dyn_end       /* x3 <- Runtime &__rel_dyn_end */
72 pie_fix_loop:
73         ldp     x0, x1, [x2], #16       /* (x0, x1) <- (Link location, fixup) */
74         ldr     x4, [x2], #8            /* x4 <- addend */
75         cmp     w1, #1027               /* relative fixup? */
76         bne     pie_skip_reloc
77         /* relative fix: store addend plus offset at dest location */
78         add     x0, x0, x9
79         add     x4, x4, x9
80         str     x4, [x0]
81 pie_skip_reloc:
82         cmp     x2, x3
83         b.lo    pie_fix_loop
84 pie_fixup_done:
85 #endif
86
87 #ifdef CONFIG_SYS_RESET_SCTRL
88         bl reset_sctrl
89 #endif
90
91 #if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
92 .macro  set_vbar, regname, reg
93         msr     \regname, \reg
94 .endm
95         adr     x0, vectors
96 #else
97 .macro  set_vbar, regname, reg
98 .endm
99 #endif
100         /*
101          * Could be EL3/EL2/EL1, Initial State:
102          * Little Endian, MMU Disabled, i/dCache Disabled
103          */
104         switch_el x1, 3f, 2f, 1f
105 3:      set_vbar vbar_el3, x0
106         mrs     x0, scr_el3
107         orr     x0, x0, #0xf                    /* SCR_EL3.NS|IRQ|FIQ|EA */
108         msr     scr_el3, x0
109         msr     cptr_el3, xzr                   /* Enable FP/SIMD */
110 #ifdef COUNTER_FREQUENCY
111         ldr     x0, =COUNTER_FREQUENCY
112         msr     cntfrq_el0, x0                  /* Initialize CNTFRQ */
113 #endif
114         b       0f
115 2:      set_vbar        vbar_el2, x0
116         mov     x0, #0x33ff
117         msr     cptr_el2, x0                    /* Enable FP/SIMD */
118         b       0f
119 1:      set_vbar        vbar_el1, x0
120         mov     x0, #3 << 20
121         msr     cpacr_el1, x0                   /* Enable FP/SIMD */
122 0:
123
124         /*
125          * Enable SMPEN bit for coherency.
126          * This register is not architectural but at the moment
127          * this bit should be set for A53/A57/A72.
128          */
129 #ifdef CONFIG_ARMV8_SET_SMPEN
130         switch_el x1, 3f, 1f, 1f
131 3:
132         mrs     x0, S3_1_c15_c2_1               /* cpuectlr_el1 */
133         orr     x0, x0, #0x40
134         msr     S3_1_c15_c2_1, x0
135 1:
136 #endif
137
138         /* Apply ARM core specific erratas */
139         bl      apply_core_errata
140
141         /*
142          * Cache/BPB/TLB Invalidate
143          * i-cache is invalidated before enabled in icache_enable()
144          * tlb is invalidated before mmu is enabled in dcache_enable()
145          * d-cache is invalidated before enabled in dcache_enable()
146          */
147
148         /* Processor specific initialization */
149         bl      lowlevel_init
150
151 #if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
152         branch_if_master x0, x1, master_cpu
153         b       spin_table_secondary_jump
154         /* never return */
155 #elif defined(CONFIG_ARMV8_MULTIENTRY)
156         branch_if_master x0, x1, master_cpu
157
158         /*
159          * Slave CPUs
160          */
161 slave_cpu:
162         wfe
163         ldr     x1, =CPU_RELEASE_ADDR
164         ldr     x0, [x1]
165         cbz     x0, slave_cpu
166         br      x0                      /* branch to the given address */
167 #endif /* CONFIG_ARMV8_MULTIENTRY */
168 master_cpu:
169         bl      _main
170
171 #ifdef CONFIG_SYS_RESET_SCTRL
172 reset_sctrl:
173         switch_el x1, 3f, 2f, 1f
174 3:
175         mrs     x0, sctlr_el3
176         b       0f
177 2:
178         mrs     x0, sctlr_el2
179         b       0f
180 1:
181         mrs     x0, sctlr_el1
182
183 0:
184         ldr     x1, =0xfdfffffa
185         and     x0, x0, x1
186
187         switch_el x1, 6f, 5f, 4f
188 6:
189         msr     sctlr_el3, x0
190         b       7f
191 5:
192         msr     sctlr_el2, x0
193         b       7f
194 4:
195         msr     sctlr_el1, x0
196
197 7:
198         dsb     sy
199         isb
200         b       __asm_invalidate_tlb_all
201         ret
202 #endif
203
204 /*-----------------------------------------------------------------------*/
205
206 WEAK(apply_core_errata)
207
208         mov     x29, lr                 /* Save LR */
209         /* For now, we support Cortex-A53, Cortex-A57 specific errata */
210
211         /* Check if we are running on a Cortex-A53 core */
212         branch_if_a53_core x0, apply_a53_core_errata
213
214         /* Check if we are running on a Cortex-A57 core */
215         branch_if_a57_core x0, apply_a57_core_errata
216 0:
217         mov     lr, x29                 /* Restore LR */
218         ret
219
220 apply_a53_core_errata:
221
222 #ifdef CONFIG_ARM_ERRATA_855873
223         mrs     x0, midr_el1
224         tst     x0, #(0xf << 20)
225         b.ne    0b
226
227         mrs     x0, midr_el1
228         and     x0, x0, #0xf
229         cmp     x0, #3
230         b.lt    0b
231
232         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
233         /* Enable data cache clean as data cache clean/invalidate */
234         orr     x0, x0, #1 << 44
235         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
236 #endif
237         b 0b
238
239 apply_a57_core_errata:
240
241 #ifdef CONFIG_ARM_ERRATA_828024
242         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
243         /* Disable non-allocate hint of w-b-n-a memory type */
244         orr     x0, x0, #1 << 49
245         /* Disable write streaming no L1-allocate threshold */
246         orr     x0, x0, #3 << 25
247         /* Disable write streaming no-allocate threshold */
248         orr     x0, x0, #3 << 27
249         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
250 #endif
251
252 #ifdef CONFIG_ARM_ERRATA_826974
253         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
254         /* Disable speculative load execution ahead of a DMB */
255         orr     x0, x0, #1 << 59
256         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
257 #endif
258
259 #ifdef CONFIG_ARM_ERRATA_833471
260         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
261         /* FPSCR write flush.
262          * Note that in some cases where a flush is unnecessary this
263             could impact performance. */
264         orr     x0, x0, #1 << 38
265         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
266 #endif
267
268 #ifdef CONFIG_ARM_ERRATA_829520
269         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
270         /* Disable Indirect Predictor bit will prevent this erratum
271             from occurring
272          * Note that in some cases where a flush is unnecessary this
273             could impact performance. */
274         orr     x0, x0, #1 << 4
275         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
276 #endif
277
278 #ifdef CONFIG_ARM_ERRATA_833069
279         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
280         /* Disable Enable Invalidates of BTB bit */
281         and     x0, x0, #0xE
282         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
283 #endif
284         b 0b
285 ENDPROC(apply_core_errata)
286
287 /*-----------------------------------------------------------------------*/
288
289 WEAK(lowlevel_init)
290         mov     x29, lr                 /* Save LR */
291
292 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
293         branch_if_slave x0, 1f
294         ldr     x0, =GICD_BASE
295         bl      gic_init_secure
296 1:
297 #if defined(CONFIG_GICV3)
298         ldr     x0, =GICR_BASE
299         bl      gic_init_secure_percpu
300 #elif defined(CONFIG_GICV2)
301         ldr     x0, =GICD_BASE
302         ldr     x1, =GICC_BASE
303         bl      gic_init_secure_percpu
304 #endif
305 #endif
306
307 #ifdef CONFIG_ARMV8_MULTIENTRY
308         branch_if_master x0, x1, 2f
309
310         /*
311          * Slave should wait for master clearing spin table.
312          * This sync prevent salves observing incorrect
313          * value of spin table and jumping to wrong place.
314          */
315 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
316 #ifdef CONFIG_GICV2
317         ldr     x0, =GICC_BASE
318 #endif
319         bl      gic_wait_for_interrupt
320 #endif
321
322         /*
323          * All slaves will enter EL2 and optionally EL1.
324          */
325         adr     x4, lowlevel_in_el2
326         ldr     x5, =ES_TO_AARCH64
327         bl      armv8_switch_to_el2
328
329 lowlevel_in_el2:
330 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
331         adr     x4, lowlevel_in_el1
332         ldr     x5, =ES_TO_AARCH64
333         bl      armv8_switch_to_el1
334
335 lowlevel_in_el1:
336 #endif
337
338 #endif /* CONFIG_ARMV8_MULTIENTRY */
339
340 2:
341         mov     lr, x29                 /* Restore LR */
342         ret
343 ENDPROC(lowlevel_init)
344
345 WEAK(smp_kick_all_cpus)
346         /* Kick secondary cpus up by SGI 0 interrupt */
347 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
348         ldr     x0, =GICD_BASE
349         b       gic_kick_secondary_cpus
350 #endif
351         ret
352 ENDPROC(smp_kick_all_cpus)
353
354 /*-----------------------------------------------------------------------*/
355
356 ENTRY(c_runtime_cpu_setup)
357 #if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
358         /* Relocate vBAR */
359         adr     x0, vectors
360         switch_el x1, 3f, 2f, 1f
361 3:      msr     vbar_el3, x0
362         b       0f
363 2:      msr     vbar_el2, x0
364         b       0f
365 1:      msr     vbar_el1, x0
366 0:
367 #endif
368
369         ret
370 ENDPROC(c_runtime_cpu_setup)
371
372 WEAK(save_boot_params)
373         b       save_boot_params_ret    /* back to my caller */
374 ENDPROC(save_boot_params)