xref: /openbmc/u-boot/arch/arm/cpu/arm1136/start.S (revision fa8f9508)
1/*
2 *  armboot - Startup Code for OMP2420/ARM1136 CPU-core
3 *
4 *  Copyright (c) 2004	Texas Instruments <r-woodruff2@ti.com>
5 *
6 *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
7 *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
8 *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
9 *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
10 *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
11 *
12 * SPDX-License-Identifier:	GPL-2.0+
13 */
14
15#include <asm-offsets.h>
16#include <config.h>
17#include <version.h>
18.globl _start
19_start: b	reset
20#ifdef CONFIG_SPL_BUILD
21	ldr	pc, _hang
22	ldr	pc, _hang
23	ldr	pc, _hang
24	ldr	pc, _hang
25	ldr	pc, _hang
26	ldr	pc, _hang
27	ldr	pc, _hang
28
29_hang:
30	.word	do_hang
31	.word	0x12345678
32	.word	0x12345678
33	.word	0x12345678
34	.word	0x12345678
35	.word	0x12345678
36	.word	0x12345678
37	.word	0x12345678	/* now 16*4=64 */
38#else
39	ldr	pc, _undefined_instruction
40	ldr	pc, _software_interrupt
41	ldr	pc, _prefetch_abort
42	ldr	pc, _data_abort
43	ldr	pc, _not_used
44	ldr	pc, _irq
45	ldr	pc, _fiq
46
47_undefined_instruction: .word undefined_instruction
48_software_interrupt:	.word software_interrupt
49_prefetch_abort:	.word prefetch_abort
50_data_abort:		.word data_abort
51_not_used:		.word not_used
52_irq:			.word irq
53_fiq:			.word fiq
54_pad:			.word 0x12345678 /* now 16*4=64 */
55#endif	/* CONFIG_SPL_BUILD */
56.global _end_vect
57_end_vect:
58
59	.balignl 16,0xdeadbeef
60/*
61 *************************************************************************
62 *
63 * Startup Code (reset vector)
64 *
65 * do important init only if we don't start from memory!
66 * setup Memory and board specific bits prior to relocation.
67 * relocate armboot to ram
68 * setup stack
69 *
70 *************************************************************************
71 */
72
73.globl _TEXT_BASE
74_TEXT_BASE:
75#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
76	.word	CONFIG_SPL_TEXT_BASE
77#else
78	.word	CONFIG_SYS_TEXT_BASE
79#endif
80
81/*
82 * These are defined in the board-specific linker script.
83 * Subtracting _start from them lets the linker put their
84 * relative position in the executable instead of leaving
85 * them null.
86 */
87.globl _bss_start_ofs
88_bss_start_ofs:
89	.word __bss_start - _start
90
91.globl _bss_end_ofs
92_bss_end_ofs:
93	.word __bss_end - _start
94
95.globl _end_ofs
96_end_ofs:
97	.word _end - _start
98
99#ifdef CONFIG_USE_IRQ
100/* IRQ stack memory (calculated at run-time) */
101.globl IRQ_STACK_START
102IRQ_STACK_START:
103	.word	0x0badc0de
104
105/* IRQ stack memory (calculated at run-time) */
106.globl FIQ_STACK_START
107FIQ_STACK_START:
108	.word 0x0badc0de
109#endif
110
111/* IRQ stack memory (calculated at run-time) + 8 bytes */
112.globl IRQ_STACK_START_IN
113IRQ_STACK_START_IN:
114	.word	0x0badc0de
115
116/*
117 * the actual reset code
118 */
119
120reset:
121	/*
122	 * set the cpu to SVC32 mode
123	 */
124	mrs	r0,cpsr
125	bic	r0,r0,#0x1f
126	orr	r0,r0,#0xd3
127	msr	cpsr,r0
128
129	/* the mask ROM code should have PLL and others stable */
130#ifndef CONFIG_SKIP_LOWLEVEL_INIT
131	bl  cpu_init_crit
132#endif
133
134	bl	_main
135
136/*------------------------------------------------------------------------------*/
137
138	.globl	c_runtime_cpu_setup
139c_runtime_cpu_setup:
140
141	bx	lr
142
143/*
144 *************************************************************************
145 *
146 * CPU_init_critical registers
147 *
148 * setup important registers
149 * setup memory timing
150 *
151 *************************************************************************
152 */
153#ifndef CONFIG_SKIP_LOWLEVEL_INIT
154cpu_init_crit:
155	/*
156	 * flush v4 I/D caches
157	 */
158	mov	r0, #0
159	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
160	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
161
162	/*
163	 * disable MMU stuff and caches
164	 */
165	mrc	p15, 0, r0, c1, c0, 0
166	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
167	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
168	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
169	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
170	mcr	p15, 0, r0, c1, c0, 0
171
172	/*
173	 * Jump to board specific initialization... The Mask ROM will have already initialized
174	 * basic memory.  Go here to bump up clock rate and handle wake up conditions.
175	 */
176	mov	ip, lr		/* persevere link reg across call */
177	bl	lowlevel_init	/* go setup pll,mux,memory */
178	mov	lr, ip		/* restore link */
179	mov	pc, lr		/* back to my caller */
180#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
181
182#ifndef CONFIG_SPL_BUILD
183/*
184 *************************************************************************
185 *
186 * Interrupt handling
187 *
188 *************************************************************************
189 */
190@
191@ IRQ stack frame.
192@
193#define S_FRAME_SIZE	72
194
195#define S_OLD_R0	68
196#define S_PSR		64
197#define S_PC		60
198#define S_LR		56
199#define S_SP		52
200
201#define S_IP		48
202#define S_FP		44
203#define S_R10		40
204#define S_R9		36
205#define S_R8		32
206#define S_R7		28
207#define S_R6		24
208#define S_R5		20
209#define S_R4		16
210#define S_R3		12
211#define S_R2		8
212#define S_R1		4
213#define S_R0		0
214
215#define MODE_SVC 0x13
216#define I_BIT	 0x80
217
218/*
219 * use bad_save_user_regs for abort/prefetch/undef/swi ...
220 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
221 */
222
223	.macro	bad_save_user_regs
224	sub	sp, sp, #S_FRAME_SIZE		@ carve out a frame on current user stack
225	stmia	sp, {r0 - r12}			@ Save user registers (now in svc mode) r0-r12
226
227	ldr	r2, IRQ_STACK_START_IN		@ set base 2 words into abort stack
228	ldmia	r2, {r2 - r3}			@ get values for "aborted" pc and cpsr (into parm regs)
229	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
230
231	add	r5, sp, #S_SP
232	mov	r1, lr
233	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
234	mov	r0, sp				@ save current stack into r0 (param register)
235	.endm
236
237	.macro	irq_save_user_regs
238	sub	sp, sp, #S_FRAME_SIZE
239	stmia	sp, {r0 - r12}			@ Calling r0-r12
240	add	r8, sp, #S_PC			@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
241	stmdb	r8, {sp, lr}^			@ Calling SP, LR
242	str	lr, [r8, #0]			@ Save calling PC
243	mrs	r6, spsr
244	str	r6, [r8, #4]			@ Save CPSR
245	str	r0, [r8, #8]			@ Save OLD_R0
246	mov	r0, sp
247	.endm
248
249	.macro	irq_restore_user_regs
250	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
251	mov	r0, r0
252	ldr	lr, [sp, #S_PC]			@ Get PC
253	add	sp, sp, #S_FRAME_SIZE
254	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
255	.endm
256
257	.macro get_bad_stack
258	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack (enter in banked mode)
259
260	str	lr, [r13]			@ save caller lr in position 0 of saved stack
261	mrs	lr, spsr			@ get the spsr
262	str	lr, [r13, #4]			@ save spsr in position 1 of saved stack
263
264	mov	r13, #MODE_SVC			@ prepare SVC-Mode
265	@ msr	spsr_c, r13
266	msr	spsr, r13			@ switch modes, make sure moves will execute
267	mov	lr, pc				@ capture return pc
268	movs	pc, lr				@ jump to next instruction & switch modes.
269	.endm
270
271	.macro get_bad_stack_swi
272	sub	r13, r13, #4			@ space on current stack for scratch reg.
273	str	r0, [r13]			@ save R0's value.
274	ldr	r0, IRQ_STACK_START_IN		@ get data regions start
275	str	lr, [r0]			@ save caller lr in position 0 of saved stack
276	mrs	lr, spsr			@ get the spsr
277	str	lr, [r0, #4]			@ save spsr in position 1 of saved stack
278	ldr	lr, [r0]			@ restore lr
279	ldr	r0, [r13]			@ restore r0
280	add	r13, r13, #4			@ pop stack entry
281	.endm
282
283	.macro get_irq_stack			@ setup IRQ stack
284	ldr	sp, IRQ_STACK_START
285	.endm
286
287	.macro get_fiq_stack			@ setup FIQ stack
288	ldr	sp, FIQ_STACK_START
289	.endm
290#endif	/* CONFIG_SPL_BUILD */
291
292/*
293 * exception handlers
294 */
295#ifdef CONFIG_SPL_BUILD
296	.align	5
297do_hang:
298	ldr	sp, _TEXT_BASE			/* use 32 words about stack */
299	bl	hang				/* hang and never return */
300#else	/* !CONFIG_SPL_BUILD */
301	.align	5
302undefined_instruction:
303	get_bad_stack
304	bad_save_user_regs
305	bl	do_undefined_instruction
306
307	.align	5
308software_interrupt:
309	get_bad_stack_swi
310	bad_save_user_regs
311	bl	do_software_interrupt
312
313	.align	5
314prefetch_abort:
315	get_bad_stack
316	bad_save_user_regs
317	bl	do_prefetch_abort
318
319	.align	5
320data_abort:
321	get_bad_stack
322	bad_save_user_regs
323	bl	do_data_abort
324
325	.align	5
326not_used:
327	get_bad_stack
328	bad_save_user_regs
329	bl	do_not_used
330
331#ifdef CONFIG_USE_IRQ
332
333	.align	5
334irq:
335	get_irq_stack
336	irq_save_user_regs
337	bl	do_irq
338	irq_restore_user_regs
339
340	.align	5
341fiq:
342	get_fiq_stack
343	/* someone ought to write a more effiction fiq_save_user_regs */
344	irq_save_user_regs
345	bl	do_fiq
346	irq_restore_user_regs
347
348#else
349
350	.align	5
351irq:
352	get_bad_stack
353	bad_save_user_regs
354	bl	do_irq
355
356	.align	5
357fiq:
358	get_bad_stack
359	bad_save_user_regs
360	bl	do_fiq
361
362#endif
363	.align 5
364.global arm1136_cache_flush
365arm1136_cache_flush:
366#if !defined(CONFIG_SYS_ICACHE_OFF)
367		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I cache
368#endif
369#if !defined(CONFIG_SYS_DCACHE_OFF)
370		mcr	p15, 0, r1, c7, c14, 0	@ invalidate D cache
371#endif
372		mov	pc, lr			@ back to caller
373#endif	/* CONFIG_SPL_BUILD */
374