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