]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/pxa/start.S
Coding Style cleanup: remove trailing white space
[karo-tx-uboot.git] / arch / arm / cpu / pxa / start.S
1 /*
2  *  armboot - Startup Code for XScale CPU-core
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) 2001  Marius Groger <mag@sysgo.de>
9  *  Copyright (C) 2002  Alex Zupke <azu@sysgo.de>
10  *  Copyright (C) 2002  Gary Jennejohn <garyj@denx.de>
11  *  Copyright (C) 2002  Kyle Harris <kharris@nexus-tech.net>
12  *  Copyright (C) 2003  Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
13  *  Copyright (C) 2003  Kshitij <kshitij@ti.com>
14  *  Copyright (C) 2003  Richard Woodruff <r-woodruff2@ti.com>
15  *  Copyright (C) 2003  Robert Schwebel <r.schwebel@pengutronix.de>
16  *  Copyright (C) 2004  Texas Instruments <r-woodruff2@ti.com>
17  *  Copyright (C) 2010  Marek Vasut <marek.vasut@gmail.com>
18  *
19  * SPDX-License-Identifier:     GPL-2.0+
20  */
21
22 #include <asm-offsets.h>
23 #include <config.h>
24 #include <version.h>
25
26 #ifdef CONFIG_CPU_PXA25X
27 #if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800)
28 #error "Init SP address must be set to 0xfffff800 for PXA250"
29 #endif
30 #endif
31
32 .globl _start
33 _start: b       reset
34 #ifdef CONFIG_SPL_BUILD
35         ldr     pc, _hang
36         ldr     pc, _hang
37         ldr     pc, _hang
38         ldr     pc, _hang
39         ldr     pc, _hang
40         ldr     pc, _hang
41         ldr     pc, _hang
42
43 _hang:
44         .word   do_hang
45         .word   0x12345678
46         .word   0x12345678
47         .word   0x12345678
48         .word   0x12345678
49         .word   0x12345678
50         .word   0x12345678
51         .word   0x12345678      /* now 16*4=64 */
52 #else
53         ldr     pc, _undefined_instruction
54         ldr     pc, _software_interrupt
55         ldr     pc, _prefetch_abort
56         ldr     pc, _data_abort
57         ldr     pc, _not_used
58         ldr     pc, _irq
59         ldr     pc, _fiq
60
61 _undefined_instruction: .word undefined_instruction
62 _software_interrupt:    .word software_interrupt
63 _prefetch_abort:        .word prefetch_abort
64 _data_abort:            .word data_abort
65 _not_used:              .word not_used
66 _irq:                   .word irq
67 _fiq:                   .word fiq
68 _pad:                   .word 0x12345678 /* now 16*4=64 */
69 #endif  /* CONFIG_SPL_BUILD */
70 .global _end_vect
71 _end_vect:
72
73         .balignl 16,0xdeadbeef
74 /*
75  *************************************************************************
76  *
77  * Startup Code (reset vector)
78  *
79  * do important init only if we don't start from memory!
80  * setup Memory and board specific bits prior to relocation.
81  * relocate armboot to ram
82  * setup stack
83  *
84  *************************************************************************
85  */
86
87 .globl _TEXT_BASE
88 _TEXT_BASE:
89 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
90         .word   CONFIG_SPL_TEXT_BASE
91 #else
92         .word   CONFIG_SYS_TEXT_BASE
93 #endif
94
95 /*
96  * These are defined in the board-specific linker script.
97  * Subtracting _start from them lets the linker put their
98  * relative position in the executable instead of leaving
99  * them null.
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
124
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 /*
131  * the actual reset code
132  */
133
134 reset:
135         /*
136          * set the cpu to SVC32 mode
137          */
138         mrs     r0,cpsr
139         bic     r0,r0,#0x1f
140         orr     r0,r0,#0xd3
141         msr     cpsr,r0
142
143 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
144         bl  cpu_init_crit
145 #endif
146
147 #ifdef  CONFIG_CPU_PXA25X
148         bl      lock_cache_for_stack
149 #endif
150
151         bl      _main
152
153 /*------------------------------------------------------------------------------*/
154
155         .globl  c_runtime_cpu_setup
156 c_runtime_cpu_setup:
157
158 #ifdef CONFIG_CPU_PXA25X
159         /*
160          * Unlock (actually, disable) the cache now that board_init_f
161          * is done. We could do this earlier but we would need to add
162          * a new C runtime hook, whereas c_runtime_cpu_setup already
163          * exists.
164          * As this routine is just a call to cpu_init_crit, let us
165          * tail-optimize and do a simple branch here.
166          */
167         b       cpu_init_crit
168 #else
169         bx      lr
170 #endif
171
172 /*
173  *************************************************************************
174  *
175  * CPU_init_critical registers
176  *
177  * setup important registers
178  * setup memory timing
179  *
180  *************************************************************************
181  */
182 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X)
183 cpu_init_crit:
184         /*
185          * flush v4 I/D caches
186          */
187         mov     r0, #0
188         mcr     p15, 0, r0, c7, c7, 0   /* Invalidate I+D+BTB caches */
189         mcr     p15, 0, r0, c8, c7, 0   /* Invalidate Unified TLB */
190
191         /*
192          * disable MMU stuff and caches
193          */
194         mrc     p15, 0, r0, c1, c0, 0
195         bic     r0, r0, #0x00003300     @ clear bits 13:12, 9:8 (--VI --RS)
196         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
197         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
198         mcr     p15, 0, r0, c1, c0, 0
199
200         mov     pc, lr          /* back to my caller */
201 #endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */
202
203 #ifndef CONFIG_SPL_BUILD
204 /*
205  *************************************************************************
206  *
207  * Interrupt handling
208  *
209  *************************************************************************
210  */
211 @
212 @ IRQ stack frame.
213 @
214 #define S_FRAME_SIZE    72
215
216 #define S_OLD_R0        68
217 #define S_PSR           64
218 #define S_PC            60
219 #define S_LR            56
220 #define S_SP            52
221
222 #define S_IP            48
223 #define S_FP            44
224 #define S_R10           40
225 #define S_R9            36
226 #define S_R8            32
227 #define S_R7            28
228 #define S_R6            24
229 #define S_R5            20
230 #define S_R4            16
231 #define S_R3            12
232 #define S_R2            8
233 #define S_R1            4
234 #define S_R0            0
235
236 #define MODE_SVC 0x13
237 #define I_BIT    0x80
238
239 /*
240  * use bad_save_user_regs for abort/prefetch/undef/swi ...
241  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
242  */
243
244         .macro  bad_save_user_regs
245         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
246         stmia   sp, {r0 - r12}                  @ Save user registers (now in svc mode) r0-r12
247
248         ldr     r2, IRQ_STACK_START_IN          @ set base 2 words into abort stack
249         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc and cpsr (into parm regs)
250         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
251
252         add     r5, sp, #S_SP
253         mov     r1, lr
254         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
255         mov     r0, sp                          @ save current stack into r0 (param register)
256         .endm
257
258         .macro  irq_save_user_regs
259         sub     sp, sp, #S_FRAME_SIZE
260         stmia   sp, {r0 - r12}                  @ Calling r0-r12
261         add     r8, sp, #S_PC                   @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
262         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
263         str     lr, [r8, #0]                    @ Save calling PC
264         mrs     r6, spsr
265         str     r6, [r8, #4]                    @ Save CPSR
266         str     r0, [r8, #8]                    @ Save OLD_R0
267         mov     r0, sp
268         .endm
269
270         .macro  irq_restore_user_regs
271         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
272         mov     r0, r0
273         ldr     lr, [sp, #S_PC]                 @ Get PC
274         add     sp, sp, #S_FRAME_SIZE
275         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
276         .endm
277
278         .macro get_bad_stack
279         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack (enter in banked mode)
280
281         str     lr, [r13]                       @ save caller lr in position 0 of saved stack
282         mrs     lr, spsr                        @ get the spsr
283         str     lr, [r13, #4]                   @ save spsr in position 1 of saved stack
284
285         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
286         @ msr   spsr_c, r13
287         msr     spsr, r13                       @ switch modes, make sure moves will execute
288         mov     lr, pc                          @ capture return pc
289         movs    pc, lr                          @ jump to next instruction & switch modes.
290         .endm
291
292         .macro get_bad_stack_swi
293         sub     r13, r13, #4                    @ space on current stack for scratch reg.
294         str     r0, [r13]                       @ save R0's value.
295         ldr     r0, IRQ_STACK_START_IN          @ get data regions start
296         str     lr, [r0]                        @ save caller lr in position 0 of saved stack
297         mrs     lr, spsr                        @ get the spsr
298         str     lr, [r0, #4]                    @ save spsr in position 1 of saved stack
299         ldr     lr, [r0]                        @ restore lr
300         ldr     r0, [r13]                       @ restore r0
301         add     r13, r13, #4                    @ pop stack entry
302         .endm
303
304         .macro get_irq_stack                    @ setup IRQ stack
305         ldr     sp, IRQ_STACK_START
306         .endm
307
308         .macro get_fiq_stack                    @ setup FIQ stack
309         ldr     sp, FIQ_STACK_START
310         .endm
311 #endif  /* CONFIG_SPL_BUILD */
312
313 /*
314  * exception handlers
315  */
316 #ifdef CONFIG_SPL_BUILD
317         .align  5
318 do_hang:
319         ldr     sp, _TEXT_BASE                  /* use 32 words about stack */
320         bl      hang                            /* hang and never return */
321 #else   /* !CONFIG_SPL_BUILD */
322         .align  5
323 undefined_instruction:
324         get_bad_stack
325         bad_save_user_regs
326         bl      do_undefined_instruction
327
328         .align  5
329 software_interrupt:
330         get_bad_stack_swi
331         bad_save_user_regs
332         bl      do_software_interrupt
333
334         .align  5
335 prefetch_abort:
336         get_bad_stack
337         bad_save_user_regs
338         bl      do_prefetch_abort
339
340         .align  5
341 data_abort:
342         get_bad_stack
343         bad_save_user_regs
344         bl      do_data_abort
345
346         .align  5
347 not_used:
348         get_bad_stack
349         bad_save_user_regs
350         bl      do_not_used
351
352 #ifdef CONFIG_USE_IRQ
353
354         .align  5
355 irq:
356         get_irq_stack
357         irq_save_user_regs
358         bl      do_irq
359         irq_restore_user_regs
360
361         .align  5
362 fiq:
363         get_fiq_stack
364         /* someone ought to write a more effiction fiq_save_user_regs */
365         irq_save_user_regs
366         bl      do_fiq
367         irq_restore_user_regs
368
369 #else
370
371         .align  5
372 irq:
373         get_bad_stack
374         bad_save_user_regs
375         bl      do_irq
376
377         .align  5
378 fiq:
379         get_bad_stack
380         bad_save_user_regs
381         bl      do_fiq
382
383 #endif
384         .align 5
385 #endif  /* CONFIG_SPL_BUILD */
386
387
388 /*
389  * Enable MMU to use DCache as DRAM.
390  *
391  * This is useful on PXA25x and PXA26x in early bootstages, where there is no
392  * other possible memory available to hold stack.
393  */
394 #ifdef CONFIG_CPU_PXA25X
395 .macro CPWAIT reg
396         mrc     p15, 0, \reg, c2, c0, 0
397         mov     \reg, \reg
398         sub     pc, pc, #4
399 .endm
400 lock_cache_for_stack:
401         /* Domain access -- enable for all CPs */
402         ldr     r0, =0x0000ffff
403         mcr     p15, 0, r0, c3, c0, 0
404
405         /* Point TTBR to MMU table */
406         ldr     r0, =mmutable
407         mcr     p15, 0, r0, c2, c0, 0
408
409         /* Kick in MMU, ICache, DCache, BTB */
410         mrc     p15, 0, r0, c1, c0, 0
411         bic     r0, #0x1b00
412         bic     r0, #0x0087
413         orr     r0, #0x1800
414         orr     r0, #0x0005
415         mcr     p15, 0, r0, c1, c0, 0
416         CPWAIT  r0
417
418         /* Unlock Icache, Dcache */
419         mcr     p15, 0, r0, c9, c1, 1
420         mcr     p15, 0, r0, c9, c2, 1
421
422         /* Flush Icache, Dcache, BTB */
423         mcr     p15, 0, r0, c7, c7, 0
424
425         /* Unlock I-TLB, D-TLB */
426         mcr     p15, 0, r0, c10, c4, 1
427         mcr     p15, 0, r0, c10, c8, 1
428
429         /* Flush TLB */
430         mcr     p15, 0, r0, c8, c7, 0
431
432         /* Allocate 4096 bytes of Dcache as RAM */
433
434         /* Drain pending loads and stores */
435         mcr     p15, 0, r0, c7, c10, 4
436
437         mov     r4, #0x00
438         mov     r5, #0x00
439         mov     r2, #0x01
440         mcr     p15, 0, r0, c9, c2, 0
441         CPWAIT  r0
442
443         /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
444         mov     r0, #128
445         ldr     r1, =0xfffff000
446
447 alloc:
448         mcr     p15, 0, r1, c7, c2, 5
449         /* Drain pending loads and stores */
450         mcr     p15, 0, r0, c7, c10, 4
451         strd    r4, [r1], #8
452         strd    r4, [r1], #8
453         strd    r4, [r1], #8
454         strd    r4, [r1], #8
455         subs    r0, #0x01
456         bne     alloc
457         /* Drain pending loads and stores */
458         mcr     p15, 0, r0, c7, c10, 4
459         mov     r2, #0x00
460         mcr     p15, 0, r2, c9, c2, 0
461         CPWAIT  r0
462
463         mov     pc, lr
464
465 .section .mmutable, "a"
466 mmutable:
467         .align  14
468         /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */
469         .set    __base, 0
470         .rept   0xfff
471         .word   (__base << 20) | 0xc12
472         .set    __base, __base + 1
473         .endr
474
475         /* 0xfff00000 : 1:1, cached mapping */
476         .word   (0xfff << 20) | 0x1c1e
477 #endif  /* CONFIG_CPU_PXA25X */