]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/armv7/start.S
eefe1ed254955455154528040e0302a95200f4c3
[u-boot] / arch / arm / cpu / armv7 / start.S
1 /*
2  * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
3  *
4  * Copyright (c) 2004   Texas Instruments <r-woodruff2@ti.com>
5  *
6  * Copyright (c) 2001   Marius Gröger <mag@sysgo.de>
7  * Copyright (c) 2002   Alex Züpke <azu@sysgo.de>
8  * Copyright (c) 2002   Gary Jennejohn <garyj@denx.de>
9  * Copyright (c) 2003   Richard Woodruff <r-woodruff2@ti.com>
10  * Copyright (c) 2003   Kshitij <kshitij@ti.com>
11  * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
12  *
13  * SPDX-License-Identifier:     GPL-2.0+
14  */
15
16 #include <asm-offsets.h>
17 #include <config.h>
18 #include <version.h>
19 #include <asm/system.h>
20 #include <linux/linkage.h>
21
22 .globl _start
23 _start: b       reset
24         ldr     pc, _undefined_instruction
25         ldr     pc, _software_interrupt
26         ldr     pc, _prefetch_abort
27         ldr     pc, _data_abort
28         ldr     pc, _not_used
29         ldr     pc, _irq
30         ldr     pc, _fiq
31 #ifdef CONFIG_SPL_BUILD
32 _undefined_instruction: .word _undefined_instruction
33 _software_interrupt:    .word _software_interrupt
34 _prefetch_abort:        .word _prefetch_abort
35 _data_abort:            .word _data_abort
36 _not_used:              .word _not_used
37 _irq:                   .word _irq
38 _fiq:                   .word _fiq
39 _pad:                   .word 0x12345678 /* now 16*4=64 */
40 #else
41 .globl _undefined_instruction
42 _undefined_instruction: .word undefined_instruction
43 .globl _software_interrupt
44 _software_interrupt:    .word software_interrupt
45 .globl _prefetch_abort
46 _prefetch_abort:        .word prefetch_abort
47 .globl _data_abort
48 _data_abort:            .word data_abort
49 .globl _not_used
50 _not_used:              .word not_used
51 .globl _irq
52 _irq:                   .word irq
53 .globl _fiq
54 _fiq:                   .word fiq
55 _pad:                   .word 0x12345678 /* now 16*4=64 */
56 #endif  /* CONFIG_SPL_BUILD */
57
58         .balignl 16,0xdeadbeef
59 /*************************************************************************
60  *
61  * Startup Code (reset vector)
62  *
63  * do important init only if we don't start from memory!
64  * setup Memory and board specific bits prior to relocation.
65  * relocate armboot to ram
66  * setup stack
67  *
68  *************************************************************************/
69
70 #ifdef CONFIG_USE_IRQ
71 /* IRQ stack memory (calculated at run-time) */
72 .globl IRQ_STACK_START
73 IRQ_STACK_START:
74         .word   0x0badc0de
75
76 /* IRQ stack memory (calculated at run-time) */
77 .globl FIQ_STACK_START
78 FIQ_STACK_START:
79         .word 0x0badc0de
80 #endif
81
82 /* IRQ stack memory (calculated at run-time) + 8 bytes */
83 .globl IRQ_STACK_START_IN
84 IRQ_STACK_START_IN:
85         .word   0x0badc0de
86
87 /*
88  * the actual reset code
89  */
90
91 reset:
92         bl      save_boot_params
93         /*
94          * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
95          * except if in HYP mode already
96          */
97         mrs     r0, cpsr
98         and     r1, r0, #0x1f           @ mask mode bits
99         teq     r1, #0x1a               @ test for HYP mode
100         bicne   r0, r0, #0x1f           @ clear all mode bits
101         orrne   r0, r0, #0x13           @ set SVC mode
102         orr     r0, r0, #0xc0           @ disable FIQ and IRQ
103         msr     cpsr,r0
104
105 /*
106  * Setup vector:
107  * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
108  * Continue to use ROM code vector only in OMAP4 spl)
109  */
110 #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
111         /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
112         mrc     p15, 0, r0, c1, c0, 0   @ Read CP15 SCTRL Register
113         bic     r0, #CR_V               @ V = 0
114         mcr     p15, 0, r0, c1, c0, 0   @ Write CP15 SCTRL Register
115
116         /* Set vector address in CP15 VBAR register */
117         ldr     r0, =_start
118         mcr     p15, 0, r0, c12, c0, 0  @Set VBAR
119 #endif
120
121         /* the mask ROM code should have PLL and others stable */
122 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
123         bl      cpu_init_cp15
124         bl      cpu_init_crit
125 #endif
126
127         bl      _main
128
129 /*------------------------------------------------------------------------------*/
130
131 ENTRY(c_runtime_cpu_setup)
132 /*
133  * If I-cache is enabled invalidate it
134  */
135 #ifndef CONFIG_SYS_ICACHE_OFF
136         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
137         mcr     p15, 0, r0, c7, c10, 4  @ DSB
138         mcr     p15, 0, r0, c7, c5, 4   @ ISB
139 #endif
140 /*
141  * Move vector table
142  */
143         /* Set vector address in CP15 VBAR register */
144         ldr     r0, =_start
145         mcr     p15, 0, r0, c12, c0, 0  @Set VBAR
146
147         bx      lr
148
149 ENDPROC(c_runtime_cpu_setup)
150
151 /*************************************************************************
152  *
153  * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
154  *      __attribute__((weak));
155  *
156  * Stack pointer is not yet initialized at this moment
157  * Don't save anything to stack even if compiled with -O0
158  *
159  *************************************************************************/
160 ENTRY(save_boot_params)
161         bx      lr                      @ back to my caller
162 ENDPROC(save_boot_params)
163         .weak   save_boot_params
164
165 /*************************************************************************
166  *
167  * cpu_init_cp15
168  *
169  * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
170  * CONFIG_SYS_ICACHE_OFF is defined.
171  *
172  *************************************************************************/
173 ENTRY(cpu_init_cp15)
174         /*
175          * Invalidate L1 I/D
176          */
177         mov     r0, #0                  @ set up for MCR
178         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
179         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
180         mcr     p15, 0, r0, c7, c5, 6   @ invalidate BP array
181         mcr     p15, 0, r0, c7, c10, 4  @ DSB
182         mcr     p15, 0, r0, c7, c5, 4   @ ISB
183
184         /*
185          * disable MMU stuff and caches
186          */
187         mrc     p15, 0, r0, c1, c0, 0
188         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
189         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
190         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
191         orr     r0, r0, #0x00000800     @ set bit 11 (Z---) BTB
192 #ifdef CONFIG_SYS_ICACHE_OFF
193         bic     r0, r0, #0x00001000     @ clear bit 12 (I) I-cache
194 #else
195         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-cache
196 #endif
197         mcr     p15, 0, r0, c1, c0, 0
198
199 #ifdef CONFIG_ARM_ERRATA_716044
200         mrc     p15, 0, r0, c1, c0, 0   @ read system control register
201         orr     r0, r0, #1 << 11        @ set bit #11
202         mcr     p15, 0, r0, c1, c0, 0   @ write system control register
203 #endif
204
205 #if (defined(CONFIG_ARM_ERRATA_742230) || defined(CONFIG_ARM_ERRATA_794072))
206         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
207         orr     r0, r0, #1 << 4         @ set bit #4
208         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
209 #endif
210
211 #ifdef CONFIG_ARM_ERRATA_743622
212         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
213         orr     r0, r0, #1 << 6         @ set bit #6
214         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
215 #endif
216
217 #ifdef CONFIG_ARM_ERRATA_751472
218         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
219         orr     r0, r0, #1 << 11        @ set bit #11
220         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
221 #endif
222 #ifdef CONFIG_ARM_ERRATA_761320
223         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
224         orr     r0, r0, #1 << 21        @ set bit #21
225         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
226 #endif
227
228         mov     pc, lr                  @ back to my caller
229 ENDPROC(cpu_init_cp15)
230
231 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
232 /*************************************************************************
233  *
234  * CPU_init_critical registers
235  *
236  * setup important registers
237  * setup memory timing
238  *
239  *************************************************************************/
240 ENTRY(cpu_init_crit)
241         /*
242          * Jump to board specific initialization...
243          * The Mask ROM will have already initialized
244          * basic memory. Go here to bump up clock rate and handle
245          * wake up conditions.
246          */
247         b       lowlevel_init           @ go setup pll,mux,memory
248 ENDPROC(cpu_init_crit)
249 #endif
250
251 #ifndef CONFIG_SPL_BUILD
252 /*
253  *************************************************************************
254  *
255  * Interrupt handling
256  *
257  *************************************************************************
258  */
259 @
260 @ IRQ stack frame.
261 @
262 #define S_FRAME_SIZE    72
263
264 #define S_OLD_R0        68
265 #define S_PSR           64
266 #define S_PC            60
267 #define S_LR            56
268 #define S_SP            52
269
270 #define S_IP            48
271 #define S_FP            44
272 #define S_R10           40
273 #define S_R9            36
274 #define S_R8            32
275 #define S_R7            28
276 #define S_R6            24
277 #define S_R5            20
278 #define S_R4            16
279 #define S_R3            12
280 #define S_R2            8
281 #define S_R1            4
282 #define S_R0            0
283
284 #define MODE_SVC 0x13
285 #define I_BIT    0x80
286
287 /*
288  * use bad_save_user_regs for abort/prefetch/undef/swi ...
289  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
290  */
291
292         .macro  bad_save_user_regs
293         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current
294                                                 @ user stack
295         stmia   sp, {r0 - r12}                  @ Save user registers (now in
296                                                 @ svc mode) r0-r12
297         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort
298                                                 @ stack
299         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc
300                                                 @ and cpsr (into parm regs)
301         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
302
303         add     r5, sp, #S_SP
304         mov     r1, lr
305         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
306         mov     r0, sp                          @ save current stack into r0
307                                                 @ (param register)
308         .endm
309
310         .macro  irq_save_user_regs
311         sub     sp, sp, #S_FRAME_SIZE
312         stmia   sp, {r0 - r12}                  @ Calling r0-r12
313         add     r8, sp, #S_PC                   @ !! R8 NEEDS to be saved !!
314                                                 @ a reserved stack spot would
315                                                 @ be good.
316         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
317         str     lr, [r8, #0]                    @ Save calling PC
318         mrs     r6, spsr
319         str     r6, [r8, #4]                    @ Save CPSR
320         str     r0, [r8, #8]                    @ Save OLD_R0
321         mov     r0, sp
322         .endm
323
324         .macro  irq_restore_user_regs
325         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
326         mov     r0, r0
327         ldr     lr, [sp, #S_PC]                 @ Get PC
328         add     sp, sp, #S_FRAME_SIZE
329         subs    pc, lr, #4                      @ return & move spsr_svc into
330                                                 @ cpsr
331         .endm
332
333         .macro get_bad_stack
334         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter
335                                                 @ in banked mode)
336
337         str     lr, [r13]                       @ save caller lr in position 0
338                                                 @ of saved stack
339         mrs     lr, spsr                        @ get the spsr
340         str     lr, [r13, #4]                   @ save spsr in position 1 of
341                                                 @ saved stack
342
343         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
344         @ msr   spsr_c, r13
345         msr     spsr, r13                       @ switch modes, make sure
346                                                 @ moves will execute
347         mov     lr, pc                          @ capture return pc
348         movs    pc, lr                          @ jump to next instruction &
349                                                 @ switch modes.
350         .endm
351
352         .macro get_bad_stack_swi
353         sub     r13, r13, #4                    @ space on current stack for
354                                                 @ scratch reg.
355         str     r0, [r13]                       @ save R0's value.
356         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
357                                                 @ spots for abort stack
358         str     lr, [r0]                        @ save caller lr in position 0
359                                                 @ of saved stack
360         mrs     lr, spsr                        @ get the spsr
361         str     lr, [r0, #4]                    @ save spsr in position 1 of
362                                                 @ saved stack
363         ldr     lr, [r0]                        @ restore lr
364         ldr     r0, [r13]                       @ restore r0
365         add     r13, r13, #4                    @ pop stack entry
366         .endm
367
368         .macro get_irq_stack                    @ setup IRQ stack
369         ldr     sp, IRQ_STACK_START
370         .endm
371
372         .macro get_fiq_stack                    @ setup FIQ stack
373         ldr     sp, FIQ_STACK_START
374         .endm
375
376 /*
377  * exception handlers
378  */
379         .align  5
380 undefined_instruction:
381         get_bad_stack
382         bad_save_user_regs
383         bl      do_undefined_instruction
384
385         .align  5
386 software_interrupt:
387         get_bad_stack_swi
388         bad_save_user_regs
389         bl      do_software_interrupt
390
391         .align  5
392 prefetch_abort:
393         get_bad_stack
394         bad_save_user_regs
395         bl      do_prefetch_abort
396
397         .align  5
398 data_abort:
399         get_bad_stack
400         bad_save_user_regs
401         bl      do_data_abort
402
403         .align  5
404 not_used:
405         get_bad_stack
406         bad_save_user_regs
407         bl      do_not_used
408
409 #ifdef CONFIG_USE_IRQ
410
411         .align  5
412 irq:
413         get_irq_stack
414         irq_save_user_regs
415         bl      do_irq
416         irq_restore_user_regs
417
418         .align  5
419 fiq:
420         get_fiq_stack
421         /* someone ought to write a more effective fiq_save_user_regs */
422         irq_save_user_regs
423         bl      do_fiq
424         irq_restore_user_regs
425
426 #else
427
428         .align  5
429 irq:
430         get_bad_stack
431         bad_save_user_regs
432         bl      do_irq
433
434         .align  5
435 fiq:
436         get_bad_stack
437         bad_save_user_regs
438         bl      do_fiq
439
440 #endif /* CONFIG_USE_IRQ */
441 #endif /* CONFIG_SPL_BUILD */