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