tizen 2.4 release
[kernel/u-boot-tm1.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 <asm-offsets.h>
33 #include <config.h>
34 #include <common.h>
35 #include <version.h>
36
37 #if   defined CONFIG_SC8830
38 #define SVC_STACK_TEMP 0x5000CFF0 //for shark
39 #define SPL_STACK      0x808f0000
40 #elif defined CONFIG_SC8825
41 #define SVC_STACK_TEMP 0x00027F60 //for tiger
42 #define SPL_STACK      0x808f0000
43 #else
44 #define SVC_STACK_TEMP 0x40008000
45 #define SPL_STACK      0x008f0000
46 #endif
47 .globl _start
48 _start: b       reset
49 #ifdef CONFIG_PRELOADER
50 /* No exception handlers in preloader */
51         ldr     pc, _hang
52         ldr     pc, _hang
53         ldr     pc, _hang
54         ldr     pc, _hang
55         ldr     pc, _hang
56         ldr     pc, _hang
57         ldr     pc, _hang
58
59                /*22 begin*/     
60         nop
61         nop
62         nop
63         nop
64         nop
65         nop
66         nop
67         nop
68         nop
69         nop
70         nop
71         nop
72         nop
73         nop
74         nop
75         nop
76         nop
77         nop
78         nop
79         nop
80         nop
81         nop
82 #ifdef CONFIG_NAND_SC7710G2
83     nop
84     
85         nop
86         nop
87         nop
88         nop
89         nop
90
91         nop
92         nop
93         nop
94         nop
95         nop
96
97     nop
98     nop
99     nop
100     nop
101     nop
102
103     nop
104 #endif
105         
106         /*22 end*/
107
108 _hang:
109         .word   do_hang
110 /* pad to 64 byte boundary */
111         .word   0x12345678
112         .word   0x12345678
113         .word   0x12345678
114         .word   0x12345678
115         .word   0x12345678
116         .word   0x12345678
117         .word   0x12345678
118 #else
119         ldr     pc, _undefined_instruction
120         ldr     pc, _software_interrupt
121         ldr     pc, _prefetch_abort
122         ldr     pc, _data_abort
123         ldr     pc, _not_used
124         ldr     pc, _irq
125         ldr     pc, _fiq
126
127 _undefined_instruction: .word undefined_instruction
128 _software_interrupt:    .word software_interrupt
129 _prefetch_abort:        .word prefetch_abort
130 _data_abort:            .word data_abort
131 _not_used:              .word not_used
132 _irq:                   .word irq
133 _fiq:                   .word fiq
134 _pad:                   .word 0x12345678 /* now 16*4=64 */
135 .global _end_vect
136 _end_vect:
137
138 #endif  /* CONFIG_PRELOADER */
139         
140         .balignl 16,0xdeadbeef
141 /*************************************************************************
142  *
143  * Startup Code (reset vector)
144  *
145  * do important init only if we don't start from memory!
146  * setup Memory and board specific bits prior to relocation.
147  * relocate armboot to ram
148  * setup stack
149  *
150  *************************************************************************/
151
152 .globl _TEXT_BASE
153 _TEXT_BASE:
154         .word   CONFIG_SYS_TEXT_BASE
155
156 /*
157  * These are defined in the board-specific linker script.
158  */
159 .globl _bss_start_ofs
160 _bss_start_ofs:
161         .word __bss_start - _start
162
163 .globl _bss_end_ofs
164 _bss_end_ofs:
165         .word _end - _start
166
167 #ifdef CONFIG_USE_IRQ
168 /* IRQ stack memory (calculated at run-time) */
169 .globl IRQ_STACK_START
170 IRQ_STACK_START:
171         .word   0x0badc0de
172
173 /* IRQ stack memory (calculated at run-time) */
174 .globl FIQ_STACK_START
175 FIQ_STACK_START:
176         .word 0x0badc0de
177 #endif
178
179 /* IRQ stack memory (calculated at run-time) + 8 bytes */
180 .globl IRQ_STACK_START_IN
181 IRQ_STACK_START_IN:
182         .word   0x0badc0de
183
184 /*
185  * the actual reset code
186  */
187
188 reset:
189         /*
190          * set the cpu to SVC32 mode
191          */
192 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
193 #ifdef SPRD_EVM_TAG_ON
194         ldr r0,=SPRD_EVM_ADDR_START
195         ldr r1,=0x87003004
196         ldr r2,[r1]
197         str r2,[r0]
198 #endif
199         mrs     r0, cpsr
200         bic     r0, r0, #0x1f
201         orr     r0, r0, #0xd3
202         msr     cpsr,r0
203 #endif
204
205         /* the mask ROM code should have PLL and others stable */
206 #ifdef  CONFIG_SC8810
207 #ifndef CONFIG_NAND_SPL
208 #if 0
209         ldr     r1, =0xeffff
210 time:   subs    r1,r1,#0x1
211         bne     time
212 #endif
213 #endif
214         mrc p15, 0, r1, c1, c0, 0
215         bic r1, #0x5
216         mcr p15, 0, r1, c1, c0, 0
217 #if 0
218         ldr     r0, =0x8b00002c
219         ldr     r1, =0xf
220         ldr     r2,  [r0]
221         orr     r1,  r1,r2
222         str     r1,  [r0]
223 #endif
224 #else
225         ldr r0, =_start
226         mcr p15, 0, r0, c12, c0, 0
227 #if !defined(CONFIG_FPGA)
228         /*
229          * Enable coherent requested to the processor.
230         */
231         mrc     p15, 0, r0, c1, c0, 1
232         orr r0, r0,#(0x1<<6)
233         mcr p15, 0, r0, c1, c0, 1 @write aux control register
234 #endif /* CONFIG_ARCH_SCX35L*/
235 #endif
236 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
237         bl      cpu_init_crit
238         mov    r10, #0
239         /*set up temp stack*/
240         LDR    sp, =SVC_STACK_TEMP
241
242         STMDB sp!,{lr} 
243         bl lowlevel_init
244         @bl MMU_Init
245         /*Re-set up stack
246           The sp here must be in the reserved region
247           */
248         LDMIA sp!, {lr}
249         LDR     sp, =SPL_STACK 
250 #endif
251
252 /* Set stackpointer in internal RAM to call board_init_f */
253 call_board_init_f:
254         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
255         bic     sp, sp, #7 /* 8-byte alignment for ABI compliance */
256 #ifndef CONFIG_NAND_SPL
257         ldr     r0,=0x00000000
258         bl      board_init_f
259 #else
260         ldr r0, =(CONFIG_SYS_INIT_SP_ADDR)
261         ldr r1, =0x00000000
262         ldr r2, =(CONFIG_SYS_TEXT_BASE)
263         bl relocate_code
264 #endif
265
266 /*------------------------------------------------------------------------------*/
267
268 /*
269  * void relocate_code (addr_sp, gd, addr_moni)
270  *
271  * This "function" does not return, instead it continues in RAM
272  * after relocating the monitor code.
273  *
274  */
275         .globl  relocate_code
276 relocate_code:
277         mov     r4, r0  /* save addr_sp */
278         mov     r5, r1  /* save addr of gd */
279         mov     r6, r2  /* save addr of destination */
280
281         /* Set up the stack                                                 */
282 stack_setup:
283         mov     sp, r4
284
285         adr     r0, _start
286         ldr r6, =(CONFIG_SYS_TEXT_BASE)
287         cmp     r0, r6
288         mov r9, #0x0
289         beq     clear_bss               /* skip relocation */
290         mov     r1, r6                  /* r1 <- scratch for copy loop */
291         ldr     r2, _TEXT_BASE
292         ldr     r3, _bss_start_ofs
293         add     r2, r0, r3              /* r2 <- source end address         */
294
295 copy_loop:
296         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
297         stmia   r1!, {r9-r10}           /* copy to   target address [r1]    */
298         cmp     r0, r2                  /* until source end address [r2]    */
299         blo     copy_loop
300
301 #ifndef CONFIG_PRELOADER
302         /*
303          * fix .rel.dyn relocations
304          */
305         ldr     r0, _TEXT_BASE          /* r0 <- Text base */
306         sub     r9, r6, r0              /* r9 <- relocation offset */
307         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
308         add     r10, r10, r0            /* r10 <- sym table in FLASH */
309         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
310         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
311         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
312         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
313 fixloop:
314         ldr     r0, [r2]                /* r0 <- location to fix up, IN FLASH! */
315         add     r0, r0, r9              /* r0 <- location to fix up in RAM */
316         ldr     r1, [r2, #4]
317         and     r7, r1, #0xff
318         cmp     r7, #23                 /* relative fixup? */
319         beq     fixrel
320         cmp     r7, #2                  /* absolute fixup? */
321         beq     fixabs
322         /* ignore unknown type of fixup */
323         b       fixnext
324 fixabs:
325         /* absolute fix: set location to (offset) symbol value */
326         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
327         add     r1, r10, r1             /* r1 <- address of symbol in table */
328         ldr     r1, [r1, #4]            /* r1 <- symbol value */
329         add     r1, r1, r9              /* r1 <- relocated sym addr */
330         b       fixnext
331 fixrel:
332         /* relative fix: increase location by offset */
333         ldr     r1, [r0]
334         add     r1, r1, r9
335 fixnext:
336         str     r1, [r0]
337         add     r2, r2, #8              /* each rel.dyn entry is 8 bytes */
338         cmp     r2, r3
339         blo     fixloop
340 #endif
341
342 clear_bss:
343 #ifndef CONFIG_PRELOADER
344         ldr     r0, _bss_start_ofs
345         ldr     r1, _bss_end_ofs
346         ldr     r3, _TEXT_BASE          /* Text base */
347         mov     r4, r6                  /* reloc addr */
348         add     r0, r0, r4
349         add     r1, r1, r4
350         mov     r2, #0x00000000         /* clear                            */
351
352 clbss_l:str     r2, [r0]                /* clear loop...                    */
353         add     r0, r0, #4
354         cmp     r0, r1
355         bne     clbss_l
356
357         bl coloured_LED_init
358         bl red_LED_on
359 #endif
360
361 /*
362  * We are done. Do not return, instead branch to second part of board
363  * initialization, now running from RAM.
364  */
365 jump_2_ram:
366 #ifdef CONFIG_NAND_SPL
367         ldr     r0, _nand_boot_ofs
368         mov     pc, r0
369
370 _nand_boot_ofs:
371         .word nand_boot
372 #else
373         ldr     r0, _board_init_r_ofs
374         adr     r1, _start
375         add     lr, r0, r1
376         add     lr, lr, r9
377         /* setup parameters for board_init_r */
378         mov     r0, r5          /* gd_t */
379         mov     r1, r6          /* dest_addr */
380         /* jump to it ... */
381         mov     pc, lr
382
383 _board_init_r_ofs:
384         .word board_init_r - _start
385 #endif
386
387 _rel_dyn_start_ofs:
388         .word __rel_dyn_start - _start
389 _rel_dyn_end_ofs:
390         .word __rel_dyn_end - _start
391 _dynsym_start_ofs:
392         .word __dynsym_start - _start
393
394 /*************************************************************************
395  *
396  * CPU_init_critical registers
397  *
398  * setup important registers
399  * setup memory timing
400  *
401  *************************************************************************/
402 cpu_init_crit:
403         /*
404          * Invalidate L1 I/D
405          */
406         mov     r0, #0                  @ set up for MCR
407         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
408         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
409
410         /*
411          * disable MMU stuff and caches
412          */
413         mrc     p15, 0, r0, c1, c0, 0
414         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
415         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
416         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
417         orr     r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
418         mcr     p15, 0, r0, c1, c0, 0
419
420         /*
421          * Jump to board specific initialization...
422          * The Mask ROM will have already initialized
423          * basic memory. Go here to bump up clock rate and handle
424          * wake up conditions.
425          */
426         mov     ip, lr                  @ persevere link reg across call
427 @       bl      lowlevel_init           @ go setup pll,mux,memory
428         mov     lr, ip                  @ restore link
429         mov     pc, lr                  @ back to my caller
430
431 /*
432  *************************************************************************
433  *
434  * Interrupt handling
435  *
436  *************************************************************************
437  */
438 @
439 @ IRQ stack frame.
440 @
441 #define S_FRAME_SIZE    72
442
443 #define S_OLD_R0        68
444 #define S_PSR           64
445 #define S_PC            60
446 #define S_LR            56
447 #define S_SP            52
448
449 #define S_IP            48
450 #define S_FP            44
451 #define S_R10           40
452 #define S_R9            36
453 #define S_R8            32
454 #define S_R7            28
455 #define S_R6            24
456 #define S_R5            20
457 #define S_R4            16
458 #define S_R3            12
459 #define S_R2            8
460 #define S_R1            4
461 #define S_R0            0
462
463 #define MODE_SVC 0x13
464 #define I_BIT    0x80
465
466 /*
467  * use bad_save_user_regs for abort/prefetch/undef/swi ...
468  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
469  */
470
471         .macro  bad_save_user_regs
472         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current
473                                                 @ user stack
474         stmia   sp, {r0 - r12}                  @ Save user registers (now in
475                                                 @ svc mode) r0-r12
476         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort
477                                                 @ stack
478         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc
479                                                 @ and cpsr (into parm regs)
480         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
481
482         add     r5, sp, #S_SP
483         mov     r1, lr
484         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
485         mov     r0, sp                          @ save current stack into r0
486                                                 @ (param register)
487         .endm
488
489         .macro  irq_save_user_regs
490         sub     sp, sp, #S_FRAME_SIZE
491         stmia   sp, {r0 - r12}                  @ Calling r0-r12
492         add     r8, sp, #S_PC                   @ !! R8 NEEDS to be saved !!
493                                                 @ a reserved stack spot would
494                                                 @ be good.
495         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
496         str     lr, [r8, #0]                    @ Save calling PC
497         mrs     r6, spsr
498         str     r6, [r8, #4]                    @ Save CPSR
499         str     r0, [r8, #8]                    @ Save OLD_R0
500         mov     r0, sp
501         .endm
502
503         .macro  irq_restore_user_regs
504         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
505         mov     r0, r0
506         ldr     lr, [sp, #S_PC]                 @ Get PC
507         add     sp, sp, #S_FRAME_SIZE
508         subs    pc, lr, #4                      @ return & move spsr_svc into
509                                                 @ cpsr
510         .endm
511
512         .macro get_bad_stack
513         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter
514                                                 @ in banked mode)
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         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
536                                                 @ spots for abort stack
537         str     lr, [r0]                        @ save caller lr in position 0
538                                                 @ of saved stack
539         mrs     r0, spsr                        @ get the spsr
540         str     lr, [r0, #4]                    @ save spsr in position 1 of
541                                                 @ saved stack
542         ldr     r0, [r13]                       @ restore r0
543         add     r13, r13, #4                    @ pop stack entry
544         .endm
545
546         .macro get_irq_stack                    @ setup IRQ stack
547         ldr     sp, IRQ_STACK_START
548         .endm
549
550         .macro get_fiq_stack                    @ setup FIQ stack
551         ldr     sp, FIQ_STACK_START
552         .endm
553
554 /*
555  * exception handlers
556  */
557 #ifdef CONFIG_PRELOADER
558         .align  5
559 do_hang:
560         ldr     sp, _TEXT_BASE                  /* switch to abort stack */
561 1:
562         bl      1b                              /* hang and never return */
563 #else   /* !CONFIG_PRELOADER */
564         .align  5
565 undefined_instruction:
566         get_bad_stack
567         bad_save_user_regs
568         bl      do_undefined_instruction
569
570         .align  5
571 software_interrupt:
572         get_bad_stack_swi
573         bad_save_user_regs
574         bl      do_software_interrupt
575
576         .align  5
577 prefetch_abort:
578         get_bad_stack
579         bad_save_user_regs
580         bl      do_prefetch_abort
581
582         .align  5
583 data_abort:
584         get_bad_stack
585         bad_save_user_regs
586         bl      do_data_abort
587
588         .align  5
589 not_used:
590         get_bad_stack
591         bad_save_user_regs
592         bl      do_not_used
593
594 #ifdef CONFIG_USE_IRQ
595
596         .align  5
597 irq:
598         get_irq_stack
599         irq_save_user_regs
600         bl      do_irq
601         irq_restore_user_regs
602
603         .align  5
604 fiq:
605         get_fiq_stack
606         /* someone ought to write a more effective fiq_save_user_regs */
607         irq_save_user_regs
608         bl      do_fiq
609         irq_restore_user_regs
610
611 #else
612
613         .align  5
614 irq:
615         get_bad_stack
616         bad_save_user_regs
617         bl      do_irq
618
619         .align  5
620 fiq:
621         get_bad_stack
622         bad_save_user_regs
623         bl      do_fiq
624
625 #endif
626 #endif  /* CONFIG_PRELOADER */