]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/pxa/start.S
ARM: fix address setup in start.S
[karo-tx-uboot.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     lr, r0, r1
335 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
336         add     lr, lr, r9
337 #endif
338         /* setup parameters for board_init_r */
339         mov     r0, r5          /* gd_t */
340         mov     r1, r7          /* dest_addr */
341         /* jump to it ... */
342         mov     pc, lr
343
344 _board_init_r_ofs:
345         .word board_init_r - _start
346 #endif
347
348 _rel_dyn_start_ofs:
349         .word __rel_dyn_start - _start
350 _rel_dyn_end_ofs:
351         .word __rel_dyn_end - _start
352 _dynsym_start_ofs:
353         .word __dynsym_start - _start
354
355 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
356
357 /****************************************************************************/
358 /*                                                                          */
359 /* the actual reset code for OneNAND IPL                                    */
360 /*                                                                          */
361 /****************************************************************************/
362
363 #ifndef CONFIG_PXA27X
364 #error OneNAND IPL is not supported on PXA25x and 26x due to lack of SRAM
365 #endif
366
367 reset:
368         /* Set CPU to SVC32 mode */
369         mrs     r0,cpsr
370         bic     r0,r0,#0x1f
371         orr     r0,r0,#0x13
372         msr     cpsr,r0
373
374         /* Point stack at the end of SRAM and leave 32 words for abort-stack */
375         ldr     sp, =0x5c03ff80
376
377         /* Start OneNAND IPL */
378         ldr     pc, =start_oneboot
379
380 #endif /* #if !defined(CONFIG_ONENAND_IPL) */
381
382 #ifndef CONFIG_PRELOADER
383 /****************************************************************************/
384 /*                                                                          */
385 /* Interrupt handling                                                       */
386 /*                                                                          */
387 /****************************************************************************/
388
389 /* IRQ stack frame                                                          */
390
391 #define S_FRAME_SIZE    72
392
393 #define S_OLD_R0        68
394 #define S_PSR           64
395 #define S_PC            60
396 #define S_LR            56
397 #define S_SP            52
398
399 #define S_IP            48
400 #define S_FP            44
401 #define S_R10           40
402 #define S_R9            36
403 #define S_R8            32
404 #define S_R7            28
405 #define S_R6            24
406 #define S_R5            20
407 #define S_R4            16
408 #define S_R3            12
409 #define S_R2            8
410 #define S_R1            4
411 #define S_R0            0
412
413 #define MODE_SVC 0x13
414
415         /* use bad_save_user_regs for abort/prefetch/undef/swi ...          */
416
417         .macro  bad_save_user_regs
418         sub     sp, sp, #S_FRAME_SIZE
419         stmia   sp, {r0 - r12}                  /* Calling r0-r12           */
420         add     r8, sp, #S_PC
421
422 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
423         ldr     r2, _armboot_start
424         sub     r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
425         sub     r2, r2, #(GENERATED_GBL_DATA_SIZE+8)    @ set base 2 words into abort stack
426 #else
427         ldr     r2, IRQ_STACK_START_IN
428 #endif
429         ldmia   r2, {r2 - r4}                   /* get pc, cpsr, old_r0     */
430         add     r0, sp, #S_FRAME_SIZE           /* restore sp_SVC           */
431
432         add     r5, sp, #S_SP
433         mov     r1, lr
434         stmia   r5, {r0 - r4}                   /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
435         mov     r0, sp
436         .endm
437
438
439         /* use irq_save_user_regs / irq_restore_user_regs for                */
440         /* IRQ/FIQ handling                                                  */
441
442         .macro  irq_save_user_regs
443         sub     sp, sp, #S_FRAME_SIZE
444         stmia   sp, {r0 - r12}                  /* Calling r0-r12            */
445         add     r8, sp, #S_PC
446         stmdb   r8, {sp, lr}^                   /* Calling SP, LR            */
447         str     lr, [r8, #0]                    /* Save calling PC           */
448         mrs     r6, spsr
449         str     r6, [r8, #4]                    /* Save CPSR                 */
450         str     r0, [r8, #8]                    /* Save OLD_R0               */
451         mov     r0, sp
452         .endm
453
454         .macro  irq_restore_user_regs
455         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
456         mov     r0, r0
457         ldr     lr, [sp, #S_PC]                 @ Get PC
458         add     sp, sp, #S_FRAME_SIZE
459         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
460         .endm
461
462         .macro get_bad_stack
463 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
464         ldr     r13, _armboot_start             @ setup our mode stack
465         sub     r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
466         sub     r13, r13, #(GENERATED_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
467 #else
468         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
469 #endif
470
471         str     lr, [r13]                       @ save caller lr / spsr
472         mrs     lr, spsr
473         str     lr, [r13, #4]
474
475         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
476         msr     spsr_c, r13
477         mov     lr, pc
478         movs    pc, lr
479         .endm
480
481         .macro get_irq_stack                    @ setup IRQ stack
482         ldr     sp, IRQ_STACK_START
483         .endm
484
485         .macro get_fiq_stack                    @ setup FIQ stack
486         ldr     sp, FIQ_STACK_START
487         .endm
488 #endif  /* CONFIG_PRELOADER */
489
490
491 /****************************************************************************/
492 /*                                                                          */
493 /* exception handlers                                                       */
494 /*                                                                          */
495 /****************************************************************************/
496
497 #ifdef CONFIG_PRELOADER
498         .align  5
499 do_hang:
500         ldr     sp, _TEXT_BASE                  /* use 32 words abort stack */
501         bl      hang                            /* hang and never return */
502 #else   /* !CONFIG_PRELOADER */
503         .align  5
504 undefined_instruction:
505         get_bad_stack
506         bad_save_user_regs
507         bl      do_undefined_instruction
508
509         .align  5
510 software_interrupt:
511         get_bad_stack
512         bad_save_user_regs
513         bl      do_software_interrupt
514
515         .align  5
516 prefetch_abort:
517         get_bad_stack
518         bad_save_user_regs
519         bl      do_prefetch_abort
520
521         .align  5
522 data_abort:
523         get_bad_stack
524         bad_save_user_regs
525         bl      do_data_abort
526
527         .align  5
528 not_used:
529         get_bad_stack
530         bad_save_user_regs
531         bl      do_not_used
532
533 #ifdef CONFIG_USE_IRQ
534
535         .align  5
536 irq:
537         get_irq_stack
538         irq_save_user_regs
539         bl      do_irq
540         irq_restore_user_regs
541
542         .align  5
543 fiq:
544         get_fiq_stack
545         irq_save_user_regs              /* someone ought to write a more    */
546         bl      do_fiq                  /* effiction fiq_save_user_regs     */
547         irq_restore_user_regs
548
549 #else /* !CONFIG_USE_IRQ */
550
551         .align  5
552 irq:
553         get_bad_stack
554         bad_save_user_regs
555         bl      do_irq
556
557         .align  5
558 fiq:
559         get_bad_stack
560         bad_save_user_regs
561         bl      do_fiq
562 #endif  /* CONFIG_PRELOADER */
563 #endif /* CONFIG_USE_IRQ */
564
565 /****************************************************************************/
566 /*                                                                          */
567 /* Reset function: the PXA250 doesn't have a reset function, so we have to  */
568 /* perform a watchdog timeout for a soft reset.                             */
569 /*                                                                          */
570 /****************************************************************************/
571 /* Operating System Timer */
572 .align  5
573 .globl reset_cpu
574
575         /* FIXME: this code is PXA250 specific. How is this handled on      */
576         /*        other XScale processors?                                  */
577
578 reset_cpu:
579
580         /* We set OWE:WME (watchdog enable) and wait until timeout happens  */
581
582         ldr     r0, =OWER
583         ldr     r1, [r0]
584         orr     r1, r1, #0x0001                 /* bit0: WME                */
585         str     r1, [r0]
586
587         /* OS timer does only wrap every 1165 seconds, so we have to set    */
588         /* the match register as well.                                      */
589
590         ldr     r0, =OSCR
591         ldr     r1, [r0]                        /* read OS timer            */
592         add     r1, r1, #0x800                  /* let OSMR3 match after    */
593         add     r1, r1, #0x800                  /* 4096*(1/3.6864MHz)=1ms   */
594         ldr     r0, =OSMR3
595         str     r1, [r0]
596
597 reset_endless:
598
599         b       reset_endless
600
601 #ifndef CONFIG_PRELOADER
602 .section .mmudata, "a"
603         .align  14
604         .globl  mmu_table
605 mmu_table:
606         /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */
607         .set    __base, 0
608         .rept   0xa00
609         .word   (__base << 20) | 0xc12
610         .set    __base, __base + 1
611         .endr
612
613         /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */
614         .word   (0xa00 << 20) | 0x1c1e
615
616         .set    __base, 0xa01
617         .rept   0x1000 - 0xa01
618         .word   (__base << 20) | 0xc12
619         .set    __base, __base + 1
620         .endr
621 #endif