Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / arm / cpu / arm920t / start.S
1 /*
2  *  armboot - Startup Code for ARM920 CPU-core
3  *
4  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
5  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
6  *  Copyright (c) 2002  Gary Jennejohn <garyj@denx.de>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <asm-offsets.h>
12 #include <common.h>
13 #include <config.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       start_code
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 _undefined_instruction: .word undefined_instruction
35 _software_interrupt:    .word software_interrupt
36 _prefetch_abort:        .word prefetch_abort
37 _data_abort:            .word data_abort
38 _not_used:              .word not_used
39 _irq:                   .word irq
40 _fiq:                   .word fiq
41
42         .balignl 16,0xdeadbeef
43
44
45 /*
46  *************************************************************************
47  *
48  * Startup Code (called from the ARM reset exception vector)
49  *
50  * do important init only if we don't start from memory!
51  * relocate armboot to ram
52  * setup stack
53  * jump to second stage
54  *
55  *************************************************************************
56  */
57
58 .globl _TEXT_BASE
59 _TEXT_BASE:
60 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
61         .word   CONFIG_SPL_TEXT_BASE
62 #else
63         .word   CONFIG_SYS_TEXT_BASE
64 #endif
65
66 /*
67  * These are defined in the board-specific linker script.
68  * Subtracting _start from them lets the linker put their
69  * relative position in the executable instead of leaving
70  * them null.
71  */
72 .globl _bss_start_ofs
73 _bss_start_ofs:
74         .word __bss_start - _start
75
76 .globl _bss_end_ofs
77 _bss_end_ofs:
78         .word __bss_end - _start
79
80 .globl _end_ofs
81 _end_ofs:
82         .word _end - _start
83
84 #ifdef CONFIG_USE_IRQ
85 /* IRQ stack memory (calculated at run-time) */
86 .globl IRQ_STACK_START
87 IRQ_STACK_START:
88         .word   0x0badc0de
89
90 /* IRQ stack memory (calculated at run-time) */
91 .globl FIQ_STACK_START
92 FIQ_STACK_START:
93         .word 0x0badc0de
94 #endif
95
96 /* IRQ stack memory (calculated at run-time) + 8 bytes */
97 .globl IRQ_STACK_START_IN
98 IRQ_STACK_START_IN:
99         .word   0x0badc0de
100
101 /*
102  * the actual start code
103  */
104
105 start_code:
106         /*
107          * set the cpu to SVC32 mode
108          */
109         mrs     r0, cpsr
110         bic     r0, r0, #0x1f
111         orr     r0, r0, #0xd3
112         msr     cpsr, r0
113
114 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
115         /*
116          * relocate exception table
117          */
118         ldr     r0, =_start
119         ldr     r1, =0x0
120         mov     r2, #16
121 copyex:
122         subs    r2, r2, #1
123         ldr     r3, [r0], #4
124         str     r3, [r1], #4
125         bne     copyex
126 #endif
127
128 #ifdef CONFIG_S3C24X0
129         /* turn off the watchdog */
130
131 # if defined(CONFIG_S3C2400)
132 #  define pWTCON        0x15300000
133 #  define INTMSK        0x14400008      /* Interrupt-Controller base addresses */
134 #  define CLKDIVN       0x14800014      /* clock divisor register */
135 #else
136 #  define pWTCON        0x53000000
137 #  define INTMSK        0x4A000008      /* Interrupt-Controller base addresses */
138 #  define INTSUBMSK     0x4A00001C
139 #  define CLKDIVN       0x4C000014      /* clock divisor register */
140 # endif
141
142         ldr     r0, =pWTCON
143         mov     r1, #0x0
144         str     r1, [r0]
145
146         /*
147          * mask all IRQs by setting all bits in the INTMR - default
148          */
149         mov     r1, #0xffffffff
150         ldr     r0, =INTMSK
151         str     r1, [r0]
152 # if defined(CONFIG_S3C2410)
153         ldr     r1, =0x3ff
154         ldr     r0, =INTSUBMSK
155         str     r1, [r0]
156 # endif
157
158         /* FCLK:HCLK:PCLK = 1:2:4 */
159         /* default FCLK is 120 MHz ! */
160         ldr     r0, =CLKDIVN
161         mov     r1, #3
162         str     r1, [r0]
163 #endif  /* CONFIG_S3C24X0 */
164
165         /*
166          * we do sys-critical inits only at reboot,
167          * not when booting from ram!
168          */
169 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
170         bl      cpu_init_crit
171 #endif
172
173         bl      _main
174
175 /*------------------------------------------------------------------------------*/
176
177         .globl  c_runtime_cpu_setup
178 c_runtime_cpu_setup:
179
180         mov     pc, lr
181
182 /*
183  *************************************************************************
184  *
185  * CPU_init_critical registers
186  *
187  * setup important registers
188  * setup memory timing
189  *
190  *************************************************************************
191  */
192
193
194 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
195 cpu_init_crit:
196         /*
197          * flush v4 I/D caches
198          */
199         mov     r0, #0
200         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
201         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
202
203         /*
204          * disable MMU stuff and caches
205          */
206         mrc     p15, 0, r0, c1, c0, 0
207         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
208         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
209         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
210         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
211         mcr     p15, 0, r0, c1, c0, 0
212
213         /*
214          * before relocating, we have to setup RAM timing
215          * because memory timing is board-dependend, you will
216          * find a lowlevel_init.S in your board directory.
217          */
218         mov     ip, lr
219
220         bl      lowlevel_init
221
222         mov     lr, ip
223         mov     pc, lr
224 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
225
226 /*
227  *************************************************************************
228  *
229  * Interrupt handling
230  *
231  *************************************************************************
232  */
233
234 @
235 @ IRQ stack frame.
236 @
237 #define S_FRAME_SIZE    72
238
239 #define S_OLD_R0        68
240 #define S_PSR           64
241 #define S_PC            60
242 #define S_LR            56
243 #define S_SP            52
244
245 #define S_IP            48
246 #define S_FP            44
247 #define S_R10           40
248 #define S_R9            36
249 #define S_R8            32
250 #define S_R7            28
251 #define S_R6            24
252 #define S_R5            20
253 #define S_R4            16
254 #define S_R3            12
255 #define S_R2            8
256 #define S_R1            4
257 #define S_R0            0
258
259 #define MODE_SVC        0x13
260 #define I_BIT           0x80
261
262 /*
263  * use bad_save_user_regs for abort/prefetch/undef/swi ...
264  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
265  */
266
267         .macro  bad_save_user_regs
268         sub     sp, sp, #S_FRAME_SIZE
269         stmia   sp, {r0 - r12}                  @ Calling r0-r12
270         ldr     r2, IRQ_STACK_START_IN
271         ldmia   r2, {r2 - r3}                   @ get pc, cpsr
272         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
273
274         add     r5, sp, #S_SP
275         mov     r1, lr
276         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
277         mov     r0, sp
278         .endm
279
280         .macro  irq_save_user_regs
281         sub     sp, sp, #S_FRAME_SIZE
282         stmia   sp, {r0 - r12}                  @ Calling r0-r12
283         add     r7, sp, #S_PC
284         stmdb   r7, {sp, lr}^                   @ Calling SP, LR
285         str     lr, [r7, #0]                    @ Save calling PC
286         mrs     r6, spsr
287         str     r6, [r7, #4]                    @ Save CPSR
288         str     r0, [r7, #8]                    @ Save OLD_R0
289         mov     r0, sp
290         .endm
291
292         .macro  irq_restore_user_regs
293         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
294         mov     r0, r0
295         ldr     lr, [sp, #S_PC]                 @ Get PC
296         add     sp, sp, #S_FRAME_SIZE
297         /* return & move spsr_svc into cpsr */
298         subs    pc, lr, #4
299         .endm
300
301         .macro get_bad_stack
302         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
303
304         str     lr, [r13]                       @ save caller lr / spsr
305         mrs     lr, spsr
306         str     lr, [r13, #4]
307
308         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
309         @ msr   spsr_c, r13
310         msr     spsr, r13
311         mov     lr, pc
312         movs    pc, lr
313         .endm
314
315         .macro get_irq_stack                    @ setup IRQ stack
316         ldr     sp, IRQ_STACK_START
317         .endm
318
319         .macro get_fiq_stack                    @ setup FIQ stack
320         ldr     sp, FIQ_STACK_START
321         .endm
322
323 /*
324  * exception handlers
325  */
326         .align  5
327 undefined_instruction:
328         get_bad_stack
329         bad_save_user_regs
330         bl      do_undefined_instruction
331
332         .align  5
333 software_interrupt:
334         get_bad_stack
335         bad_save_user_regs
336         bl      do_software_interrupt
337
338         .align  5
339 prefetch_abort:
340         get_bad_stack
341         bad_save_user_regs
342         bl      do_prefetch_abort
343
344         .align  5
345 data_abort:
346         get_bad_stack
347         bad_save_user_regs
348         bl      do_data_abort
349
350         .align  5
351 not_used:
352         get_bad_stack
353         bad_save_user_regs
354         bl      do_not_used
355
356 #ifdef CONFIG_USE_IRQ
357
358         .align  5
359 irq:
360         get_irq_stack
361         irq_save_user_regs
362         bl      do_irq
363         irq_restore_user_regs
364
365         .align  5
366 fiq:
367         get_fiq_stack
368         /* someone ought to write a more effiction fiq_save_user_regs */
369         irq_save_user_regs
370         bl      do_fiq
371         irq_restore_user_regs
372
373 #else
374
375         .align  5
376 irq:
377         get_bad_stack
378         bad_save_user_regs
379         bl      do_irq
380
381         .align  5
382 fiq:
383         get_bad_stack
384         bad_save_user_regs
385         bl      do_fiq
386
387 #endif