]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/pxa/start.S
PXA: Fix reloc, Push lowlevel init into C code
[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  *
12  * See file CREDITS for list of people who contributed to this
13  * project.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  */
30
31 #include <config.h>
32 #include <version.h>
33 #include <asm/arch/pxa-regs.h>
34 #include <asm/arch/macro.h>
35
36 /* takes care the CP15 update has taken place */
37 .macro CPWAIT reg
38 mrc  p15,0,\reg,c2,c0,0
39 mov  \reg,\reg
40 sub  pc,pc,#4
41 .endm
42
43 .globl _start
44 _start: b       reset
45 #ifdef CONFIG_PRELOADER
46         ldr     pc, _hang
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
54 _hang:
55         .word   do_hang
56         .word   0x12345678
57         .word   0x12345678
58         .word   0x12345678
59         .word   0x12345678
60         .word   0x12345678
61         .word   0x12345678
62         .word   0x12345678      /* now 16*4=64 */
63 #else
64         ldr     pc, _undefined_instruction
65         ldr     pc, _software_interrupt
66         ldr     pc, _prefetch_abort
67         ldr     pc, _data_abort
68         ldr     pc, _not_used
69         ldr     pc, _irq
70         ldr     pc, _fiq
71
72 _undefined_instruction: .word undefined_instruction
73 _software_interrupt:    .word software_interrupt
74 _prefetch_abort:        .word prefetch_abort
75 _data_abort:            .word data_abort
76 _not_used:              .word not_used
77 _irq:                   .word irq
78 _fiq:                   .word fiq
79 #endif  /* CONFIG_PRELOADER */
80
81         .balignl 16,0xdeadbeef
82
83
84 /*
85  * Startup Code (reset vector)
86  *
87  * do important init only if we don't start from RAM!
88  * - relocate armboot to RAM
89  * - setup stack
90  * - jump to second stage
91  */
92
93 .globl _TEXT_BASE
94 _TEXT_BASE:
95         .word   CONFIG_SYS_TEXT_BASE
96
97 .globl _armboot_start
98 _armboot_start:
99         .word _start
100
101 /*
102  * These are defined in the board-specific linker script.
103  */
104 .globl _bss_start
105 _bss_start:
106         .word __bss_start
107
108 .globl _bss_end
109 _bss_end:
110         .word _end
111
112 #ifdef CONFIG_USE_IRQ
113 /* IRQ stack memory (calculated at run-time) */
114 .globl IRQ_STACK_START
115 IRQ_STACK_START:
116         .word   0x0badc0de
117
118 /* IRQ stack memory (calculated at run-time) */
119 .globl FIQ_STACK_START
120 FIQ_STACK_START:
121         .word 0x0badc0de
122 #endif /* CONFIG_USE_IRQ */
123
124 #ifndef CONFIG_PRELOADER
125 /* IRQ stack memory (calculated at run-time) + 8 bytes */
126 .globl IRQ_STACK_START_IN
127 IRQ_STACK_START_IN:
128         .word   0x0badc0de
129
130 .globl _datarel_start
131 _datarel_start:
132         .word __datarel_start
133
134 .globl _datarelrolocal_start
135 _datarelrolocal_start:
136         .word __datarelrolocal_start
137
138 .globl _datarellocal_start
139 _datarellocal_start:
140         .word __datarellocal_start
141
142 .globl _datarelro_start
143 _datarelro_start:
144         .word __datarelro_start
145
146 .globl _got_start
147 _got_start:
148         .word __got_start
149
150 .globl _got_end
151 _got_end:
152         .word __got_end
153
154 /*
155  * the actual reset code
156  */
157
158 reset:
159         /*
160          * set the cpu to SVC32 mode
161          */
162         mrs     r0,cpsr
163         bic     r0,r0,#0x1f
164         orr     r0,r0,#0xd3
165         msr     cpsr,r0
166
167         /*
168          * Enable MMU to use DCache as DRAM
169          */
170         /* Domain access -- enable for all CPs */
171         ldr     r0, =0x0000ffff
172         mcr     p15, 0, r0, c3, c0, 0
173
174         /* Point TTBR to MMU table */
175         ldr     r0, =mmu_table
176         adr     r2, _start
177         orr     r0, r2
178         mcr     p15, 0, r0, c2, c0, 0
179
180 /* !!! Hereby, check if the code is running from SRAM !!! */
181 /* If the code is running from SRAM, alias SRAM to 0x0 to simulate NOR. The code
182  * is linked to 0x0 too, so this makes things easier. */
183         cmp     r2, #0x5c000000
184
185         ldreq   r1, [r0]
186         orreq   r1, r2
187         streq   r1, [r0]
188
189         /* Kick in MMU, ICache, DCache, BTB */
190         mrc     p15, 0, r0, c1, c0, 0
191         bic     r0, #0x1b00
192         bic     r0, #0x0087
193         orr     r0, #0x1800
194         orr     r0, #0x0005
195         mcr     p15, 0, r0, c1, c0, 0
196         CPWAIT  r0
197
198         /* Unlock Icache, Dcache */
199         mcr     p15, 0, r0, c9, c1, 1
200         mcr     p15, 0, r0, c9, c2, 1
201
202         /* Flush Icache, Dcache, BTB */
203         mcr     p15, 0, r0, c7, c7, 0
204
205         /* Unlock I-TLB, D-TLB */
206         mcr     p15, 0, r0, c10, c4, 1
207         mcr     p15, 0, r0, c10, c8, 1
208
209         /* Flush TLB */
210         mcr     p15, 0, r0, c8, c7, 0
211         /* Allocate 4096 bytes of Dcache as RAM */
212
213         /* Drain pending loads and stores */
214         mcr     p15, 0, r0, c7, c10, 4
215
216         mov     r4, #0x00
217         mov     r5, #0x00
218         mov     r2, #0x01
219         mcr     p15, 0, r0, c9, c2, 0
220         CPWAIT  r0
221
222         /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
223         mov     r0, #128
224         mov     r1, #0xa0000000
225 alloc:
226         mcr     p15, 0, r1, c7, c2, 5
227         /* Drain pending loads and stores */
228         mcr     p15, 0, r0, c7, c10, 4
229         strd    r4, [r1], #8
230         strd    r4, [r1], #8
231         strd    r4, [r1], #8
232         strd    r4, [r1], #8
233         subs    r0, #0x01
234         bne     alloc
235         /* Drain pending loads and stores */
236         mcr     p15, 0, r0, c7, c10, 4
237         mov     r2, #0x00
238         mcr     p15, 0, r2, c9, c2, 0
239         CPWAIT  r0
240
241         /* Jump to 0x0 ( + offset) if running from SRAM */
242         adr     r0, zerojmp
243         bic     r0, #0x5c000000
244         mov     pc, r0
245 zerojmp:
246
247 /* Set stackpointer in internal RAM to call board_init_f */
248 call_board_init_f:
249         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
250         ldr     r0,=0x00000000
251         bl      board_init_f
252
253 /*------------------------------------------------------------------------------*/
254
255 /*
256  * void relocate_code (addr_sp, gd, addr_moni)
257  *
258  * This "function" does not return, instead it continues in RAM
259  * after relocating the monitor code.
260  *
261  */
262         .globl  relocate_code
263 relocate_code:
264         mov     r4, r0  /* save addr_sp */
265         mov     r5, r1  /* save addr of gd */
266         mov     r6, r2  /* save addr of destination */
267         mov     r7, r2  /* save addr of destination */
268
269         /* Set up the stack                                                 */
270 stack_setup:
271         mov     sp, r4
272
273         adr     r0, _start
274         ldr     r2, _TEXT_BASE
275         ldr     r3, _bss_start
276         sub     r2, r3, r2              /* r2 <- size of armboot            */
277         add     r2, r0, r2              /* r2 <- source end address         */
278         cmp     r0, r6
279         beq     clear_bss
280
281 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
282         stmfd sp!, {r0-r12}
283 copy_loop:
284         ldmia   r0!, {r3-r5, r7-r11}    /* copy from source address [r0]    */
285         stmia   r6!, {r3-r5, r7-r11}    /* copy to   target address [r1]    */
286         cmp     r0, r2                  /* until source end address [r2]    */
287         blo     copy_loop
288         ldmfd sp!, {r0-r12}
289
290 #ifndef CONFIG_PRELOADER
291         /* fix got entries */
292         ldr     r1, _TEXT_BASE          /* Text base */
293         mov     r0, r7                  /* reloc addr */
294         ldr     r2, _got_start          /* addr in Flash */
295         ldr     r3, _got_end            /* addr in Flash */
296         sub     r3, r3, r1
297         add     r3, r3, r0
298         sub     r2, r2, r1
299         add     r2, r2, r0
300
301 fixloop:
302         ldr     r4, [r2]
303         sub     r4, r4, r1
304         add     r4, r4, r0
305         str     r4, [r2]
306         add     r2, r2, #4
307         cmp     r2, r3
308         bne     fixloop
309 #endif
310 #endif  /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
311
312 clear_bss:
313 #ifndef CONFIG_PRELOADER
314         ldr     r0, _bss_start
315         ldr     r1, _bss_end
316         ldr     r3, _TEXT_BASE          /* Text base */
317         mov     r4, r7                  /* reloc addr */
318         sub     r0, r0, r3
319         add     r0, r0, r4
320         sub     r1, r1, r3
321         add     r1, r1, r4
322         mov     r2, #0x00000000         /* clear                            */
323
324 clbss_l:str     r2, [r0]                /* clear loop...                    */
325         add     r0, r0, #4
326         cmp     r0, r1
327         bne     clbss_l
328 #endif
329
330 /*
331  * We are done. Do not return, instead branch to second part of board
332  * initialization, now running from RAM.
333  */
334 #ifdef CONFIG_ONENAND_IPL
335         ldr     pc, _start_oneboot
336
337 _start_oneboot: .word start_oneboot
338 #else
339         ldr     r0, _TEXT_BASE
340         ldr     r2, _board_init_r
341         sub     r2, r2, r0
342         add     r2, r2, r7      /* position from board_init_r in RAM */
343         /* setup parameters for board_init_r */
344         mov     r0, r5          /* gd_t */
345         mov     r1, r7          /* dest_addr */
346         /* jump to it ... */
347         mov     lr, r2
348         mov     pc, lr
349
350 _board_init_r: .word board_init_r
351 #endif
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, #(CONFIG_SYS_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, #(CONFIG_SYS_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 OSTIMER_BASE:   .word   0x40a00000
571 #define OSMR3   0x0C
572 #define OSCR    0x10
573 #define OWER    0x18
574 #define OIER    0x1C
575
576         .align  5
577 .globl reset_cpu
578
579         /* FIXME: this code is PXA250 specific. How is this handled on      */
580         /*        other XScale processors?                                  */
581
582 reset_cpu:
583
584         /* We set OWE:WME (watchdog enable) and wait until timeout happens  */
585
586         ldr     r0, OSTIMER_BASE
587         ldr     r1, [r0, #OWER]
588         orr     r1, r1, #0x0001                 /* bit0: WME                */
589         str     r1, [r0, #OWER]
590
591         /* OS timer does only wrap every 1165 seconds, so we have to set    */
592         /* the match register as well.                                      */
593
594         ldr     r1, [r0, #OSCR]                 /* read OS timer            */
595         add     r1, r1, #0x800                  /* let OSMR3 match after    */
596         add     r1, r1, #0x800                  /* 4096*(1/3.6864MHz)=1ms   */
597         str     r1, [r0, #OSMR3]
598
599 reset_endless:
600
601         b       reset_endless
602
603 #ifndef CONFIG_PRELOADER
604 .section .mmudata, "a"
605         .align  14
606         .globl  mmu_table
607 mmu_table:
608         /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */
609         .set    __base, 0
610         .rept   0xa00
611         .word   (__base << 20) | 0xc12
612         .set    __base, __base + 1
613         .endr
614
615         /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */
616         .word   (0xa00 << 20) | 0x1c1e
617
618         .set    __base, 0xa01
619         .rept   0x1000 - 0xa01
620         .word   (__base << 20) | 0xc12
621         .set    __base, __base + 1
622         .endr
623 #endif