Merge git://git.denx.de/u-boot-sunxi
[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(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          * Could be EL3/EL2/EL1, Initial State:
92          * Little Endian, MMU Disabled, i/dCache Disabled
93          */
94         adr     x0, vectors
95         switch_el x1, 3f, 2f, 1f
96 3:      msr     vbar_el3, x0
97         mrs     x0, scr_el3
98         orr     x0, x0, #0xf                    /* SCR_EL3.NS|IRQ|FIQ|EA */
99         msr     scr_el3, x0
100         msr     cptr_el3, xzr                   /* Enable FP/SIMD */
101 #ifdef COUNTER_FREQUENCY
102         ldr     x0, =COUNTER_FREQUENCY
103         msr     cntfrq_el0, x0                  /* Initialize CNTFRQ */
104 #endif
105         b       0f
106 2:      msr     vbar_el2, x0
107         mov     x0, #0x33ff
108         msr     cptr_el2, x0                    /* Enable FP/SIMD */
109         b       0f
110 1:      msr     vbar_el1, x0
111         mov     x0, #3 << 20
112         msr     cpacr_el1, x0                   /* Enable FP/SIMD */
113 0:
114
115         /*
116          * Enable SMPEN bit for coherency.
117          * This register is not architectural but at the moment
118          * this bit should be set for A53/A57/A72.
119          */
120 #ifdef CONFIG_ARMV8_SET_SMPEN
121         switch_el x1, 3f, 1f, 1f
122 3:
123         mrs     x0, S3_1_c15_c2_1               /* cpuectlr_el1 */
124         orr     x0, x0, #0x40
125         msr     S3_1_c15_c2_1, x0
126 1:
127 #endif
128
129         /* Apply ARM core specific erratas */
130         bl      apply_core_errata
131
132         /*
133          * Cache/BPB/TLB Invalidate
134          * i-cache is invalidated before enabled in icache_enable()
135          * tlb is invalidated before mmu is enabled in dcache_enable()
136          * d-cache is invalidated before enabled in dcache_enable()
137          */
138
139         /* Processor specific initialization */
140         bl      lowlevel_init
141
142 #if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
143         branch_if_master x0, x1, master_cpu
144         b       spin_table_secondary_jump
145         /* never return */
146 #elif defined(CONFIG_ARMV8_MULTIENTRY)
147         branch_if_master x0, x1, master_cpu
148
149         /*
150          * Slave CPUs
151          */
152 slave_cpu:
153         wfe
154         ldr     x1, =CPU_RELEASE_ADDR
155         ldr     x0, [x1]
156         cbz     x0, slave_cpu
157         br      x0                      /* branch to the given address */
158 #endif /* CONFIG_ARMV8_MULTIENTRY */
159 master_cpu:
160         bl      _main
161
162 #ifdef CONFIG_SYS_RESET_SCTRL
163 reset_sctrl:
164         switch_el x1, 3f, 2f, 1f
165 3:
166         mrs     x0, sctlr_el3
167         b       0f
168 2:
169         mrs     x0, sctlr_el2
170         b       0f
171 1:
172         mrs     x0, sctlr_el1
173
174 0:
175         ldr     x1, =0xfdfffffa
176         and     x0, x0, x1
177
178         switch_el x1, 6f, 5f, 4f
179 6:
180         msr     sctlr_el3, x0
181         b       7f
182 5:
183         msr     sctlr_el2, x0
184         b       7f
185 4:
186         msr     sctlr_el1, x0
187
188 7:
189         dsb     sy
190         isb
191         b       __asm_invalidate_tlb_all
192         ret
193 #endif
194
195 /*-----------------------------------------------------------------------*/
196
197 WEAK(apply_core_errata)
198
199         mov     x29, lr                 /* Save LR */
200         /* For now, we support Cortex-A53, Cortex-A57 specific errata */
201
202         /* Check if we are running on a Cortex-A53 core */
203         branch_if_a53_core x0, apply_a53_core_errata
204
205         /* Check if we are running on a Cortex-A57 core */
206         branch_if_a57_core x0, apply_a57_core_errata
207 0:
208         mov     lr, x29                 /* Restore LR */
209         ret
210
211 apply_a53_core_errata:
212
213 #ifdef CONFIG_ARM_ERRATA_855873
214         mrs     x0, midr_el1
215         tst     x0, #(0xf << 20)
216         b.ne    0b
217
218         mrs     x0, midr_el1
219         and     x0, x0, #0xf
220         cmp     x0, #3
221         b.lt    0b
222
223         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
224         /* Enable data cache clean as data cache clean/invalidate */
225         orr     x0, x0, #1 << 44
226         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
227 #endif
228         b 0b
229
230 apply_a57_core_errata:
231
232 #ifdef CONFIG_ARM_ERRATA_828024
233         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
234         /* Disable non-allocate hint of w-b-n-a memory type */
235         orr     x0, x0, #1 << 49
236         /* Disable write streaming no L1-allocate threshold */
237         orr     x0, x0, #3 << 25
238         /* Disable write streaming no-allocate threshold */
239         orr     x0, x0, #3 << 27
240         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
241 #endif
242
243 #ifdef CONFIG_ARM_ERRATA_826974
244         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
245         /* Disable speculative load execution ahead of a DMB */
246         orr     x0, x0, #1 << 59
247         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
248 #endif
249
250 #ifdef CONFIG_ARM_ERRATA_833471
251         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
252         /* FPSCR write flush.
253          * Note that in some cases where a flush is unnecessary this
254             could impact performance. */
255         orr     x0, x0, #1 << 38
256         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
257 #endif
258
259 #ifdef CONFIG_ARM_ERRATA_829520
260         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
261         /* Disable Indirect Predictor bit will prevent this erratum
262             from occurring
263          * Note that in some cases where a flush is unnecessary this
264             could impact performance. */
265         orr     x0, x0, #1 << 4
266         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
267 #endif
268
269 #ifdef CONFIG_ARM_ERRATA_833069
270         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
271         /* Disable Enable Invalidates of BTB bit */
272         and     x0, x0, #0xE
273         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
274 #endif
275         b 0b
276 ENDPROC(apply_core_errata)
277
278 /*-----------------------------------------------------------------------*/
279
280 WEAK(lowlevel_init)
281         mov     x29, lr                 /* Save LR */
282
283 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
284         branch_if_slave x0, 1f
285         ldr     x0, =GICD_BASE
286         bl      gic_init_secure
287 1:
288 #if defined(CONFIG_GICV3)
289         ldr     x0, =GICR_BASE
290         bl      gic_init_secure_percpu
291 #elif defined(CONFIG_GICV2)
292         ldr     x0, =GICD_BASE
293         ldr     x1, =GICC_BASE
294         bl      gic_init_secure_percpu
295 #endif
296 #endif
297
298 #ifdef CONFIG_ARMV8_MULTIENTRY
299         branch_if_master x0, x1, 2f
300
301         /*
302          * Slave should wait for master clearing spin table.
303          * This sync prevent salves observing incorrect
304          * value of spin table and jumping to wrong place.
305          */
306 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
307 #ifdef CONFIG_GICV2
308         ldr     x0, =GICC_BASE
309 #endif
310         bl      gic_wait_for_interrupt
311 #endif
312
313         /*
314          * All slaves will enter EL2 and optionally EL1.
315          */
316         adr     x4, lowlevel_in_el2
317         ldr     x5, =ES_TO_AARCH64
318         bl      armv8_switch_to_el2
319
320 lowlevel_in_el2:
321 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
322         adr     x4, lowlevel_in_el1
323         ldr     x5, =ES_TO_AARCH64
324         bl      armv8_switch_to_el1
325
326 lowlevel_in_el1:
327 #endif
328
329 #endif /* CONFIG_ARMV8_MULTIENTRY */
330
331 2:
332         mov     lr, x29                 /* Restore LR */
333         ret
334 ENDPROC(lowlevel_init)
335
336 WEAK(smp_kick_all_cpus)
337         /* Kick secondary cpus up by SGI 0 interrupt */
338 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
339         ldr     x0, =GICD_BASE
340         b       gic_kick_secondary_cpus
341 #endif
342         ret
343 ENDPROC(smp_kick_all_cpus)
344
345 /*-----------------------------------------------------------------------*/
346
347 ENTRY(c_runtime_cpu_setup)
348         /* Relocate vBAR */
349         adr     x0, vectors
350         switch_el x1, 3f, 2f, 1f
351 3:      msr     vbar_el3, x0
352         b       0f
353 2:      msr     vbar_el2, x0
354         b       0f
355 1:      msr     vbar_el1, x0
356 0:
357
358         ret
359 ENDPROC(c_runtime_cpu_setup)
360
361 WEAK(save_boot_params)
362         b       save_boot_params_ret    /* back to my caller */
363 ENDPROC(save_boot_params)