]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/start.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / start.S
1 /*
2  * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
3  *
4  * Copyright (c) 2004   Texas Instruments <r-woodruff2@ti.com>
5  *
6  * Copyright (c) 2001   Marius Gröger <mag@sysgo.de>
7  * Copyright (c) 2002   Alex Züpke <azu@sysgo.de>
8  * Copyright (c) 2002   Gary Jennejohn <garyj@denx.de>
9  * Copyright (c) 2003   Richard Woodruff <r-woodruff2@ti.com>
10  * Copyright (c) 2003   Kshitij <kshitij@ti.com>
11  * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
12  *
13  * See file CREDITS for list of people who contributed to this
14  * project.
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation; either version 2 of
19  * the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  * MA 02111-1307 USA
30  */
31
32 #include <config.h>
33 #include <version.h>
34
35 .globl _start
36 _start: b       reset
37         ldr     pc, _undefined_instruction
38         ldr     pc, _software_interrupt
39         ldr     pc, _prefetch_abort
40         ldr     pc, _data_abort
41         ldr     pc, _not_used
42         ldr     pc, _irq
43         ldr     pc, _fiq
44
45 _undefined_instruction: .word undefined_instruction
46 _software_interrupt:    .word software_interrupt
47 _prefetch_abort:        .word prefetch_abort
48 _data_abort:            .word data_abort
49 _not_used:              .word not_used
50 _irq:                   .word irq
51 _fiq:                   .word fiq
52 _pad:                   .word 0x12345678 /* now 16*4=64 */
53 .global _end_vect
54 _end_vect:
55
56         .balignl 16,0xdeadbeef
57 /*************************************************************************
58  *
59  * Startup Code (reset vector)
60  *
61  * do important init only if we don't start from memory!
62  * setup Memory and board specific bits prior to relocation.
63  * relocate armboot to ram
64  * setup stack
65  *
66  *************************************************************************/
67
68 .globl _TEXT_BASE
69 _TEXT_BASE:
70         .word   CONFIG_SYS_TEXT_BASE
71
72 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
73 .globl _armboot_start
74 _armboot_start:
75         .word _start
76 #endif
77
78 /*
79  * These are defined in the board-specific linker script.
80  */
81 .globl _bss_start_ofs
82 _bss_start_ofs:
83         .word __bss_start - _start
84
85 .globl _bss_end_ofs
86 _bss_end_ofs:
87         .word _end - _start
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 #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
102 /* IRQ stack memory (calculated at run-time) + 8 bytes */
103 .globl IRQ_STACK_START_IN
104 IRQ_STACK_START_IN:
105         .word   0x0badc0de
106
107 .globl _datarel_start_ofs
108 _datarel_start_ofs:
109         .word __datarel_start - _start
110
111 .globl _datarelrolocal_start_ofs
112 _datarelrolocal_start_ofs:
113         .word __datarelrolocal_start - _start
114
115 .globl _datarellocal_start_ofs
116 _datarellocal_start_ofs:
117         .word __datarellocal_start - _start
118
119 .globl _datarelro_start_ofs
120 _datarelro_start_ofs:
121         .word __datarelro_start - _start
122
123 .globl _got_start_ofs
124 _got_start_ofs:
125         .word __got_start - _start
126
127 .globl _got_end_Ofs
128 _got_end_ofs:
129         .word __got_end - _start
130
131 /*
132  * the actual reset code
133  */
134
135 reset:
136         /*
137          * set the cpu to SVC32 mode
138          */
139         mrs     r0, cpsr
140         bic     r0, r0, #0x1f
141         orr     r0, r0, #0xd3
142         msr     cpsr,r0
143
144 #if (CONFIG_OMAP34XX)
145         /* Copy vectors to mask ROM indirect addr */
146         adr     r0, _start              @ r0 <- current position of code
147         add     r0, r0, #4              @ skip reset vector
148         mov     r2, #64                 @ r2 <- size to copy
149         add     r2, r0, r2              @ r2 <- source end address
150         mov     r1, #SRAM_OFFSET0       @ build vect addr
151         mov     r3, #SRAM_OFFSET1
152         add     r1, r1, r3
153         mov     r3, #SRAM_OFFSET2
154         add     r1, r1, r3
155 next:
156         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
157         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
158         cmp     r0, r2                  @ until source end address [r2]
159         bne     next                    @ loop until equal */
160 #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
161         /* No need to copy/exec the clock code - DPLL adjust already done
162          * in NAND/oneNAND Boot.
163          */
164         bl      cpy_clk_code            @ put dpll adjust code behind vectors
165 #endif /* NAND Boot */
166 #endif
167         /* the mask ROM code should have PLL and others stable */
168 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
169         bl      cpu_init_crit
170 #endif
171
172 /* Set stackpointer in internal RAM to call board_init_f */
173 call_board_init_f:
174         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
175         ldr     r0,=0x00000000
176         bl      board_init_f
177
178 /*------------------------------------------------------------------------------*/
179
180 /*
181  * void relocate_code (addr_sp, gd, addr_moni)
182  *
183  * This "function" does not return, instead it continues in RAM
184  * after relocating the monitor code.
185  *
186  */
187         .globl  relocate_code
188 relocate_code:
189         mov     r4, r0  /* save addr_sp */
190         mov     r5, r1  /* save addr of gd */
191         mov     r6, r2  /* save addr of destination */
192         mov     r7, r2  /* save addr of destination */
193
194         /* Set up the stack                                                 */
195 stack_setup:
196         mov     sp, r4
197
198 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
199         adr     r0, _start
200         ldr     r2, _TEXT_BASE
201         ldr     r3, _bss_start_ofs
202         add     r2, r0, r3              /* r2 <- source end address         */
203         cmp     r0, r6
204 #ifndef CONFIG_PRELOADER
205         beq     jump_2_ram
206 #endif
207
208 copy_loop:
209         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
210         stmia   r6!, {r9-r10}           /* copy to   target address [r1]    */
211         cmp     r0, r2                  /* until source end address [r2]    */
212         blo     copy_loop
213
214 #ifndef CONFIG_PRELOADER
215         /*
216          * fix .rel.dyn relocations
217          */
218         ldr     r0, _TEXT_BASE          /* r0 <- Text base */
219         sub     r9, r7, r0              /* r9 <- relocation offset */
220         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
221         add     r10, r10, r0            /* r10 <- sym table in FLASH */
222         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
223         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
224         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
225         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
226 fixloop:
227         ldr     r0, [r2]        /* r0 <- location to fix up, IN FLASH! */
228         add     r0, r9          /* r0 <- location to fix up in RAM */
229         ldr     r1, [r2, #4]
230         and     r8, r1, #0xff
231         cmp     r8, #23         /* relative fixup? */
232         beq     fixrel
233         cmp     r8, #2          /* absolute fixup? */
234         beq     fixabs
235         /* ignore unknown type of fixup */
236         b       fixnext
237 fixabs:
238         /* absolute fix: set location to (offset) symbol value */
239         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
240         add     r1, r10, r1             /* r1 <- address of symbol in table */
241         ldr     r1, [r1, #4]            /* r1 <- symbol value */
242         add     r1, r9                  /* r1 <- relocated sym addr */
243         b       fixnext
244 fixrel:
245         /* relative fix: increase location by offset */
246         ldr     r1, [r0]
247         add     r1, r1, r9
248 fixnext:
249         str     r1, [r0]
250         add     r2, r2, #8      /* each rel.dyn entry is 8 bytes */
251         cmp     r2, r3
252         blo     fixloop
253
254 clear_bss:
255         ldr     r0, _bss_start_ofs
256         ldr     r1, _bss_end_ofs
257         ldr     r3, _TEXT_BASE          /* Text base */
258         mov     r4, r7                  /* reloc addr */
259         add     r0, r0, r4
260         add     r1, r1, r4
261         mov     r2, #0x00000000         /* clear                            */
262
263 clbss_l:str     r2, [r0]                /* clear loop...                    */
264         add     r0, r0, #4
265         cmp     r0, r1
266         bne     clbss_l
267 #endif  /* #ifndef CONFIG_PRELOADER */
268 #endif  /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
269
270 /*
271  * We are done. Do not return, instead branch to second part of board
272  * initialization, now running from RAM.
273  */
274 jump_2_ram:
275         ldr     r0, _board_init_r_ofs
276         adr     r1, _start
277         add     r0, r0, r1
278         add     lr, r0, r9
279         /* setup parameters for board_init_r */
280         mov     r0, r5          /* gd_t */
281         mov     r1, r7          /* dest_addr */
282         /* jump to it ... */
283         mov     pc, lr
284
285 _board_init_r_ofs:
286         .word board_init_r - _start
287
288 _rel_dyn_start_ofs:
289         .word __rel_dyn_start - _start
290 _rel_dyn_end_ofs:
291         .word __rel_dyn_end - _start
292 _dynsym_start_ofs:
293         .word __dynsym_start - _start
294
295 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
296 /*
297  * the actual reset code
298  */
299
300 reset:
301         /*
302          * set the cpu to SVC32 mode
303          */
304         mrs     r0, cpsr
305         bic     r0, r0, #0x1f
306         orr     r0, r0, #0xd3
307         msr     cpsr,r0
308
309 #if (CONFIG_OMAP34XX)
310         /* Copy vectors to mask ROM indirect addr */
311         adr     r0, _start              @ r0 <- current position of code
312         add     r0, r0, #4              @ skip reset vector
313         mov     r2, #64                 @ r2 <- size to copy
314         add     r2, r0, r2              @ r2 <- source end address
315         mov     r1, #SRAM_OFFSET0       @ build vect addr
316         mov     r3, #SRAM_OFFSET1
317         add     r1, r1, r3
318         mov     r3, #SRAM_OFFSET2
319         add     r1, r1, r3
320 next:
321         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
322         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
323         cmp     r0, r2                  @ until source end address [r2]
324         bne     next                    @ loop until equal */
325 #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
326         /* No need to copy/exec the clock code - DPLL adjust already done
327          * in NAND/oneNAND Boot.
328          */
329         bl      cpy_clk_code            @ put dpll adjust code behind vectors
330 #endif /* NAND Boot */
331 #endif
332         /* the mask ROM code should have PLL and others stable */
333 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
334         bl      cpu_init_crit
335 #endif
336
337 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
338 relocate:                               @ relocate U-Boot to RAM
339         adr     r0, _start              @ r0 <- current position of code
340         ldr     r1, _TEXT_BASE          @ test if we run from flash or RAM
341         cmp     r0, r1                  @ don't reloc during debug
342         beq     stack_setup
343
344         ldr     r2, _armboot_start
345         ldr     r3, _bss_start
346         sub     r2, r3, r2              @ r2 <- size of armboot
347         add     r2, r0, r2              @ r2 <- source end address
348
349 copy_loop:                              @ copy 32 bytes at a time
350         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
351         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
352         cmp     r0, r2                  @ until source end address [r2]
353         blo     copy_loop
354 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
355
356         /* Set up the stack */
357 stack_setup:
358         ldr     r0, _TEXT_BASE          @ upper 128 KiB: relocated uboot
359         sub     r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
360         sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
361 #ifdef CONFIG_USE_IRQ
362         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
363 #endif
364         sub     sp, r0, #12             @ leave 3 words for abort-stack
365         bic     sp, sp, #7              @ 8-byte alignment for ABI compliance
366
367         /* Clear BSS (if any). Is below tx (watch load addr - need space) */
368 clear_bss:
369         ldr     r0, _bss_start          @ find start of bss segment
370         ldr     r1, _bss_end            @ stop here
371         mov     r2, #0x00000000         @ clear value
372 clbss_l:
373         str     r2, [r0]                @ clear BSS location
374         cmp     r0, r1                  @ are we at the end yet
375         add     r0, r0, #4              @ increment clear index pointer
376         bne     clbss_l                 @ keep clearing till at end
377
378         ldr     pc, _start_armboot      @ jump to C code
379
380 _start_armboot: .word start_armboot
381 #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
382
383 /*************************************************************************
384  *
385  * CPU_init_critical registers
386  *
387  * setup important registers
388  * setup memory timing
389  *
390  *************************************************************************/
391 cpu_init_crit:
392         /*
393          * Invalidate L1 I/D
394          */
395         mov     r0, #0                  @ set up for MCR
396         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
397         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
398
399         /*
400          * disable MMU stuff and caches
401          */
402         mrc     p15, 0, r0, c1, c0, 0
403         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
404         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
405         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
406         orr     r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
407         mcr     p15, 0, r0, c1, c0, 0
408
409         /*
410          * Jump to board specific initialization...
411          * The Mask ROM will have already initialized
412          * basic memory. Go here to bump up clock rate and handle
413          * wake up conditions.
414          */
415         mov     ip, lr                  @ persevere link reg across call
416         bl      lowlevel_init           @ go setup pll,mux,memory
417         mov     lr, ip                  @ restore link
418         mov     pc, lr                  @ back to my caller
419 /*
420  *************************************************************************
421  *
422  * Interrupt handling
423  *
424  *************************************************************************
425  */
426 @
427 @ IRQ stack frame.
428 @
429 #define S_FRAME_SIZE    72
430
431 #define S_OLD_R0        68
432 #define S_PSR           64
433 #define S_PC            60
434 #define S_LR            56
435 #define S_SP            52
436
437 #define S_IP            48
438 #define S_FP            44
439 #define S_R10           40
440 #define S_R9            36
441 #define S_R8            32
442 #define S_R7            28
443 #define S_R6            24
444 #define S_R5            20
445 #define S_R4            16
446 #define S_R3            12
447 #define S_R2            8
448 #define S_R1            4
449 #define S_R0            0
450
451 #define MODE_SVC 0x13
452 #define I_BIT    0x80
453
454 /*
455  * use bad_save_user_regs for abort/prefetch/undef/swi ...
456  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
457  */
458
459         .macro  bad_save_user_regs
460         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current
461                                                 @ user stack
462         stmia   sp, {r0 - r12}                  @ Save user registers (now in
463                                                 @ svc mode) r0-r12
464 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
465         ldr     r2, _armboot_start
466         sub     r2, r2, #(CONFIG_SYS_MALLOC_LEN)
467         sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort
468 #else
469         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort
470                                                 @ stack
471 #endif
472         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc
473                                                 @ and cpsr (into parm regs)
474         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
475
476         add     r5, sp, #S_SP
477         mov     r1, lr
478         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
479         mov     r0, sp                          @ save current stack into r0
480                                                 @ (param register)
481         .endm
482
483         .macro  irq_save_user_regs
484         sub     sp, sp, #S_FRAME_SIZE
485         stmia   sp, {r0 - r12}                  @ Calling r0-r12
486         add     r8, sp, #S_PC                   @ !! R8 NEEDS to be saved !!
487                                                 @ a reserved stack spot would
488                                                 @ be good.
489         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
490         str     lr, [r8, #0]                    @ Save calling PC
491         mrs     r6, spsr
492         str     r6, [r8, #4]                    @ Save CPSR
493         str     r0, [r8, #8]                    @ Save OLD_R0
494         mov     r0, sp
495         .endm
496
497         .macro  irq_restore_user_regs
498         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
499         mov     r0, r0
500         ldr     lr, [sp, #S_PC]                 @ Get PC
501         add     sp, sp, #S_FRAME_SIZE
502         subs    pc, lr, #4                      @ return & move spsr_svc into
503                                                 @ cpsr
504         .endm
505
506         .macro get_bad_stack
507 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
508         ldr     r13, _armboot_start             @ setup our mode stack (enter
509         sub     r13, r13, #(CONFIG_SYS_MALLOC_LEN)      @ move past malloc pool
510         sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
511 #else
512         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter
513                                                 @ in banked mode)
514 #endif
515
516         str     lr, [r13]                       @ save caller lr in position 0
517                                                 @ of saved stack
518         mrs     lr, spsr                        @ get the spsr
519         str     lr, [r13, #4]                   @ save spsr in position 1 of
520                                                 @ saved stack
521
522         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
523         @ msr   spsr_c, r13
524         msr     spsr, r13                       @ switch modes, make sure
525                                                 @ moves will execute
526         mov     lr, pc                          @ capture return pc
527         movs    pc, lr                          @ jump to next instruction &
528                                                 @ switch modes.
529         .endm
530
531         .macro get_bad_stack_swi
532         sub     r13, r13, #4                    @ space on current stack for
533                                                 @ scratch reg.
534         str     r0, [r13]                       @ save R0's value.
535 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
536         ldr     r0, _armboot_start              @ get data regions start
537         sub     r0, r0, #(CONFIG_SYS_MALLOC_LEN)        @ move past malloc pool
538         sub     r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple
539 #else
540         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
541                                                 @ spots for abort stack
542 #endif
543         str     lr, [r0]                        @ save caller lr in position 0
544                                                 @ of saved stack
545         mrs     r0, spsr                        @ get the spsr
546         str     lr, [r0, #4]                    @ save spsr in position 1 of
547                                                 @ saved stack
548         ldr     r0, [r13]                       @ restore r0
549         add     r13, r13, #4                    @ pop stack entry
550         .endm
551
552         .macro get_irq_stack                    @ setup IRQ stack
553         ldr     sp, IRQ_STACK_START
554         .endm
555
556         .macro get_fiq_stack                    @ setup FIQ stack
557         ldr     sp, FIQ_STACK_START
558         .endm
559
560 /*
561  * exception handlers
562  */
563         .align  5
564 undefined_instruction:
565         get_bad_stack
566         bad_save_user_regs
567         bl      do_undefined_instruction
568
569         .align  5
570 software_interrupt:
571         get_bad_stack_swi
572         bad_save_user_regs
573         bl      do_software_interrupt
574
575         .align  5
576 prefetch_abort:
577         get_bad_stack
578         bad_save_user_regs
579         bl      do_prefetch_abort
580
581         .align  5
582 data_abort:
583         get_bad_stack
584         bad_save_user_regs
585         bl      do_data_abort
586
587         .align  5
588 not_used:
589         get_bad_stack
590         bad_save_user_regs
591         bl      do_not_used
592
593 #ifdef CONFIG_USE_IRQ
594
595         .align  5
596 irq:
597         get_irq_stack
598         irq_save_user_regs
599         bl      do_irq
600         irq_restore_user_regs
601
602         .align  5
603 fiq:
604         get_fiq_stack
605         /* someone ought to write a more effective fiq_save_user_regs */
606         irq_save_user_regs
607         bl      do_fiq
608         irq_restore_user_regs
609
610 #else
611
612         .align  5
613 irq:
614         get_bad_stack
615         bad_save_user_regs
616         bl      do_irq
617
618         .align  5
619 fiq:
620         get_bad_stack
621         bad_save_user_regs
622         bl      do_fiq
623
624 #endif