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