b8065b70df5f4c8989d93481451bb61a004d7dcd
[platform/kernel/u-boot.git] / arch / arm / cpu / pxa / start.S
1 /*
2  *  armboot - Startup Code for XScale
3  *
4  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
5  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6  *  Copyright (C) 2000  Wolfgang Denk <wd@denx.de>
7  *  Copyright (C) 2001  Alex Zuepke <azu@sysgo.de>
8  *  Copyright (C) 2002  Kyle Harris <kharris@nexus-tech.net>
9  *  Copyright (C) 2003  Robert Schwebel <r.schwebel@pengutronix.de>
10  *  Copyright (C) 2003  Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
11  *  Copyright (c) 2010  Marek Vasut <marek.vasut@gmail.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 <version.h>
35 #include <asm/arch/pxa-regs.h>
36 #include <asm/arch/macro.h>
37
38 /* takes care the CP15 update has taken place */
39 .macro CPWAIT reg
40 mrc  p15,0,\reg,c2,c0,0
41 mov  \reg,\reg
42 sub  pc,pc,#4
43 .endm
44
45 .globl _start
46 _start: b       reset
47 #ifdef CONFIG_PRELOADER
48         ldr     pc, _hang
49         ldr     pc, _hang
50         ldr     pc, _hang
51         ldr     pc, _hang
52         ldr     pc, _hang
53         ldr     pc, _hang
54         ldr     pc, _hang
55
56 _hang:
57         .word   do_hang
58         .word   0x12345678
59         .word   0x12345678
60         .word   0x12345678
61         .word   0x12345678
62         .word   0x12345678
63         .word   0x12345678
64         .word   0x12345678      /* now 16*4=64 */
65 #else
66         ldr     pc, _undefined_instruction
67         ldr     pc, _software_interrupt
68         ldr     pc, _prefetch_abort
69         ldr     pc, _data_abort
70         ldr     pc, _not_used
71         ldr     pc, _irq
72         ldr     pc, _fiq
73
74 _undefined_instruction: .word undefined_instruction
75 _software_interrupt:    .word software_interrupt
76 _prefetch_abort:        .word prefetch_abort
77 _data_abort:            .word data_abort
78 _not_used:              .word not_used
79 _irq:                   .word irq
80 _fiq:                   .word fiq
81 #endif  /* CONFIG_PRELOADER */
82
83         .balignl 16,0xdeadbeef
84
85
86 /*
87  * Startup Code (reset vector)
88  *
89  * do important init only if we don't start from RAM!
90  * - relocate armboot to RAM
91  * - setup stack
92  * - jump to second stage
93  */
94
95 .globl _TEXT_BASE
96 _TEXT_BASE:
97         .word   CONFIG_SYS_TEXT_BASE
98
99 /*
100  * These are defined in the board-specific linker script.
101  */
102 .globl _bss_start_ofs
103 _bss_start_ofs:
104         .word __bss_start - _start
105
106 .globl _bss_end_ofs
107 _bss_end_ofs:
108         .word _end - _start
109
110 #ifdef CONFIG_USE_IRQ
111 /* IRQ stack memory (calculated at run-time) */
112 .globl IRQ_STACK_START
113 IRQ_STACK_START:
114         .word   0x0badc0de
115
116 /* IRQ stack memory (calculated at run-time) */
117 .globl FIQ_STACK_START
118 FIQ_STACK_START:
119         .word 0x0badc0de
120 #endif /* CONFIG_USE_IRQ */
121
122 #ifndef CONFIG_PRELOADER
123 /* IRQ stack memory (calculated at run-time) + 8 bytes */
124 .globl IRQ_STACK_START_IN
125 IRQ_STACK_START_IN:
126         .word   0x0badc0de
127
128 /*
129  * the actual reset code
130  */
131
132 reset:
133         /*
134          * set the cpu to SVC32 mode
135          */
136         mrs     r0,cpsr
137         bic     r0,r0,#0x1f
138         orr     r0,r0,#0xd3
139         msr     cpsr,r0
140
141         /*
142          * Enable MMU to use DCache as DRAM
143          */
144         /* Domain access -- enable for all CPs */
145         ldr     r0, =0x0000ffff
146         mcr     p15, 0, r0, c3, c0, 0
147
148         /* Point TTBR to MMU table */
149         ldr     r0, =mmu_table
150         adr     r2, _start
151         orr     r0, r2
152         mcr     p15, 0, r0, c2, c0, 0
153
154 /* !!! Hereby, check if the code is running from SRAM !!! */
155 /* If the code is running from SRAM, alias SRAM to 0x0 to simulate NOR. The code
156  * is linked to 0x0 too, so this makes things easier. */
157         cmp     r2, #0x5c000000
158
159         ldreq   r1, [r0]
160         orreq   r1, r2
161         streq   r1, [r0]
162
163         /* Kick in MMU, ICache, DCache, BTB */
164         mrc     p15, 0, r0, c1, c0, 0
165         bic     r0, #0x1b00
166         bic     r0, #0x0087
167         orr     r0, #0x1800
168         orr     r0, #0x0005
169         mcr     p15, 0, r0, c1, c0, 0
170         CPWAIT  r0
171
172         /* Unlock Icache, Dcache */
173         mcr     p15, 0, r0, c9, c1, 1
174         mcr     p15, 0, r0, c9, c2, 1
175
176         /* Flush Icache, Dcache, BTB */
177         mcr     p15, 0, r0, c7, c7, 0
178
179         /* Unlock I-TLB, D-TLB */
180         mcr     p15, 0, r0, c10, c4, 1
181         mcr     p15, 0, r0, c10, c8, 1
182
183         /* Flush TLB */
184         mcr     p15, 0, r0, c8, c7, 0
185         /* Allocate 4096 bytes of Dcache as RAM */
186
187         /* Drain pending loads and stores */
188         mcr     p15, 0, r0, c7, c10, 4
189
190         mov     r4, #0x00
191         mov     r5, #0x00
192         mov     r2, #0x01
193         mcr     p15, 0, r0, c9, c2, 0
194         CPWAIT  r0
195
196         /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
197         mov     r0, #128
198         mov     r1, #0xa0000000
199 alloc:
200         mcr     p15, 0, r1, c7, c2, 5
201         /* Drain pending loads and stores */
202         mcr     p15, 0, r0, c7, c10, 4
203         strd    r4, [r1], #8
204         strd    r4, [r1], #8
205         strd    r4, [r1], #8
206         strd    r4, [r1], #8
207         subs    r0, #0x01
208         bne     alloc
209         /* Drain pending loads and stores */
210         mcr     p15, 0, r0, c7, c10, 4
211         mov     r2, #0x00
212         mcr     p15, 0, r2, c9, c2, 0
213         CPWAIT  r0
214
215         /* Jump to 0x0 ( + offset) if running from SRAM */
216         adr     r0, zerojmp
217         bic     r0, #0x5c000000
218         mov     pc, r0
219 zerojmp:
220
221 /* Set stackpointer in internal RAM to call board_init_f */
222 call_board_init_f:
223         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
224         ldr     r0,=0x00000000
225         bl      board_init_f
226
227 /*------------------------------------------------------------------------------*/
228
229 /*
230  * void relocate_code (addr_sp, gd, addr_moni)
231  *
232  * This "function" does not return, instead it continues in RAM
233  * after relocating the monitor code.
234  *
235  */
236         .globl  relocate_code
237 relocate_code:
238         mov     r4, r0  /* save addr_sp */
239         mov     r5, r1  /* save addr of gd */
240         mov     r6, r2  /* save addr of destination */
241         mov     r7, r2  /* save addr of destination */
242
243         /* Set up the stack                                                 */
244 stack_setup:
245         mov     sp, r4
246
247         adr     r0, _start
248         ldr     r2, _TEXT_BASE
249         ldr     r3, _bss_start_ofs
250         add     r2, r0, r3              /* r2 <- source end address         */
251         cmp     r0, r6
252         beq     clear_bss
253
254 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
255         stmfd sp!, {r0-r12}
256 copy_loop:
257         ldmia   r0!, {r3-r5, r7-r11}    /* copy from source address [r0]    */
258         stmia   r6!, {r3-r5, r7-r11}    /* copy to   target address [r1]    */
259         cmp     r0, r2                  /* until source end address [r2]    */
260         blo     copy_loop
261         ldmfd sp!, {r0-r12}
262
263 #ifndef CONFIG_PRELOADER
264         /*
265          * fix .rel.dyn relocations
266          */
267         ldr     r0, _TEXT_BASE          /* r0 <- Text base */
268         sub     r9, r7, r0              /* r9 <- relocation offset */
269         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
270         add     r10, r10, r0            /* r10 <- sym table in FLASH */
271         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
272         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
273         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
274         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
275 fixloop:
276         ldr     r0, [r2]        /* r0 <- location to fix up, IN FLASH! */
277         add     r0, r9          /* r0 <- location to fix up in RAM */
278         ldr     r1, [r2, #4]
279         and     r8, r1, #0xff
280         cmp     r8, #23         /* relative fixup? */
281         beq     fixrel
282         cmp     r8, #2          /* absolute fixup? */
283         beq     fixabs
284         /* ignore unknown type of fixup */
285         b       fixnext
286 fixabs:
287         /* absolute fix: set location to (offset) symbol value */
288         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
289         add     r1, r10, r1             /* r1 <- address of symbol in table */
290         ldr     r1, [r1, #4]            /* r1 <- symbol value */
291         add     r1, r9                  /* r1 <- relocated sym addr */
292         b       fixnext
293 fixrel:
294         /* relative fix: increase location by offset */
295         ldr     r1, [r0]
296         add     r1, r1, r9
297 fixnext:
298         str     r1, [r0]
299         add     r2, r2, #8      /* each rel.dyn entry is 8 bytes */
300         cmp     r2, r3
301         blo     fixloop
302 #endif
303 #endif  /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
304
305 clear_bss:
306 #ifndef CONFIG_PRELOADER
307         ldr     r0, _bss_start_ofs
308         ldr     r1, _bss_end_ofs
309         ldr     r3, _TEXT_BASE          /* Text base */
310         mov     r4, r7                  /* reloc addr */
311         add     r0, r0, r4
312         add     r1, r1, r4
313         mov     r2, #0x00000000         /* clear                            */
314
315 clbss_l:str     r2, [r0]                /* clear loop...                    */
316         add     r0, r0, #4
317         cmp     r0, r1
318         bne     clbss_l
319 #endif
320
321 /*
322  * We are done. Do not return, instead branch to second part of board
323  * initialization, now running from RAM.
324  */
325 #ifdef CONFIG_ONENAND_IPL
326         ldr     r0, _start_oneboot_ofs
327         mov     pc, r0
328
329 _start_oneboot_ofs
330         : .word start_oneboot
331 #else
332         ldr     r0, _board_init_r_ofs
333         adr     r1, _start
334         add     r0, r0, r1
335         add     lr, r0, r9
336         /* setup parameters for board_init_r */
337         mov     r0, r5          /* gd_t */
338         mov     r1, r7          /* dest_addr */
339         /* jump to it ... */
340         mov     pc, lr
341
342 _board_init_r_ofs:
343         .word board_init_r - _start
344 #endif
345
346 _rel_dyn_start_ofs:
347         .word __rel_dyn_start - _start
348 _rel_dyn_end_ofs:
349         .word __rel_dyn_end - _start
350 _dynsym_start_ofs:
351         .word __dynsym_start - _start
352
353 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
354
355 /****************************************************************************/
356 /*                                                                          */
357 /* the actual reset code for OneNAND IPL                                    */
358 /*                                                                          */
359 /****************************************************************************/
360
361 #ifndef CONFIG_PXA27X
362 #error OneNAND IPL is not supported on PXA25x and 26x due to lack of SRAM
363 #endif
364
365 reset:
366         /* Set CPU to SVC32 mode */
367         mrs     r0,cpsr
368         bic     r0,r0,#0x1f
369         orr     r0,r0,#0x13
370         msr     cpsr,r0
371
372         /* Point stack at the end of SRAM and leave 32 words for abort-stack */
373         ldr     sp, =0x5c03ff80
374
375         /* Start OneNAND IPL */
376         ldr     pc, =start_oneboot
377
378 #endif /* #if !defined(CONFIG_ONENAND_IPL) */
379
380 #ifndef CONFIG_PRELOADER
381 /****************************************************************************/
382 /*                                                                          */
383 /* Interrupt handling                                                       */
384 /*                                                                          */
385 /****************************************************************************/
386
387 /* IRQ stack frame                                                          */
388
389 #define S_FRAME_SIZE    72
390
391 #define S_OLD_R0        68
392 #define S_PSR           64
393 #define S_PC            60
394 #define S_LR            56
395 #define S_SP            52
396
397 #define S_IP            48
398 #define S_FP            44
399 #define S_R10           40
400 #define S_R9            36
401 #define S_R8            32
402 #define S_R7            28
403 #define S_R6            24
404 #define S_R5            20
405 #define S_R4            16
406 #define S_R3            12
407 #define S_R2            8
408 #define S_R1            4
409 #define S_R0            0
410
411 #define MODE_SVC 0x13
412
413         /* use bad_save_user_regs for abort/prefetch/undef/swi ...          */
414
415         .macro  bad_save_user_regs
416         sub     sp, sp, #S_FRAME_SIZE
417         stmia   sp, {r0 - r12}                  /* Calling r0-r12           */
418         add     r8, sp, #S_PC
419
420 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
421         ldr     r2, _armboot_start
422         sub     r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
423         sub     r2, r2, #(GENERATED_GBL_DATA_SIZE+8)    @ set base 2 words into abort stack
424 #else
425         ldr     r2, IRQ_STACK_START_IN
426 #endif
427         ldmia   r2, {r2 - r4}                   /* get pc, cpsr, old_r0     */
428         add     r0, sp, #S_FRAME_SIZE           /* restore sp_SVC           */
429
430         add     r5, sp, #S_SP
431         mov     r1, lr
432         stmia   r5, {r0 - r4}                   /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
433         mov     r0, sp
434         .endm
435
436
437         /* use irq_save_user_regs / irq_restore_user_regs for                */
438         /* IRQ/FIQ handling                                                  */
439
440         .macro  irq_save_user_regs
441         sub     sp, sp, #S_FRAME_SIZE
442         stmia   sp, {r0 - r12}                  /* Calling r0-r12            */
443         add     r8, sp, #S_PC
444         stmdb   r8, {sp, lr}^                   /* Calling SP, LR            */
445         str     lr, [r8, #0]                    /* Save calling PC           */
446         mrs     r6, spsr
447         str     r6, [r8, #4]                    /* Save CPSR                 */
448         str     r0, [r8, #8]                    /* Save OLD_R0               */
449         mov     r0, sp
450         .endm
451
452         .macro  irq_restore_user_regs
453         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
454         mov     r0, r0
455         ldr     lr, [sp, #S_PC]                 @ Get PC
456         add     sp, sp, #S_FRAME_SIZE
457         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
458         .endm
459
460         .macro get_bad_stack
461 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
462         ldr     r13, _armboot_start             @ setup our mode stack
463         sub     r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
464         sub     r13, r13, #(GENERATED_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
465 #else
466         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
467 #endif
468
469         str     lr, [r13]                       @ save caller lr / spsr
470         mrs     lr, spsr
471         str     lr, [r13, #4]
472
473         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
474         msr     spsr_c, r13
475         mov     lr, pc
476         movs    pc, lr
477         .endm
478
479         .macro get_irq_stack                    @ setup IRQ stack
480         ldr     sp, IRQ_STACK_START
481         .endm
482
483         .macro get_fiq_stack                    @ setup FIQ stack
484         ldr     sp, FIQ_STACK_START
485         .endm
486 #endif  /* CONFIG_PRELOADER */
487
488
489 /****************************************************************************/
490 /*                                                                          */
491 /* exception handlers                                                       */
492 /*                                                                          */
493 /****************************************************************************/
494
495 #ifdef CONFIG_PRELOADER
496         .align  5
497 do_hang:
498         ldr     sp, _TEXT_BASE                  /* use 32 words abort stack */
499         bl      hang                            /* hang and never return */
500 #else   /* !CONFIG_PRELOADER */
501         .align  5
502 undefined_instruction:
503         get_bad_stack
504         bad_save_user_regs
505         bl      do_undefined_instruction
506
507         .align  5
508 software_interrupt:
509         get_bad_stack
510         bad_save_user_regs
511         bl      do_software_interrupt
512
513         .align  5
514 prefetch_abort:
515         get_bad_stack
516         bad_save_user_regs
517         bl      do_prefetch_abort
518
519         .align  5
520 data_abort:
521         get_bad_stack
522         bad_save_user_regs
523         bl      do_data_abort
524
525         .align  5
526 not_used:
527         get_bad_stack
528         bad_save_user_regs
529         bl      do_not_used
530
531 #ifdef CONFIG_USE_IRQ
532
533         .align  5
534 irq:
535         get_irq_stack
536         irq_save_user_regs
537         bl      do_irq
538         irq_restore_user_regs
539
540         .align  5
541 fiq:
542         get_fiq_stack
543         irq_save_user_regs              /* someone ought to write a more    */
544         bl      do_fiq                  /* effiction fiq_save_user_regs     */
545         irq_restore_user_regs
546
547 #else /* !CONFIG_USE_IRQ */
548
549         .align  5
550 irq:
551         get_bad_stack
552         bad_save_user_regs
553         bl      do_irq
554
555         .align  5
556 fiq:
557         get_bad_stack
558         bad_save_user_regs
559         bl      do_fiq
560 #endif  /* CONFIG_PRELOADER */
561 #endif /* CONFIG_USE_IRQ */
562
563 /****************************************************************************/
564 /*                                                                          */
565 /* Reset function: the PXA250 doesn't have a reset function, so we have to  */
566 /* perform a watchdog timeout for a soft reset.                             */
567 /*                                                                          */
568 /****************************************************************************/
569 /* Operating System Timer */
570 .align  5
571 .globl reset_cpu
572
573         /* FIXME: this code is PXA250 specific. How is this handled on      */
574         /*        other XScale processors?                                  */
575
576 reset_cpu:
577
578         /* We set OWE:WME (watchdog enable) and wait until timeout happens  */
579
580         ldr     r0, =OWER
581         ldr     r1, [r0]
582         orr     r1, r1, #0x0001                 /* bit0: WME                */
583         str     r1, [r0]
584
585         /* OS timer does only wrap every 1165 seconds, so we have to set    */
586         /* the match register as well.                                      */
587
588         ldr     r0, =OSCR
589         ldr     r1, [r0]                        /* read OS timer            */
590         add     r1, r1, #0x800                  /* let OSMR3 match after    */
591         add     r1, r1, #0x800                  /* 4096*(1/3.6864MHz)=1ms   */
592         ldr     r0, =OSMR3
593         str     r1, [r0]
594
595 reset_endless:
596
597         b       reset_endless
598
599 #ifndef CONFIG_PRELOADER
600 .section .mmudata, "a"
601         .align  14
602         .globl  mmu_table
603 mmu_table:
604         /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */
605         .set    __base, 0
606         .rept   0xa00
607         .word   (__base << 20) | 0xc12
608         .set    __base, __base + 1
609         .endr
610
611         /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */
612         .word   (0xa00 << 20) | 0x1c1e
613
614         .set    __base, 0xa01
615         .rept   0x1000 - 0xa01
616         .word   (__base << 20) | 0xc12
617         .set    __base, __base + 1
618         .endr
619 #endif