]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/cpu/arm920t/start.S
Drop support for CONFIG_SYS_ARM_WITHOUT_RELOC
[people/ms/u-boot.git] / arch / arm / cpu / arm920t / start.S
1 /*
2 * armboot - Startup Code for ARM920 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
6 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27 #include <asm-offsets.h>
28 #include <common.h>
29 #include <config.h>
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 start_code
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 (called from the ARM reset exception 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
74 .globl _TEXT_BASE
75 _TEXT_BASE:
76 .word CONFIG_SYS_TEXT_BASE
77
78 /*
79 * These are defined in the board-specific linker script.
80 */
81 .globl _bss_start
82 _bss_start:
83 .word __bss_start
84
85 .globl _bss_end
86 _bss_end:
87 .word _end
88
89 #ifdef CONFIG_USE_IRQ
90 /* IRQ stack memory (calculated at run-time) */
91 .globl IRQ_STACK_START
92 IRQ_STACK_START:
93 .word 0x0badc0de
94
95 /* IRQ stack memory (calculated at run-time) */
96 .globl FIQ_STACK_START
97 FIQ_STACK_START:
98 .word 0x0badc0de
99 #endif
100
101 /* IRQ stack memory (calculated at run-time) + 8 bytes */
102 .globl IRQ_STACK_START_IN
103 IRQ_STACK_START_IN:
104 .word 0x0badc0de
105
106 .globl _datarel_start
107 _datarel_start:
108 .word __datarel_start
109
110 .globl _datarelrolocal_start
111 _datarelrolocal_start:
112 .word __datarelrolocal_start
113
114 .globl _datarellocal_start
115 _datarellocal_start:
116 .word __datarellocal_start
117
118 .globl _datarelro_start
119 _datarelro_start:
120 .word __datarelro_start
121
122 .globl _got_start
123 _got_start:
124 .word __got_start
125
126 .globl _got_end
127 _got_end:
128 .word __got_end
129
130 /*
131 * the actual start code
132 */
133
134 start_code:
135 /*
136 * set the cpu to SVC32 mode
137 */
138 mrs r0, cpsr
139 bic r0, r0, #0x1f
140 orr r0, r0, #0xd3
141 msr cpsr, r0
142
143 bl coloured_LED_init
144 bl red_LED_on
145
146 #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
147 /*
148 * relocate exception table
149 */
150 ldr r0, =_start
151 ldr r1, =0x0
152 mov r2, #16
153 copyex:
154 subs r2, r2, #1
155 ldr r3, [r0], #4
156 str r3, [r1], #4
157 bne copyex
158 #endif
159
160 #ifdef CONFIG_S3C24X0
161 /* turn off the watchdog */
162
163 # if defined(CONFIG_S3C2400)
164 # define pWTCON 0x15300000
165 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
166 # define CLKDIVN 0x14800014 /* clock divisor register */
167 #else
168 # define pWTCON 0x53000000
169 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
170 # define INTSUBMSK 0x4A00001C
171 # define CLKDIVN 0x4C000014 /* clock divisor register */
172 # endif
173
174 ldr r0, =pWTCON
175 mov r1, #0x0
176 str r1, [r0]
177
178 /*
179 * mask all IRQs by setting all bits in the INTMR - default
180 */
181 mov r1, #0xffffffff
182 ldr r0, =INTMSK
183 str r1, [r0]
184 # if defined(CONFIG_S3C2410)
185 ldr r1, =0x3ff
186 ldr r0, =INTSUBMSK
187 str r1, [r0]
188 # endif
189
190 /* FCLK:HCLK:PCLK = 1:2:4 */
191 /* default FCLK is 120 MHz ! */
192 ldr r0, =CLKDIVN
193 mov r1, #3
194 str r1, [r0]
195 #endif /* CONFIG_S3C24X0 */
196
197 /*
198 * we do sys-critical inits only at reboot,
199 * not when booting from ram!
200 */
201 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
202 bl cpu_init_crit
203 #endif
204
205 /* Set stackpointer in internal RAM to call board_init_f */
206 call_board_init_f:
207 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
208 ldr r0,=0x00000000
209 bl board_init_f
210
211 /*------------------------------------------------------------------------------*/
212
213 /*
214 * void relocate_code (addr_sp, gd, addr_moni)
215 *
216 * This "function" does not return, instead it continues in RAM
217 * after relocating the monitor code.
218 *
219 */
220 .globl relocate_code
221 relocate_code:
222 mov r4, r0 /* save addr_sp */
223 mov r5, r1 /* save addr of gd */
224 mov r6, r2 /* save addr of destination */
225 mov r7, r2 /* save addr of destination */
226
227 /* Set up the stack */
228 stack_setup:
229 mov sp, r4
230
231 adr r0, _start
232 ldr r2, _TEXT_BASE
233 ldr r3, _bss_start
234 sub r2, r3, r2 /* r2 <- size of armboot */
235 add r2, r0, r2 /* r2 <- source end address */
236 cmp r0, r6
237 beq clear_bss
238
239 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
240 copy_loop:
241 ldmia r0!, {r9-r10} /* copy from source address [r0] */
242 stmia r6!, {r9-r10} /* copy to target address [r1] */
243 cmp r0, r2 /* until source end address [r2] */
244 blo copy_loop
245
246 #ifndef CONFIG_PRELOADER
247 /* fix got entries */
248 ldr r1, _TEXT_BASE /* Text base */
249 mov r0, r7 /* reloc addr */
250 ldr r2, _got_start /* addr in Flash */
251 ldr r3, _got_end /* addr in Flash */
252 sub r3, r3, r1
253 add r3, r3, r0
254 sub r2, r2, r1
255 add r2, r2, r0
256
257 fixloop:
258 ldr r4, [r2]
259 sub r4, r4, r1
260 add r4, r4, r0
261 str r4, [r2]
262 add r2, r2, #4
263 cmp r2, r3
264 blo fixloop
265 #endif
266 #endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
267
268 clear_bss:
269 #ifndef CONFIG_PRELOADER
270 ldr r0, _bss_start
271 ldr r1, _bss_end
272 ldr r3, _TEXT_BASE /* Text base */
273 mov r4, r7 /* reloc addr */
274 sub r0, r0, r3
275 add r0, r0, r4
276 sub r1, r1, r3
277 add r1, r1, r4
278 mov r2, #0x00000000 /* clear */
279
280 clbss_l:str r2, [r0] /* clear loop... */
281 add r0, r0, #4
282 cmp r0, r1
283 bne clbss_l
284
285 bl coloured_LED_init
286 bl red_LED_on
287 #endif
288
289 /*
290 * We are done. Do not return, instead branch to second part of board
291 * initialization, now running from RAM.
292 */
293 #ifdef CONFIG_NAND_SPL
294 ldr pc, _nand_boot
295
296 _nand_boot: .word nand_boot
297 #else
298 ldr r0, _TEXT_BASE
299 ldr r2, _board_init_r
300 sub r2, r2, r0
301 add r2, r2, r7 /* position from board_init_r in RAM */
302 /* setup parameters for board_init_r */
303 mov r0, r5 /* gd_t */
304 mov r1, r7 /* dest_addr */
305 /* jump to it ... */
306 mov lr, r2
307 mov pc, lr
308
309 _board_init_r: .word board_init_r
310 #endif
311
312 /*
313 *************************************************************************
314 *
315 * CPU_init_critical registers
316 *
317 * setup important registers
318 * setup memory timing
319 *
320 *************************************************************************
321 */
322
323
324 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
325 cpu_init_crit:
326 /*
327 * flush v4 I/D caches
328 */
329 mov r0, #0
330 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
331 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
332
333 /*
334 * disable MMU stuff and caches
335 */
336 mrc p15, 0, r0, c1, c0, 0
337 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
338 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
339 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
340 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
341 mcr p15, 0, r0, c1, c0, 0
342
343 /*
344 * before relocating, we have to setup RAM timing
345 * because memory timing is board-dependend, you will
346 * find a lowlevel_init.S in your board directory.
347 */
348 mov ip, lr
349
350 bl lowlevel_init
351
352 mov lr, ip
353 mov pc, lr
354 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
355
356 /*
357 *************************************************************************
358 *
359 * Interrupt handling
360 *
361 *************************************************************************
362 */
363
364 @
365 @ IRQ stack frame.
366 @
367 #define S_FRAME_SIZE 72
368
369 #define S_OLD_R0 68
370 #define S_PSR 64
371 #define S_PC 60
372 #define S_LR 56
373 #define S_SP 52
374
375 #define S_IP 48
376 #define S_FP 44
377 #define S_R10 40
378 #define S_R9 36
379 #define S_R8 32
380 #define S_R7 28
381 #define S_R6 24
382 #define S_R5 20
383 #define S_R4 16
384 #define S_R3 12
385 #define S_R2 8
386 #define S_R1 4
387 #define S_R0 0
388
389 #define MODE_SVC 0x13
390 #define I_BIT 0x80
391
392 /*
393 * use bad_save_user_regs for abort/prefetch/undef/swi ...
394 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
395 */
396
397 .macro bad_save_user_regs
398 sub sp, sp, #S_FRAME_SIZE
399 stmia sp, {r0 - r12} @ Calling r0-r12
400 ldr r2, IRQ_STACK_START_IN
401 ldmia r2, {r2 - r3} @ get pc, cpsr
402 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
403
404 add r5, sp, #S_SP
405 mov r1, lr
406 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
407 mov r0, sp
408 .endm
409
410 .macro irq_save_user_regs
411 sub sp, sp, #S_FRAME_SIZE
412 stmia sp, {r0 - r12} @ Calling r0-r12
413 add r7, sp, #S_PC
414 stmdb r7, {sp, lr}^ @ Calling SP, LR
415 str lr, [r7, #0] @ Save calling PC
416 mrs r6, spsr
417 str r6, [r7, #4] @ Save CPSR
418 str r0, [r7, #8] @ Save OLD_R0
419 mov r0, sp
420 .endm
421
422 .macro irq_restore_user_regs
423 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
424 mov r0, r0
425 ldr lr, [sp, #S_PC] @ Get PC
426 add sp, sp, #S_FRAME_SIZE
427 /* return & move spsr_svc into cpsr */
428 subs pc, lr, #4
429 .endm
430
431 .macro get_bad_stack
432 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
433
434 str lr, [r13] @ save caller lr / spsr
435 mrs lr, spsr
436 str lr, [r13, #4]
437
438 mov r13, #MODE_SVC @ prepare SVC-Mode
439 @ msr spsr_c, r13
440 msr spsr, r13
441 mov lr, pc
442 movs pc, lr
443 .endm
444
445 .macro get_irq_stack @ setup IRQ stack
446 ldr sp, IRQ_STACK_START
447 .endm
448
449 .macro get_fiq_stack @ setup FIQ stack
450 ldr sp, FIQ_STACK_START
451 .endm
452
453 /*
454 * exception handlers
455 */
456 .align 5
457 undefined_instruction:
458 get_bad_stack
459 bad_save_user_regs
460 bl do_undefined_instruction
461
462 .align 5
463 software_interrupt:
464 get_bad_stack
465 bad_save_user_regs
466 bl do_software_interrupt
467
468 .align 5
469 prefetch_abort:
470 get_bad_stack
471 bad_save_user_regs
472 bl do_prefetch_abort
473
474 .align 5
475 data_abort:
476 get_bad_stack
477 bad_save_user_regs
478 bl do_data_abort
479
480 .align 5
481 not_used:
482 get_bad_stack
483 bad_save_user_regs
484 bl do_not_used
485
486 #ifdef CONFIG_USE_IRQ
487
488 .align 5
489 irq:
490 get_irq_stack
491 irq_save_user_regs
492 bl do_irq
493 irq_restore_user_regs
494
495 .align 5
496 fiq:
497 get_fiq_stack
498 /* someone ought to write a more effiction fiq_save_user_regs */
499 irq_save_user_regs
500 bl do_fiq
501 irq_restore_user_regs
502
503 #else
504
505 .align 5
506 irq:
507 get_bad_stack
508 bad_save_user_regs
509 bl do_irq
510
511 .align 5
512 fiq:
513 get_bad_stack
514 bad_save_user_regs
515 bl do_fiq
516
517 #endif