xref: /openbmc/u-boot/arch/arm/cpu/arm1136/start.S (revision 544d97e9)
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.globl _TEXT_BASE
89_TEXT_BASE:
90	.word	TEXT_BASE
91
92#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
93.globl _armboot_start
94_armboot_start:
95	.word _start
96#endif
97
98/*
99 * These are defined in the board-specific linker script.
100 */
101.globl _bss_start
102_bss_start:
103	.word __bss_start
104
105.globl _bss_end
106_bss_end:
107	.word _end
108
109#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
110.globl _datarel_start
111_datarel_start:
112	.word __datarel_start
113
114.globl _datarelrolocal_start
115_datarelrolocal_start:
116	.word __datarelrolocal_start
117
118.globl _datarellocal_start
119_datarellocal_start:
120	.word __datarellocal_start
121
122.globl _datarelro_start
123_datarelro_start:
124	.word __datarelro_start
125
126.globl _got_start
127_got_start:
128	.word __got_start
129
130.globl _got_end
131_got_end:
132	.word __got_end
133#endif
134
135#ifdef CONFIG_USE_IRQ
136/* IRQ stack memory (calculated at run-time) */
137.globl IRQ_STACK_START
138IRQ_STACK_START:
139	.word	0x0badc0de
140
141/* IRQ stack memory (calculated at run-time) */
142.globl FIQ_STACK_START
143FIQ_STACK_START:
144	.word 0x0badc0de
145#endif
146
147#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
148/* IRQ stack memory (calculated at run-time) + 8 bytes */
149.globl IRQ_STACK_START_IN
150IRQ_STACK_START_IN:
151	.word	0x0badc0de
152#endif
153
154#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
155/*
156 * the actual reset code
157 */
158
159reset:
160	/*
161	 * set the cpu to SVC32 mode
162	 */
163	mrs	r0,cpsr
164	bic	r0,r0,#0x1f
165	orr	r0,r0,#0xd3
166	msr	cpsr,r0
167
168#ifdef CONFIG_OMAP2420H4
169       /* Copy vectors to mask ROM indirect addr */
170	adr	r0, _start		/* r0 <- current position of code   */
171		add     r0, r0, #4				/* skip reset vector			*/
172	mov	r2, #64			/* r2 <- size to copy  */
173	add	r2, r0, r2		/* r2 <- source end address	    */
174	mov	r1, #SRAM_OFFSET0	  /* build vect addr */
175	mov	r3, #SRAM_OFFSET1
176	add	r1, r1, r3
177	mov	r3, #SRAM_OFFSET2
178	add	r1, r1, r3
179next:
180	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
181	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
182	cmp	r0, r2			/* until source end address [r2]    */
183	bne	next			/* loop until equal */
184	bl	cpy_clk_code		/* put dpll adjust code behind vectors */
185#endif
186	/* the mask ROM code should have PLL and others stable */
187#ifndef CONFIG_SKIP_LOWLEVEL_INIT
188	bl  cpu_init_crit
189#endif
190
191/* Set stackpointer in internal RAM to call board_init_f */
192call_board_init_f:
193	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
194	ldr	r0,=0x00000000
195
196#ifdef CONFIG_NAND_SPL
197	bl	nand_boot
198#else
199#ifdef CONFIG_ONENAND_IPL
200	bl	start_oneboot
201#else
202	bl	board_init_f
203#endif /* CONFIG_ONENAND_IPL */
204#endif /* CONFIG_NAND_SPL */
205
206/*------------------------------------------------------------------------------*/
207
208/*
209 * void relocate_code (addr_sp, gd, addr_moni)
210 *
211 * This "function" does not return, instead it continues in RAM
212 * after relocating the monitor code.
213 *
214 */
215	.globl	relocate_code
216relocate_code:
217	mov	r4, r0	/* save addr_sp */
218	mov	r5, r1	/* save addr of gd */
219	mov	r6, r2	/* save addr of destination */
220	mov	r7, r2	/* save addr of destination */
221
222	/* Set up the stack						    */
223stack_setup:
224	mov	sp, r4
225
226	adr	r0, _start
227	ldr	r2, _TEXT_BASE
228	ldr	r3, _bss_start
229	sub	r2, r3, r2		/* r2 <- size of armboot	    */
230	add	r2, r0, r2		/* r2 <- source end address	    */
231	cmp	r0, r6
232	beq	clear_bss
233
234#ifndef CONFIG_SKIP_RELOCATE_UBOOT
235copy_loop:
236	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
237	stmia	r6!, {r9-r10}		/* copy to   target address [r1]    */
238	cmp	r0, r2			/* until source end addreee [r2]    */
239	ble	copy_loop
240
241#ifndef CONFIG_PRELOADER
242	/* fix got entries */
243	ldr	r1, _TEXT_BASE
244	mov	r0, r7			/* reloc addr */
245	ldr	r2, _got_start		/* addr in Flash */
246	ldr	r3, _got_end		/* addr in Flash */
247	sub	r3, r3, r1
248	add	r3, r3, r0
249	sub	r2, r2, r1
250	add	r2, r2, r0
251
252fixloop:
253	ldr	r4, [r2]
254	sub	r4, r4, r1
255	add	r4, r4, r0
256	str	r4, [r2]
257	add	r2, r2, #4
258	cmp	r2, r3
259	bne	fixloop
260#endif
261#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
262
263clear_bss:
264#ifndef CONFIG_PRELOADER
265	ldr	r0, _bss_start
266	ldr	r1, _bss_end
267	ldr	r3, _TEXT_BASE		/* Text base */
268	mov	r4, r7			/* reloc addr */
269	sub	r0, r0, r3
270	add	r0, r0, r4
271	sub	r1, r1, r3
272	add	r1, r1, r4
273	mov	r2, #0x00000000		/* clear			    */
274
275clbss_l:str	r2, [r0]		/* clear loop...		    */
276	add	r0, r0, #4
277	cmp	r0, r1
278	bne	clbss_l
279#endif	/* #ifndef CONFIG_PRELOADER */
280
281/*
282 * We are done. Do not return, instead branch to second part of board
283 * initialization, now running from RAM.
284 */
285#ifdef CONFIG_NAND_SPL
286	ldr     pc, _nand_boot
287
288_nand_boot: .word nand_boot
289#else
290jump_2_ram:
291	ldr	r0, _TEXT_BASE
292	ldr	r2, _board_init_r
293	sub	r2, r2, r0
294	add	r2, r2, r7	/* position from board_init_r in RAM */
295	/* setup parameters for board_init_r */
296	mov	r0, r5		/* gd_t */
297	mov	r1, r7		/* dest_addr */
298	/* jump to it ... */
299	mov	lr, r2
300	mov	pc, lr
301
302_board_init_r: .word board_init_r
303#endif
304#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
305/*
306 * the actual reset code
307 */
308
309reset:
310	/*
311	 * set the cpu to SVC32 mode
312	 */
313	mrs	r0,cpsr
314	bic	r0,r0,#0x1f
315	orr	r0,r0,#0xd3
316	msr	cpsr,r0
317
318#ifdef CONFIG_OMAP2420H4
319       /* Copy vectors to mask ROM indirect addr */
320	adr	r0, _start		/* r0 <- current position of code   */
321		add     r0, r0, #4				/* skip reset vector			*/
322	mov	r2, #64			/* r2 <- size to copy  */
323	add	r2, r0, r2		/* r2 <- source end address	    */
324	mov	r1, #SRAM_OFFSET0	  /* build vect addr */
325	mov	r3, #SRAM_OFFSET1
326	add	r1, r1, r3
327	mov	r3, #SRAM_OFFSET2
328	add	r1, r1, r3
329next:
330	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
331	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
332	cmp	r0, r2			/* until source end address [r2]    */
333	bne	next			/* loop until equal */
334	bl	cpy_clk_code		/* put dpll adjust code behind vectors */
335#endif
336	/* the mask ROM code should have PLL and others stable */
337#ifndef CONFIG_SKIP_LOWLEVEL_INIT
338	bl  cpu_init_crit
339#endif
340
341#ifndef CONFIG_SKIP_RELOCATE_UBOOT
342relocate:				/* relocate U-Boot to RAM	    */
343	adr	r0, _start		/* r0 <- current position of code   */
344	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
345	cmp	r0, r1			/* don't reloc during debug	    */
346#ifndef CONFIG_PRELOADER
347	beq	stack_setup
348#endif	/* CONFIG_PRELOADER */
349
350	ldr	r2, _armboot_start
351	ldr	r3, _bss_start
352	sub	r2, r3, r2		/* r2 <- size of armboot	    */
353	add	r2, r0, r2		/* r2 <- source end address	    */
354
355copy_loop:
356	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
357	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
358	cmp	r0, r2			/* until source end addreee [r2]    */
359	ble	copy_loop
360#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */
361
362	/* Set up the stack						    */
363stack_setup:
364	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
365#ifdef CONFIG_PRELOADER
366	sub	sp, r0, #128		/* leave 32 words for abort-stack   */
367#else
368	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area			    */
369	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo			    */
370#ifdef CONFIG_USE_IRQ
371	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
372#endif
373	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
374#endif	/* CONFIG_PRELOADER */
375	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
376
377clear_bss:
378	ldr	r0, _bss_start		/* find start of bss segment	    */
379	ldr	r1, _bss_end		/* stop here			    */
380	mov	r2, #0x00000000		/* clear			    */
381
382#ifndef CONFIG_PRELOADER
383clbss_l:str	r2, [r0]		/* clear loop...		    */
384	add	r0, r0, #4
385	cmp	r0, r1
386	bne	clbss_l
387#endif
388
389	ldr	pc, _start_armboot
390
391#ifdef CONFIG_NAND_SPL
392_start_armboot: .word nand_boot
393#else
394#ifdef CONFIG_ONENAND_IPL
395_start_armboot: .word start_oneboot
396#else
397_start_armboot: .word start_armboot
398#endif /* CONFIG_ONENAND_IPL */
399#endif /* CONFIG_NAND_SPL */
400
401#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
402
403/*
404 *************************************************************************
405 *
406 * CPU_init_critical registers
407 *
408 * setup important registers
409 * setup memory timing
410 *
411 *************************************************************************
412 */
413#ifndef CONFIG_SKIP_LOWLEVEL_INIT
414cpu_init_crit:
415	/*
416	 * flush v4 I/D caches
417	 */
418	mov	r0, #0
419	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
420	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
421
422	/*
423	 * disable MMU stuff and caches
424	 */
425	mrc	p15, 0, r0, c1, c0, 0
426	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
427	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
428	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
429	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
430	mcr	p15, 0, r0, c1, c0, 0
431
432	/*
433	 * Jump to board specific initialization... The Mask ROM will have already initialized
434	 * basic memory.  Go here to bump up clock rate and handle wake up conditions.
435	 */
436	mov	ip, lr		/* persevere link reg across call */
437	bl	lowlevel_init	/* go setup pll,mux,memory */
438	mov	lr, ip		/* restore link */
439	mov	pc, lr		/* back to my caller */
440#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
441
442#ifndef CONFIG_PRELOADER
443/*
444 *************************************************************************
445 *
446 * Interrupt handling
447 *
448 *************************************************************************
449 */
450@
451@ IRQ stack frame.
452@
453#define S_FRAME_SIZE	72
454
455#define S_OLD_R0	68
456#define S_PSR		64
457#define S_PC		60
458#define S_LR		56
459#define S_SP		52
460
461#define S_IP		48
462#define S_FP		44
463#define S_R10		40
464#define S_R9		36
465#define S_R8		32
466#define S_R7		28
467#define S_R6		24
468#define S_R5		20
469#define S_R4		16
470#define S_R3		12
471#define S_R2		8
472#define S_R1		4
473#define S_R0		0
474
475#define MODE_SVC 0x13
476#define I_BIT	 0x80
477
478/*
479 * use bad_save_user_regs for abort/prefetch/undef/swi ...
480 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
481 */
482
483	.macro	bad_save_user_regs
484	sub	sp, sp, #S_FRAME_SIZE		@ carve out a frame on current user stack
485	stmia	sp, {r0 - r12}			@ Save user registers (now in svc mode) r0-r12
486
487#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
488	ldr	r2, IRQ_STACK_START_IN		@ set base 2 words into abort stack
489#else
490	ldr	r2, _armboot_start
491	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
492	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
493#endif
494	ldmia	r2, {r2 - r3}			@ get values for "aborted" pc and cpsr (into parm regs)
495	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
496
497	add	r5, sp, #S_SP
498	mov	r1, lr
499	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
500	mov	r0, sp				@ save current stack into r0 (param register)
501	.endm
502
503	.macro	irq_save_user_regs
504	sub	sp, sp, #S_FRAME_SIZE
505	stmia	sp, {r0 - r12}			@ Calling r0-r12
506	add	r8, sp, #S_PC			@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
507	stmdb	r8, {sp, lr}^			@ Calling SP, LR
508	str	lr, [r8, #0]			@ Save calling PC
509	mrs	r6, spsr
510	str	r6, [r8, #4]			@ Save CPSR
511	str	r0, [r8, #8]			@ Save OLD_R0
512	mov	r0, sp
513	.endm
514
515	.macro	irq_restore_user_regs
516	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
517	mov	r0, r0
518	ldr	lr, [sp, #S_PC]			@ Get PC
519	add	sp, sp, #S_FRAME_SIZE
520	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
521	.endm
522
523	.macro get_bad_stack
524#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
525	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack (enter in banked mode)
526#else
527	ldr	r13, _armboot_start		@ setup our mode stack (enter in banked mode)
528	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
529	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack
530#endif
531
532	str	lr, [r13]			@ save caller lr in position 0 of saved stack
533	mrs	lr, spsr			@ get the spsr
534	str	lr, [r13, #4]			@ save spsr in position 1 of saved stack
535
536	mov	r13, #MODE_SVC			@ prepare SVC-Mode
537	@ msr	spsr_c, r13
538	msr	spsr, r13			@ switch modes, make sure moves will execute
539	mov	lr, pc				@ capture return pc
540	movs	pc, lr				@ jump to next instruction & switch modes.
541	.endm
542
543	.macro get_bad_stack_swi
544	sub	r13, r13, #4			@ space on current stack for scratch reg.
545	str	r0, [r13]			@ save R0's value.
546#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
547	ldr	r0, IRQ_STACK_START_IN		@ get data regions start
548#else
549	ldr	r0, _armboot_start		@ get data regions start
550	sub	r0, r0, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
551	sub	r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ move past gbl and a couple spots for abort stack
552#endif
553	str	lr, [r0]			@ save caller lr in position 0 of saved stack
554	mrs	r0, spsr			@ get the spsr
555	str	lr, [r0, #4]			@ save spsr in position 1 of saved stack
556	ldr	r0, [r13]			@ restore r0
557	add	r13, r13, #4			@ pop stack entry
558	.endm
559
560	.macro get_irq_stack			@ setup IRQ stack
561	ldr	sp, IRQ_STACK_START
562	.endm
563
564	.macro get_fiq_stack			@ setup FIQ stack
565	ldr	sp, FIQ_STACK_START
566	.endm
567#endif	/* CONFIG_PRELOADER */
568
569/*
570 * exception handlers
571 */
572#ifdef CONFIG_PRELOADER
573	.align	5
574do_hang:
575	ldr	sp, _TEXT_BASE			/* use 32 words about stack */
576	bl	hang				/* hang and never return */
577#else	/* !CONFIG_PRELOADER */
578	.align	5
579undefined_instruction:
580	get_bad_stack
581	bad_save_user_regs
582	bl	do_undefined_instruction
583
584	.align	5
585software_interrupt:
586	get_bad_stack_swi
587	bad_save_user_regs
588	bl	do_software_interrupt
589
590	.align	5
591prefetch_abort:
592	get_bad_stack
593	bad_save_user_regs
594	bl	do_prefetch_abort
595
596	.align	5
597data_abort:
598	get_bad_stack
599	bad_save_user_regs
600	bl	do_data_abort
601
602	.align	5
603not_used:
604	get_bad_stack
605	bad_save_user_regs
606	bl	do_not_used
607
608#ifdef CONFIG_USE_IRQ
609
610	.align	5
611irq:
612	get_irq_stack
613	irq_save_user_regs
614	bl	do_irq
615	irq_restore_user_regs
616
617	.align	5
618fiq:
619	get_fiq_stack
620	/* someone ought to write a more effiction fiq_save_user_regs */
621	irq_save_user_regs
622	bl	do_fiq
623	irq_restore_user_regs
624
625#else
626
627	.align	5
628irq:
629	get_bad_stack
630	bad_save_user_regs
631	bl	do_irq
632
633	.align	5
634fiq:
635	get_bad_stack
636	bad_save_user_regs
637	bl	do_fiq
638
639#endif
640	.align 5
641.global arm1136_cache_flush
642arm1136_cache_flush:
643#if !defined(CONFIG_SYS_NO_ICACHE)
644		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I cache
645#endif
646#if !defined(CONFIG_SYS_NO_DCACHE)
647		mcr	p15, 0, r1, c7, c14, 0	@ invalidate D cache
648#endif
649		mov	pc, lr			@ back to caller
650#endif	/* CONFIG_PRELOADER */
651