]> git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/sa1100/start.S
* Patch by Gleb Natapov, 19 Sep 2003:
[people/ms/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