blob: 0c8946e008c3f484b0870bc9ae7693e94604af17 [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*
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
wdenkfe8c2802002-11-03 00:38:21 +000029#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
wdenkfe8c2802002-11-03 00:38:21 +000076_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
wdenkfe8c2802002-11-03 00:38:21 +000095#ifdef CONFIG_USE_IRQ
96/* IRQ stack memory (calculated at run-time) */
97.globl IRQ_STACK_START
98IRQ_STACK_START:
99 .word 0x0badc0de
100
101/* IRQ stack memory (calculated at run-time) */
102.globl FIQ_STACK_START
103FIQ_STACK_START:
104 .word 0x0badc0de
105#endif
106
107
108/*
109 * the actual reset code
110 */
111
112reset:
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
wdenkc0aa5c52003-12-06 19:49:23 +0000129relocate: /* 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
wdenkfe8c2802002-11-03 00:38:21 +0000135 ldr r2, _armboot_start
136 ldr r3, _armboot_end
wdenkc0aa5c52003-12-06 19:49:23 +0000137 sub r2, r3, r2 /* r2 <- size of armboot */
138 add r2, r0, r2 /* r2 <- source end address */
wdenkfe8c2802002-11-03 00:38:21 +0000139
wdenkfe8c2802002-11-03 00:38:21 +0000140copy_loop:
wdenkc0aa5c52003-12-06 19:49:23 +0000141 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] */
wdenkfe8c2802002-11-03 00:38:21 +0000144 ble copy_loop
145
wdenkc0aa5c52003-12-06 19:49:23 +0000146 /* Set up the stack */
147stack_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 */
wdenkfe8c2802002-11-03 00:38:21 +0000155
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 */
174IC_BASE: .word 0x90050000
175#define ICMR 0x04
176
177
178/* Reset-Controller */
179RST_BASE: .word 0x90030000
180#define RSRR 0x00
181#define RCSR 0x04
182
183
184/* PWR */
185PWR_BASE: .word 0x90020000
186#define PSPR 0x08
187#define PPCR 0x14
188cpuspeed: .word CFG_CPUSPEED
189
190
191cpu_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
wdenkfe8c2802002-11-03 00:38:21 +0000233/*
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
338undefined_instruction:
339 get_bad_stack
340 bad_save_user_regs
341 bl do_undefined_instruction
342
343 .align 5
344software_interrupt:
345 get_bad_stack
346 bad_save_user_regs
347 bl do_software_interrupt
348
349 .align 5
350prefetch_abort:
351 get_bad_stack
352 bad_save_user_regs
353 bl do_prefetch_abort
354
355 .align 5
356data_abort:
357 get_bad_stack
358 bad_save_user_regs
359 bl do_data_abort
360
361 .align 5
362not_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
370irq:
371 get_irq_stack
372 irq_save_user_regs
373 bl do_irq
374 irq_restore_user_regs
375
376 .align 5
377fiq:
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
387irq:
388 get_bad_stack
389 bad_save_user_regs
390 bl do_irq
391
392 .align 5
393fiq:
394 get_bad_stack
395 bad_save_user_regs
396 bl do_fiq
397
398#endif
399
400 .align 5
401.globl reset_cpu
402reset_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