Merge git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / arch / arm / cpu / arm720t / start.S
1 /*
2  *  armboot - Startup Code for ARM720 CPU-core
3  *
4  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
5  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+ 
8  */
9
10 #include <asm-offsets.h>
11 #include <config.h>
12 #include <version.h>
13 #include <asm/hardware.h>
14
15 /*
16  *************************************************************************
17  *
18  * Jump vector table as in table 3.1 in [1]
19  *
20  *************************************************************************
21  */
22
23
24 .globl _start
25 _start: b       reset
26         ldr     pc, _undefined_instruction
27         ldr     pc, _software_interrupt
28         ldr     pc, _prefetch_abort
29         ldr     pc, _data_abort
30         ldr     pc, _not_used
31         ldr     pc, _irq
32         ldr     pc, _fiq
33
34 #ifdef CONFIG_SPL_BUILD
35 _undefined_instruction: .word _undefined_instruction
36 _software_interrupt:    .word _software_interrupt
37 _prefetch_abort:        .word _prefetch_abort
38 _data_abort:            .word _data_abort
39 _not_used:              .word _not_used
40 _irq:                   .word _irq
41 _fiq:                   .word _fiq
42 _pad:                   .word 0x12345678 /* now 16*4=64 */
43 #else
44 _undefined_instruction: .word undefined_instruction
45 _software_interrupt:    .word software_interrupt
46 _prefetch_abort:        .word prefetch_abort
47 _data_abort:            .word data_abort
48 _not_used:              .word not_used
49 _irq:                   .word irq
50 _fiq:                   .word fiq
51 _pad:                   .word 0x12345678 /* now 16*4=64 */
52 #endif  /* CONFIG_SPL_BUILD */
53
54         .balignl 16,0xdeadbeef
55
56
57 /*
58  *************************************************************************
59  *
60  * Startup Code (reset vector)
61  *
62  * do important init only if we don't start from RAM!
63  * relocate armboot to ram
64  * setup stack
65  * jump to second stage
66  *
67  *************************************************************************
68  */
69
70 .globl _TEXT_BASE
71 _TEXT_BASE:
72 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
73         .word   CONFIG_SPL_TEXT_BASE
74 #else
75         .word   CONFIG_SYS_TEXT_BASE
76 #endif
77
78 /*
79  * These are defined in the board-specific linker script.
80  * Subtracting _start from them lets the linker put their
81  * relative position in the executable instead of leaving
82  * them null.
83  */
84 .globl _bss_start_ofs
85 _bss_start_ofs:
86         .word __bss_start - _start
87
88 .globl _bss_end_ofs
89 _bss_end_ofs:
90         .word __bss_end - _start
91
92 .globl _end_ofs
93 _end_ofs:
94         .word _end - _start
95
96 #ifdef CONFIG_USE_IRQ
97 /* IRQ stack memory (calculated at run-time) */
98 .globl IRQ_STACK_START
99 IRQ_STACK_START:
100         .word   0x0badc0de
101
102 /* IRQ stack memory (calculated at run-time) */
103 .globl FIQ_STACK_START
104 FIQ_STACK_START:
105         .word 0x0badc0de
106 #endif
107
108 /* IRQ stack memory (calculated at run-time) + 8 bytes */
109 .globl IRQ_STACK_START_IN
110 IRQ_STACK_START_IN:
111         .word   0x0badc0de
112
113 /*
114  * the actual reset code
115  */
116
117 reset:
118         /*
119          * set the cpu to SVC32 mode
120          */
121         mrs     r0,cpsr
122         bic     r0,r0,#0x1f
123         orr     r0,r0,#0xd3
124         msr     cpsr,r0
125
126         /*
127          * we do sys-critical inits only at reboot,
128          * not when booting from ram!
129          */
130 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
131         bl      cpu_init_crit
132 #endif
133
134         bl      _main
135
136 /*------------------------------------------------------------------------------*/
137
138         .globl  c_runtime_cpu_setup
139 c_runtime_cpu_setup:
140
141         mov     pc, lr
142
143 /*
144  *************************************************************************
145  *
146  * CPU_init_critical registers
147  *
148  * setup important registers
149  * setup memory timing
150  *
151  *************************************************************************
152  */
153
154 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
155 cpu_init_crit:
156
157         mov     ip, lr
158         /*
159          * before relocating, we have to setup RAM timing
160          * because memory timing is board-dependent, you will
161          * find a lowlevel_init.S in your board directory.
162          */
163         bl      lowlevel_init
164         mov     lr, ip
165
166         mov     pc, lr
167 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
168
169
170 #ifndef CONFIG_SPL_BUILD
171 /*
172  *************************************************************************
173  *
174  * Interrupt handling
175  *
176  *************************************************************************
177  */
178
179 @
180 @ IRQ stack frame.
181 @
182 #define S_FRAME_SIZE    72
183
184 #define S_OLD_R0        68
185 #define S_PSR           64
186 #define S_PC            60
187 #define S_LR            56
188 #define S_SP            52
189
190 #define S_IP            48
191 #define S_FP            44
192 #define S_R10           40
193 #define S_R9            36
194 #define S_R8            32
195 #define S_R7            28
196 #define S_R6            24
197 #define S_R5            20
198 #define S_R4            16
199 #define S_R3            12
200 #define S_R2            8
201 #define S_R1            4
202 #define S_R0            0
203
204 #define MODE_SVC 0x13
205 #define I_BIT    0x80
206
207 /*
208  * use bad_save_user_regs for abort/prefetch/undef/swi ...
209  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
210  */
211
212         .macro  bad_save_user_regs
213         sub     sp, sp, #S_FRAME_SIZE
214         stmia   sp, {r0 - r12}                  @ Calling r0-r12
215         add     r8, sp, #S_PC
216
217         ldr     r2, IRQ_STACK_START_IN
218         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
219         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
220
221         add     r5, sp, #S_SP
222         mov     r1, lr
223         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
224         mov     r0, sp
225         .endm
226
227         .macro  irq_save_user_regs
228         sub     sp, sp, #S_FRAME_SIZE
229         stmia   sp, {r0 - r12}                  @ Calling r0-r12
230         add     r8, sp, #S_PC
231         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
232         str     lr, [r8, #0]                    @ Save calling PC
233         mrs     r6, spsr
234         str     r6, [r8, #4]                    @ Save CPSR
235         str     r0, [r8, #8]                    @ Save OLD_R0
236         mov     r0, sp
237         .endm
238
239         .macro  irq_restore_user_regs
240         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
241         mov     r0, r0
242         ldr     lr, [sp, #S_PC]                 @ Get PC
243         add     sp, sp, #S_FRAME_SIZE
244         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
245         .endm
246
247         .macro get_bad_stack
248         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
249
250         str     lr, [r13]                       @ save caller lr / spsr
251         mrs     lr, spsr
252         str     lr, [r13, #4]
253
254         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
255         msr     spsr_c, r13
256         mov     lr, pc
257         movs    pc, lr
258         .endm
259
260         .macro get_irq_stack                    @ setup IRQ stack
261         ldr     sp, IRQ_STACK_START
262         .endm
263
264         .macro get_fiq_stack                    @ setup FIQ stack
265         ldr     sp, FIQ_STACK_START
266         .endm
267
268 /*
269  * exception handlers
270  */
271         .align  5
272 undefined_instruction:
273         get_bad_stack
274         bad_save_user_regs
275         bl      do_undefined_instruction
276
277         .align  5
278 software_interrupt:
279         get_bad_stack
280         bad_save_user_regs
281         bl      do_software_interrupt
282
283         .align  5
284 prefetch_abort:
285         get_bad_stack
286         bad_save_user_regs
287         bl      do_prefetch_abort
288
289         .align  5
290 data_abort:
291         get_bad_stack
292         bad_save_user_regs
293         bl      do_data_abort
294
295         .align  5
296 not_used:
297         get_bad_stack
298         bad_save_user_regs
299         bl      do_not_used
300
301 #ifdef CONFIG_USE_IRQ
302
303         .align  5
304 irq:
305         get_irq_stack
306         irq_save_user_regs
307         bl      do_irq
308         irq_restore_user_regs
309
310         .align  5
311 fiq:
312         get_fiq_stack
313         /* someone ought to write a more effiction fiq_save_user_regs */
314         irq_save_user_regs
315         bl      do_fiq
316         irq_restore_user_regs
317
318 #else
319
320         .align  5
321 irq:
322         get_bad_stack
323         bad_save_user_regs
324         bl      do_irq
325
326         .align  5
327 fiq:
328         get_bad_stack
329         bad_save_user_regs
330         bl      do_fiq
331
332 #endif
333 #endif /* CONFIG_SPL_BUILD */