blob: b9b889ab8cd75d9686b358dc9a27d221d843508a [file] [log] [blame]
wdenkdc7c9a12003-03-26 06:55:25 +00001/*
2 * armboot - Startup Code for ARM720 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26
wdenkdc7c9a12003-03-26 06:55:25 +000027#include "config.h"
28#include "version.h"
29
30
31/*
32 *************************************************************************
33 *
34 * Jump vector table as in table 3.1 in [1]
35 *
36 *************************************************************************
37 */
38
39
40.globl _start
41_start: b reset
42 ldr pc, _undefined_instruction
43 ldr pc, _software_interrupt
44 ldr pc, _prefetch_abort
45 ldr pc, _data_abort
46 ldr pc, _not_used
47 ldr pc, _irq
48 ldr pc, _fiq
49
50_undefined_instruction: .word undefined_instruction
51_software_interrupt: .word software_interrupt
52_prefetch_abort: .word prefetch_abort
53_data_abort: .word data_abort
54_not_used: .word not_used
55_irq: .word irq
56_fiq: .word fiq
57
58 .balignl 16,0xdeadbeef
59
60
61/*
62 *************************************************************************
63 *
64 * Startup Code (reset vector)
65 *
66 * do important init only if we don't start from memory!
67 * relocate armboot to ram
68 * setup stack
69 * jump to second stage
70 *
71 *************************************************************************
72 */
73
wdenkdc7c9a12003-03-26 06:55:25 +000074_TEXT_BASE:
75 .word TEXT_BASE
76
77.globl _armboot_start
78_armboot_start:
79 .word _start
80
81/*
wdenkf6e20fc2004-02-08 19:38:38 +000082 * These are defined in the board-specific linker script.
wdenkdc7c9a12003-03-26 06:55:25 +000083 */
wdenkf6e20fc2004-02-08 19:38:38 +000084.globl _bss_start
85_bss_start:
86 .word __bss_start
87
88.globl _bss_end
89_bss_end:
90 .word _end
wdenkdc7c9a12003-03-26 06:55:25 +000091
wdenkdc7c9a12003-03-26 06:55:25 +000092#ifdef CONFIG_USE_IRQ
93/* IRQ stack memory (calculated at run-time) */
94.globl IRQ_STACK_START
95IRQ_STACK_START:
96 .word 0x0badc0de
97
98/* IRQ stack memory (calculated at run-time) */
99.globl FIQ_STACK_START
100FIQ_STACK_START:
101 .word 0x0badc0de
102#endif
103
104
105/*
106 * the actual reset code
107 */
108
109reset:
110 /*
wdenk8bde7f72003-06-27 21:31:46 +0000111 * set the cpu to SVC32 mode
112 */
113 mrs r0,cpsr
114 bic r0,r0,#0x1f
115 orr r0,r0,#0x13
116 msr cpsr,r0
wdenkdc7c9a12003-03-26 06:55:25 +0000117
118 /*
119 * relocate exeception table
120 */
121 ldr r0, =_start
122 ldr r1, =0x0
123 mov r2, #16
124copyex:
125 subs r2, r2, #1
126 ldr r3, [r0], #4
127 str r3, [r1], #4
128 bne copyex
129
130 /*
wdenk8bde7f72003-06-27 21:31:46 +0000131 * we do sys-critical inits only at reboot,
132 * not when booting from ram!
133 */
wdenkdc7c9a12003-03-26 06:55:25 +0000134#ifdef CONFIG_INIT_CRITICAL
wdenk8bde7f72003-06-27 21:31:46 +0000135 bl cpu_init_crit
wdenkdc7c9a12003-03-26 06:55:25 +0000136#endif
137
wdenka8c7c702003-12-06 19:49:23 +0000138 /* Set up the stack */
139stack_setup:
140 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
141 sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
142 sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
143#ifdef CONFIG_USE_IRQ
144 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
145#endif
146 sub sp, r0, #12 /* leave 3 words for abort-stack */
147
wdenkf6e20fc2004-02-08 19:38:38 +0000148clear_bss:
149 ldr r0, _bss_start /* find start of bss segment */
150 add r0, r0, #4 /* start at first byte of bss */
151 ldr r1, _bss_end /* stop here */
152 mov r2, #0x00000000 /* clear */
153
154clbss_l:str r2, [r0] /* clear loop... */
155 add r0, r0, #4
156 cmp r0, r1
157 bne clbss_l
158
wdenk8bde7f72003-06-27 21:31:46 +0000159 ldr pc,_start_armboot
wdenkdc7c9a12003-03-26 06:55:25 +0000160
161_start_armboot: .word start_armboot
162
163/*
164 *************************************************************************
165 *
166 * CPU_init_critical registers
167 *
168 *************************************************************************
169 */
170
171cpu_init_crit:
172 # actually do nothing for now!
173 mov pc, lr
174
175
wdenkdc7c9a12003-03-26 06:55:25 +0000176/*
177 *************************************************************************
178 *
179 * Interrupt handling
180 *
181 *************************************************************************
182 */
183
184@
185@ IRQ stack frame.
186@
187#define S_FRAME_SIZE 72
188
189#define S_OLD_R0 68
190#define S_PSR 64
191#define S_PC 60
192#define S_LR 56
193#define S_SP 52
194
195#define S_IP 48
196#define S_FP 44
197#define S_R10 40
198#define S_R9 36
199#define S_R8 32
200#define S_R7 28
201#define S_R6 24
202#define S_R5 20
203#define S_R4 16
204#define S_R3 12
205#define S_R2 8
206#define S_R1 4
207#define S_R0 0
208
209#define MODE_SVC 0x13
210#define I_BIT 0x80
211
212/*
213 * use bad_save_user_regs for abort/prefetch/undef/swi ...
214 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
215 */
216
217 .macro bad_save_user_regs
218 sub sp, sp, #S_FRAME_SIZE
219 stmia sp, {r0 - r12} @ Calling r0-r12
220 add r8, sp, #S_PC
221
wdenkf6e20fc2004-02-08 19:38:38 +0000222 ldr r2, _armboot_start
223 sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
224 sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
wdenkdc7c9a12003-03-26 06:55:25 +0000225 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
226 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
227
228 add r5, sp, #S_SP
229 mov r1, lr
230 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
231 mov r0, sp
232 .endm
233
234 .macro irq_save_user_regs
235 sub sp, sp, #S_FRAME_SIZE
236 stmia sp, {r0 - r12} @ Calling r0-r12
237 add r8, sp, #S_PC
238 stmdb r8, {sp, lr}^ @ Calling SP, LR
239 str lr, [r8, #0] @ Save calling PC
240 mrs r6, spsr
241 str r6, [r8, #4] @ Save CPSR
242 str r0, [r8, #8] @ Save OLD_R0
243 mov r0, sp
244 .endm
245
246 .macro irq_restore_user_regs
247 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
248 mov r0, r0
249 ldr lr, [sp, #S_PC] @ Get PC
250 add sp, sp, #S_FRAME_SIZE
251 subs pc, lr, #4 @ return & move spsr_svc into cpsr
252 .endm
253
254 .macro get_bad_stack
wdenkf6e20fc2004-02-08 19:38:38 +0000255 ldr r13, _armboot_start @ setup our mode stack
256 sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
257 sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
wdenkdc7c9a12003-03-26 06:55:25 +0000258
259 str lr, [r13] @ save caller lr / spsr
260 mrs lr, spsr
261 str lr, [r13, #4]
262
263 mov r13, #MODE_SVC @ prepare SVC-Mode
264 msr spsr_c, r13
265 mov lr, pc
266 movs pc, lr
267 .endm
268
269 .macro get_irq_stack @ setup IRQ stack
270 ldr sp, IRQ_STACK_START
271 .endm
272
273 .macro get_fiq_stack @ setup FIQ stack
274 ldr sp, FIQ_STACK_START
275 .endm
276
277/*
278 * exception handlers
279 */
280 .align 5
281undefined_instruction:
282 get_bad_stack
283 bad_save_user_regs
284 bl do_undefined_instruction
285
286 .align 5
287software_interrupt:
288 get_bad_stack
289 bad_save_user_regs
290 bl do_software_interrupt
291
292 .align 5
293prefetch_abort:
294 get_bad_stack
295 bad_save_user_regs
296 bl do_prefetch_abort
297
298 .align 5
299data_abort:
300 get_bad_stack
301 bad_save_user_regs
302 bl do_data_abort
303
304 .align 5
305not_used:
306 get_bad_stack
307 bad_save_user_regs
308 bl do_not_used
309
310#ifdef CONFIG_USE_IRQ
311
312 .align 5
313irq:
314 get_irq_stack
315 irq_save_user_regs
316 bl do_irq
317 irq_restore_user_regs
318
319 .align 5
320fiq:
321 get_fiq_stack
322 /* someone ought to write a more effiction fiq_save_user_regs */
323 irq_save_user_regs
324 bl do_fiq
325 irq_restore_user_regs
326
327#else
328
329 .align 5
330irq:
331 get_bad_stack
332 bad_save_user_regs
333 bl do_irq
334
335 .align 5
336fiq:
337 get_bad_stack
338 bad_save_user_regs
339 bl do_fiq
340
341#endif
342
343 .align 5
344.globl reset_cpu
345reset_cpu:
346 mov pc, r0