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