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	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
189
190clear_bss:
191	ldr	r0, _bss_start		/* find start of bss segment	    */
192	ldr	r1, _bss_end		/* stop here			    */
193	mov	r2, #0x00000000		/* clear			    */
194
195#ifndef CONFIG_PRELOADER
196clbss_l:str	r2, [r0]		/* clear loop...		    */
197	add	r0, r0, #4
198	cmp	r0, r1
199	bne	clbss_l
200#endif
201
202	ldr	pc, _start_armboot
203
204#ifdef CONFIG_NAND_SPL
205_start_armboot: .word nand_boot
206#else
207#ifdef CONFIG_ONENAND_IPL
208_start_armboot: .word start_oneboot
209#else
210_start_armboot: .word start_armboot
211#endif /* CONFIG_ONENAND_IPL */
212#endif /* CONFIG_NAND_SPL */
213
214/*
215 *************************************************************************
216 *
217 * CPU_init_critical registers
218 *
219 * setup important registers
220 * setup memory timing
221 *
222 *************************************************************************
223 */
224#ifndef CONFIG_SKIP_LOWLEVEL_INIT
225cpu_init_crit:
226	/*
227	 * flush v4 I/D caches
228	 */
229	mov	r0, #0
230	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
231	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
232
233	/*
234	 * disable MMU stuff and caches
235	 */
236	mrc	p15, 0, r0, c1, c0, 0
237	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
238	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
239	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
240	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
241	mcr	p15, 0, r0, c1, c0, 0
242
243	/*
244	 * Jump to board specific initialization... The Mask ROM will have already initialized
245	 * basic memory.  Go here to bump up clock rate and handle wake up conditions.
246	 */
247	mov	ip, lr		/* persevere link reg across call */
248	bl	lowlevel_init	/* go setup pll,mux,memory */
249	mov	lr, ip		/* restore link */
250	mov	pc, lr		/* back to my caller */
251#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
252
253#ifndef CONFIG_PRELOADER
254/*
255 *************************************************************************
256 *
257 * Interrupt handling
258 *
259 *************************************************************************
260 */
261@
262@ IRQ stack frame.
263@
264#define S_FRAME_SIZE	72
265
266#define S_OLD_R0	68
267#define S_PSR		64
268#define S_PC		60
269#define S_LR		56
270#define S_SP		52
271
272#define S_IP		48
273#define S_FP		44
274#define S_R10		40
275#define S_R9		36
276#define S_R8		32
277#define S_R7		28
278#define S_R6		24
279#define S_R5		20
280#define S_R4		16
281#define S_R3		12
282#define S_R2		8
283#define S_R1		4
284#define S_R0		0
285
286#define MODE_SVC 0x13
287#define I_BIT	 0x80
288
289/*
290 * use bad_save_user_regs for abort/prefetch/undef/swi ...
291 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
292 */
293
294	.macro	bad_save_user_regs
295	sub	sp, sp, #S_FRAME_SIZE		@ carve out a frame on current user stack
296	stmia	sp, {r0 - r12}			@ Save user registers (now in svc mode) r0-r12
297
298	ldr	r2, _armboot_start
299	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
300	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
301	ldmia	r2, {r2 - r3}			@ get values for "aborted" pc and cpsr (into parm regs)
302	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
303
304	add	r5, sp, #S_SP
305	mov	r1, lr
306	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
307	mov	r0, sp				@ save current stack into r0 (param register)
308	.endm
309
310	.macro	irq_save_user_regs
311	sub	sp, sp, #S_FRAME_SIZE
312	stmia	sp, {r0 - r12}			@ Calling r0-r12
313	add	r8, sp, #S_PC			@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
314	stmdb	r8, {sp, lr}^			@ Calling SP, LR
315	str	lr, [r8, #0]			@ Save calling PC
316	mrs	r6, spsr
317	str	r6, [r8, #4]			@ Save CPSR
318	str	r0, [r8, #8]			@ Save OLD_R0
319	mov	r0, sp
320	.endm
321
322	.macro	irq_restore_user_regs
323	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
324	mov	r0, r0
325	ldr	lr, [sp, #S_PC]			@ Get PC
326	add	sp, sp, #S_FRAME_SIZE
327	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
328	.endm
329
330	.macro get_bad_stack
331	ldr	r13, _armboot_start		@ setup our mode stack (enter in banked mode)
332	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
333	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack
334
335	str	lr, [r13]			@ save caller lr in position 0 of saved stack
336	mrs	lr, spsr			@ get the spsr
337	str	lr, [r13, #4]			@ save spsr in position 1 of saved stack
338
339	mov	r13, #MODE_SVC			@ prepare SVC-Mode
340	@ msr	spsr_c, r13
341	msr	spsr, r13			@ switch modes, make sure moves will execute
342	mov	lr, pc				@ capture return pc
343	movs	pc, lr				@ jump to next instruction & switch modes.
344	.endm
345
346	.macro get_bad_stack_swi
347	sub	r13, r13, #4			@ space on current stack for scratch reg.
348	str	r0, [r13]			@ save R0's value.
349	ldr	r0, _armboot_start		@ get data regions start
350	sub	r0, r0, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
351	sub	r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ move past gbl and a couple spots for abort stack
352	str	lr, [r0]			@ save caller lr in position 0 of saved stack
353	mrs	r0, spsr			@ get the spsr
354	str	lr, [r0, #4]			@ save spsr in position 1 of saved stack
355	ldr	r0, [r13]			@ restore r0
356	add	r13, r13, #4			@ pop stack entry
357	.endm
358
359	.macro get_irq_stack			@ setup IRQ stack
360	ldr	sp, IRQ_STACK_START
361	.endm
362
363	.macro get_fiq_stack			@ setup FIQ stack
364	ldr	sp, FIQ_STACK_START
365	.endm
366#endif	/* CONFIG_PRELOADER */
367
368/*
369 * exception handlers
370 */
371#ifdef CONFIG_PRELOADER
372	.align	5
373do_hang:
374	ldr	sp, _TEXT_BASE			/* use 32 words about stack */
375	bl	hang				/* hang and never return */
376#else	/* !CONFIG_PRELOADER */
377	.align	5
378undefined_instruction:
379	get_bad_stack
380	bad_save_user_regs
381	bl	do_undefined_instruction
382
383	.align	5
384software_interrupt:
385	get_bad_stack_swi
386	bad_save_user_regs
387	bl	do_software_interrupt
388
389	.align	5
390prefetch_abort:
391	get_bad_stack
392	bad_save_user_regs
393	bl	do_prefetch_abort
394
395	.align	5
396data_abort:
397	get_bad_stack
398	bad_save_user_regs
399	bl	do_data_abort
400
401	.align	5
402not_used:
403	get_bad_stack
404	bad_save_user_regs
405	bl	do_not_used
406
407#ifdef CONFIG_USE_IRQ
408
409	.align	5
410irq:
411	get_irq_stack
412	irq_save_user_regs
413	bl	do_irq
414	irq_restore_user_regs
415
416	.align	5
417fiq:
418	get_fiq_stack
419	/* someone ought to write a more effiction fiq_save_user_regs */
420	irq_save_user_regs
421	bl	do_fiq
422	irq_restore_user_regs
423
424#else
425
426	.align	5
427irq:
428	get_bad_stack
429	bad_save_user_regs
430	bl	do_irq
431
432	.align	5
433fiq:
434	get_bad_stack
435	bad_save_user_regs
436	bl	do_fiq
437
438#endif
439	.align 5
440.global arm1136_cache_flush
441arm1136_cache_flush:
442		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I cache
443		mov	pc, lr			@ back to caller
444#endif	/* CONFIG_PRELOADER */
445