xref: /openbmc/u-boot/arch/arm/cpu/arm1136/start.S (revision 441cac10)
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 * See file CREDITS for list of people who contributed to this
13 * project.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 * MA 02111-1307 USA
29 */
30
31#include <config.h>
32#include <version.h>
33.globl _start
34_start: b	reset
35#ifdef CONFIG_PRELOADER
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	ldr	pc, _hang
43
44_hang:
45	.word	do_hang
46	.word	0x12345678
47	.word	0x12345678
48	.word	0x12345678
49	.word	0x12345678
50	.word	0x12345678
51	.word	0x12345678
52	.word	0x12345678	/* now 16*4=64 */
53#else
54	ldr	pc, _undefined_instruction
55	ldr	pc, _software_interrupt
56	ldr	pc, _prefetch_abort
57	ldr	pc, _data_abort
58	ldr	pc, _not_used
59	ldr	pc, _irq
60	ldr	pc, _fiq
61
62_undefined_instruction: .word undefined_instruction
63_software_interrupt:	.word software_interrupt
64_prefetch_abort:	.word prefetch_abort
65_data_abort:		.word data_abort
66_not_used:		.word not_used
67_irq:			.word irq
68_fiq:			.word fiq
69_pad:			.word 0x12345678 /* now 16*4=64 */
70#endif	/* CONFIG_PRELOADER */
71.global _end_vect
72_end_vect:
73
74	.balignl 16,0xdeadbeef
75/*
76 *************************************************************************
77 *
78 * Startup Code (reset vector)
79 *
80 * do important init only if we don't start from memory!
81 * setup Memory and board specific bits prior to relocation.
82 * relocate armboot to ram
83 * setup stack
84 *
85 *************************************************************************
86 */
87
88_TEXT_BASE:
89	.word	TEXT_BASE
90
91.globl _armboot_start
92_armboot_start:
93	.word _start
94
95/*
96 * These are defined in the board-specific linker script.
97 */
98.globl _bss_start
99_bss_start:
100	.word __bss_start
101
102.globl _bss_end
103_bss_end:
104	.word _end
105
106#ifdef CONFIG_USE_IRQ
107/* IRQ stack memory (calculated at run-time) */
108.globl IRQ_STACK_START
109IRQ_STACK_START:
110	.word	0x0badc0de
111
112/* IRQ stack memory (calculated at run-time) */
113.globl FIQ_STACK_START
114FIQ_STACK_START:
115	.word 0x0badc0de
116#endif
117
118/*
119 * the actual reset code
120 */
121
122reset:
123	/*
124	 * set the cpu to SVC32 mode
125	 */
126	mrs	r0,cpsr
127	bic	r0,r0,#0x1f
128	orr	r0,r0,#0xd3
129	msr	cpsr,r0
130
131#ifdef CONFIG_OMAP2420H4
132       /* Copy vectors to mask ROM indirect addr */
133	adr	r0, _start		/* r0 <- current position of code   */
134		add     r0, r0, #4				/* skip reset vector			*/
135	mov	r2, #64			/* r2 <- size to copy  */
136	add	r2, r0, r2		/* r2 <- source end address	    */
137	mov	r1, #SRAM_OFFSET0	  /* build vect addr */
138	mov	r3, #SRAM_OFFSET1
139	add	r1, r1, r3
140	mov	r3, #SRAM_OFFSET2
141	add	r1, r1, r3
142next:
143	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
144	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
145	cmp	r0, r2			/* until source end address [r2]    */
146	bne	next			/* loop until equal */
147	bl	cpy_clk_code		/* put dpll adjust code behind vectors */
148#endif
149	/* the mask ROM code should have PLL and others stable */
150#ifndef CONFIG_SKIP_LOWLEVEL_INIT
151	bl  cpu_init_crit
152#endif
153
154#ifndef CONFIG_SKIP_RELOCATE_UBOOT
155relocate:				/* relocate U-Boot to RAM	    */
156	adr	r0, _start		/* r0 <- current position of code   */
157	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
158	cmp	r0, r1			/* don't reloc during debug	    */
159#ifndef CONFIG_PRELOADER
160	beq	stack_setup
161#endif	/* CONFIG_PRELOADER */
162
163	ldr	r2, _armboot_start
164	ldr	r3, _bss_start
165	sub	r2, r3, r2		/* r2 <- size of armboot	    */
166	add	r2, r0, r2		/* r2 <- source end address	    */
167
168copy_loop:
169	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
170	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
171	cmp	r0, r2			/* until source end addreee [r2]    */
172	ble	copy_loop
173#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */
174
175	/* Set up the stack						    */
176stack_setup:
177	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
178#ifdef CONFIG_PRELOADER
179	sub	sp, r0, #128		/* leave 32 words for abort-stack   */
180#else
181	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area			    */
182	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo			    */
183#ifdef CONFIG_USE_IRQ
184	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
185#endif
186	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
187#endif	/* CONFIG_PRELOADER */
188
189clear_bss:
190	ldr	r0, _bss_start		/* find start of bss segment	    */
191	ldr	r1, _bss_end		/* stop here			    */
192	mov	r2, #0x00000000		/* clear			    */
193
194#ifndef CONFIG_PRELOADER
195clbss_l:str	r2, [r0]		/* clear loop...		    */
196	add	r0, r0, #4
197	cmp	r0, r1
198	bne	clbss_l
199#endif
200
201	ldr	pc, _start_armboot
202
203#ifdef CONFIG_NAND_SPL
204_start_armboot: .word nand_boot
205#else
206#ifdef CONFIG_ONENAND_IPL
207_start_armboot: .word start_oneboot
208#else
209_start_armboot: .word start_armboot
210#endif /* CONFIG_ONENAND_IPL */
211#endif /* CONFIG_NAND_SPL */
212
213/*
214 *************************************************************************
215 *
216 * CPU_init_critical registers
217 *
218 * setup important registers
219 * setup memory timing
220 *
221 *************************************************************************
222 */
223#ifndef CONFIG_SKIP_LOWLEVEL_INIT
224cpu_init_crit:
225	/*
226	 * flush v4 I/D caches
227	 */
228	mov	r0, #0
229	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
230	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
231
232	/*
233	 * disable MMU stuff and caches
234	 */
235	mrc	p15, 0, r0, c1, c0, 0
236	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
237	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
238	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
239	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
240	mcr	p15, 0, r0, c1, c0, 0
241
242	/*
243	 * Jump to board specific initialization... The Mask ROM will have already initialized
244	 * basic memory.  Go here to bump up clock rate and handle wake up conditions.
245	 */
246	mov	ip, lr		/* persevere link reg across call */
247	bl	lowlevel_init	/* go setup pll,mux,memory */
248	mov	lr, ip		/* restore link */
249	mov	pc, lr		/* back to my caller */
250#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
251
252#ifndef CONFIG_PRELOADER
253/*
254 *************************************************************************
255 *
256 * Interrupt handling
257 *
258 *************************************************************************
259 */
260@
261@ IRQ stack frame.
262@
263#define S_FRAME_SIZE	72
264
265#define S_OLD_R0	68
266#define S_PSR		64
267#define S_PC		60
268#define S_LR		56
269#define S_SP		52
270
271#define S_IP		48
272#define S_FP		44
273#define S_R10		40
274#define S_R9		36
275#define S_R8		32
276#define S_R7		28
277#define S_R6		24
278#define S_R5		20
279#define S_R4		16
280#define S_R3		12
281#define S_R2		8
282#define S_R1		4
283#define S_R0		0
284
285#define MODE_SVC 0x13
286#define I_BIT	 0x80
287
288/*
289 * use bad_save_user_regs for abort/prefetch/undef/swi ...
290 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
291 */
292
293	.macro	bad_save_user_regs
294	sub	sp, sp, #S_FRAME_SIZE		@ carve out a frame on current user stack
295	stmia	sp, {r0 - r12}			@ Save user registers (now in svc mode) r0-r12
296
297	ldr	r2, _armboot_start
298	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
299	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
300	ldmia	r2, {r2 - r3}			@ get values for "aborted" pc and cpsr (into parm regs)
301	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
302
303	add	r5, sp, #S_SP
304	mov	r1, lr
305	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
306	mov	r0, sp				@ save current stack into r0 (param register)
307	.endm
308
309	.macro	irq_save_user_regs
310	sub	sp, sp, #S_FRAME_SIZE
311	stmia	sp, {r0 - r12}			@ Calling r0-r12
312	add	r8, sp, #S_PC			@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
313	stmdb	r8, {sp, lr}^			@ Calling SP, LR
314	str	lr, [r8, #0]			@ Save calling PC
315	mrs	r6, spsr
316	str	r6, [r8, #4]			@ Save CPSR
317	str	r0, [r8, #8]			@ Save OLD_R0
318	mov	r0, sp
319	.endm
320
321	.macro	irq_restore_user_regs
322	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
323	mov	r0, r0
324	ldr	lr, [sp, #S_PC]			@ Get PC
325	add	sp, sp, #S_FRAME_SIZE
326	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
327	.endm
328
329	.macro get_bad_stack
330	ldr	r13, _armboot_start		@ setup our mode stack (enter in banked mode)
331	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
332	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack
333
334	str	lr, [r13]			@ save caller lr in position 0 of saved stack
335	mrs	lr, spsr			@ get the spsr
336	str	lr, [r13, #4]			@ save spsr in position 1 of saved stack
337
338	mov	r13, #MODE_SVC			@ prepare SVC-Mode
339	@ msr	spsr_c, r13
340	msr	spsr, r13			@ switch modes, make sure moves will execute
341	mov	lr, pc				@ capture return pc
342	movs	pc, lr				@ jump to next instruction & switch modes.
343	.endm
344
345	.macro get_bad_stack_swi
346	sub	r13, r13, #4			@ space on current stack for scratch reg.
347	str	r0, [r13]			@ save R0's value.
348	ldr	r0, _armboot_start		@ get data regions start
349	sub	r0, r0, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
350	sub	r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ move past gbl and a couple spots for abort stack
351	str	lr, [r0]			@ save caller lr in position 0 of saved stack
352	mrs	r0, spsr			@ get the spsr
353	str	lr, [r0, #4]			@ save spsr in position 1 of saved stack
354	ldr	r0, [r13]			@ restore r0
355	add	r13, r13, #4			@ pop stack entry
356	.endm
357
358	.macro get_irq_stack			@ setup IRQ stack
359	ldr	sp, IRQ_STACK_START
360	.endm
361
362	.macro get_fiq_stack			@ setup FIQ stack
363	ldr	sp, FIQ_STACK_START
364	.endm
365#endif	/* CONFIG_PRELOADER */
366
367/*
368 * exception handlers
369 */
370#ifdef CONFIG_PRELOADER
371	.align	5
372do_hang:
373	ldr	sp, _TEXT_BASE			/* use 32 words about stack */
374	bl	hang				/* hang and never return */
375#else	/* !CONFIG_PRELOADER */
376	.align	5
377undefined_instruction:
378	get_bad_stack
379	bad_save_user_regs
380	bl	do_undefined_instruction
381
382	.align	5
383software_interrupt:
384	get_bad_stack_swi
385	bad_save_user_regs
386	bl	do_software_interrupt
387
388	.align	5
389prefetch_abort:
390	get_bad_stack
391	bad_save_user_regs
392	bl	do_prefetch_abort
393
394	.align	5
395data_abort:
396	get_bad_stack
397	bad_save_user_regs
398	bl	do_data_abort
399
400	.align	5
401not_used:
402	get_bad_stack
403	bad_save_user_regs
404	bl	do_not_used
405
406#ifdef CONFIG_USE_IRQ
407
408	.align	5
409irq:
410	get_irq_stack
411	irq_save_user_regs
412	bl	do_irq
413	irq_restore_user_regs
414
415	.align	5
416fiq:
417	get_fiq_stack
418	/* someone ought to write a more effiction fiq_save_user_regs */
419	irq_save_user_regs
420	bl	do_fiq
421	irq_restore_user_regs
422
423#else
424
425	.align	5
426irq:
427	get_bad_stack
428	bad_save_user_regs
429	bl	do_irq
430
431	.align	5
432fiq:
433	get_bad_stack
434	bad_save_user_regs
435	bl	do_fiq
436
437#endif
438	.align 5
439.global arm1136_cache_flush
440arm1136_cache_flush:
441		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I cache
442		mov	pc, lr			@ back to caller
443#endif	/* CONFIG_PRELOADER */
444