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