]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/cpu/arm_intcm/start.S
Merge branch 'next' of /home/wd/git/u-boot/next
[people/ms/u-boot.git] / arch / arm / cpu / arm_intcm / start.S
1 /*
2 * armboot - Startup Code for ARM926EJS CPU-core
3 *
4 * Copyright (c) 2003 Texas Instruments
5 *
6 * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
7 *
8 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
9 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
11 * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
12 * Copyright (c) 2003 Kshitij <kshitij@ti.com>
13 *
14 * See file CREDITS for list of people who contributed to this
15 * project.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 * MA 02111-1307 USA
31 */
32
33
34 #include <config.h>
35 #include <version.h>
36
37 /*
38 *************************************************************************
39 *
40 * Jump vector table
41 *
42 *************************************************************************
43 */
44
45 .globl _start
46 _start:
47 b reset
48 ldr pc, _undefined_instruction
49 ldr pc, _software_interrupt
50 ldr pc, _prefetch_abort
51 ldr pc, _data_abort
52 ldr pc, _not_used
53 ldr pc, _irq
54 ldr pc, _fiq
55
56 _undefined_instruction:
57 .word undefined_instruction
58 _software_interrupt:
59 .word software_interrupt
60 _prefetch_abort:
61 .word prefetch_abort
62 _data_abort:
63 .word data_abort
64 _not_used:
65 .word not_used
66 _irq:
67 .word irq
68 _fiq:
69 .word fiq
70
71 .balignl 16,0xdeadbeef
72
73 /*
74 *************************************************************************
75 *
76 * Startup Code (reset vector)
77 *
78 * do important init only if we don't start from memory!
79 * setup memory and board specific bits prior to relocation.
80 * relocate armboot to ram
81 * setup stack
82 *
83 *************************************************************************
84 */
85
86 .globl _TEXT_BASE
87 _TEXT_BASE:
88 .word TEXT_BASE /* address of _start in the linked image */
89
90 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
91 .globl _armboot_start
92 _armboot_start:
93 .word _start
94 #endif
95
96 /*
97 * These are defined in the board-specific linker script.
98 */
99 .globl _bss_start
100 _bss_start:
101 .word __bss_start
102
103 .globl _bss_end
104 _bss_end:
105 .word _end
106
107 #ifdef CONFIG_USE_IRQ
108 /* IRQ stack memory (calculated at run-time) */
109 .globl IRQ_STACK_START
110 IRQ_STACK_START:
111 .word 0x0badc0de
112
113 /* IRQ stack memory (calculated at run-time) */
114 .globl FIQ_STACK_START
115 FIQ_STACK_START:
116 .word 0x0badc0de
117 #endif
118
119 #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
120 /* IRQ stack memory (calculated at run-time) + 8 bytes */
121 .globl IRQ_STACK_START_IN
122 IRQ_STACK_START_IN:
123 .word 0x0badc0de
124
125 .globl _datarel_start
126 _datarel_start:
127 .word __datarel_start
128
129 .globl _datarelrolocal_start
130 _datarelrolocal_start:
131 .word __datarelrolocal_start
132
133 .globl _datarellocal_start
134 _datarellocal_start:
135 .word __datarellocal_start
136
137 .globl _datarelro_start
138 _datarelro_start:
139 .word __datarelro_start
140
141 .globl _got_start
142 _got_start:
143 .word __got_start
144
145 .globl _got_end
146 _got_end:
147 .word __got_end
148
149 /*
150 * the actual reset code
151 */
152
153 reset:
154 /*
155 * set the cpu to SVC32 mode
156 */
157 mrs r0,cpsr
158 bic r0,r0,#0x1f
159 orr r0,r0,#0xd3
160 msr cpsr,r0
161
162 /*
163 * we do sys-critical inits only at reboot,
164 * not when booting from ram!
165 */
166 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
167 bl cpu_init_crit
168 #endif
169
170 /* Set stackpointer in internal RAM to call board_init_f */
171 call_board_init_f:
172 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
173 ldr r0,=0x00000000
174 bl board_init_f
175
176 /*------------------------------------------------------------------------------*/
177
178 /*
179 * void relocate_code (addr_sp, gd, addr_moni)
180 *
181 * This "function" does not return, instead it continues in RAM
182 * after relocating the monitor code.
183 *
184 */
185 .globl relocate_code
186 relocate_code:
187 mov r4, r0 /* save addr_sp */
188 mov r5, r1 /* save addr of gd */
189 mov r6, r2 /* save addr of destination */
190 mov r7, r2 /* save addr of destination */
191
192 /* Set up the stack */
193 stack_setup:
194 mov sp, r4
195
196 adr r0, _start
197 ldr r2, _TEXT_BASE
198 ldr r3, _bss_start
199 sub r2, r3, r2 /* r2 <- size of armboot */
200 add r2, r0, r2 /* r2 <- source end address */
201 cmp r0, r6
202 beq clear_bss
203
204 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
205 copy_loop:
206 ldmia r0!, {r9-r10} /* copy from source address [r0] */
207 stmia r6!, {r9-r10} /* copy to target address [r1] */
208 cmp r0, r2 /* until source end addreee [r2] */
209 ble copy_loop
210
211 #ifndef CONFIG_PRELOADER
212 /* fix got entries */
213 ldr r1, _TEXT_BASE /* Text base */
214 mov r0, r7 /* reloc addr */
215 ldr r2, _got_start /* addr in Flash */
216 ldr r3, _got_end /* addr in Flash */
217 sub r3, r3, r1
218 add r3, r3, r0
219 sub r2, r2, r1
220 add r2, r2, r0
221
222 fixloop:
223 ldr r4, [r2]
224 sub r4, r4, r1
225 add r4, r4, r0
226 str r4, [r2]
227 add r2, r2, #4
228 cmp r2, r3
229 bne fixloop
230 #endif
231 #endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
232
233 clear_bss:
234 #ifndef CONFIG_PRELOADER
235 ldr r0, _bss_start
236 ldr r1, _bss_end
237 ldr r3, _TEXT_BASE /* Text base */
238 mov r4, r7 /* reloc addr */
239 sub r0, r0, r3
240 add r0, r0, r4
241 sub r1, r1, r3
242 add r1, r1, r4
243 mov r2, #0x00000000 /* clear */
244
245 clbss_l:str r2, [r0] /* clear loop... */
246 add r0, r0, #4
247 cmp r0, r1
248 bne clbss_l
249
250 bl coloured_LED_init
251 bl red_LED_on
252 #endif
253
254 /*
255 * We are done. Do not return, instead branch to second part of board
256 * initialization, now running from RAM.
257 */
258 ldr r0, _TEXT_BASE
259 ldr r2, _board_init_r
260 sub r2, r2, r0
261 add r2, r2, r7 /* position from board_init_r in RAM */
262 /* setup parameters for board_init_r */
263 mov r0, r5 /* gd_t */
264 mov r1, r7 /* dest_addr */
265 /* jump to it ... */
266 mov lr, r2
267 mov pc, lr
268
269 _board_init_r: .word board_init_r
270
271 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
272
273 /*
274 * the actual reset code
275 */
276 .globl reset
277 reset:
278 /*
279 * set the cpu to SVC32 mode
280 */
281 mrs r0,cpsr
282 bic r0,r0,#0x1f
283 orr r0,r0,#0xd3
284 msr cpsr,r0
285
286 /*
287 * we do sys-critical inits only at reboot,
288 * not when booting from ram!
289 */
290 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
291 bl cpu_init_crit
292 #endif
293
294 relocate: /* relocate U-Boot to RAM */
295 adr r0, _start /* pc relative address of label */
296 ldr r1, _TEXT_BASE /* linked image address of label */
297 cmp r0, r1 /* test if we run from flash or RAM */
298 beq stack_setup /* ifeq we are in the RAM copy */
299
300 ldr r2, _armboot_start
301 ldr r3, _bss_start
302 sub r2, r3, r2 /* r2 <- size of armboot */
303 add r2, r0, r2 /* r2 <- source end address */
304
305 copy_loop:
306 ldmia r0!, {r3-r10} /* copy from source address [r0] */
307 stmia r1!, {r3-r10} /* copy to target address [r1] */
308 cmp r0, r2 /* until source end addreee [r2] */
309 ble copy_loop
310
311 /* Set up the stack */
312 stack_setup:
313 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
314 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
315 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
316 #ifdef CONFIG_USE_IRQ
317 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
318 #endif
319 sub sp, r0, #12 /* leave 3 words for abort-stack */
320 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
321
322 clear_bss:
323 ldr r0, _bss_start /* find start of bss segment */
324 ldr r1, _bss_end /* stop here */
325 mov r2, #0x00000000 /* clear */
326
327 clbss_l:str r2, [r0] /* clear loop... */
328 add r0, r0, #4
329 cmp r0, r1
330 ble clbss_l
331
332 ldr pc, _start_armboot
333
334 _start_armboot:
335 .word start_armboot
336
337 #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
338
339 /*
340 *************************************************************************
341 *
342 * CPU_init_critical registers
343 *
344 * setup important registers
345 * setup memory timing
346 *
347 *************************************************************************
348 */
349
350 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
351 cpu_init_crit:
352 /* arm_int_generic assumes the ARM boot monitor, or user software,
353 * has initialized the platform
354 */
355 mov pc, lr /* back to my caller */
356 #endif
357 /*
358 *************************************************************************
359 *
360 * Interrupt handling
361 *
362 *************************************************************************
363 */
364
365 @
366 @ IRQ stack frame.
367 @
368 #define S_FRAME_SIZE 72
369
370 #define S_OLD_R0 68
371 #define S_PSR 64
372 #define S_PC 60
373 #define S_LR 56
374 #define S_SP 52
375
376 #define S_IP 48
377 #define S_FP 44
378 #define S_R10 40
379 #define S_R9 36
380 #define S_R8 32
381 #define S_R7 28
382 #define S_R6 24
383 #define S_R5 20
384 #define S_R4 16
385 #define S_R3 12
386 #define S_R2 8
387 #define S_R1 4
388 #define S_R0 0
389
390 #define MODE_SVC 0x13
391 #define I_BIT 0x80
392
393 /*
394 * use bad_save_user_regs for abort/prefetch/undef/swi ...
395 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
396 */
397
398 .macro bad_save_user_regs
399 @ carve out a frame on current user stack
400 sub sp, sp, #S_FRAME_SIZE
401 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
402
403 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
404 ldr r2, _armboot_start
405 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
406 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
407 #else
408 ldr r2, IRQ_STACK_START_IN
409 #endif
410 @ get values for "aborted" pc and cpsr (into parm regs)
411 ldmia r2, {r2 - r3}
412 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
413 add r5, sp, #S_SP
414 mov r1, lr
415 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
416 mov r0, sp @ save current stack into r0 (param register)
417 .endm
418
419 .macro irq_save_user_regs
420 sub sp, sp, #S_FRAME_SIZE
421 stmia sp, {r0 - r12} @ Calling r0-r12
422 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
423 add r8, sp, #S_PC
424 stmdb r8, {sp, lr}^ @ Calling SP, LR
425 str lr, [r8, #0] @ Save calling PC
426 mrs r6, spsr
427 str r6, [r8, #4] @ Save CPSR
428 str r0, [r8, #8] @ Save OLD_R0
429 mov r0, sp
430 .endm
431
432 .macro irq_restore_user_regs
433 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
434 mov r0, r0
435 ldr lr, [sp, #S_PC] @ Get PC
436 add sp, sp, #S_FRAME_SIZE
437 subs pc, lr, #4 @ return & move spsr_svc into cpsr
438 .endm
439
440 .macro get_bad_stack
441 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
442 ldr r13, _armboot_start @ setup our mode stack
443 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
444 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
445 #else
446 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
447 #endif
448
449 str lr, [r13] @ save caller lr in position 0 of saved stack
450 mrs lr, spsr @ get the spsr
451 str lr, [r13, #4] @ save spsr in position 1 of saved stack
452 mov r13, #MODE_SVC @ prepare SVC-Mode
453 @ msr spsr_c, r13
454 msr spsr, r13 @ switch modes, make sure moves will execute
455 mov lr, pc @ capture return pc
456 movs pc, lr @ jump to next instruction & switch modes.
457 .endm
458
459 .macro get_irq_stack @ setup IRQ stack
460 ldr sp, IRQ_STACK_START
461 .endm
462
463 .macro get_fiq_stack @ setup FIQ stack
464 ldr sp, FIQ_STACK_START
465 .endm
466
467 /*
468 * exception handlers
469 */
470 .align 5
471 .globl undefined_instruction
472 undefined_instruction:
473 get_bad_stack
474 bad_save_user_regs
475 bl do_undefined_instruction
476
477 .align 5
478 .globl software_interrupt
479 software_interrupt:
480 get_bad_stack
481 bad_save_user_regs
482 bl do_software_interrupt
483
484 .align 5
485 .globl prefetch_abort
486 prefetch_abort:
487 get_bad_stack
488 bad_save_user_regs
489 bl do_prefetch_abort
490
491 .align 5
492 .globl data_abort
493 data_abort:
494 get_bad_stack
495 bad_save_user_regs
496 bl do_data_abort
497
498 .align 5
499 .globl not_used
500 not_used:
501 get_bad_stack
502 bad_save_user_regs
503 bl do_not_used
504
505 #ifdef CONFIG_USE_IRQ
506 .align 5
507 .globl irq
508 irq:
509 get_irq_stack
510 irq_save_user_regs
511 bl do_irq
512 irq_restore_user_regs
513
514 .align 5
515 .globl fiq
516 fiq:
517 get_fiq_stack
518 /* someone ought to write a more effiction fiq_save_user_regs */
519 irq_save_user_regs
520 bl do_fiq
521 irq_restore_user_regs
522
523 #else
524
525 .align 5
526 .globl irq
527 irq:
528 get_bad_stack
529 bad_save_user_regs
530 bl do_irq
531
532 .align 5
533 .globl fiq
534 fiq:
535 get_bad_stack
536 bad_save_user_regs
537 bl do_fiq
538
539 #endif