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