Merge git://git.denx.de/u-boot-fsl-qoriq
[oweals/u-boot.git] / arch / arm / cpu / armv8 / start.S
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>
31 ARM_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
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 #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
70 3:      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
80 2:      msr     vbar_el2, x0
81         mov     x0, #0x33ff
82         msr     cptr_el2, x0                    /* Enable FP/SIMD */
83         b       0f
84 1:      msr     vbar_el1, x0
85         mov     x0, #3 << 20
86         msr     cpacr_el1, x0                   /* Enable FP/SIMD */
87 0:
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          */
112 slave_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 */
119 master_cpu:
120         bl      _main
121
122 #ifdef CONFIG_SYS_RESET_SCTRL
123 reset_sctrl:
124         switch_el x1, 3f, 2f, 1f
125 3:
126         mrs     x0, sctlr_el3
127         b       0f
128 2:
129         mrs     x0, sctlr_el2
130         b       0f
131 1:
132         mrs     x0, sctlr_el1
133
134 0:
135         ldr     x1, =0xfdfffffa
136         and     x0, x0, x1
137
138         switch_el x1, 6f, 5f, 4f
139 6:
140         msr     sctlr_el3, x0
141         b       7f
142 5:
143         msr     sctlr_el2, x0
144         b       7f
145 4:
146         msr     sctlr_el1, x0
147
148 7:
149         dsb     sy
150         isb
151         b       __asm_invalidate_tlb_all
152         ret
153 #endif
154
155 /*-----------------------------------------------------------------------*/
156
157 WEAK(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
164 0:
165         mov     lr, x29                 /* Restore LR */
166         ret
167
168 apply_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
214 ENDPROC(apply_core_errata)
215
216 /*-----------------------------------------------------------------------*/
217
218 WEAK(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
225 1:
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
258 lowlevel_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
264 lowlevel_in_el1:
265 #endif
266
267 #endif /* CONFIG_ARMV8_MULTIENTRY */
268
269 2:
270         mov     lr, x29                 /* Restore LR */
271         ret
272 ENDPROC(lowlevel_init)
273
274 WEAK(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
281 ENDPROC(smp_kick_all_cpus)
282
283 /*-----------------------------------------------------------------------*/
284
285 ENTRY(c_runtime_cpu_setup)
286         /* Relocate vBAR */
287         adr     x0, vectors
288         switch_el x1, 3f, 2f, 1f
289 3:      msr     vbar_el3, x0
290         b       0f
291 2:      msr     vbar_el2, x0
292         b       0f
293 1:      msr     vbar_el1, x0
294 0:
295
296         ret
297 ENDPROC(c_runtime_cpu_setup)
298
299 WEAK(save_boot_params)
300         b       save_boot_params_ret    /* back to my caller */
301 ENDPROC(save_boot_params)