]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/arm/cpu/pxa/start.S
Merge branch 'buildman' of git://git.denx.de/u-boot-x86
[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
abc20aba 26#ifdef CONFIG_CPU_PXA25X
7f4cfcf4
MV
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
c609719b 32.globl _start
384ae025 33_start: b reset
401bb30b 34#ifdef CONFIG_SPL_BUILD
5ab877b6
MV
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
c609719b
WD
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
384ae025 61_undefined_instruction: .word undefined_instruction
c609719b
WD
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
20f7b1b7 68_pad: .word 0x12345678 /* now 16*4=64 */
401bb30b 69#endif /* CONFIG_SPL_BUILD */
20f7b1b7
MV
70.global _end_vect
71_end_vect:
c609719b
WD
72
73 .balignl 16,0xdeadbeef
c609719b 74/*
20f7b1b7
MV
75 *************************************************************************
76 *
c609719b
WD
77 * Startup Code (reset vector)
78 *
20f7b1b7
MV
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 *************************************************************************
c609719b
WD
85 */
86
5347f68c 87.globl _TEXT_BASE
c609719b 88_TEXT_BASE:
508611bc 89#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
20f7b1b7
MV
90 .word CONFIG_SPL_TEXT_BASE
91#else
14d0a02a 92 .word CONFIG_SYS_TEXT_BASE
20f7b1b7 93#endif
c609719b 94
c609719b 95/*
f6e20fc6 96 * These are defined in the board-specific linker script.
20f7b1b7
MV
97 * Subtracting _start from them lets the linker put their
98 * relative position in the executable instead of leaving
99 * them null.
47cd00fa 100 */
6e96cf9a
MV
101.globl _bss_start_ofs
102_bss_start_ofs:
103 .word __bss_start - _start
47cd00fa 104
6e96cf9a
MV
105.globl _bss_end_ofs
106_bss_end_ofs:
3929fb0a 107 .word __bss_end - _start
47cd00fa 108
f326cbba
PYC
109.globl _end_ofs
110_end_ofs:
111 .word _end - _start
112
c609719b
WD
113#ifdef CONFIG_USE_IRQ
114/* IRQ stack memory (calculated at run-time) */
115.globl IRQ_STACK_START
116IRQ_STACK_START:
117 .word 0x0badc0de
118
119/* IRQ stack memory (calculated at run-time) */
120.globl FIQ_STACK_START
121FIQ_STACK_START:
122 .word 0x0badc0de
20f7b1b7 123#endif
c609719b 124
5347f68c
HS
125/* IRQ stack memory (calculated at run-time) + 8 bytes */
126.globl IRQ_STACK_START_IN
127IRQ_STACK_START_IN:
128 .word 0x0badc0de
129
5347f68c
HS
130/*
131 * the actual reset code
132 */
133
134reset:
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
20f7b1b7
MV
143#ifndef CONFIG_SKIP_LOWLEVEL_INIT
144 bl cpu_init_crit
145#endif
5347f68c 146
abc20aba 147#ifdef CONFIG_CPU_PXA25X
7f4cfcf4
MV
148 bl lock_cache_for_stack
149#endif
150
e05e5de7 151 bl _main
5347f68c
HS
152
153/*------------------------------------------------------------------------------*/
5347f68c 154
3da0e575
AA
155 .globl c_runtime_cpu_setup
156c_runtime_cpu_setup:
5347f68c 157
3da0e575 158#ifdef CONFIG_CPU_PXA25X
6e96cf9a 159 /*
3da0e575
AA
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.
6e96cf9a 166 */
3da0e575
AA
167 b cpu_init_crit
168#else
e05e5de7 169 bx lr
2cad92fd 170#endif
e05e5de7 171
20f7b1b7
MV
172/*
173 *************************************************************************
174 *
175 * CPU_init_critical registers
176 *
177 * setup important registers
178 * setup memory timing
179 *
180 *************************************************************************
181 */
abc20aba 182#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X)
20f7b1b7
MV
183cpu_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 */
2cad92fd 190
20f7b1b7
MV
191 /*
192 * disable MMU stuff and caches
193 */
194 mrc p15, 0, r0, c1, c0, 0
097d86d0 195 bic r0, r0, #0x00003300 @ clear bits 13:12, 9:8 (--VI --RS)
20f7b1b7
MV
196 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
197 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
20f7b1b7 198 mcr p15, 0, r0, c1, c0, 0
47cd00fa 199
20f7b1b7 200 mov pc, lr /* back to my caller */
abc20aba 201#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */
c609719b 202
401bb30b 203#ifndef CONFIG_SPL_BUILD
20f7b1b7
MV
204/*
205 *************************************************************************
206 *
207 * Interrupt handling
208 *
209 *************************************************************************
210 */
211@
212@ IRQ stack frame.
213@
c609719b
WD
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
20f7b1b7 237#define I_BIT 0x80
c609719b 238
20f7b1b7
MV
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 */
c609719b
WD
243
244 .macro bad_save_user_regs
20f7b1b7
MV
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
c609719b 247
20f7b1b7
MV
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
c609719b
WD
251
252 add r5, sp, #S_SP
253 mov r1, lr
20f7b1b7
MV
254 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
255 mov r0, sp @ save current stack into r0 (param register)
c609719b
WD
256 .endm
257
c609719b
WD
258 .macro irq_save_user_regs
259 sub sp, sp, #S_FRAME_SIZE
20f7b1b7
MV
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
384ae025 264 mrs r6, spsr
20f7b1b7
MV
265 str r6, [r8, #4] @ Save CPSR
266 str r0, [r8, #8] @ Save OLD_R0
c609719b
WD
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
20f7b1b7 279 ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode)
c609719b 280
20f7b1b7
MV
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
c609719b
WD
284
285 mov r13, #MODE_SVC @ prepare SVC-Mode
20f7b1b7
MV
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
4411b2ae 297 mrs lr, spsr @ get the spsr
20f7b1b7 298 str lr, [r0, #4] @ save spsr in position 1 of saved stack
4411b2ae 299 ldr lr, [r0] @ restore lr
20f7b1b7
MV
300 ldr r0, [r13] @ restore r0
301 add r13, r13, #4 @ pop stack entry
c609719b
WD
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
20f7b1b7 311#endif /* CONFIG_SPL_BUILD */
c609719b 312
20f7b1b7
MV
313/*
314 * exception handlers
315 */
401bb30b 316#ifdef CONFIG_SPL_BUILD
5ab877b6
MV
317 .align 5
318do_hang:
20f7b1b7 319 ldr sp, _TEXT_BASE /* use 32 words about stack */
5ab877b6 320 bl hang /* hang and never return */
20f7b1b7 321#else /* !CONFIG_SPL_BUILD */
384ae025 322 .align 5
c609719b
WD
323undefined_instruction:
324 get_bad_stack
325 bad_save_user_regs
384ae025 326 bl do_undefined_instruction
c609719b
WD
327
328 .align 5
329software_interrupt:
20f7b1b7 330 get_bad_stack_swi
c609719b 331 bad_save_user_regs
384ae025 332 bl do_software_interrupt
c609719b
WD
333
334 .align 5
335prefetch_abort:
336 get_bad_stack
337 bad_save_user_regs
384ae025 338 bl do_prefetch_abort
c609719b
WD
339
340 .align 5
341data_abort:
342 get_bad_stack
343 bad_save_user_regs
384ae025 344 bl do_data_abort
c609719b
WD
345
346 .align 5
347not_used:
348 get_bad_stack
349 bad_save_user_regs
384ae025 350 bl do_not_used
c609719b
WD
351
352#ifdef CONFIG_USE_IRQ
353
354 .align 5
355irq:
356 get_irq_stack
357 irq_save_user_regs
384ae025 358 bl do_irq
c609719b
WD
359 irq_restore_user_regs
360
361 .align 5
362fiq:
363 get_fiq_stack
20f7b1b7
MV
364 /* someone ought to write a more effiction fiq_save_user_regs */
365 irq_save_user_regs
366 bl do_fiq
c609719b
WD
367 irq_restore_user_regs
368
20f7b1b7 369#else
c609719b
WD
370
371 .align 5
372irq:
373 get_bad_stack
374 bad_save_user_regs
384ae025 375 bl do_irq
c609719b
WD
376
377 .align 5
378fiq:
379 get_bad_stack
380 bad_save_user_regs
384ae025 381 bl do_fiq
384ae025 382
20f7b1b7
MV
383#endif
384 .align 5
401bb30b 385#endif /* CONFIG_SPL_BUILD */
7f4cfcf4
MV
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 */
abc20aba 394#ifdef CONFIG_CPU_PXA25X
7f4cfcf4
MV
395.macro CPWAIT reg
396 mrc p15, 0, \reg, c2, c0, 0
397 mov \reg, \reg
398 sub pc, pc, #4
399.endm
400lock_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
447alloc:
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"
466mmutable:
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
abc20aba 477#endif /* CONFIG_CPU_PXA25X */