xref: /openbmc/u-boot/arch/arm/cpu/sa1100/start.S (revision c2800b16)
1/*
2 *  armboot - Startup Code for SA1100 CPU
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>
7 *  Copyright (c) 2001	Alex Züpke <azu@sysgo.de>
8 *
9 * SPDX-License-Identifier:	GPL-2.0+
10 */
11
12#include <asm-offsets.h>
13#include <config.h>
14#include <version.h>
15
16/*
17 *************************************************************************
18 *
19 * Jump vector table as in table 3.1 in [1]
20 *
21 *************************************************************************
22 */
23
24
25.globl _start
26_start:	b       reset
27	ldr	pc, _undefined_instruction
28	ldr	pc, _software_interrupt
29	ldr	pc, _prefetch_abort
30	ldr	pc, _data_abort
31	ldr	pc, _not_used
32	ldr	pc, _irq
33	ldr	pc, _fiq
34
35_undefined_instruction:	.word undefined_instruction
36_software_interrupt:	.word software_interrupt
37_prefetch_abort:	.word prefetch_abort
38_data_abort:		.word data_abort
39_not_used:		.word not_used
40_irq:			.word irq
41_fiq:			.word fiq
42
43	.balignl 16,0xdeadbeef
44
45
46/*
47 *************************************************************************
48 *
49 * Startup Code (reset vector)
50 *
51 * do important init only if we don't start from memory!
52 * relocate armboot to ram
53 * setup stack
54 * jump to second stage
55 *
56 *************************************************************************
57 */
58
59#ifdef CONFIG_USE_IRQ
60/* IRQ stack memory (calculated at run-time) */
61.globl IRQ_STACK_START
62IRQ_STACK_START:
63	.word	0x0badc0de
64
65/* IRQ stack memory (calculated at run-time) */
66.globl FIQ_STACK_START
67FIQ_STACK_START:
68	.word 0x0badc0de
69#endif
70
71/* IRQ stack memory (calculated at run-time) + 8 bytes */
72.globl IRQ_STACK_START_IN
73IRQ_STACK_START_IN:
74	.word	0x0badc0de
75
76/*
77 * the actual reset code
78 */
79
80reset:
81	/*
82	 * set the cpu to SVC32 mode
83	 */
84	mrs	r0,cpsr
85	bic	r0,r0,#0x1f
86	orr	r0,r0,#0xd3
87	msr	cpsr,r0
88
89	/*
90	 * we do sys-critical inits only at reboot,
91	 * not when booting from ram!
92	 */
93#ifndef CONFIG_SKIP_LOWLEVEL_INIT
94	bl	cpu_init_crit
95#endif
96
97	bl	_main
98
99/*------------------------------------------------------------------------------*/
100
101	.globl	c_runtime_cpu_setup
102c_runtime_cpu_setup:
103
104	mov	pc, lr
105
106/*
107 *************************************************************************
108 *
109 * CPU_init_critical registers
110 *
111 * setup important registers
112 * setup memory timing
113 *
114 *************************************************************************
115 */
116
117
118/* Interrupt-Controller base address */
119IC_BASE:	.word	0x90050000
120#define ICMR	0x04
121
122
123/* Reset-Controller */
124RST_BASE:		.word   0x90030000
125#define RSRR	0x00
126#define RCSR	0x04
127
128
129/* PWR */
130PWR_BASE:		.word   0x90020000
131#define PSPR    0x08
132#define PPCR    0x14
133cpuspeed:		.word   CONFIG_SYS_CPUSPEED
134
135
136cpu_init_crit:
137	/*
138	 * mask all IRQs
139	 */
140	ldr	r0, IC_BASE
141	mov	r1, #0x00
142	str	r1, [r0, #ICMR]
143
144	/* set clock speed */
145	ldr	r0, PWR_BASE
146	ldr	r1, cpuspeed
147	str	r1, [r0, #PPCR]
148
149	/*
150	 * before relocating, we have to setup RAM timing
151	 * because memory timing is board-dependend, you will
152	 * find a lowlevel_init.S in your board directory.
153	 */
154	mov	ip,	lr
155	bl	lowlevel_init
156	mov	lr,	ip
157
158	/*
159	 * disable MMU stuff and enable I-cache
160	 */
161	mrc	p15,0,r0,c1,c0
162	bic	r0, r0, #0x00002000	@ clear bit 13 (X)
163	bic	r0, r0, #0x0000000f	@ clear bits 3-0 (WCAM)
164	orr	r0, r0, #0x00001000	@ set bit 12 (I) Icache
165	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
166	mcr	p15,0,r0,c1,c0
167
168	/*
169	 * flush v4 I/D caches
170	 */
171	mov	r0, #0
172	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
173	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
174
175	mov	pc, lr
176
177
178/*
179 *************************************************************************
180 *
181 * Interrupt handling
182 *
183 *************************************************************************
184 */
185
186@
187@ IRQ stack frame.
188@
189#define S_FRAME_SIZE	72
190
191#define S_OLD_R0	68
192#define S_PSR		64
193#define S_PC		60
194#define S_LR		56
195#define S_SP		52
196
197#define S_IP		48
198#define S_FP		44
199#define S_R10		40
200#define S_R9		36
201#define S_R8		32
202#define S_R7		28
203#define S_R6		24
204#define S_R5		20
205#define S_R4		16
206#define S_R3		12
207#define S_R2		8
208#define S_R1		4
209#define S_R0		0
210
211#define MODE_SVC 0x13
212#define I_BIT	 0x80
213
214/*
215 * use bad_save_user_regs for abort/prefetch/undef/swi ...
216 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
217 */
218
219	.macro	bad_save_user_regs
220	sub	sp, sp, #S_FRAME_SIZE
221	stmia	sp, {r0 - r12}			@ Calling r0-r12
222	add     r8, sp, #S_PC
223
224	ldr	r2, IRQ_STACK_START_IN
225	ldmia	r2, {r2 - r4}                   @ get pc, cpsr, old_r0
226	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC
227
228	add	r5, sp, #S_SP
229	mov	r1, lr
230	stmia	r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
231	mov	r0, sp
232	.endm
233
234	.macro	irq_save_user_regs
235	sub	sp, sp, #S_FRAME_SIZE
236	stmia	sp, {r0 - r12}			@ Calling r0-r12
237	add     r8, sp, #S_PC
238	stmdb   r8, {sp, lr}^                   @ Calling SP, LR
239	str     lr, [r8, #0]                    @ Save calling PC
240	mrs     r6, spsr
241	str     r6, [r8, #4]                    @ Save CPSR
242	str     r0, [r8, #8]                    @ Save OLD_R0
243	mov	r0, sp
244	.endm
245
246	.macro	irq_restore_user_regs
247	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
248	mov	r0, r0
249	ldr	lr, [sp, #S_PC]			@ Get PC
250	add	sp, sp, #S_FRAME_SIZE
251	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
252	.endm
253
254	.macro get_bad_stack
255	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
256
257	str	lr, [r13]			@ save caller lr / spsr
258	mrs	lr, spsr
259	str     lr, [r13, #4]
260
261	mov	r13, #MODE_SVC			@ prepare SVC-Mode
262	msr	spsr_c, r13
263	mov	lr, pc
264	movs	pc, lr
265	.endm
266
267	.macro get_irq_stack			@ setup IRQ stack
268	ldr	sp, IRQ_STACK_START
269	.endm
270
271	.macro get_fiq_stack			@ setup FIQ stack
272	ldr	sp, FIQ_STACK_START
273	.endm
274
275/*
276 * exception handlers
277 */
278	.align  5
279undefined_instruction:
280	get_bad_stack
281	bad_save_user_regs
282	bl	do_undefined_instruction
283
284	.align	5
285software_interrupt:
286	get_bad_stack
287	bad_save_user_regs
288	bl	do_software_interrupt
289
290	.align	5
291prefetch_abort:
292	get_bad_stack
293	bad_save_user_regs
294	bl	do_prefetch_abort
295
296	.align	5
297data_abort:
298	get_bad_stack
299	bad_save_user_regs
300	bl	do_data_abort
301
302	.align	5
303not_used:
304	get_bad_stack
305	bad_save_user_regs
306	bl	do_not_used
307
308#ifdef CONFIG_USE_IRQ
309
310	.align	5
311irq:
312	get_irq_stack
313	irq_save_user_regs
314	bl	do_irq
315	irq_restore_user_regs
316
317	.align	5
318fiq:
319	get_fiq_stack
320	/* someone ought to write a more effiction fiq_save_user_regs */
321	irq_save_user_regs
322	bl	do_fiq
323	irq_restore_user_regs
324
325#else
326
327	.align	5
328irq:
329	get_bad_stack
330	bad_save_user_regs
331	bl	do_irq
332
333	.align	5
334fiq:
335	get_bad_stack
336	bad_save_user_regs
337	bl	do_fiq
338
339#endif
340
341	.align	5
342.globl reset_cpu
343reset_cpu:
344	ldr	r0, RST_BASE
345	mov	r1, #0x0			@ set bit 3-0 ...
346	str	r1, [r0, #RCSR]			@ ... to clear in RCSR
347	mov	r1, #0x1
348	str	r1, [r0, #RSRR]			@ and perform reset
349	b	reset_cpu			@ silly, but repeat endlessly
350