blob: 36d44da1f83819d6695bdb396d8b356b13a1ca2f [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
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020028#include <asm-offsets.h>
wdenkfe8c2802002-11-03 00:38:21 +000029#include <config.h>
30#include <version.h>
31
wdenkfe8c2802002-11-03 00:38:21 +000032/*
33 *************************************************************************
34 *
35 * Jump vector table as in table 3.1 in [1]
36 *
37 *************************************************************************
38 */
39
40
41.globl _start
42_start: b reset
43 ldr pc, _undefined_instruction
44 ldr pc, _software_interrupt
45 ldr pc, _prefetch_abort
46 ldr pc, _data_abort
47 ldr pc, _not_used
48 ldr pc, _irq
49 ldr pc, _fiq
50
51_undefined_instruction: .word undefined_instruction
52_software_interrupt: .word software_interrupt
53_prefetch_abort: .word prefetch_abort
54_data_abort: .word data_abort
55_not_used: .word not_used
56_irq: .word irq
57_fiq: .word fiq
58
59 .balignl 16,0xdeadbeef
60
61
62/*
63 *************************************************************************
64 *
65 * Startup Code (reset vector)
66 *
67 * do important init only if we don't start from memory!
68 * relocate armboot to ram
69 * setup stack
70 * jump to second stage
71 *
72 *************************************************************************
73 */
74
Heiko Schochere30ceca2010-09-17 13:10:48 +020075.globl _TEXT_BASE
wdenkfe8c2802002-11-03 00:38:21 +000076_TEXT_BASE:
Wolfgang Denk14d0a022010-10-07 21:51:12 +020077 .word CONFIG_SYS_TEXT_BASE
wdenkfe8c2802002-11-03 00:38:21 +000078
wdenkfe8c2802002-11-03 00:38:21 +000079/*
wdenkf6e20fc2004-02-08 19:38:38 +000080 * These are defined in the board-specific linker script.
Albert Aribaud3336ca62010-11-25 22:45:02 +010081 * Subtracting _start from them lets the linker put their
82 * relative position in the executable instead of leaving
83 * them null.
wdenkfe8c2802002-11-03 00:38:21 +000084 */
Albert Aribaud3336ca62010-11-25 22:45:02 +010085.globl _bss_start_ofs
86_bss_start_ofs:
87 .word __bss_start - _start
wdenkf6e20fc2004-02-08 19:38:38 +000088
Albert Aribaud3336ca62010-11-25 22:45:02 +010089.globl _bss_end_ofs
90_bss_end_ofs:
91 .word _end - _start
wdenkfe8c2802002-11-03 00:38:21 +000092
wdenkfe8c2802002-11-03 00:38:21 +000093#ifdef CONFIG_USE_IRQ
94/* IRQ stack memory (calculated at run-time) */
95.globl IRQ_STACK_START
96IRQ_STACK_START:
97 .word 0x0badc0de
98
99/* IRQ stack memory (calculated at run-time) */
100.globl FIQ_STACK_START
101FIQ_STACK_START:
102 .word 0x0badc0de
103#endif
104
Heiko Schochere30ceca2010-09-17 13:10:48 +0200105/* IRQ stack memory (calculated at run-time) + 8 bytes */
106.globl IRQ_STACK_START_IN
107IRQ_STACK_START_IN:
108 .word 0x0badc0de
109
Heiko Schochere30ceca2010-09-17 13:10:48 +0200110/*
111 * the actual reset code
112 */
113
114reset:
115 /*
116 * set the cpu to SVC32 mode
117 */
118 mrs r0,cpsr
119 bic r0,r0,#0x1f
120 orr r0,r0,#0xd3
121 msr cpsr,r0
122
123 /*
124 * we do sys-critical inits only at reboot,
125 * not when booting from ram!
126 */
127#ifndef CONFIG_SKIP_LOWLEVEL_INIT
128 bl cpu_init_crit
129#endif
130
131/* Set stackpointer in internal RAM to call board_init_f */
132call_board_init_f:
133 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
134 ldr r0,=0x00000000
135 bl board_init_f
136
137/*------------------------------------------------------------------------------*/
138
139/*
140 * void relocate_code (addr_sp, gd, addr_moni)
141 *
142 * This "function" does not return, instead it continues in RAM
143 * after relocating the monitor code.
144 *
145 */
146 .globl relocate_code
147relocate_code:
148 mov r4, r0 /* save addr_sp */
149 mov r5, r1 /* save addr of gd */
150 mov r6, r2 /* save addr of destination */
151 mov r7, r2 /* save addr of destination */
152
153 /* Set up the stack */
154stack_setup:
155 mov sp, r4
156
157 adr r0, _start
158 ldr r2, _TEXT_BASE
Albert Aribaud3336ca62010-11-25 22:45:02 +0100159 ldr r3, _bss_start_ofs
160 add r2, r0, r3 /* r2 <- source end address */
Heiko Schochere30ceca2010-09-17 13:10:48 +0200161 cmp r0, r6
162 beq clear_bss
163
Heiko Schochere30ceca2010-09-17 13:10:48 +0200164copy_loop:
165 ldmia r0!, {r9-r10} /* copy from source address [r0] */
166 stmia r6!, {r9-r10} /* copy to target address [r1] */
Albert Aribaudda90d4c2010-10-05 16:06:39 +0200167 cmp r0, r2 /* until source end address [r2] */
168 blo copy_loop
Heiko Schochere30ceca2010-09-17 13:10:48 +0200169
170#ifndef CONFIG_PRELOADER
Albert Aribaud3336ca62010-11-25 22:45:02 +0100171 /*
172 * fix .rel.dyn relocations
173 */
174 ldr r0, _TEXT_BASE /* r0 <- Text base */
175 sub r9, r7, r0 /* r9 <- relocation offset */
176 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
177 add r10, r10, r0 /* r10 <- sym table in FLASH */
178 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
179 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
180 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
181 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
Heiko Schochere30ceca2010-09-17 13:10:48 +0200182fixloop:
Albert Aribaud3336ca62010-11-25 22:45:02 +0100183 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
184 add r0, r0, r9 /* r0 <- location to fix up in RAM */
185 ldr r1, [r2, #4]
186 and r8, r1, #0xff
187 cmp r8, #23 /* relative fixup? */
188 beq fixrel
189 cmp r8, #2 /* absolute fixup? */
190 beq fixabs
191 /* ignore unknown type of fixup */
192 b fixnext
193fixabs:
194 /* absolute fix: set location to (offset) symbol value */
195 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
196 add r1, r10, r1 /* r1 <- address of symbol in table */
197 ldr r1, [r1, #4] /* r1 <- symbol value */
198 add r1, r9 /* r1 <- relocated sym addr */
199 b fixnext
200fixrel:
201 /* relative fix: increase location by offset */
202 ldr r1, [r0]
203 add r1, r1, r9
204fixnext:
205 str r1, [r0]
206 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
Heiko Schochere30ceca2010-09-17 13:10:48 +0200207 cmp r2, r3
Wolfgang Denk79e63132010-10-23 23:22:38 +0200208 blo fixloop
Heiko Schochere30ceca2010-09-17 13:10:48 +0200209#endif
Heiko Schochere30ceca2010-09-17 13:10:48 +0200210
211clear_bss:
212#ifndef CONFIG_PRELOADER
Albert Aribaud3336ca62010-11-25 22:45:02 +0100213 ldr r0, _bss_start_ofs
214 ldr r1, _bss_end_ofs
Heiko Schochere30ceca2010-09-17 13:10:48 +0200215 ldr r3, _TEXT_BASE /* Text base */
216 mov r4, r7 /* reloc addr */
Heiko Schochere30ceca2010-09-17 13:10:48 +0200217 add r0, r0, r4
Heiko Schochere30ceca2010-09-17 13:10:48 +0200218 add r1, r1, r4
219 mov r2, #0x00000000 /* clear */
220
221clbss_l:str r2, [r0] /* clear loop... */
222 add r0, r0, #4
223 cmp r0, r1
224 bne clbss_l
225#endif
226
227/*
228 * We are done. Do not return, instead branch to second part of board
229 * initialization, now running from RAM.
230 */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100231 ldr r0, _board_init_r_ofs
232 adr r1, _start
233 add lr, r0, r1
234 add lr, lr, r9
Heiko Schochere30ceca2010-09-17 13:10:48 +0200235 /* setup parameters for board_init_r */
236 mov r0, r5 /* gd_t */
237 mov r1, r7 /* dest_addr */
238 /* jump to it ... */
Heiko Schochere30ceca2010-09-17 13:10:48 +0200239 mov pc, lr
240
Albert Aribaud3336ca62010-11-25 22:45:02 +0100241_board_init_r_ofs:
242 .word board_init_r - _start
243
244_rel_dyn_start_ofs:
245 .word __rel_dyn_start - _start
246_rel_dyn_end_ofs:
247 .word __rel_dyn_end - _start
248_dynsym_start_ofs:
249 .word __dynsym_start - _start
Heiko Schochere30ceca2010-09-17 13:10:48 +0200250
wdenkfe8c2802002-11-03 00:38:21 +0000251/*
252 *************************************************************************
253 *
254 * CPU_init_critical registers
255 *
256 * setup important registers
257 * setup memory timing
258 *
259 *************************************************************************
260 */
261
262
263/* Interupt-Controller base address */
264IC_BASE: .word 0x90050000
265#define ICMR 0x04
266
267
268/* Reset-Controller */
269RST_BASE: .word 0x90030000
270#define RSRR 0x00
271#define RCSR 0x04
272
273
274/* PWR */
275PWR_BASE: .word 0x90020000
276#define PSPR 0x08
277#define PPCR 0x14
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200278cpuspeed: .word CONFIG_SYS_CPUSPEED
wdenkfe8c2802002-11-03 00:38:21 +0000279
280
281cpu_init_crit:
282 /*
283 * mask all IRQs
284 */
285 ldr r0, IC_BASE
286 mov r1, #0x00
287 str r1, [r0, #ICMR]
288
289 /* set clock speed */
290 ldr r0, PWR_BASE
291 ldr r1, cpuspeed
292 str r1, [r0, #PPCR]
293
294 /*
295 * before relocating, we have to setup RAM timing
296 * because memory timing is board-dependend, you will
wdenk400558b2005-04-02 23:52:25 +0000297 * find a lowlevel_init.S in your board directory.
wdenkfe8c2802002-11-03 00:38:21 +0000298 */
299 mov ip, lr
wdenk400558b2005-04-02 23:52:25 +0000300 bl lowlevel_init
wdenkfe8c2802002-11-03 00:38:21 +0000301 mov lr, ip
302
303 /*
304 * disable MMU stuff and enable I-cache
305 */
306 mrc p15,0,r0,c1,c0
307 bic r0, r0, #0x00002000 @ clear bit 13 (X)
308 bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM)
309 orr r0, r0, #0x00001000 @ set bit 12 (I) Icache
310 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
311 mcr p15,0,r0,c1,c0
312
313 /*
314 * flush v4 I/D caches
315 */
316 mov r0, #0
317 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
318 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
319
320 mov pc, lr
321
322
wdenkfe8c2802002-11-03 00:38:21 +0000323/*
324 *************************************************************************
325 *
326 * Interrupt handling
327 *
328 *************************************************************************
329 */
330
331@
332@ IRQ stack frame.
333@
334#define S_FRAME_SIZE 72
335
336#define S_OLD_R0 68
337#define S_PSR 64
338#define S_PC 60
339#define S_LR 56
340#define S_SP 52
341
342#define S_IP 48
343#define S_FP 44
344#define S_R10 40
345#define S_R9 36
346#define S_R8 32
347#define S_R7 28
348#define S_R6 24
349#define S_R5 20
350#define S_R4 16
351#define S_R3 12
352#define S_R2 8
353#define S_R1 4
354#define S_R0 0
355
356#define MODE_SVC 0x13
357#define I_BIT 0x80
358
359/*
360 * use bad_save_user_regs for abort/prefetch/undef/swi ...
361 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
362 */
363
364 .macro bad_save_user_regs
365 sub sp, sp, #S_FRAME_SIZE
366 stmia sp, {r0 - r12} @ Calling r0-r12
367 add r8, sp, #S_PC
368
Heiko Schochere30ceca2010-09-17 13:10:48 +0200369 ldr r2, IRQ_STACK_START_IN
wdenkfe8c2802002-11-03 00:38:21 +0000370 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
371 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
372
373 add r5, sp, #S_SP
374 mov r1, lr
375 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
376 mov r0, sp
377 .endm
378
379 .macro irq_save_user_regs
380 sub sp, sp, #S_FRAME_SIZE
381 stmia sp, {r0 - r12} @ Calling r0-r12
382 add r8, sp, #S_PC
383 stmdb r8, {sp, lr}^ @ Calling SP, LR
384 str lr, [r8, #0] @ Save calling PC
385 mrs r6, spsr
386 str r6, [r8, #4] @ Save CPSR
387 str r0, [r8, #8] @ Save OLD_R0
388 mov r0, sp
389 .endm
390
391 .macro irq_restore_user_regs
392 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
393 mov r0, r0
394 ldr lr, [sp, #S_PC] @ Get PC
395 add sp, sp, #S_FRAME_SIZE
396 subs pc, lr, #4 @ return & move spsr_svc into cpsr
397 .endm
398
399 .macro get_bad_stack
Heiko Schochere30ceca2010-09-17 13:10:48 +0200400 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
wdenkfe8c2802002-11-03 00:38:21 +0000401
402 str lr, [r13] @ save caller lr / spsr
403 mrs lr, spsr
404 str lr, [r13, #4]
405
406 mov r13, #MODE_SVC @ prepare SVC-Mode
407 msr spsr_c, r13
408 mov lr, pc
409 movs pc, lr
410 .endm
411
412 .macro get_irq_stack @ setup IRQ stack
413 ldr sp, IRQ_STACK_START
414 .endm
415
416 .macro get_fiq_stack @ setup FIQ stack
417 ldr sp, FIQ_STACK_START
418 .endm
419
420/*
421 * exception handlers
422 */
423 .align 5
424undefined_instruction:
425 get_bad_stack
426 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200427 bl do_undefined_instruction
wdenkfe8c2802002-11-03 00:38:21 +0000428
429 .align 5
430software_interrupt:
431 get_bad_stack
432 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200433 bl do_software_interrupt
wdenkfe8c2802002-11-03 00:38:21 +0000434
435 .align 5
436prefetch_abort:
437 get_bad_stack
438 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200439 bl do_prefetch_abort
wdenkfe8c2802002-11-03 00:38:21 +0000440
441 .align 5
442data_abort:
443 get_bad_stack
444 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200445 bl do_data_abort
wdenkfe8c2802002-11-03 00:38:21 +0000446
447 .align 5
448not_used:
449 get_bad_stack
450 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200451 bl do_not_used
wdenkfe8c2802002-11-03 00:38:21 +0000452
453#ifdef CONFIG_USE_IRQ
454
455 .align 5
456irq:
457 get_irq_stack
458 irq_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200459 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000460 irq_restore_user_regs
461
462 .align 5
463fiq:
464 get_fiq_stack
465 /* someone ought to write a more effiction fiq_save_user_regs */
466 irq_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200467 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000468 irq_restore_user_regs
469
470#else
471
472 .align 5
473irq:
474 get_bad_stack
475 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200476 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000477
478 .align 5
479fiq:
480 get_bad_stack
481 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200482 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000483
484#endif
485
486 .align 5
487.globl reset_cpu
488reset_cpu:
489 ldr r0, RST_BASE
490 mov r1, #0x0 @ set bit 3-0 ...
491 str r1, [r0, #RCSR] @ ... to clear in RCSR
492 mov r1, #0x1
493 str r1, [r0, #RSRR] @ and perform reset
494 b reset_cpu @ silly, but repeat endlessly