]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm1136/start.S
13567b9ce4c99ef00efa1d190d0aecea6817e8ec
[karo-tx-uboot.git] / arch / arm / cpu / arm1136 / start.S
1 /*
2  *  armboot - Startup Code for OMP2420/ARM1136 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  *
12  * SPDX-License-Identifier:     GPL-2.0+
13  */
14
15 #include <asm-offsets.h>
16 #include <config.h>
17 #include <version.h>
18 .globl _start
19 _start: b       reset
20 #ifdef CONFIG_SPL_BUILD
21         ldr     pc, _hang
22         ldr     pc, _hang
23         ldr     pc, _hang
24         ldr     pc, _hang
25         ldr     pc, _hang
26         ldr     pc, _hang
27         ldr     pc, _hang
28
29 _hang:
30         .word   do_hang
31         .word   0x12345678
32         .word   0x12345678
33         .word   0x12345678
34         .word   0x12345678
35         .word   0x12345678
36         .word   0x12345678
37         .word   0x12345678      /* now 16*4=64 */
38 #else
39         ldr     pc, _undefined_instruction
40         ldr     pc, _software_interrupt
41         ldr     pc, _prefetch_abort
42         ldr     pc, _data_abort
43         ldr     pc, _not_used
44         ldr     pc, _irq
45         ldr     pc, _fiq
46
47 _undefined_instruction: .word undefined_instruction
48 _software_interrupt:    .word software_interrupt
49 _prefetch_abort:        .word prefetch_abort
50 _data_abort:            .word data_abort
51 _not_used:              .word not_used
52 _irq:                   .word irq
53 _fiq:                   .word fiq
54 _pad:                   .word 0x12345678 /* now 16*4=64 */
55 #endif  /* CONFIG_SPL_BUILD */
56
57         .balignl 16,0xdeadbeef
58 /*
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
71 #ifdef CONFIG_USE_IRQ
72 /* IRQ stack memory (calculated at run-time) */
73 .globl IRQ_STACK_START
74 IRQ_STACK_START:
75         .word   0x0badc0de
76
77 /* IRQ stack memory (calculated at run-time) */
78 .globl FIQ_STACK_START
79 FIQ_STACK_START:
80         .word 0x0badc0de
81 #endif
82
83 /* IRQ stack memory (calculated at run-time) + 8 bytes */
84 .globl IRQ_STACK_START_IN
85 IRQ_STACK_START_IN:
86         .word   0x0badc0de
87
88 /*
89  * the actual reset code
90  */
91
92 reset:
93         /*
94          * set the cpu to SVC32 mode
95          */
96         mrs     r0,cpsr
97         bic     r0,r0,#0x1f
98         orr     r0,r0,#0xd3
99         msr     cpsr,r0
100
101         /* the mask ROM code should have PLL and others stable */
102 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
103         bl  cpu_init_crit
104 #endif
105
106         bl      _main
107
108 /*------------------------------------------------------------------------------*/
109
110         .globl  c_runtime_cpu_setup
111 c_runtime_cpu_setup:
112
113         bx      lr
114
115 /*
116  *************************************************************************
117  *
118  * CPU_init_critical registers
119  *
120  * setup important registers
121  * setup memory timing
122  *
123  *************************************************************************
124  */
125 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
126 cpu_init_crit:
127         /*
128          * flush v4 I/D caches
129          */
130         mov     r0, #0
131         mcr     p15, 0, r0, c7, c7, 0   /* Invalidate I+D+BTB caches */
132         mcr     p15, 0, r0, c8, c7, 0   /* Invalidate Unified TLB */
133
134         /*
135          * disable MMU stuff and caches
136          */
137         mrc     p15, 0, r0, c1, c0, 0
138         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
139         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
140         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
141         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
142         mcr     p15, 0, r0, c1, c0, 0
143
144         /*
145          * Jump to board specific initialization... The Mask ROM will have already initialized
146          * basic memory.  Go here to bump up clock rate and handle wake up conditions.
147          */
148         mov     ip, lr          /* persevere link reg across call */
149         bl      lowlevel_init   /* go setup pll,mux,memory */
150         mov     lr, ip          /* restore link */
151         mov     pc, lr          /* back to my caller */
152 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
153
154 #ifndef CONFIG_SPL_BUILD
155 /*
156  *************************************************************************
157  *
158  * Interrupt handling
159  *
160  *************************************************************************
161  */
162 @
163 @ IRQ stack frame.
164 @
165 #define S_FRAME_SIZE    72
166
167 #define S_OLD_R0        68
168 #define S_PSR           64
169 #define S_PC            60
170 #define S_LR            56
171 #define S_SP            52
172
173 #define S_IP            48
174 #define S_FP            44
175 #define S_R10           40
176 #define S_R9            36
177 #define S_R8            32
178 #define S_R7            28
179 #define S_R6            24
180 #define S_R5            20
181 #define S_R4            16
182 #define S_R3            12
183 #define S_R2            8
184 #define S_R1            4
185 #define S_R0            0
186
187 #define MODE_SVC 0x13
188 #define I_BIT    0x80
189
190 /*
191  * use bad_save_user_regs for abort/prefetch/undef/swi ...
192  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
193  */
194
195         .macro  bad_save_user_regs
196         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
197         stmia   sp, {r0 - r12}                  @ Save user registers (now in svc mode) r0-r12
198
199         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort stack
200         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc and cpsr (into parm regs)
201         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
202
203         add     r5, sp, #S_SP
204         mov     r1, lr
205         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
206         mov     r0, sp                          @ save current stack into r0 (param register)
207         .endm
208
209         .macro  irq_save_user_regs
210         sub     sp, sp, #S_FRAME_SIZE
211         stmia   sp, {r0 - r12}                  @ Calling r0-r12
212         add     r8, sp, #S_PC                   @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
213         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
214         str     lr, [r8, #0]                    @ Save calling PC
215         mrs     r6, spsr
216         str     r6, [r8, #4]                    @ Save CPSR
217         str     r0, [r8, #8]                    @ Save OLD_R0
218         mov     r0, sp
219         .endm
220
221         .macro  irq_restore_user_regs
222         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
223         mov     r0, r0
224         ldr     lr, [sp, #S_PC]                 @ Get PC
225         add     sp, sp, #S_FRAME_SIZE
226         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
227         .endm
228
229         .macro get_bad_stack
230         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter in banked mode)
231
232         str     lr, [r13]                       @ save caller lr in position 0 of saved stack
233         mrs     lr, spsr                        @ get the spsr
234         str     lr, [r13, #4]                   @ save spsr in position 1 of saved stack
235
236         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
237         @ msr   spsr_c, r13
238         msr     spsr, r13                       @ switch modes, make sure moves will execute
239         mov     lr, pc                          @ capture return pc
240         movs    pc, lr                          @ jump to next instruction & switch modes.
241         .endm
242
243         .macro get_bad_stack_swi
244         sub     r13, r13, #4                    @ space on current stack for scratch reg.
245         str     r0, [r13]                       @ save R0's value.
246         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
247         str     lr, [r0]                        @ save caller lr in position 0 of saved stack
248         mrs     lr, spsr                        @ get the spsr
249         str     lr, [r0, #4]                    @ save spsr in position 1 of saved stack
250         ldr     lr, [r0]                        @ restore lr
251         ldr     r0, [r13]                       @ restore r0
252         add     r13, r13, #4                    @ pop stack entry
253         .endm
254
255         .macro get_irq_stack                    @ setup IRQ stack
256         ldr     sp, IRQ_STACK_START
257         .endm
258
259         .macro get_fiq_stack                    @ setup FIQ stack
260         ldr     sp, FIQ_STACK_START
261         .endm
262 #endif  /* CONFIG_SPL_BUILD */
263
264 /*
265  * exception handlers
266  */
267 #ifdef CONFIG_SPL_BUILD
268         .align  5
269 do_hang:
270         bl      hang                            /* hang and never return */
271 #else   /* !CONFIG_SPL_BUILD */
272         .align  5
273 undefined_instruction:
274         get_bad_stack
275         bad_save_user_regs
276         bl      do_undefined_instruction
277
278         .align  5
279 software_interrupt:
280         get_bad_stack_swi
281         bad_save_user_regs
282         bl      do_software_interrupt
283
284         .align  5
285 prefetch_abort:
286         get_bad_stack
287         bad_save_user_regs
288         bl      do_prefetch_abort
289
290         .align  5
291 data_abort:
292         get_bad_stack
293         bad_save_user_regs
294         bl      do_data_abort
295
296         .align  5
297 not_used:
298         get_bad_stack
299         bad_save_user_regs
300         bl      do_not_used
301
302 #ifdef CONFIG_USE_IRQ
303
304         .align  5
305 irq:
306         get_irq_stack
307         irq_save_user_regs
308         bl      do_irq
309         irq_restore_user_regs
310
311         .align  5
312 fiq:
313         get_fiq_stack
314         /* someone ought to write a more effiction fiq_save_user_regs */
315         irq_save_user_regs
316         bl      do_fiq
317         irq_restore_user_regs
318
319 #else
320
321         .align  5
322 irq:
323         get_bad_stack
324         bad_save_user_regs
325         bl      do_irq
326
327         .align  5
328 fiq:
329         get_bad_stack
330         bad_save_user_regs
331         bl      do_fiq
332
333 #endif
334 #endif  /* CONFIG_SPL_BUILD */