xref: /openbmc/u-boot/arch/arm/cpu/arm926ejs/start.S (revision 70ad375e)
1/*
2 *  armboot - Startup Code for ARM926EJS CPU-core
3 *
4 *  Copyright (c) 2003  Texas Instruments
5 *
6 *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
7 *
8 *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
9 *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
10 *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
11 *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
12 *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
13 *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
14 *
15 * SPDX-License-Identifier:	GPL-2.0+
16 */
17
18#include <asm-offsets.h>
19#include <config.h>
20#include <common.h>
21#include <version.h>
22
23/*
24 *************************************************************************
25 *
26 * Jump vector table as in table 3.1 in [1]
27 *
28 *************************************************************************
29 */
30
31
32#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
33.globl _start
34_start:
35.globl _NOR_BOOT_CFG
36_NOR_BOOT_CFG:
37	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
38	b	reset
39#else
40.globl _start
41_start:
42	b	reset
43#endif
44#ifdef CONFIG_SPL_BUILD
45/* No exception handlers in preloader */
46	ldr	pc, _hang
47	ldr	pc, _hang
48	ldr	pc, _hang
49	ldr	pc, _hang
50	ldr	pc, _hang
51	ldr	pc, _hang
52	ldr	pc, _hang
53
54_hang:
55	.word	do_hang
56/* pad to 64 byte boundary */
57	.word	0x12345678
58	.word	0x12345678
59	.word	0x12345678
60	.word	0x12345678
61	.word	0x12345678
62	.word	0x12345678
63	.word	0x12345678
64#else
65	ldr	pc, _undefined_instruction
66	ldr	pc, _software_interrupt
67	ldr	pc, _prefetch_abort
68	ldr	pc, _data_abort
69	ldr	pc, _not_used
70	ldr	pc, _irq
71	ldr	pc, _fiq
72
73_undefined_instruction:
74	.word undefined_instruction
75_software_interrupt:
76	.word software_interrupt
77_prefetch_abort:
78	.word prefetch_abort
79_data_abort:
80	.word data_abort
81_not_used:
82	.word not_used
83_irq:
84	.word irq
85_fiq:
86	.word fiq
87
88#endif	/* CONFIG_SPL_BUILD */
89	.balignl 16,0xdeadbeef
90
91
92/*
93 *************************************************************************
94 *
95 * Startup Code (reset vector)
96 *
97 * do important init only if we don't start from memory!
98 * setup Memory and board specific bits prior to relocation.
99 * relocate armboot to ram
100 * setup stack
101 *
102 *************************************************************************
103 */
104
105#ifdef CONFIG_USE_IRQ
106/* IRQ stack memory (calculated at run-time) */
107.globl IRQ_STACK_START
108IRQ_STACK_START:
109	.word	0x0badc0de
110
111/* IRQ stack memory (calculated at run-time) */
112.globl FIQ_STACK_START
113FIQ_STACK_START:
114	.word 0x0badc0de
115#endif
116
117/* IRQ stack memory (calculated at run-time) + 8 bytes */
118.globl IRQ_STACK_START_IN
119IRQ_STACK_START_IN:
120	.word	0x0badc0de
121
122/*
123 * the actual reset code
124 */
125
126reset:
127	/*
128	 * set the cpu to SVC32 mode
129	 */
130	mrs	r0,cpsr
131	bic	r0,r0,#0x1f
132	orr	r0,r0,#0xd3
133	msr	cpsr,r0
134
135	/*
136	 * we do sys-critical inits only at reboot,
137	 * not when booting from ram!
138	 */
139#ifndef CONFIG_SKIP_LOWLEVEL_INIT
140	bl	cpu_init_crit
141#endif
142
143	bl	_main
144
145/*------------------------------------------------------------------------------*/
146
147	.globl	c_runtime_cpu_setup
148c_runtime_cpu_setup:
149
150	bx	lr
151
152/*
153 *************************************************************************
154 *
155 * CPU_init_critical registers
156 *
157 * setup important registers
158 * setup memory timing
159 *
160 *************************************************************************
161 */
162#ifndef CONFIG_SKIP_LOWLEVEL_INIT
163cpu_init_crit:
164	/*
165	 * flush D cache before disabling it
166	 */
167	mov	r0, #0
168flush_dcache:
169	mrc	p15, 0, r15, c7, c10, 3
170	bne	flush_dcache
171
172	mcr	p15, 0, r0, c8, c7, 0	/* invalidate TLB */
173	mcr	p15, 0, r0, c7, c5, 0	/* invalidate I Cache */
174
175	/*
176	 * disable MMU and D cache
177	 * enable I cache if CONFIG_SYS_ICACHE_OFF is not defined
178	 */
179	mrc	p15, 0, r0, c1, c0, 0
180	bic	r0, r0, #0x00000300	/* clear bits 9:8 (---- --RS) */
181	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
182#ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH
183	orr	r0, r0, #0x00002000	/* set bit 13 (--V- ----) */
184#else
185	bic	r0, r0, #0x00002000	/* clear bit 13 (--V- ----) */
186#endif
187	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
188#ifndef CONFIG_SYS_ICACHE_OFF
189	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
190#endif
191	mcr	p15, 0, r0, c1, c0, 0
192
193	/*
194	 * Go setup Memory and board specific bits prior to relocation.
195	 */
196	mov	ip, lr		/* perserve link reg across call */
197	bl	lowlevel_init	/* go setup pll,mux,memory */
198	mov	lr, ip		/* restore link */
199	mov	pc, lr		/* back to my caller */
200#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
201
202#ifndef CONFIG_SPL_BUILD
203/*
204 *************************************************************************
205 *
206 * Interrupt handling
207 *
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	@ carve out a frame on current user stack
246	sub	sp, sp, #S_FRAME_SIZE
247	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
248	ldr	r2, IRQ_STACK_START_IN
249	@ get values for "aborted" pc and cpsr (into parm regs)
250	ldmia	r2, {r2 - r3}
251	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
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	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
262	add	r8, sp, #S_PC
263	stmdb	r8, {sp, lr}^		@ Calling SP, LR
264	str	lr, [r8, #0]		@ Save calling PC
265	mrs	r6, spsr
266	str	r6, [r8, #4]		@ Save CPSR
267	str	r0, [r8, #8]		@ Save OLD_R0
268	mov	r0, sp
269	.endm
270
271	.macro	irq_restore_user_regs
272	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
273	mov	r0, r0
274	ldr	lr, [sp, #S_PC]			@ Get PC
275	add	sp, sp, #S_FRAME_SIZE
276	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
277	.endm
278
279	.macro get_bad_stack
280	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
281
282	str	lr, [r13]	@ save caller lr in position 0 of saved stack
283	mrs	lr, spsr	@ get the spsr
284	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
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_irq_stack			@ setup IRQ stack
293	ldr	sp, IRQ_STACK_START
294	.endm
295
296	.macro get_fiq_stack			@ setup FIQ stack
297	ldr	sp, FIQ_STACK_START
298	.endm
299#endif	/* CONFIG_SPL_BUILD */
300
301/*
302 * exception handlers
303 */
304#ifdef CONFIG_SPL_BUILD
305	.align	5
306do_hang:
3071:
308	bl	1b				/* hang and never return */
309#else	/* !CONFIG_SPL_BUILD */
310	.align  5
311undefined_instruction:
312	get_bad_stack
313	bad_save_user_regs
314	bl	do_undefined_instruction
315
316	.align	5
317software_interrupt:
318	get_bad_stack
319	bad_save_user_regs
320	bl	do_software_interrupt
321
322	.align	5
323prefetch_abort:
324	get_bad_stack
325	bad_save_user_regs
326	bl	do_prefetch_abort
327
328	.align	5
329data_abort:
330	get_bad_stack
331	bad_save_user_regs
332	bl	do_data_abort
333
334	.align	5
335not_used:
336	get_bad_stack
337	bad_save_user_regs
338	bl	do_not_used
339
340#ifdef CONFIG_USE_IRQ
341
342	.align	5
343irq:
344	get_irq_stack
345	irq_save_user_regs
346	bl	do_irq
347	irq_restore_user_regs
348
349	.align	5
350fiq:
351	get_fiq_stack
352	/* someone ought to write a more effiction fiq_save_user_regs */
353	irq_save_user_regs
354	bl	do_fiq
355	irq_restore_user_regs
356
357#else
358
359	.align	5
360irq:
361	get_bad_stack
362	bad_save_user_regs
363	bl	do_irq
364
365	.align	5
366fiq:
367	get_bad_stack
368	bad_save_user_regs
369	bl	do_fiq
370
371#endif
372#endif	/* CONFIG_SPL_BUILD */
373