* Patch by Gleb Natapov, 19 Sep 2003:
[oweals/u-boot.git] / cpu / sa1100 / start.S
1 /*
2  *  armboot - Startup Code for SA1100 CPU
3  *
4  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
5  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6  *  Copyright (C) 2000  Wolfgang Denk <wd@denx.de>
7  *  Copyright (c) 2001  Alex Züpke <azu@sysgo.de>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28
29 #include <config.h>
30 #include <version.h>
31
32
33 /*
34  *************************************************************************
35  *
36  * Jump vector table as in table 3.1 in [1]
37  *
38  *************************************************************************
39  */
40
41
42 .globl _start
43 _start: b       reset
44         ldr     pc, _undefined_instruction
45         ldr     pc, _software_interrupt
46         ldr     pc, _prefetch_abort
47         ldr     pc, _data_abort
48         ldr     pc, _not_used
49         ldr     pc, _irq
50         ldr     pc, _fiq
51
52 _undefined_instruction: .word undefined_instruction
53 _software_interrupt:    .word software_interrupt
54 _prefetch_abort:        .word prefetch_abort
55 _data_abort:            .word data_abort
56 _not_used:              .word not_used
57 _irq:                   .word irq
58 _fiq:                   .word fiq
59
60         .balignl 16,0xdeadbeef
61
62
63 /*
64  *************************************************************************
65  *
66  * Startup Code (reset vector)
67  *
68  * do important init only if we don't start from memory!
69  * relocate armboot to ram
70  * setup stack
71  * jump to second stage
72  *
73  *************************************************************************
74  */
75
76 _TEXT_BASE:
77         .word   TEXT_BASE
78
79 .globl _armboot_start
80 _armboot_start:
81         .word _start
82
83 /*
84  * Note: _armboot_end_data and _armboot_end are defined
85  * by the (board-dependent) linker script.
86  * _armboot_end_data is the first usable FLASH address after armboot
87  */
88 .globl _armboot_end_data
89 _armboot_end_data:
90         .word armboot_end_data
91 .globl _armboot_end
92 _armboot_end:
93         .word armboot_end
94
95 #ifdef CONFIG_USE_IRQ
96 /* IRQ stack memory (calculated at run-time) */
97 .globl IRQ_STACK_START
98 IRQ_STACK_START:
99         .word   0x0badc0de
100
101 /* IRQ stack memory (calculated at run-time) */
102 .globl FIQ_STACK_START
103 FIQ_STACK_START:
104         .word 0x0badc0de
105 #endif
106
107
108 /*
109  * the actual reset code
110  */
111
112 reset:
113         /*
114          * set the cpu to SVC32 mode
115          */
116         mrs     r0,cpsr
117         bic     r0,r0,#0x1f
118         orr     r0,r0,#0x13
119         msr     cpsr,r0
120
121         /*
122          * we do sys-critical inits only at reboot,
123          * not when booting from ram!
124          */
125 #ifdef CONFIG_INIT_CRITICAL
126         bl      cpu_init_crit
127 #endif
128
129 relocate:                               /* relocate U-Boot to RAM           */
130         adr     r0, _start              /* r0 <- current position of code   */
131         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
132         cmp     r0, r1                  /* don't reloc during debug         */
133         beq     stack_setup
134
135         ldr     r2, _armboot_start
136         ldr     r3, _armboot_end
137         sub     r2, r3, r2              /* r2 <- size of armboot            */
138         add     r2, r0, r2              /* r2 <- source end address         */
139
140 copy_loop:
141         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
142         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
143         cmp     r0, r2                  /* until source end addreee [r2]    */
144         ble     copy_loop
145
146         /* Set up the stack                                                 */
147 stack_setup:
148         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
149         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
150         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
151 #ifdef CONFIG_USE_IRQ
152         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
153 #endif
154         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
155
156         ldr     pc, _start_armboot
157
158 _start_armboot: .word start_armboot
159
160
161 /*
162  *************************************************************************
163  *
164  * CPU_init_critical registers
165  *
166  * setup important registers
167  * setup memory timing
168  *
169  *************************************************************************
170  */
171
172
173 /* Interupt-Controller base address */
174 IC_BASE:        .word   0x90050000
175 #define ICMR    0x04
176
177
178 /* Reset-Controller */
179 RST_BASE:               .word   0x90030000
180 #define RSRR    0x00
181 #define RCSR    0x04
182
183
184 /* PWR */
185 PWR_BASE:               .word   0x90020000
186 #define PSPR    0x08
187 #define PPCR    0x14
188 cpuspeed:               .word   CFG_CPUSPEED
189
190
191 cpu_init_crit:
192         /*
193          * mask all IRQs
194          */
195         ldr     r0, IC_BASE
196         mov     r1, #0x00
197         str     r1, [r0, #ICMR]
198
199         /* set clock speed */
200         ldr     r0, PWR_BASE
201         ldr     r1, cpuspeed
202         str     r1, [r0, #PPCR]
203
204         /*
205          * before relocating, we have to setup RAM timing
206          * because memory timing is board-dependend, you will
207          * find a memsetup.S in your board directory.
208          */
209         mov     ip,     lr
210         bl      memsetup
211         mov     lr,     ip
212
213         /*
214          * disable MMU stuff and enable I-cache
215          */
216         mrc     p15,0,r0,c1,c0
217         bic     r0, r0, #0x00002000     @ clear bit 13 (X)
218         bic     r0, r0, #0x0000000f     @ clear bits 3-0 (WCAM)
219         orr     r0, r0, #0x00001000     @ set bit 12 (I) Icache
220         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
221         mcr     p15,0,r0,c1,c0
222
223         /*
224          * flush v4 I/D caches
225          */
226         mov     r0, #0
227         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
228         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
229
230         mov     pc, lr
231
232
233 /*
234  *************************************************************************
235  *
236  * Interrupt handling
237  *
238  *************************************************************************
239  */
240
241 @
242 @ IRQ stack frame.
243 @
244 #define S_FRAME_SIZE    72
245
246 #define S_OLD_R0        68
247 #define S_PSR           64
248 #define S_PC            60
249 #define S_LR            56
250 #define S_SP            52
251
252 #define S_IP            48
253 #define S_FP            44
254 #define S_R10           40
255 #define S_R9            36
256 #define S_R8            32
257 #define S_R7            28
258 #define S_R6            24
259 #define S_R5            20
260 #define S_R4            16
261 #define S_R3            12
262 #define S_R2            8
263 #define S_R1            4
264 #define S_R0            0
265
266 #define MODE_SVC 0x13
267 #define I_BIT    0x80
268
269 /*
270  * use bad_save_user_regs for abort/prefetch/undef/swi ...
271  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
272  */
273
274         .macro  bad_save_user_regs
275         sub     sp, sp, #S_FRAME_SIZE
276         stmia   sp, {r0 - r12}                  @ Calling r0-r12
277         add     r8, sp, #S_PC
278
279         ldr     r2, _armboot_end
280         add     r2, r2, #CONFIG_STACKSIZE
281         sub     r2, r2, #8
282         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
283         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
284
285         add     r5, sp, #S_SP
286         mov     r1, lr
287         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
288         mov     r0, sp
289         .endm
290
291         .macro  irq_save_user_regs
292         sub     sp, sp, #S_FRAME_SIZE
293         stmia   sp, {r0 - r12}                  @ Calling r0-r12
294         add     r8, sp, #S_PC
295         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
296         str     lr, [r8, #0]                    @ Save calling PC
297         mrs     r6, spsr
298         str     r6, [r8, #4]                    @ Save CPSR
299         str     r0, [r8, #8]                    @ Save OLD_R0
300         mov     r0, sp
301         .endm
302
303         .macro  irq_restore_user_regs
304         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
305         mov     r0, r0
306         ldr     lr, [sp, #S_PC]                 @ Get PC
307         add     sp, sp, #S_FRAME_SIZE
308         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
309         .endm
310
311         .macro get_bad_stack
312         ldr     r13, _armboot_end               @ setup our mode stack
313         add     r13, r13, #CONFIG_STACKSIZE     @ resides at top of normal stack
314         sub     r13, r13, #8
315
316         str     lr, [r13]                       @ save caller lr / spsr
317         mrs     lr, spsr
318         str     lr, [r13, #4]
319
320         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
321         msr     spsr_c, r13
322         mov     lr, pc
323         movs    pc, lr
324         .endm
325
326         .macro get_irq_stack                    @ setup IRQ stack
327         ldr     sp, IRQ_STACK_START
328         .endm
329
330         .macro get_fiq_stack                    @ setup FIQ stack
331         ldr     sp, FIQ_STACK_START
332         .endm
333
334 /*
335  * exception handlers
336  */
337         .align  5
338 undefined_instruction:
339         get_bad_stack
340         bad_save_user_regs
341         bl      do_undefined_instruction
342
343         .align  5
344 software_interrupt:
345         get_bad_stack
346         bad_save_user_regs
347         bl      do_software_interrupt
348
349         .align  5
350 prefetch_abort:
351         get_bad_stack
352         bad_save_user_regs
353         bl      do_prefetch_abort
354
355         .align  5
356 data_abort:
357         get_bad_stack
358         bad_save_user_regs
359         bl      do_data_abort
360
361         .align  5
362 not_used:
363         get_bad_stack
364         bad_save_user_regs
365         bl      do_not_used
366
367 #ifdef CONFIG_USE_IRQ
368
369         .align  5
370 irq:
371         get_irq_stack
372         irq_save_user_regs
373         bl      do_irq
374         irq_restore_user_regs
375
376         .align  5
377 fiq:
378         get_fiq_stack
379         /* someone ought to write a more effiction fiq_save_user_regs */
380         irq_save_user_regs
381         bl      do_fiq
382         irq_restore_user_regs
383
384 #else
385
386         .align  5
387 irq:
388         get_bad_stack
389         bad_save_user_regs
390         bl      do_irq
391
392         .align  5
393 fiq:
394         get_bad_stack
395         bad_save_user_regs
396         bl      do_fiq
397
398 #endif
399
400         .align  5
401 .globl reset_cpu
402 reset_cpu:
403         ldr     r0, RST_BASE
404         mov     r1, #0x0                        @ set bit 3-0 ...
405         str     r1, [r0, #RCSR]                 @ ... to clear in RCSR
406         mov     r1, #0x1
407         str     r1, [r0, #RSRR]                 @ and perform reset
408         b       reset_cpu                       @ silly, but repeat endlessly