]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm_intcm/start.S
07356cb5fd018983d5fd98a0382c1caf6b9f5467
[karo-tx-uboot.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   CONFIG_SYS_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 address [r2]    */
209         blo     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 address [r2]    */
309         blo     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         blo     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