blob: ae0d13ce8fe449fb72c59f7b4df1504e7e1f5800 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Marek Vasut20f7b1b2011-10-31 14:12:39 +01002 * armboot - Startup Code for XScale CPU-core
wdenkc6097192002-11-03 00:24:07 +00003 *
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>
wdenka8c7c702003-12-06 19:49:23 +00007 * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de>
Marek Vasut20f7b1b2011-10-31 14:12:39 +01008 * 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>
wdenk1cb8e982003-03-06 21:55:29 +000011 * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net>
Wolfgang Denk951a9542006-03-06 23:18:48 +010012 * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
Marek Vasut20f7b1b2011-10-31 14:12:39 +010013 * 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>
wdenkc6097192002-11-03 00:24:07 +000018 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +020019 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +000020 */
21
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020022#include <asm-offsets.h>
wdenkc6097192002-11-03 00:24:07 +000023#include <config.h>
24#include <version.h>
Marek Vasut7f4cfcf2011-11-05 19:26:47 +010025
Marek Vasutabc20ab2011-11-26 07:20:07 +010026#ifdef CONFIG_CPU_PXA25X
Marek Vasut7f4cfcf2011-11-05 19:26:47 +010027#if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800)
28#error "Init SP address must be set to 0xfffff800 for PXA250"
29#endif
30#endif
31
wdenkc6097192002-11-03 00:24:07 +000032.globl _start
wdenk384ae022002-11-05 00:17:55 +000033_start: b reset
Aneesh V401bb302011-07-13 05:11:07 +000034#ifdef CONFIG_SPL_BUILD
Marek Vasut5ab877b2010-07-06 02:48:35 +020035 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
wdenkc6097192002-11-03 00:24:07 +000053 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
wdenk384ae022002-11-05 00:17:55 +000061_undefined_instruction: .word undefined_instruction
wdenkc6097192002-11-03 00:24:07 +000062_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
Marek Vasut20f7b1b2011-10-31 14:12:39 +010068_pad: .word 0x12345678 /* now 16*4=64 */
Aneesh V401bb302011-07-13 05:11:07 +000069#endif /* CONFIG_SPL_BUILD */
Marek Vasut20f7b1b2011-10-31 14:12:39 +010070.global _end_vect
71_end_vect:
wdenkc6097192002-11-03 00:24:07 +000072
73 .balignl 16,0xdeadbeef
wdenkc6097192002-11-03 00:24:07 +000074/*
Marek Vasut20f7b1b2011-10-31 14:12:39 +010075 *************************************************************************
76 *
wdenkc6097192002-11-03 00:24:07 +000077 * Startup Code (reset vector)
78 *
Marek Vasut20f7b1b2011-10-31 14:12:39 +010079 * 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 *************************************************************************
wdenkc6097192002-11-03 00:24:07 +000085 */
86
wdenkc6097192002-11-03 00:24:07 +000087#ifdef CONFIG_USE_IRQ
88/* IRQ stack memory (calculated at run-time) */
89.globl IRQ_STACK_START
90IRQ_STACK_START:
91 .word 0x0badc0de
92
93/* IRQ stack memory (calculated at run-time) */
94.globl FIQ_STACK_START
95FIQ_STACK_START:
96 .word 0x0badc0de
Marek Vasut20f7b1b2011-10-31 14:12:39 +010097#endif
wdenkc6097192002-11-03 00:24:07 +000098
Heiko Schocher5347f682010-09-17 13:10:46 +020099/* IRQ stack memory (calculated at run-time) + 8 bytes */
100.globl IRQ_STACK_START_IN
101IRQ_STACK_START_IN:
102 .word 0x0badc0de
103
Heiko Schocher5347f682010-09-17 13:10:46 +0200104/*
105 * the actual reset code
106 */
107
108reset:
109 /*
110 * set the cpu to SVC32 mode
111 */
112 mrs r0,cpsr
113 bic r0,r0,#0x1f
114 orr r0,r0,#0xd3
115 msr cpsr,r0
116
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100117#ifndef CONFIG_SKIP_LOWLEVEL_INIT
118 bl cpu_init_crit
119#endif
Heiko Schocher5347f682010-09-17 13:10:46 +0200120
Marek Vasutabc20ab2011-11-26 07:20:07 +0100121#ifdef CONFIG_CPU_PXA25X
Marek Vasut7f4cfcf2011-11-05 19:26:47 +0100122 bl lock_cache_for_stack
123#endif
124
Albert ARIBAUDe05e5de2013-01-08 10:18:02 +0000125 bl _main
Heiko Schocher5347f682010-09-17 13:10:46 +0200126
127/*------------------------------------------------------------------------------*/
Albert ARIBAUDe05e5de2013-01-08 10:18:02 +0000128
129 .globl c_runtime_cpu_setup
130c_runtime_cpu_setup:
131
Albert ARIBAUD3da0e572013-05-19 01:48:15 +0000132#ifdef CONFIG_CPU_PXA25X
133 /*
134 * Unlock (actually, disable) the cache now that board_init_f
135 * is done. We could do this earlier but we would need to add
136 * a new C runtime hook, whereas c_runtime_cpu_setup already
137 * exists.
138 * As this routine is just a call to cpu_init_crit, let us
139 * tail-optimize and do a simple branch here.
140 */
141 b cpu_init_crit
142#else
Albert ARIBAUDe05e5de2013-01-08 10:18:02 +0000143 bx lr
Albert ARIBAUD3da0e572013-05-19 01:48:15 +0000144#endif
Albert ARIBAUDe05e5de2013-01-08 10:18:02 +0000145
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100146/*
147 *************************************************************************
148 *
149 * CPU_init_critical registers
150 *
151 * setup important registers
152 * setup memory timing
153 *
154 *************************************************************************
155 */
Marek Vasutabc20ab2011-11-26 07:20:07 +0100156#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X)
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100157cpu_init_crit:
158 /*
159 * flush v4 I/D caches
160 */
161 mov r0, #0
162 mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */
163 mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */
Marek Vasut2cad92f2010-09-28 15:44:10 +0200164
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100165 /*
166 * disable MMU stuff and caches
167 */
168 mrc p15, 0, r0, c1, c0, 0
Mike Dunn097d86d2013-06-17 10:47:28 -0700169 bic r0, r0, #0x00003300 @ clear bits 13:12, 9:8 (--VI --RS)
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100170 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
171 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100172 mcr p15, 0, r0, c1, c0, 0
wdenkc6097192002-11-03 00:24:07 +0000173
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100174 mov pc, lr /* back to my caller */
Marek Vasutabc20ab2011-11-26 07:20:07 +0100175#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */
wdenkc6097192002-11-03 00:24:07 +0000176
Aneesh V401bb302011-07-13 05:11:07 +0000177#ifndef CONFIG_SPL_BUILD
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100178/*
179 *************************************************************************
180 *
181 * Interrupt handling
182 *
183 *************************************************************************
184 */
185@
186@ IRQ stack frame.
187@
wdenkc6097192002-11-03 00:24:07 +0000188#define S_FRAME_SIZE 72
189
190#define S_OLD_R0 68
191#define S_PSR 64
192#define S_PC 60
193#define S_LR 56
194#define S_SP 52
195
196#define S_IP 48
197#define S_FP 44
198#define S_R10 40
199#define S_R9 36
200#define S_R8 32
201#define S_R7 28
202#define S_R6 24
203#define S_R5 20
204#define S_R4 16
205#define S_R3 12
206#define S_R2 8
207#define S_R1 4
208#define S_R0 0
209
210#define MODE_SVC 0x13
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100211#define I_BIT 0x80
wdenkc6097192002-11-03 00:24:07 +0000212
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100213/*
214 * use bad_save_user_regs for abort/prefetch/undef/swi ...
215 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
216 */
wdenkc6097192002-11-03 00:24:07 +0000217
218 .macro bad_save_user_regs
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100219 sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack
220 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
wdenkc6097192002-11-03 00:24:07 +0000221
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100222 ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack
223 ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs)
224 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
wdenkc6097192002-11-03 00:24:07 +0000225
226 add r5, sp, #S_SP
227 mov r1, lr
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100228 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
229 mov r0, sp @ save current stack into r0 (param register)
wdenkc6097192002-11-03 00:24:07 +0000230 .endm
231
wdenkc6097192002-11-03 00:24:07 +0000232 .macro irq_save_user_regs
233 sub sp, sp, #S_FRAME_SIZE
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100234 stmia sp, {r0 - r12} @ Calling r0-r12
235 add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
236 stmdb r8, {sp, lr}^ @ Calling SP, LR
237 str lr, [r8, #0] @ Save calling PC
wdenk384ae022002-11-05 00:17:55 +0000238 mrs r6, spsr
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100239 str r6, [r8, #4] @ Save CPSR
240 str r0, [r8, #8] @ Save OLD_R0
wdenkc6097192002-11-03 00:24:07 +0000241 mov r0, sp
242 .endm
243
244 .macro irq_restore_user_regs
245 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
246 mov r0, r0
247 ldr lr, [sp, #S_PC] @ Get PC
248 add sp, sp, #S_FRAME_SIZE
249 subs pc, lr, #4 @ return & move spsr_svc into cpsr
250 .endm
251
252 .macro get_bad_stack
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100253 ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode)
wdenkc6097192002-11-03 00:24:07 +0000254
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100255 str lr, [r13] @ save caller lr in position 0 of saved stack
256 mrs lr, spsr @ get the spsr
257 str lr, [r13, #4] @ save spsr in position 1 of saved stack
wdenkc6097192002-11-03 00:24:07 +0000258
259 mov r13, #MODE_SVC @ prepare SVC-Mode
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100260 @ msr spsr_c, r13
261 msr spsr, r13 @ switch modes, make sure moves will execute
262 mov lr, pc @ capture return pc
263 movs pc, lr @ jump to next instruction & switch modes.
264 .endm
265
266 .macro get_bad_stack_swi
267 sub r13, r13, #4 @ space on current stack for scratch reg.
268 str r0, [r13] @ save R0's value.
269 ldr r0, IRQ_STACK_START_IN @ get data regions start
270 str lr, [r0] @ save caller lr in position 0 of saved stack
Tetsuyuki Kobayashi4411b2a2013-04-05 00:12:51 +0000271 mrs lr, spsr @ get the spsr
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100272 str lr, [r0, #4] @ save spsr in position 1 of saved stack
Tetsuyuki Kobayashi4411b2a2013-04-05 00:12:51 +0000273 ldr lr, [r0] @ restore lr
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100274 ldr r0, [r13] @ restore r0
275 add r13, r13, #4 @ pop stack entry
wdenkc6097192002-11-03 00:24:07 +0000276 .endm
277
278 .macro get_irq_stack @ setup IRQ stack
279 ldr sp, IRQ_STACK_START
280 .endm
281
282 .macro get_fiq_stack @ setup FIQ stack
283 ldr sp, FIQ_STACK_START
284 .endm
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100285#endif /* CONFIG_SPL_BUILD */
wdenkc6097192002-11-03 00:24:07 +0000286
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100287/*
288 * exception handlers
289 */
Aneesh V401bb302011-07-13 05:11:07 +0000290#ifdef CONFIG_SPL_BUILD
Marek Vasut5ab877b2010-07-06 02:48:35 +0200291 .align 5
292do_hang:
Marek Vasut5ab877b2010-07-06 02:48:35 +0200293 bl hang /* hang and never return */
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100294#else /* !CONFIG_SPL_BUILD */
wdenk384ae022002-11-05 00:17:55 +0000295 .align 5
wdenkc6097192002-11-03 00:24:07 +0000296undefined_instruction:
297 get_bad_stack
298 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000299 bl do_undefined_instruction
wdenkc6097192002-11-03 00:24:07 +0000300
301 .align 5
302software_interrupt:
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100303 get_bad_stack_swi
wdenkc6097192002-11-03 00:24:07 +0000304 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000305 bl do_software_interrupt
wdenkc6097192002-11-03 00:24:07 +0000306
307 .align 5
308prefetch_abort:
309 get_bad_stack
310 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000311 bl do_prefetch_abort
wdenkc6097192002-11-03 00:24:07 +0000312
313 .align 5
314data_abort:
315 get_bad_stack
316 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000317 bl do_data_abort
wdenkc6097192002-11-03 00:24:07 +0000318
319 .align 5
320not_used:
321 get_bad_stack
322 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000323 bl do_not_used
wdenkc6097192002-11-03 00:24:07 +0000324
325#ifdef CONFIG_USE_IRQ
326
327 .align 5
328irq:
329 get_irq_stack
330 irq_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000331 bl do_irq
wdenkc6097192002-11-03 00:24:07 +0000332 irq_restore_user_regs
333
334 .align 5
335fiq:
336 get_fiq_stack
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100337 /* someone ought to write a more effiction fiq_save_user_regs */
338 irq_save_user_regs
339 bl do_fiq
wdenkc6097192002-11-03 00:24:07 +0000340 irq_restore_user_regs
341
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100342#else
wdenkc6097192002-11-03 00:24:07 +0000343
344 .align 5
345irq:
346 get_bad_stack
347 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000348 bl do_irq
wdenkc6097192002-11-03 00:24:07 +0000349
350 .align 5
351fiq:
352 get_bad_stack
353 bad_save_user_regs
wdenk384ae022002-11-05 00:17:55 +0000354 bl do_fiq
wdenkc6097192002-11-03 00:24:07 +0000355
Marek Vasut20f7b1b2011-10-31 14:12:39 +0100356#endif
357 .align 5
Aneesh V401bb302011-07-13 05:11:07 +0000358#endif /* CONFIG_SPL_BUILD */
Marek Vasut7f4cfcf2011-11-05 19:26:47 +0100359
360
361/*
362 * Enable MMU to use DCache as DRAM.
363 *
364 * This is useful on PXA25x and PXA26x in early bootstages, where there is no
365 * other possible memory available to hold stack.
366 */
Marek Vasutabc20ab2011-11-26 07:20:07 +0100367#ifdef CONFIG_CPU_PXA25X
Marek Vasut7f4cfcf2011-11-05 19:26:47 +0100368.macro CPWAIT reg
369 mrc p15, 0, \reg, c2, c0, 0
370 mov \reg, \reg
371 sub pc, pc, #4
372.endm
373lock_cache_for_stack:
374 /* Domain access -- enable for all CPs */
375 ldr r0, =0x0000ffff
376 mcr p15, 0, r0, c3, c0, 0
377
378 /* Point TTBR to MMU table */
379 ldr r0, =mmutable
380 mcr p15, 0, r0, c2, c0, 0
381
382 /* Kick in MMU, ICache, DCache, BTB */
383 mrc p15, 0, r0, c1, c0, 0
384 bic r0, #0x1b00
385 bic r0, #0x0087
386 orr r0, #0x1800
387 orr r0, #0x0005
388 mcr p15, 0, r0, c1, c0, 0
389 CPWAIT r0
390
391 /* Unlock Icache, Dcache */
392 mcr p15, 0, r0, c9, c1, 1
393 mcr p15, 0, r0, c9, c2, 1
394
395 /* Flush Icache, Dcache, BTB */
396 mcr p15, 0, r0, c7, c7, 0
397
398 /* Unlock I-TLB, D-TLB */
399 mcr p15, 0, r0, c10, c4, 1
400 mcr p15, 0, r0, c10, c8, 1
401
402 /* Flush TLB */
403 mcr p15, 0, r0, c8, c7, 0
404
405 /* Allocate 4096 bytes of Dcache as RAM */
406
407 /* Drain pending loads and stores */
408 mcr p15, 0, r0, c7, c10, 4
409
410 mov r4, #0x00
411 mov r5, #0x00
412 mov r2, #0x01
413 mcr p15, 0, r0, c9, c2, 0
414 CPWAIT r0
415
416 /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
417 mov r0, #128
418 ldr r1, =0xfffff000
419
420alloc:
421 mcr p15, 0, r1, c7, c2, 5
422 /* Drain pending loads and stores */
423 mcr p15, 0, r0, c7, c10, 4
424 strd r4, [r1], #8
425 strd r4, [r1], #8
426 strd r4, [r1], #8
427 strd r4, [r1], #8
428 subs r0, #0x01
429 bne alloc
430 /* Drain pending loads and stores */
431 mcr p15, 0, r0, c7, c10, 4
432 mov r2, #0x00
433 mcr p15, 0, r2, c9, c2, 0
434 CPWAIT r0
435
436 mov pc, lr
437
438.section .mmutable, "a"
439mmutable:
440 .align 14
441 /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */
442 .set __base, 0
443 .rept 0xfff
444 .word (__base << 20) | 0xc12
445 .set __base, __base + 1
446 .endr
447
448 /* 0xfff00000 : 1:1, cached mapping */
449 .word (0xfff << 20) | 0x1c1e
Marek Vasutabc20ab2011-11-26 07:20:07 +0100450#endif /* CONFIG_CPU_PXA25X */