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