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