]> 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-imx
[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   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
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 #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
108 _datarel_start:
109         .word __datarel_start
110
111 .globl _datarelrolocal_start
112 _datarelrolocal_start:
113         .word __datarelrolocal_start
114
115 .globl _datarellocal_start
116 _datarellocal_start:
117         .word __datarellocal_start
118
119 .globl _datarelro_start
120 _datarelro_start:
121         .word __datarelro_start
122
123 .globl _got_start
124 _got_start:
125         .word __got_start
126
127 .globl _got_end
128 _got_end:
129         .word __got_end
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
202         sub     r2, r3, r2              /* r2 <- size of armboot            */
203         add     r2, r0, r2              /* r2 <- source end address         */
204         cmp     r0, r6
205 #ifndef CONFIG_PRELOADER
206         beq     jump_2_ram
207 #endif
208
209 copy_loop:
210         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
211         stmia   r6!, {r9-r10}           /* copy to   target address [r1]    */
212         cmp     r0, r2                  /* until source end address [r2]    */
213         blo     copy_loop
214
215 #ifndef CONFIG_PRELOADER
216         /* fix got entries */
217         ldr     r1, _TEXT_BASE
218         mov     r0, r7                  /* reloc addr */
219         ldr     r2, _got_start          /* addr in Flash */
220         ldr     r3, _got_end            /* addr in Flash */
221         sub     r3, r3, r1
222         add     r3, r3, r0
223         sub     r2, r2, r1
224         add     r2, r2, r0
225
226 fixloop:
227         ldr     r4, [r2]
228         sub     r4, r4, r1
229         add     r4, r4, r0
230         str     r4, [r2]
231         add     r2, r2, #4
232         cmp     r2, r3
233         bne     fixloop
234
235 clear_bss:
236         ldr     r0, _bss_start
237         ldr     r1, _bss_end
238         ldr     r3, _TEXT_BASE          /* Text base */
239         mov     r4, r7                  /* reloc addr */
240         sub     r0, r0, r3
241         add     r0, r0, r4
242         sub     r1, r1, r3
243         add     r1, r1, r4
244         mov     r2, #0x00000000         /* clear                            */
245
246 clbss_l:str     r2, [r0]                /* clear loop...                    */
247         add     r0, r0, #4
248         cmp     r0, r1
249         bne     clbss_l
250 #endif  /* #ifndef CONFIG_PRELOADER */
251 #endif  /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
252
253 /*
254  * We are done. Do not return, instead branch to second part of board
255  * initialization, now running from RAM.
256  */
257 jump_2_ram:
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 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
271 /*
272  * the actual reset code
273  */
274
275 reset:
276         /*
277          * set the cpu to SVC32 mode
278          */
279         mrs     r0, cpsr
280         bic     r0, r0, #0x1f
281         orr     r0, r0, #0xd3
282         msr     cpsr,r0
283
284 #if (CONFIG_OMAP34XX)
285         /* Copy vectors to mask ROM indirect addr */
286         adr     r0, _start              @ r0 <- current position of code
287         add     r0, r0, #4              @ skip reset vector
288         mov     r2, #64                 @ r2 <- size to copy
289         add     r2, r0, r2              @ r2 <- source end address
290         mov     r1, #SRAM_OFFSET0       @ build vect addr
291         mov     r3, #SRAM_OFFSET1
292         add     r1, r1, r3
293         mov     r3, #SRAM_OFFSET2
294         add     r1, r1, r3
295 next:
296         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
297         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
298         cmp     r0, r2                  @ until source end address [r2]
299         bne     next                    @ loop until equal */
300 #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
301         /* No need to copy/exec the clock code - DPLL adjust already done
302          * in NAND/oneNAND Boot.
303          */
304         bl      cpy_clk_code            @ put dpll adjust code behind vectors
305 #endif /* NAND Boot */
306 #endif
307         /* the mask ROM code should have PLL and others stable */
308 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
309         bl      cpu_init_crit
310 #endif
311
312 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
313 relocate:                               @ relocate U-Boot to RAM
314         adr     r0, _start              @ r0 <- current position of code
315         ldr     r1, _TEXT_BASE          @ test if we run from flash or RAM
316         cmp     r0, r1                  @ don't reloc during debug
317         beq     stack_setup
318
319         ldr     r2, _armboot_start
320         ldr     r3, _bss_start
321         sub     r2, r3, r2              @ r2 <- size of armboot
322         add     r2, r0, r2              @ r2 <- source end address
323
324 copy_loop:                              @ copy 32 bytes at a time
325         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
326         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
327         cmp     r0, r2                  @ until source end address [r2]
328         blo     copy_loop
329 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
330
331         /* Set up the stack */
332 stack_setup:
333         ldr     r0, _TEXT_BASE          @ upper 128 KiB: relocated uboot
334         sub     r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
335         sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
336 #ifdef CONFIG_USE_IRQ
337         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
338 #endif
339         sub     sp, r0, #12             @ leave 3 words for abort-stack
340         bic     sp, sp, #7              @ 8-byte alignment for ABI compliance
341
342         /* Clear BSS (if any). Is below tx (watch load addr - need space) */
343 clear_bss:
344         ldr     r0, _bss_start          @ find start of bss segment
345         ldr     r1, _bss_end            @ stop here
346         mov     r2, #0x00000000         @ clear value
347 clbss_l:
348         str     r2, [r0]                @ clear BSS location
349         cmp     r0, r1                  @ are we at the end yet
350         add     r0, r0, #4              @ increment clear index pointer
351         bne     clbss_l                 @ keep clearing till at end
352
353         ldr     pc, _start_armboot      @ jump to C code
354
355 _start_armboot: .word start_armboot
356 #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
357
358 /*************************************************************************
359  *
360  * CPU_init_critical registers
361  *
362  * setup important registers
363  * setup memory timing
364  *
365  *************************************************************************/
366 cpu_init_crit:
367         /*
368          * Invalidate L1 I/D
369          */
370         mov     r0, #0                  @ set up for MCR
371         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
372         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
373
374         /*
375          * disable MMU stuff and caches
376          */
377         mrc     p15, 0, r0, c1, c0, 0
378         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
379         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
380         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
381         orr     r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
382         mcr     p15, 0, r0, c1, c0, 0
383
384         /*
385          * Jump to board specific initialization...
386          * The Mask ROM will have already initialized
387          * basic memory. Go here to bump up clock rate and handle
388          * wake up conditions.
389          */
390         mov     ip, lr                  @ persevere link reg across call
391         bl      lowlevel_init           @ go setup pll,mux,memory
392         mov     lr, ip                  @ restore link
393         mov     pc, lr                  @ back to my caller
394 /*
395  *************************************************************************
396  *
397  * Interrupt handling
398  *
399  *************************************************************************
400  */
401 @
402 @ IRQ stack frame.
403 @
404 #define S_FRAME_SIZE    72
405
406 #define S_OLD_R0        68
407 #define S_PSR           64
408 #define S_PC            60
409 #define S_LR            56
410 #define S_SP            52
411
412 #define S_IP            48
413 #define S_FP            44
414 #define S_R10           40
415 #define S_R9            36
416 #define S_R8            32
417 #define S_R7            28
418 #define S_R6            24
419 #define S_R5            20
420 #define S_R4            16
421 #define S_R3            12
422 #define S_R2            8
423 #define S_R1            4
424 #define S_R0            0
425
426 #define MODE_SVC 0x13
427 #define I_BIT    0x80
428
429 /*
430  * use bad_save_user_regs for abort/prefetch/undef/swi ...
431  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
432  */
433
434         .macro  bad_save_user_regs
435         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current
436                                                 @ user stack
437         stmia   sp, {r0 - r12}                  @ Save user registers (now in
438                                                 @ svc mode) r0-r12
439 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
440         ldr     r2, _armboot_start
441         sub     r2, r2, #(CONFIG_SYS_MALLOC_LEN)
442         sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort
443 #else
444         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort
445                                                 @ stack
446 #endif
447         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc
448                                                 @ and cpsr (into parm regs)
449         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
450
451         add     r5, sp, #S_SP
452         mov     r1, lr
453         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
454         mov     r0, sp                          @ save current stack into r0
455                                                 @ (param register)
456         .endm
457
458         .macro  irq_save_user_regs
459         sub     sp, sp, #S_FRAME_SIZE
460         stmia   sp, {r0 - r12}                  @ Calling r0-r12
461         add     r8, sp, #S_PC                   @ !! R8 NEEDS to be saved !!
462                                                 @ a reserved stack spot would
463                                                 @ be good.
464         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
465         str     lr, [r8, #0]                    @ Save calling PC
466         mrs     r6, spsr
467         str     r6, [r8, #4]                    @ Save CPSR
468         str     r0, [r8, #8]                    @ Save OLD_R0
469         mov     r0, sp
470         .endm
471
472         .macro  irq_restore_user_regs
473         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
474         mov     r0, r0
475         ldr     lr, [sp, #S_PC]                 @ Get PC
476         add     sp, sp, #S_FRAME_SIZE
477         subs    pc, lr, #4                      @ return & move spsr_svc into
478                                                 @ cpsr
479         .endm
480
481         .macro get_bad_stack
482 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
483         ldr     r13, _armboot_start             @ setup our mode stack (enter
484         sub     r13, r13, #(CONFIG_SYS_MALLOC_LEN)      @ move past malloc pool
485         sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
486 #else
487         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter
488                                                 @ in banked mode)
489 #endif
490
491         str     lr, [r13]                       @ save caller lr in position 0
492                                                 @ of saved stack
493         mrs     lr, spsr                        @ get the spsr
494         str     lr, [r13, #4]                   @ save spsr in position 1 of
495                                                 @ saved stack
496
497         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
498         @ msr   spsr_c, r13
499         msr     spsr, r13                       @ switch modes, make sure
500                                                 @ moves will execute
501         mov     lr, pc                          @ capture return pc
502         movs    pc, lr                          @ jump to next instruction &
503                                                 @ switch modes.
504         .endm
505
506         .macro get_bad_stack_swi
507         sub     r13, r13, #4                    @ space on current stack for
508                                                 @ scratch reg.
509         str     r0, [r13]                       @ save R0's value.
510 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
511         ldr     r0, _armboot_start              @ get data regions start
512         sub     r0, r0, #(CONFIG_SYS_MALLOC_LEN)        @ move past malloc pool
513         sub     r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple
514 #else
515         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
516                                                 @ spots for abort stack
517 #endif
518         str     lr, [r0]                        @ save caller lr in position 0
519                                                 @ of saved stack
520         mrs     r0, spsr                        @ get the spsr
521         str     lr, [r0, #4]                    @ save spsr in position 1 of
522                                                 @ saved stack
523         ldr     r0, [r13]                       @ restore r0
524         add     r13, r13, #4                    @ pop stack entry
525         .endm
526
527         .macro get_irq_stack                    @ setup IRQ stack
528         ldr     sp, IRQ_STACK_START
529         .endm
530
531         .macro get_fiq_stack                    @ setup FIQ stack
532         ldr     sp, FIQ_STACK_START
533         .endm
534
535 /*
536  * exception handlers
537  */
538         .align  5
539 undefined_instruction:
540         get_bad_stack
541         bad_save_user_regs
542         bl      do_undefined_instruction
543
544         .align  5
545 software_interrupt:
546         get_bad_stack_swi
547         bad_save_user_regs
548         bl      do_software_interrupt
549
550         .align  5
551 prefetch_abort:
552         get_bad_stack
553         bad_save_user_regs
554         bl      do_prefetch_abort
555
556         .align  5
557 data_abort:
558         get_bad_stack
559         bad_save_user_regs
560         bl      do_data_abort
561
562         .align  5
563 not_used:
564         get_bad_stack
565         bad_save_user_regs
566         bl      do_not_used
567
568 #ifdef CONFIG_USE_IRQ
569
570         .align  5
571 irq:
572         get_irq_stack
573         irq_save_user_regs
574         bl      do_irq
575         irq_restore_user_regs
576
577         .align  5
578 fiq:
579         get_fiq_stack
580         /* someone ought to write a more effective fiq_save_user_regs */
581         irq_save_user_regs
582         bl      do_fiq
583         irq_restore_user_regs
584
585 #else
586
587         .align  5
588 irq:
589         get_bad_stack
590         bad_save_user_regs
591         bl      do_irq
592
593         .align  5
594 fiq:
595         get_bad_stack
596         bad_save_user_regs
597         bl      do_fiq
598
599 #endif