xref: /rk3399_rockchip-uboot/arch/arm/cpu/arm1176/start.S (revision 60a4f39fcd0d845741b4aaf9764bf54d6abef60c)
1/*
2 *  armboot - Startup Code for ARM1176 CPU-core
3 *
4 * Copyright (c) 2007	Samsung Electronics
5 *
6 * Copyright (C) 2008
7 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
8 *
9 * SPDX-License-Identifier:	GPL-2.0+
10 *
11 * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com)
12 * 2007-09-21 - Added MoviNAND and OneNAND boot codes by
13 * jsgood (jsgood.yang@samsung.com)
14 * Base codes by scsuh (sc.suh)
15 */
16
17#include <asm-offsets.h>
18#include <config.h>
19#include <version.h>
20
21#ifndef CONFIG_SYS_PHY_UBOOT_BASE
22#define CONFIG_SYS_PHY_UBOOT_BASE	CONFIG_SYS_UBOOT_BASE
23#endif
24
25/*
26 *************************************************************************
27 *
28 * Jump vector table as in table 3.1 in [1]
29 *
30 *************************************************************************
31 */
32
33.globl _start
34_start: b	reset
35#ifndef CONFIG_SPL_BUILD
36	ldr	pc, _undefined_instruction
37	ldr	pc, _software_interrupt
38	ldr	pc, _prefetch_abort
39	ldr	pc, _data_abort
40	ldr	pc, _not_used
41	ldr	pc, _irq
42	ldr	pc, _fiq
43
44_undefined_instruction:
45	.word undefined_instruction
46_software_interrupt:
47	.word software_interrupt
48_prefetch_abort:
49	.word prefetch_abort
50_data_abort:
51	.word data_abort
52_not_used:
53	.word not_used
54_irq:
55	.word irq
56_fiq:
57	.word fiq
58_pad:
59	.word 0x12345678 /* now 16*4=64 */
60#else
61	. = _start + 64
62#endif
63
64	.balignl 16,0xdeadbeef
65/*
66 *************************************************************************
67 *
68 * Startup Code (reset vector)
69 *
70 * do important init only if we don't start from memory!
71 * setup Memory and board specific bits prior to relocation.
72 * relocate armboot to ram
73 * setup stack
74 *
75 *************************************************************************
76 */
77
78/* IRQ stack memory (calculated at run-time) + 8 bytes */
79.globl IRQ_STACK_START_IN
80IRQ_STACK_START_IN:
81	.word	0x0badc0de
82
83/*
84 * the actual reset code
85 */
86
87reset:
88	/*
89	 * set the cpu to SVC32 mode
90	 */
91	mrs	r0, cpsr
92	bic	r0, r0, #0x3f
93	orr	r0, r0, #0xd3
94	msr	cpsr, r0
95
96/*
97 *************************************************************************
98 *
99 * CPU_init_critical registers
100 *
101 * setup important registers
102 * setup memory timing
103 *
104 *************************************************************************
105 */
106	/*
107	 * we do sys-critical inits only at reboot,
108	 * not when booting from ram!
109	 */
110cpu_init_crit:
111	/*
112	 * When booting from NAND - it has definitely been a reset, so, no need
113	 * to flush caches and disable the MMU
114	 */
115#ifndef CONFIG_SPL_BUILD
116	/*
117	 * flush v4 I/D caches
118	 */
119	mov	r0, #0
120	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
121	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
122
123	/*
124	 * disable MMU stuff and caches
125	 */
126	mrc	p15, 0, r0, c1, c0, 0
127	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
128	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
129	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
130	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
131
132	/* Prepare to disable the MMU */
133	adr	r2, mmu_disable_phys
134	sub	r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE)
135	b	mmu_disable
136
137	.align 5
138	/* Run in a single cache-line */
139mmu_disable:
140	mcr	p15, 0, r0, c1, c0, 0
141	nop
142	nop
143	mov	pc, r2
144mmu_disable_phys:
145
146#ifdef CONFIG_DISABLE_TCM
147	/*
148	 * Disable the TCMs
149	 */
150	mrc	p15, 0, r0, c0, c0, 2	/* Return TCM details */
151	cmp	r0, #0
152	beq	skip_tcmdisable
153	mov	r1, #0
154	mov	r2, #1
155	tst	r0, r2
156	mcrne	p15, 0, r1, c9, c1, 1	/* Disable Instruction TCM if present*/
157	tst	r0, r2, LSL #16
158	mcrne	p15, 0, r1, c9, c1, 0	/* Disable Data TCM if present*/
159skip_tcmdisable:
160#endif
161#endif
162
163#ifdef CONFIG_PERIPORT_REMAP
164	/* Peri port setup */
165	ldr	r0, =CONFIG_PERIPORT_BASE
166	orr	r0, r0, #CONFIG_PERIPORT_SIZE
167	mcr	p15,0,r0,c15,c2,4
168#endif
169
170	/*
171	 * Go setup Memory and board specific bits prior to relocation.
172	 */
173	bl	lowlevel_init		/* go setup pll,mux,memory */
174
175	bl	_main
176
177/*------------------------------------------------------------------------------*/
178
179	.globl	c_runtime_cpu_setup
180c_runtime_cpu_setup:
181
182	mov	pc, lr
183
184#ifndef CONFIG_SPL_BUILD
185/*
186 *************************************************************************
187 *
188 * Interrupt handling
189 *
190 *************************************************************************
191 */
192@
193@ IRQ stack frame.
194@
195#define S_FRAME_SIZE	72
196
197#define S_OLD_R0	68
198#define S_PSR		64
199#define S_PC		60
200#define S_LR		56
201#define S_SP		52
202
203#define S_IP		48
204#define S_FP		44
205#define S_R10		40
206#define S_R9		36
207#define S_R8		32
208#define S_R7		28
209#define S_R6		24
210#define S_R5		20
211#define S_R4		16
212#define S_R3		12
213#define S_R2		8
214#define S_R1		4
215#define S_R0		0
216
217#define MODE_SVC 0x13
218#define I_BIT	 0x80
219
220/*
221 * use bad_save_user_regs for abort/prefetch/undef/swi ...
222 */
223
224	.macro	bad_save_user_regs
225	/* carve out a frame on current user stack */
226	sub	sp, sp, #S_FRAME_SIZE
227	/* Save user registers (now in svc mode) r0-r12 */
228	stmia	sp, {r0 - r12}
229
230	ldr	r2, IRQ_STACK_START_IN
231	/* get values for "aborted" pc and cpsr (into parm regs) */
232	ldmia	r2, {r2 - r3}
233	/* grab pointer to old stack */
234	add	r0, sp, #S_FRAME_SIZE
235
236	add	r5, sp, #S_SP
237	mov	r1, lr
238	/* save sp_SVC, lr_SVC, pc, cpsr */
239	stmia	r5, {r0 - r3}
240	/* save current stack into r0 (param register) */
241	mov	r0, sp
242	.endm
243
244	.macro get_bad_stack
245	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
246
247	/* save caller lr in position 0 of saved stack */
248	str	lr, [r13]
249	/* get the spsr */
250	mrs	lr, spsr
251	/* save spsr in position 1 of saved stack */
252	str	lr, [r13, #4]
253
254	/* prepare SVC-Mode */
255	mov	r13, #MODE_SVC
256	@ msr	spsr_c, r13
257	/* switch modes, make sure moves will execute */
258	msr	spsr, r13
259	/* capture return pc */
260	mov	lr, pc
261	/* jump to next instruction & switch modes. */
262	movs	pc, lr
263	.endm
264
265	.macro get_bad_stack_swi
266	/* space on current stack for scratch reg. */
267	sub	r13, r13, #4
268	/* save R0's value. */
269	str	r0, [r13]
270	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
271	/* save caller lr in position 0 of saved stack */
272	str	lr, [r0]
273	/* get the spsr */
274	mrs	lr, spsr
275	/* save spsr in position 1 of saved stack */
276	str	lr, [r0, #4]
277	/* restore lr */
278	ldr	lr, [r0]
279	/* restore r0 */
280	ldr	r0, [r13]
281	/* pop stack entry */
282	add	r13, r13, #4
283	.endm
284
285/*
286 * exception handlers
287 */
288	.align	5
289undefined_instruction:
290	get_bad_stack
291	bad_save_user_regs
292	bl	do_undefined_instruction
293
294	.align	5
295software_interrupt:
296	get_bad_stack_swi
297	bad_save_user_regs
298	bl	do_software_interrupt
299
300	.align	5
301prefetch_abort:
302	get_bad_stack
303	bad_save_user_regs
304	bl	do_prefetch_abort
305
306	.align	5
307data_abort:
308	get_bad_stack
309	bad_save_user_regs
310	bl	do_data_abort
311
312	.align	5
313not_used:
314	get_bad_stack
315	bad_save_user_regs
316	bl	do_not_used
317
318	.align	5
319irq:
320	get_bad_stack
321	bad_save_user_regs
322	bl	do_irq
323
324	.align	5
325fiq:
326	get_bad_stack
327	bad_save_user_regs
328	bl	do_fiq
329#endif /* CONFIG_SPL_BUILD */
330