]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/pxa/start.S
Merge commit '7b2fac7654f7420c2787f74ec3b1540fa3b343e9'
[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
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_SPL_BUILD
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_SPL_BUILD */
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 __bss_end__ - _start
108
109 .globl _end_ofs
110 _end_ofs:
111         .word _end - _start
112
113 #ifdef CONFIG_USE_IRQ
114 /* IRQ stack memory (calculated at run-time) */
115 .globl IRQ_STACK_START
116 IRQ_STACK_START:
117         .word   0x0badc0de
118
119 /* IRQ stack memory (calculated at run-time) */
120 .globl FIQ_STACK_START
121 FIQ_STACK_START:
122         .word 0x0badc0de
123 #endif /* CONFIG_USE_IRQ */
124
125 #ifndef CONFIG_SPL_BUILD
126 /* IRQ stack memory (calculated at run-time) + 8 bytes */
127 .globl IRQ_STACK_START_IN
128 IRQ_STACK_START_IN:
129         .word   0x0badc0de
130
131 /*
132  * the actual reset code
133  */
134
135 reset:
136         /*
137          * set the cpu to SVC32 mode
138          */
139         mrs     r0,cpsr
140         bic     r0,r0,#0x1f
141         orr     r0,r0,#0xd3
142         msr     cpsr,r0
143
144         /*
145          * Enable MMU to use DCache as DRAM
146          */
147         /* Domain access -- enable for all CPs */
148         ldr     r0, =0x0000ffff
149         mcr     p15, 0, r0, c3, c0, 0
150
151         /* Point TTBR to MMU table */
152         ldr     r0, =mmu_table
153         adr     r2, _start
154         orr     r0, r2
155         mcr     p15, 0, r0, c2, c0, 0
156
157 /* !!! Hereby, check if the code is running from SRAM !!! */
158 /* If the code is running from SRAM, alias SRAM to 0x0 to simulate NOR. The code
159  * is linked to 0x0 too, so this makes things easier. */
160         cmp     r2, #0x5c000000
161
162         ldreq   r1, [r0]
163         orreq   r1, r2
164         streq   r1, [r0]
165
166         /* Kick in MMU, ICache, DCache, BTB */
167         mrc     p15, 0, r0, c1, c0, 0
168         bic     r0, #0x1b00
169         bic     r0, #0x0087
170         orr     r0, #0x1800
171         orr     r0, #0x0005
172         mcr     p15, 0, r0, c1, c0, 0
173         CPWAIT  r0
174
175         /* Unlock Icache, Dcache */
176         mcr     p15, 0, r0, c9, c1, 1
177         mcr     p15, 0, r0, c9, c2, 1
178
179         /* Flush Icache, Dcache, BTB */
180         mcr     p15, 0, r0, c7, c7, 0
181
182         /* Unlock I-TLB, D-TLB */
183         mcr     p15, 0, r0, c10, c4, 1
184         mcr     p15, 0, r0, c10, c8, 1
185
186         /* Flush TLB */
187         mcr     p15, 0, r0, c8, c7, 0
188         /* Allocate 4096 bytes of Dcache as RAM */
189
190         /* Drain pending loads and stores */
191         mcr     p15, 0, r0, c7, c10, 4
192
193         mov     r4, #0x00
194         mov     r5, #0x00
195         mov     r2, #0x01
196         mcr     p15, 0, r0, c9, c2, 0
197         CPWAIT  r0
198
199         /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
200         mov     r0, #128
201         mov     r1, #0xa0000000
202 alloc:
203         mcr     p15, 0, r1, c7, c2, 5
204         /* Drain pending loads and stores */
205         mcr     p15, 0, r0, c7, c10, 4
206         strd    r4, [r1], #8
207         strd    r4, [r1], #8
208         strd    r4, [r1], #8
209         strd    r4, [r1], #8
210         subs    r0, #0x01
211         bne     alloc
212         /* Drain pending loads and stores */
213         mcr     p15, 0, r0, c7, c10, 4
214         mov     r2, #0x00
215         mcr     p15, 0, r2, c9, c2, 0
216         CPWAIT  r0
217
218         /* Jump to 0x0 ( + offset) if running from SRAM */
219         adr     r0, zerojmp
220         bic     r0, #0x5c000000
221         mov     pc, r0
222 zerojmp:
223
224 /* Set stackpointer in internal RAM to call board_init_f */
225 call_board_init_f:
226         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
227         bic     sp, sp, #7 /* 8-byte alignment for ABI compliance */
228         ldr     r0,=0x00000000
229         bl      board_init_f
230
231 /*------------------------------------------------------------------------------*/
232
233 /*
234  * void relocate_code (addr_sp, gd, addr_moni)
235  *
236  * This "function" does not return, instead it continues in RAM
237  * after relocating the monitor code.
238  *
239  */
240         .globl  relocate_code
241 relocate_code:
242         mov     r4, r0  /* save addr_sp */
243         mov     r5, r1  /* save addr of gd */
244         mov     r6, r2  /* save addr of destination */
245
246         /* Set up the stack                                                 */
247 stack_setup:
248         mov     sp, r4
249
250         adr     r0, _start
251         cmp     r0, r6
252         beq     clear_bss               /* skip relocation */
253         mov     r1, r6                  /* r1 <- scratch for copy_loop */
254         ldr     r3, _bss_start_ofs
255         add     r2, r0, r3              /* r2 <- source end address         */
256
257         stmfd sp!, {r0-r12}
258 copy_loop:
259         ldmia   r0!, {r3-r5, r7-r11}    /* copy from source address [r0]    */
260         stmia   r1!, {r3-r5, r7-r11}    /* copy to   target address [r1]    */
261         cmp     r0, r2                  /* until source end address [r2]    */
262         blo     copy_loop
263         ldmfd sp!, {r0-r12}
264
265 #ifndef CONFIG_SPL_BUILD
266         /*
267          * fix .rel.dyn relocations
268          */
269         ldr     r0, _TEXT_BASE          /* r0 <- Text base */
270         sub     r9, r6, r0              /* r9 <- relocation offset */
271         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
272         add     r10, r10, r0            /* r10 <- sym table in FLASH */
273         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
274         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
275         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
276         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
277 fixloop:
278         ldr     r0, [r2]        /* r0 <- location to fix up, IN FLASH! */
279         add     r0, r9          /* r0 <- location to fix up in RAM */
280         ldr     r1, [r2, #4]
281         and     r7, r1, #0xff
282         cmp     r7, #23         /* relative fixup? */
283         beq     fixrel
284         cmp     r7, #2          /* absolute fixup? */
285         beq     fixabs
286         /* ignore unknown type of fixup */
287         b       fixnext
288 fixabs:
289         /* absolute fix: set location to (offset) symbol value */
290         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
291         add     r1, r10, r1             /* r1 <- address of symbol in table */
292         ldr     r1, [r1, #4]            /* r1 <- symbol value */
293         add     r1, r1, r9              /* r1 <- relocated sym addr */
294         b       fixnext
295 fixrel:
296         /* relative fix: increase location by offset */
297         ldr     r1, [r0]
298         add     r1, r1, r9
299 fixnext:
300         str     r1, [r0]
301         add     r2, r2, #8      /* each rel.dyn entry is 8 bytes */
302         cmp     r2, r3
303         blo     fixloop
304 #endif  /* #ifndef CONFIG_SPL_BUILD */
305
306 clear_bss:
307 #ifndef CONFIG_SPL_BUILD
308         ldr     r0, _bss_start_ofs
309         ldr     r1, _bss_end_ofs
310         mov     r4, r6                  /* 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  /* #ifndef CONFIG_SPL_BUILD */
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         add     lr, lr, r9
336         /* setup parameters for board_init_r */
337         mov     r0, r5          /* gd_t */
338         mov     r1, r6          /* dest_addr */
339         /* jump to it ... */
340         mov     pc, lr
341
342 _board_init_r_ofs:
343         .word board_init_r - _start
344 #endif  /* CONFIG_ONENAND_IPL */
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 /* CONFIG_SPL_BUILD */
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 /* CONFIG_SPL_BUILD */
379
380 #ifndef CONFIG_SPL_BUILD
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         ldr     r2, IRQ_STACK_START_IN
421         ldmia   r2, {r2 - r4}                   /* get pc, cpsr, old_r0     */
422         add     r0, sp, #S_FRAME_SIZE           /* restore sp_SVC           */
423
424         add     r5, sp, #S_SP
425         mov     r1, lr
426         stmia   r5, {r0 - r4}                   /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
427         mov     r0, sp
428         .endm
429
430
431         /* use irq_save_user_regs / irq_restore_user_regs for                */
432         /* IRQ/FIQ handling                                                  */
433
434         .macro  irq_save_user_regs
435         sub     sp, sp, #S_FRAME_SIZE
436         stmia   sp, {r0 - r12}                  /* Calling r0-r12            */
437         add     r8, sp, #S_PC
438         stmdb   r8, {sp, lr}^                   /* Calling SP, LR            */
439         str     lr, [r8, #0]                    /* Save calling PC           */
440         mrs     r6, spsr
441         str     r6, [r8, #4]                    /* Save CPSR                 */
442         str     r0, [r8, #8]                    /* Save OLD_R0               */
443         mov     r0, sp
444         .endm
445
446         .macro  irq_restore_user_regs
447         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
448         mov     r0, r0
449         ldr     lr, [sp, #S_PC]                 @ Get PC
450         add     sp, sp, #S_FRAME_SIZE
451         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
452         .endm
453
454         .macro get_bad_stack
455         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
456
457         str     lr, [r13]                       @ save caller lr / spsr
458         mrs     lr, spsr
459         str     lr, [r13, #4]
460
461         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
462         msr     spsr_c, r13
463         mov     lr, pc
464         movs    pc, lr
465         .endm
466
467         .macro get_irq_stack                    @ setup IRQ stack
468         ldr     sp, IRQ_STACK_START
469         .endm
470
471         .macro get_fiq_stack                    @ setup FIQ stack
472         ldr     sp, FIQ_STACK_START
473         .endm
474 #endif  /* CONFIG_SPL_BUILD
475
476
477 /****************************************************************************/
478 /*                                                                          */
479 /* exception handlers                                                       */
480 /*                                                                          */
481 /****************************************************************************/
482
483 #ifdef CONFIG_SPL_BUILD
484         .align  5
485 do_hang:
486         ldr     sp, _TEXT_BASE                  /* use 32 words abort stack */
487         bl      hang                            /* hang and never return */
488 #else
489         .align  5
490 undefined_instruction:
491         get_bad_stack
492         bad_save_user_regs
493         bl      do_undefined_instruction
494
495         .align  5
496 software_interrupt:
497         get_bad_stack
498         bad_save_user_regs
499         bl      do_software_interrupt
500
501         .align  5
502 prefetch_abort:
503         get_bad_stack
504         bad_save_user_regs
505         bl      do_prefetch_abort
506
507         .align  5
508 data_abort:
509         get_bad_stack
510         bad_save_user_regs
511         bl      do_data_abort
512
513         .align  5
514 not_used:
515         get_bad_stack
516         bad_save_user_regs
517         bl      do_not_used
518
519 #ifdef CONFIG_USE_IRQ
520
521         .align  5
522 irq:
523         get_irq_stack
524         irq_save_user_regs
525         bl      do_irq
526         irq_restore_user_regs
527
528         .align  5
529 fiq:
530         get_fiq_stack
531         irq_save_user_regs              /* someone ought to write a more    */
532         bl      do_fiq                  /* effiction fiq_save_user_regs     */
533         irq_restore_user_regs
534
535 #else /* !CONFIG_USE_IRQ */
536
537         .align  5
538 irq:
539         get_bad_stack
540         bad_save_user_regs
541         bl      do_irq
542
543         .align  5
544 fiq:
545         get_bad_stack
546         bad_save_user_regs
547         bl      do_fiq
548 #endif  /* CONFIG_SPL_BUILD */
549 #endif /* CONFIG_USE_IRQ */
550
551 /****************************************************************************/
552 /*                                                                          */
553 /* Reset function: the PXA250 doesn't have a reset function, so we have to  */
554 /* perform a watchdog timeout for a soft reset.                             */
555 /*                                                                          */
556 /****************************************************************************/
557 /* Operating System Timer */
558 .align  5
559 .globl reset_cpu
560
561         /* FIXME: this code is PXA250 specific. How is this handled on      */
562         /*        other XScale processors?                                  */
563
564 reset_cpu:
565
566         /* We set OWE:WME (watchdog enable) and wait until timeout happens  */
567
568         ldr     r0, =OWER
569         ldr     r1, [r0]
570         orr     r1, r1, #0x0001                 /* bit0: WME                */
571         str     r1, [r0]
572
573         /* OS timer does only wrap every 1165 seconds, so we have to set    */
574         /* the match register as well.                                      */
575
576         ldr     r0, =OSCR
577         ldr     r1, [r0]                        /* read OS timer            */
578         add     r1, r1, #0x800                  /* let OSMR3 match after    */
579         add     r1, r1, #0x800                  /* 4096*(1/3.6864MHz)=1ms   */
580         ldr     r0, =OSMR3
581         str     r1, [r0]
582
583 reset_endless:
584
585         b       reset_endless
586
587 #ifndef CONFIG_SPL_BUILD
588 .section .mmudata, "a"
589         .align  14
590         .globl  mmu_table
591 mmu_table:
592         /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */
593         .set    __base, 0
594         .rept   0xa00
595         .word   (__base << 20) | 0xc12
596         .set    __base, __base + 1
597         .endr
598
599         /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */
600         .word   (0xa00 << 20) | 0x1c1e
601
602         .set    __base, 0xa01
603         .rept   0x1000 - 0xa01
604         .word   (__base << 20) | 0xc12
605         .set    __base, __base + 1
606         .endr
607 #endif  /* CONFIG_SPL_BUILD */