xref: /openbmc/u-boot/arch/arm/cpu/pxa/start.S (revision 5347f68c)
184ad6884SPeter Tyser/*
284ad6884SPeter Tyser *  armboot - Startup Code for XScale
384ad6884SPeter Tyser *
484ad6884SPeter Tyser *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
584ad6884SPeter Tyser *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
684ad6884SPeter Tyser *  Copyright (C) 2000	Wolfgang Denk <wd@denx.de>
784ad6884SPeter Tyser *  Copyright (C) 2001	Alex Zuepke <azu@sysgo.de>
884ad6884SPeter Tyser *  Copyright (C) 2002	Kyle Harris <kharris@nexus-tech.net>
984ad6884SPeter Tyser *  Copyright (C) 2003	Robert Schwebel <r.schwebel@pengutronix.de>
1084ad6884SPeter Tyser *  Copyright (C) 2003	Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
1184ad6884SPeter Tyser *
1284ad6884SPeter Tyser * See file CREDITS for list of people who contributed to this
1384ad6884SPeter Tyser * project.
1484ad6884SPeter Tyser *
1584ad6884SPeter Tyser * This program is free software; you can redistribute it and/or
1684ad6884SPeter Tyser * modify it under the terms of the GNU General Public License as
1784ad6884SPeter Tyser * published by the Free Software Foundation; either version 2 of
1884ad6884SPeter Tyser * the License, or (at your option) any later version.
1984ad6884SPeter Tyser *
2084ad6884SPeter Tyser * This program is distributed in the hope that it will be useful,
2184ad6884SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of
2284ad6884SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
2384ad6884SPeter Tyser * GNU General Public License for more details.
2484ad6884SPeter Tyser *
2584ad6884SPeter Tyser * You should have received a copy of the GNU General Public License
2684ad6884SPeter Tyser * along with this program; if not, write to the Free Software
2784ad6884SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2884ad6884SPeter Tyser * MA 02111-1307 USA
2984ad6884SPeter Tyser */
3084ad6884SPeter Tyser
3184ad6884SPeter Tyser#include <config.h>
3284ad6884SPeter Tyser#include <version.h>
3384ad6884SPeter Tyser#include <asm/arch/pxa-regs.h>
3484ad6884SPeter Tyser
3584ad6884SPeter Tyser.globl _start
3684ad6884SPeter Tyser_start: b	reset
375ab877b6SMarek Vasut#ifdef CONFIG_PRELOADER
385ab877b6SMarek Vasut	ldr	pc, _hang
395ab877b6SMarek Vasut	ldr	pc, _hang
405ab877b6SMarek Vasut	ldr	pc, _hang
415ab877b6SMarek Vasut	ldr	pc, _hang
425ab877b6SMarek Vasut	ldr	pc, _hang
435ab877b6SMarek Vasut	ldr	pc, _hang
445ab877b6SMarek Vasut	ldr	pc, _hang
455ab877b6SMarek Vasut
465ab877b6SMarek Vasut_hang:
475ab877b6SMarek Vasut	.word	do_hang
485ab877b6SMarek Vasut	.word	0x12345678
495ab877b6SMarek Vasut	.word	0x12345678
505ab877b6SMarek Vasut	.word	0x12345678
515ab877b6SMarek Vasut	.word	0x12345678
525ab877b6SMarek Vasut	.word	0x12345678
535ab877b6SMarek Vasut	.word	0x12345678
545ab877b6SMarek Vasut	.word	0x12345678	/* now 16*4=64 */
555ab877b6SMarek Vasut#else
5684ad6884SPeter Tyser	ldr	pc, _undefined_instruction
5784ad6884SPeter Tyser	ldr	pc, _software_interrupt
5884ad6884SPeter Tyser	ldr	pc, _prefetch_abort
5984ad6884SPeter Tyser	ldr	pc, _data_abort
6084ad6884SPeter Tyser	ldr	pc, _not_used
6184ad6884SPeter Tyser	ldr	pc, _irq
6284ad6884SPeter Tyser	ldr	pc, _fiq
6384ad6884SPeter Tyser
6484ad6884SPeter Tyser_undefined_instruction: .word undefined_instruction
6584ad6884SPeter Tyser_software_interrupt:	.word software_interrupt
6684ad6884SPeter Tyser_prefetch_abort:	.word prefetch_abort
6784ad6884SPeter Tyser_data_abort:		.word data_abort
6884ad6884SPeter Tyser_not_used:		.word not_used
6984ad6884SPeter Tyser_irq:			.word irq
7084ad6884SPeter Tyser_fiq:			.word fiq
715ab877b6SMarek Vasut#endif	/* CONFIG_PRELOADER */
7284ad6884SPeter Tyser
7384ad6884SPeter Tyser	.balignl 16,0xdeadbeef
7484ad6884SPeter Tyser
7584ad6884SPeter Tyser
7684ad6884SPeter Tyser/*
7784ad6884SPeter Tyser * Startup Code (reset vector)
7884ad6884SPeter Tyser *
7984ad6884SPeter Tyser * do important init only if we don't start from RAM!
8084ad6884SPeter Tyser * - relocate armboot to RAM
8184ad6884SPeter Tyser * - setup stack
8284ad6884SPeter Tyser * - jump to second stage
8384ad6884SPeter Tyser */
8484ad6884SPeter Tyser
85*5347f68cSHeiko Schocher.globl _TEXT_BASE
8684ad6884SPeter Tyser_TEXT_BASE:
8784ad6884SPeter Tyser	.word	TEXT_BASE
8884ad6884SPeter Tyser
89*5347f68cSHeiko Schocher#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
9084ad6884SPeter Tyser.globl _armboot_start
9184ad6884SPeter Tyser_armboot_start:
9284ad6884SPeter Tyser	.word _start
93*5347f68cSHeiko Schocher#endif
9484ad6884SPeter Tyser
9584ad6884SPeter Tyser/*
9684ad6884SPeter Tyser * These are defined in the board-specific linker script.
9784ad6884SPeter Tyser */
9884ad6884SPeter Tyser.globl _bss_start
9984ad6884SPeter Tyser_bss_start:
10084ad6884SPeter Tyser	.word __bss_start
10184ad6884SPeter Tyser
10284ad6884SPeter Tyser.globl _bss_end
10384ad6884SPeter Tyser_bss_end:
10484ad6884SPeter Tyser	.word _end
10584ad6884SPeter Tyser
10684ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
10784ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */
10884ad6884SPeter Tyser.globl IRQ_STACK_START
10984ad6884SPeter TyserIRQ_STACK_START:
11084ad6884SPeter Tyser	.word	0x0badc0de
11184ad6884SPeter Tyser
11284ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */
11384ad6884SPeter Tyser.globl FIQ_STACK_START
11484ad6884SPeter TyserFIQ_STACK_START:
11584ad6884SPeter Tyser	.word 0x0badc0de
11684ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
11784ad6884SPeter Tyser
118*5347f68cSHeiko Schocher#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
119*5347f68cSHeiko Schocher/* IRQ stack memory (calculated at run-time) + 8 bytes */
120*5347f68cSHeiko Schocher.globl IRQ_STACK_START_IN
121*5347f68cSHeiko SchocherIRQ_STACK_START_IN:
122*5347f68cSHeiko Schocher	.word	0x0badc0de
123*5347f68cSHeiko Schocher
124*5347f68cSHeiko Schocher.globl _datarel_start
125*5347f68cSHeiko Schocher_datarel_start:
126*5347f68cSHeiko Schocher	.word __datarel_start
127*5347f68cSHeiko Schocher
128*5347f68cSHeiko Schocher.globl _datarelrolocal_start
129*5347f68cSHeiko Schocher_datarelrolocal_start:
130*5347f68cSHeiko Schocher	.word __datarelrolocal_start
131*5347f68cSHeiko Schocher
132*5347f68cSHeiko Schocher.globl _datarellocal_start
133*5347f68cSHeiko Schocher_datarellocal_start:
134*5347f68cSHeiko Schocher	.word __datarellocal_start
135*5347f68cSHeiko Schocher
136*5347f68cSHeiko Schocher.globl _datarelro_start
137*5347f68cSHeiko Schocher_datarelro_start:
138*5347f68cSHeiko Schocher	.word __datarelro_start
139*5347f68cSHeiko Schocher
140*5347f68cSHeiko Schocher.globl _got_start
141*5347f68cSHeiko Schocher_got_start:
142*5347f68cSHeiko Schocher	.word __got_start
143*5347f68cSHeiko Schocher
144*5347f68cSHeiko Schocher.globl _got_end
145*5347f68cSHeiko Schocher_got_end:
146*5347f68cSHeiko Schocher	.word __got_end
147*5347f68cSHeiko Schocher
148*5347f68cSHeiko Schocher/*
149*5347f68cSHeiko Schocher * the actual reset code
150*5347f68cSHeiko Schocher */
151*5347f68cSHeiko Schocher
152*5347f68cSHeiko Schocherreset:
153*5347f68cSHeiko Schocher	/*
154*5347f68cSHeiko Schocher	 * set the cpu to SVC32 mode
155*5347f68cSHeiko Schocher	 */
156*5347f68cSHeiko Schocher	mrs	r0,cpsr
157*5347f68cSHeiko Schocher	bic	r0,r0,#0x1f
158*5347f68cSHeiko Schocher	orr	r0,r0,#0xd3
159*5347f68cSHeiko Schocher	msr	cpsr,r0
160*5347f68cSHeiko Schocher
161*5347f68cSHeiko Schocher	/*
162*5347f68cSHeiko Schocher	 * we do sys-critical inits only at reboot,
163*5347f68cSHeiko Schocher	 * not when booting from ram!
164*5347f68cSHeiko Schocher	 */
165*5347f68cSHeiko Schocher#ifndef CONFIG_SKIP_LOWLEVEL_INIT
166*5347f68cSHeiko Schocher	bl	cpu_init_crit
167*5347f68cSHeiko Schocher#endif
168*5347f68cSHeiko Schocher
169*5347f68cSHeiko Schocher/* Set stackpointer in internal RAM to call board_init_f */
170*5347f68cSHeiko Schochercall_board_init_f:
171*5347f68cSHeiko Schocher	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
172*5347f68cSHeiko Schocher	ldr	r0,=0x00000000
173*5347f68cSHeiko Schocher	bl	board_init_f
174*5347f68cSHeiko Schocher
175*5347f68cSHeiko Schocher/*------------------------------------------------------------------------------*/
176*5347f68cSHeiko Schocher
177*5347f68cSHeiko Schocher/*
178*5347f68cSHeiko Schocher * void relocate_code (addr_sp, gd, addr_moni)
179*5347f68cSHeiko Schocher *
180*5347f68cSHeiko Schocher * This "function" does not return, instead it continues in RAM
181*5347f68cSHeiko Schocher * after relocating the monitor code.
182*5347f68cSHeiko Schocher *
183*5347f68cSHeiko Schocher */
184*5347f68cSHeiko Schocher	.globl	relocate_code
185*5347f68cSHeiko Schocherrelocate_code:
186*5347f68cSHeiko Schocher	mov	r4, r0	/* save addr_sp */
187*5347f68cSHeiko Schocher	mov	r5, r1	/* save addr of gd */
188*5347f68cSHeiko Schocher	mov	r6, r2	/* save addr of destination */
189*5347f68cSHeiko Schocher	mov	r7, r2	/* save addr of destination */
190*5347f68cSHeiko Schocher
191*5347f68cSHeiko Schocher	/* Set up the stack						    */
192*5347f68cSHeiko Schocherstack_setup:
193*5347f68cSHeiko Schocher	mov	sp, r4
194*5347f68cSHeiko Schocher
195*5347f68cSHeiko Schocher	adr	r0, _start
196*5347f68cSHeiko Schocher	ldr	r2, _TEXT_BASE
197*5347f68cSHeiko Schocher	ldr	r3, _bss_start
198*5347f68cSHeiko Schocher	sub	r2, r3, r2		/* r2 <- size of armboot	    */
199*5347f68cSHeiko Schocher	add	r2, r0, r2		/* r2 <- source end address	    */
200*5347f68cSHeiko Schocher	cmp	r0, r6
201*5347f68cSHeiko Schocher	beq	clear_bss
202*5347f68cSHeiko Schocher
203*5347f68cSHeiko Schocher#ifndef CONFIG_SKIP_RELOCATE_UBOOT
204*5347f68cSHeiko Schochercopy_loop:
205*5347f68cSHeiko Schocher	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
206*5347f68cSHeiko Schocher	stmia	r6!, {r9-r10}		/* copy to   target address [r1]    */
207*5347f68cSHeiko Schocher	cmp	r0, r2			/* until source end addreee [r2]    */
208*5347f68cSHeiko Schocher	ble	copy_loop
209*5347f68cSHeiko Schocher
210*5347f68cSHeiko Schocher#ifndef CONFIG_PRELOADER
211*5347f68cSHeiko Schocher	/* fix got entries */
212*5347f68cSHeiko Schocher	ldr	r1, _TEXT_BASE		/* Text base */
213*5347f68cSHeiko Schocher	mov	r0, r7			/* reloc addr */
214*5347f68cSHeiko Schocher	ldr	r2, _got_start		/* addr in Flash */
215*5347f68cSHeiko Schocher	ldr	r3, _got_end		/* addr in Flash */
216*5347f68cSHeiko Schocher	sub	r3, r3, r1
217*5347f68cSHeiko Schocher	add	r3, r3, r0
218*5347f68cSHeiko Schocher	sub	r2, r2, r1
219*5347f68cSHeiko Schocher	add	r2, r2, r0
220*5347f68cSHeiko Schocher
221*5347f68cSHeiko Schocherfixloop:
222*5347f68cSHeiko Schocher	ldr	r4, [r2]
223*5347f68cSHeiko Schocher	sub	r4, r4, r1
224*5347f68cSHeiko Schocher	add	r4, r4, r0
225*5347f68cSHeiko Schocher	str	r4, [r2]
226*5347f68cSHeiko Schocher	add	r2, r2, #4
227*5347f68cSHeiko Schocher	cmp	r2, r3
228*5347f68cSHeiko Schocher	bne	fixloop
229*5347f68cSHeiko Schocher#endif
230*5347f68cSHeiko Schocher#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
231*5347f68cSHeiko Schocher
232*5347f68cSHeiko Schocherclear_bss:
233*5347f68cSHeiko Schocher#ifndef CONFIG_PRELOADER
234*5347f68cSHeiko Schocher	ldr	r0, _bss_start
235*5347f68cSHeiko Schocher	ldr	r1, _bss_end
236*5347f68cSHeiko Schocher	ldr	r3, _TEXT_BASE		/* Text base */
237*5347f68cSHeiko Schocher	mov	r4, r7			/* reloc addr */
238*5347f68cSHeiko Schocher	sub	r0, r0, r3
239*5347f68cSHeiko Schocher	add	r0, r0, r4
240*5347f68cSHeiko Schocher	sub	r1, r1, r3
241*5347f68cSHeiko Schocher	add	r1, r1, r4
242*5347f68cSHeiko Schocher	mov	r2, #0x00000000		/* clear			    */
243*5347f68cSHeiko Schocher
244*5347f68cSHeiko Schocherclbss_l:str	r2, [r0]		/* clear loop...		    */
245*5347f68cSHeiko Schocher	add	r0, r0, #4
246*5347f68cSHeiko Schocher	cmp	r0, r1
247*5347f68cSHeiko Schocher	bne	clbss_l
248*5347f68cSHeiko Schocher#endif
249*5347f68cSHeiko Schocher
250*5347f68cSHeiko Schocher/*
251*5347f68cSHeiko Schocher * We are done. Do not return, instead branch to second part of board
252*5347f68cSHeiko Schocher * initialization, now running from RAM.
253*5347f68cSHeiko Schocher */
254*5347f68cSHeiko Schocher#ifdef CONFIG_ONENAND_IPL
255*5347f68cSHeiko Schocher	ldr     pc, _start_oneboot
256*5347f68cSHeiko Schocher
257*5347f68cSHeiko Schocher_start_oneboot: .word start_oneboot
258*5347f68cSHeiko Schocher#else
259*5347f68cSHeiko Schocher	ldr	r0, _TEXT_BASE
260*5347f68cSHeiko Schocher	ldr	r2, _board_init_r
261*5347f68cSHeiko Schocher	sub	r2, r2, r0
262*5347f68cSHeiko Schocher	add	r2, r2, r7	/* position from board_init_r in RAM */
263*5347f68cSHeiko Schocher	/* setup parameters for board_init_r */
264*5347f68cSHeiko Schocher	mov	r0, r5		/* gd_t */
265*5347f68cSHeiko Schocher	mov	r1, r7		/* dest_addr */
266*5347f68cSHeiko Schocher	/* jump to it ... */
267*5347f68cSHeiko Schocher	mov	lr, r2
268*5347f68cSHeiko Schocher	mov	pc, lr
269*5347f68cSHeiko Schocher
270*5347f68cSHeiko Schocher_board_init_r: .word board_init_r
271*5347f68cSHeiko Schocher#endif
272*5347f68cSHeiko Schocher
273*5347f68cSHeiko Schocher#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
27484ad6884SPeter Tyser
27584ad6884SPeter Tyser/****************************************************************************/
27684ad6884SPeter Tyser/*									    */
27784ad6884SPeter Tyser/* the actual reset code						    */
27884ad6884SPeter Tyser/*									    */
27984ad6884SPeter Tyser/****************************************************************************/
28084ad6884SPeter Tyser
28184ad6884SPeter Tyserreset:
28284ad6884SPeter Tyser	mrs	r0,cpsr			/* set the CPU to SVC32 mode	    */
28384ad6884SPeter Tyser	bic	r0,r0,#0x1f		/* (superviser mode, M=10011)	    */
28484ad6884SPeter Tyser	orr	r0,r0,#0x13
28584ad6884SPeter Tyser	msr	cpsr,r0
28684ad6884SPeter Tyser
28784ad6884SPeter Tyser	/*
28884ad6884SPeter Tyser	 * we do sys-critical inits only at reboot,
28984ad6884SPeter Tyser	 * not when booting from RAM!
29084ad6884SPeter Tyser	 */
29184ad6884SPeter Tyser#ifndef CONFIG_SKIP_LOWLEVEL_INIT
29284ad6884SPeter Tyser	bl	cpu_init_crit		/* we do sys-critical inits	    */
29384ad6884SPeter Tyser#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
29484ad6884SPeter Tyser
29584ad6884SPeter Tyser#ifndef CONFIG_SKIP_RELOCATE_UBOOT
29684ad6884SPeter Tyserrelocate:				/* relocate U-Boot to RAM	    */
29784ad6884SPeter Tyser	adr	r0, _start		/* r0 <- current position of code   */
29884ad6884SPeter Tyser	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
2995ab877b6SMarek Vasut#ifndef	CONFIG_PRELOADER
30084ad6884SPeter Tyser	cmp	r0, r1			/* don't reloc during debug	    */
30184ad6884SPeter Tyser	beq	stack_setup
3025ab877b6SMarek Vasut#endif
30384ad6884SPeter Tyser
30484ad6884SPeter Tyser	ldr	r2, _armboot_start
30584ad6884SPeter Tyser	ldr	r3, _bss_start
30684ad6884SPeter Tyser	sub	r2, r3, r2		/* r2 <- size of armboot	    */
30784ad6884SPeter Tyser	add	r2, r0, r2		/* r2 <- source end address	    */
30884ad6884SPeter Tyser
30984ad6884SPeter Tysercopy_loop:
31084ad6884SPeter Tyser	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
31184ad6884SPeter Tyser	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
31284ad6884SPeter Tyser	cmp	r0, r2			/* until source end address [r2]    */
31384ad6884SPeter Tyser	ble	copy_loop
31484ad6884SPeter Tyser#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */
31584ad6884SPeter Tyser
31684ad6884SPeter Tyser	/* Set up the stack						    */
31784ad6884SPeter Tyserstack_setup:
31884ad6884SPeter Tyser	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
3195ab877b6SMarek Vasut#ifdef CONFIG_PRELOADER
3205ab877b6SMarek Vasut	sub	sp, r0, #128		/* leave 32 words for abort-stack   */
3215ab877b6SMarek Vasut#else
32284ad6884SPeter Tyser	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area		    */
32384ad6884SPeter Tyser	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo		    */
32484ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
32584ad6884SPeter Tyser	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
32684ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
3271a27f7d9SVitaly Kuzmichev	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
3281a27f7d9SVitaly Kuzmichev	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
3295ab877b6SMarek Vasut#endif
33084ad6884SPeter Tyser
33184ad6884SPeter Tyserclear_bss:
33284ad6884SPeter Tyser	ldr	r0, _bss_start		/* find start of bss segment	    */
33384ad6884SPeter Tyser	ldr	r1, _bss_end		/* stop here			    */
33484ad6884SPeter Tyser	mov	r2, #0x00000000		/* clear			    */
33584ad6884SPeter Tyser
3365ab877b6SMarek Vasut#ifndef CONFIG_PRELOADER
33784ad6884SPeter Tyserclbss_l:str	r2, [r0]		/* clear loop...		    */
33884ad6884SPeter Tyser	add	r0, r0, #4
33984ad6884SPeter Tyser	cmp	r0, r1
34084ad6884SPeter Tyser	ble	clbss_l
3415ab877b6SMarek Vasut#endif
34284ad6884SPeter Tyser
34384ad6884SPeter Tyser	ldr	pc, _start_armboot
34484ad6884SPeter Tyser
3455ab877b6SMarek Vasut#ifdef CONFIG_ONENAND_IPL
3465ab877b6SMarek Vasut_start_armboot: .word start_oneboot
3475ab877b6SMarek Vasut#else
34884ad6884SPeter Tyser_start_armboot: .word start_armboot
3495ab877b6SMarek Vasut#endif
350*5347f68cSHeiko Schocher#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
35184ad6884SPeter Tyser
35284ad6884SPeter Tyser/****************************************************************************/
35384ad6884SPeter Tyser/*									    */
35484ad6884SPeter Tyser/* CPU_init_critical registers						    */
35584ad6884SPeter Tyser/*									    */
35684ad6884SPeter Tyser/* - setup important registers						    */
35784ad6884SPeter Tyser/* - setup memory timing						    */
35884ad6884SPeter Tyser/*									    */
35984ad6884SPeter Tyser/****************************************************************************/
36084ad6884SPeter Tyser/* mk@tbd: Fix this! */
36184ad6884SPeter Tyser#undef RCSR
36284ad6884SPeter Tyser#undef ICMR
36384ad6884SPeter Tyser#undef OSMR3
36484ad6884SPeter Tyser#undef OSCR
36584ad6884SPeter Tyser#undef OWER
36684ad6884SPeter Tyser#undef OIER
36784ad6884SPeter Tyser#undef CCCR
36884ad6884SPeter Tyser
36984ad6884SPeter Tyser/* Interrupt-Controller base address					    */
37084ad6884SPeter TyserIC_BASE:	   .word	   0x40d00000
37184ad6884SPeter Tyser#define ICMR	0x04
37284ad6884SPeter Tyser
37384ad6884SPeter Tyser/* Reset-Controller */
37484ad6884SPeter TyserRST_BASE:	.word	0x40f00030
37584ad6884SPeter Tyser#define RCSR	0x00
37684ad6884SPeter Tyser
37784ad6884SPeter Tyser/* Operating System Timer */
37884ad6884SPeter TyserOSTIMER_BASE:	.word	0x40a00000
37984ad6884SPeter Tyser#define OSMR3	0x0C
38084ad6884SPeter Tyser#define OSCR	0x10
38184ad6884SPeter Tyser#define OWER	0x18
38284ad6884SPeter Tyser#define OIER	0x1C
38384ad6884SPeter Tyser
38484ad6884SPeter Tyser/* Clock Manager Registers						    */
38584ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
38684ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
38784ad6884SPeter Tyser#  error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!"
38884ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */
38984ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO
39084ad6884SPeter Tyser#  define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1
39184ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */
39284ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
39384ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
39484ad6884SPeter TyserCC_BASE:	.word	0x41300000
39584ad6884SPeter Tyser#define CCCR	0x00
39684ad6884SPeter Tysercpuspeed:	.word	CONFIG_SYS_CPUSPEED
39784ad6884SPeter Tyser#else /* !CONFIG_SYS_CPUSPEED */
39884ad6884SPeter Tyser#error "You have to define CONFIG_SYS_CPUSPEED!!"
39984ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
40084ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
40184ad6884SPeter Tyser
40284ad6884SPeter Tyser	/* takes care the CP15 update has taken place */
40384ad6884SPeter Tyser	.macro CPWAIT reg
40484ad6884SPeter Tyser	mrc  p15,0,\reg,c2,c0,0
40584ad6884SPeter Tyser	mov  \reg,\reg
40684ad6884SPeter Tyser	sub  pc,pc,#4
40784ad6884SPeter Tyser	.endm
40884ad6884SPeter Tyser
40984ad6884SPeter Tysercpu_init_crit:
41084ad6884SPeter Tyser
41184ad6884SPeter Tyser	/* mask all IRQs						    */
41284ad6884SPeter Tyser#ifndef CONFIG_CPU_MONAHANS
41384ad6884SPeter Tyser	ldr	r0, IC_BASE
41484ad6884SPeter Tyser	mov	r1, #0x00
41584ad6884SPeter Tyser	str	r1, [r0, #ICMR]
41684ad6884SPeter Tyser#else /* CONFIG_CPU_MONAHANS */
41784ad6884SPeter Tyser	/* Step 1 - Enable CP6 permission */
41884ad6884SPeter Tyser	mrc	p15, 0, r1, c15, c1, 0	@ read CPAR
41984ad6884SPeter Tyser	orr	r1, r1, #0x40
42084ad6884SPeter Tyser		mcr	p15, 0, r1, c15, c1, 0
42184ad6884SPeter Tyser	CPWAIT	r1
42284ad6884SPeter Tyser
42384ad6884SPeter Tyser	/* Step 2 - Mask ICMR & ICMR2 */
42484ad6884SPeter Tyser	mov	r1, #0
42584ad6884SPeter Tyser	mcr	p6, 0, r1, c1, c0, 0	@ ICMR
42684ad6884SPeter Tyser	mcr	p6, 0, r1, c7, c0, 0	@ ICMR2
42784ad6884SPeter Tyser
42884ad6884SPeter Tyser	/* turn off all clocks but the ones we will definitly require */
42984ad6884SPeter Tyser	ldr	r1, =CKENA
43084ad6884SPeter Tyser	ldr	r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC)
43184ad6884SPeter Tyser	str	r2, [r1]
43284ad6884SPeter Tyser	ldr	r1, =CKENB
43384ad6884SPeter Tyser	ldr	r2, =(CKENB_6_IRQ)
43484ad6884SPeter Tyser	str	r2, [r1]
43584ad6884SPeter Tyser#endif /* !CONFIG_CPU_MONAHANS */
43684ad6884SPeter Tyser
43784ad6884SPeter Tyser	/* set clock speed */
43884ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
43984ad6884SPeter Tyser	ldr	r0, =ACCR
44084ad6884SPeter Tyser	ldr	r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK))
44184ad6884SPeter Tyser	str	r1, [r0]
44284ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
44384ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
44484ad6884SPeter Tyser	ldr	r0, CC_BASE
44584ad6884SPeter Tyser	ldr	r1, cpuspeed
44684ad6884SPeter Tyser	str	r1, [r0, #CCCR]
44784ad6884SPeter Tyser	mov	r0, #2
44884ad6884SPeter Tyser	mcr	p14, 0, r0, c6, c0, 0
44984ad6884SPeter Tyser
45084ad6884SPeter Tysersetspeed_done:
45184ad6884SPeter Tyser
45284ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
45384ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
45484ad6884SPeter Tyser
45584ad6884SPeter Tyser	/*
45684ad6884SPeter Tyser	 * before relocating, we have to setup RAM timing
45784ad6884SPeter Tyser	 * because memory timing is board-dependend, you will
45884ad6884SPeter Tyser	 * find a lowlevel_init.S in your board directory.
45984ad6884SPeter Tyser	 */
46084ad6884SPeter Tyser	mov	ip,	lr
46184ad6884SPeter Tyser	bl	lowlevel_init
46284ad6884SPeter Tyser	mov	lr,	ip
46384ad6884SPeter Tyser
46484ad6884SPeter Tyser	/* Memory interfaces are working. Disable MMU and enable I-cache.   */
46584ad6884SPeter Tyser	/* mk: hmm, this is not in the monahans docs, leave it now but
46684ad6884SPeter Tyser	 *     check here if it doesn't work :-) */
46784ad6884SPeter Tyser
46884ad6884SPeter Tyser	ldr	r0, =0x2001		/* enable access to all coproc.	    */
46984ad6884SPeter Tyser	mcr	p15, 0, r0, c15, c1, 0
47084ad6884SPeter Tyser	CPWAIT r0
47184ad6884SPeter Tyser
47284ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c10, 4	/* drain the write & fill buffers   */
47384ad6884SPeter Tyser	CPWAIT r0
47484ad6884SPeter Tyser
47584ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c7, 0	/* flush Icache, Dcache and BTB	    */
47684ad6884SPeter Tyser	CPWAIT r0
47784ad6884SPeter Tyser
47884ad6884SPeter Tyser	mcr	p15, 0, r0, c8, c7, 0	/* flush instuction and data TLBs   */
47984ad6884SPeter Tyser	CPWAIT r0
48084ad6884SPeter Tyser
48184ad6884SPeter Tyser	/* Enable the Icache						    */
48284ad6884SPeter Tyser/*
48384ad6884SPeter Tyser	mrc	p15, 0, r0, c1, c0, 0
48484ad6884SPeter Tyser	orr	r0, r0, #0x1800
48584ad6884SPeter Tyser	mcr	p15, 0, r0, c1, c0, 0
48684ad6884SPeter Tyser	CPWAIT
48784ad6884SPeter Tyser*/
48884ad6884SPeter Tyser	mov	pc, lr
48984ad6884SPeter Tyser
4905ab877b6SMarek Vasut#ifndef CONFIG_PRELOADER
49184ad6884SPeter Tyser/****************************************************************************/
49284ad6884SPeter Tyser/*									    */
49384ad6884SPeter Tyser/* Interrupt handling							    */
49484ad6884SPeter Tyser/*									    */
49584ad6884SPeter Tyser/****************************************************************************/
49684ad6884SPeter Tyser
49784ad6884SPeter Tyser/* IRQ stack frame							    */
49884ad6884SPeter Tyser
49984ad6884SPeter Tyser#define S_FRAME_SIZE	72
50084ad6884SPeter Tyser
50184ad6884SPeter Tyser#define S_OLD_R0	68
50284ad6884SPeter Tyser#define S_PSR		64
50384ad6884SPeter Tyser#define S_PC		60
50484ad6884SPeter Tyser#define S_LR		56
50584ad6884SPeter Tyser#define S_SP		52
50684ad6884SPeter Tyser
50784ad6884SPeter Tyser#define S_IP		48
50884ad6884SPeter Tyser#define S_FP		44
50984ad6884SPeter Tyser#define S_R10		40
51084ad6884SPeter Tyser#define S_R9		36
51184ad6884SPeter Tyser#define S_R8		32
51284ad6884SPeter Tyser#define S_R7		28
51384ad6884SPeter Tyser#define S_R6		24
51484ad6884SPeter Tyser#define S_R5		20
51584ad6884SPeter Tyser#define S_R4		16
51684ad6884SPeter Tyser#define S_R3		12
51784ad6884SPeter Tyser#define S_R2		8
51884ad6884SPeter Tyser#define S_R1		4
51984ad6884SPeter Tyser#define S_R0		0
52084ad6884SPeter Tyser
52184ad6884SPeter Tyser#define MODE_SVC 0x13
52284ad6884SPeter Tyser
52384ad6884SPeter Tyser	/* use bad_save_user_regs for abort/prefetch/undef/swi ...	    */
52484ad6884SPeter Tyser
52584ad6884SPeter Tyser	.macro	bad_save_user_regs
52684ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
52784ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	    */
52884ad6884SPeter Tyser	add	r8, sp, #S_PC
52984ad6884SPeter Tyser
530*5347f68cSHeiko Schocher#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
53184ad6884SPeter Tyser	ldr	r2, _armboot_start
53284ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
53384ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
534*5347f68cSHeiko Schocher#else
535*5347f68cSHeiko Schocher	ldr	r2, IRQ_STACK_START_IN
536*5347f68cSHeiko Schocher#endif
53784ad6884SPeter Tyser	ldmia	r2, {r2 - r4}			/* get pc, cpsr, old_r0	    */
53884ad6884SPeter Tyser	add	r0, sp, #S_FRAME_SIZE		/* restore sp_SVC	    */
53984ad6884SPeter Tyser
54084ad6884SPeter Tyser	add	r5, sp, #S_SP
54184ad6884SPeter Tyser	mov	r1, lr
54284ad6884SPeter Tyser	stmia	r5, {r0 - r4}			/* save sp_SVC, lr_SVC, pc, cpsr, old_r */
54384ad6884SPeter Tyser	mov	r0, sp
54484ad6884SPeter Tyser	.endm
54584ad6884SPeter Tyser
54684ad6884SPeter Tyser
54784ad6884SPeter Tyser	/* use irq_save_user_regs / irq_restore_user_regs for		     */
54884ad6884SPeter Tyser	/* IRQ/FIQ handling						     */
54984ad6884SPeter Tyser
55084ad6884SPeter Tyser	.macro	irq_save_user_regs
55184ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
55284ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	     */
55384ad6884SPeter Tyser	add	r8, sp, #S_PC
55484ad6884SPeter Tyser	stmdb	r8, {sp, lr}^			/* Calling SP, LR	     */
55584ad6884SPeter Tyser	str	lr, [r8, #0]			/* Save calling PC	     */
55684ad6884SPeter Tyser	mrs	r6, spsr
55784ad6884SPeter Tyser	str	r6, [r8, #4]			/* Save CPSR		     */
55884ad6884SPeter Tyser	str	r0, [r8, #8]			/* Save OLD_R0		     */
55984ad6884SPeter Tyser	mov	r0, sp
56084ad6884SPeter Tyser	.endm
56184ad6884SPeter Tyser
56284ad6884SPeter Tyser	.macro	irq_restore_user_regs
56384ad6884SPeter Tyser	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
56484ad6884SPeter Tyser	mov	r0, r0
56584ad6884SPeter Tyser	ldr	lr, [sp, #S_PC]			@ Get PC
56684ad6884SPeter Tyser	add	sp, sp, #S_FRAME_SIZE
56784ad6884SPeter Tyser	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
56884ad6884SPeter Tyser	.endm
56984ad6884SPeter Tyser
57084ad6884SPeter Tyser	.macro get_bad_stack
571*5347f68cSHeiko Schocher#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
57284ad6884SPeter Tyser	ldr	r13, _armboot_start		@ setup our mode stack
57384ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
57484ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
575*5347f68cSHeiko Schocher#else
576*5347f68cSHeiko Schocher	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
577*5347f68cSHeiko Schocher#endif
57884ad6884SPeter Tyser
57984ad6884SPeter Tyser	str	lr, [r13]			@ save caller lr / spsr
58084ad6884SPeter Tyser	mrs	lr, spsr
58184ad6884SPeter Tyser	str	lr, [r13, #4]
58284ad6884SPeter Tyser
58384ad6884SPeter Tyser	mov	r13, #MODE_SVC			@ prepare SVC-Mode
58484ad6884SPeter Tyser	msr	spsr_c, r13
58584ad6884SPeter Tyser	mov	lr, pc
58684ad6884SPeter Tyser	movs	pc, lr
58784ad6884SPeter Tyser	.endm
58884ad6884SPeter Tyser
58984ad6884SPeter Tyser	.macro get_irq_stack			@ setup IRQ stack
59084ad6884SPeter Tyser	ldr	sp, IRQ_STACK_START
59184ad6884SPeter Tyser	.endm
59284ad6884SPeter Tyser
59384ad6884SPeter Tyser	.macro get_fiq_stack			@ setup FIQ stack
59484ad6884SPeter Tyser	ldr	sp, FIQ_STACK_START
59584ad6884SPeter Tyser	.endm
5965ab877b6SMarek Vasut#endif	/* CONFIG_PRELOADER */
59784ad6884SPeter Tyser
59884ad6884SPeter Tyser
59984ad6884SPeter Tyser/****************************************************************************/
60084ad6884SPeter Tyser/*									    */
60184ad6884SPeter Tyser/* exception handlers							    */
60284ad6884SPeter Tyser/*									    */
60384ad6884SPeter Tyser/****************************************************************************/
60484ad6884SPeter Tyser
6055ab877b6SMarek Vasut#ifdef CONFIG_PRELOADER
6065ab877b6SMarek Vasut	.align	5
6075ab877b6SMarek Vasutdo_hang:
6085ab877b6SMarek Vasut	ldr	sp, _TEXT_BASE			/* use 32 words abort stack */
6095ab877b6SMarek Vasut	bl	hang				/* hang and never return */
6105ab877b6SMarek Vasut#else	/* !CONFIG_PRELOADER */
61184ad6884SPeter Tyser	.align	5
61284ad6884SPeter Tyserundefined_instruction:
61384ad6884SPeter Tyser	get_bad_stack
61484ad6884SPeter Tyser	bad_save_user_regs
61584ad6884SPeter Tyser	bl	do_undefined_instruction
61684ad6884SPeter Tyser
61784ad6884SPeter Tyser	.align	5
61884ad6884SPeter Tysersoftware_interrupt:
61984ad6884SPeter Tyser	get_bad_stack
62084ad6884SPeter Tyser	bad_save_user_regs
62184ad6884SPeter Tyser	bl	do_software_interrupt
62284ad6884SPeter Tyser
62384ad6884SPeter Tyser	.align	5
62484ad6884SPeter Tyserprefetch_abort:
62584ad6884SPeter Tyser	get_bad_stack
62684ad6884SPeter Tyser	bad_save_user_regs
62784ad6884SPeter Tyser	bl	do_prefetch_abort
62884ad6884SPeter Tyser
62984ad6884SPeter Tyser	.align	5
63084ad6884SPeter Tyserdata_abort:
63184ad6884SPeter Tyser	get_bad_stack
63284ad6884SPeter Tyser	bad_save_user_regs
63384ad6884SPeter Tyser	bl	do_data_abort
63484ad6884SPeter Tyser
63584ad6884SPeter Tyser	.align	5
63684ad6884SPeter Tysernot_used:
63784ad6884SPeter Tyser	get_bad_stack
63884ad6884SPeter Tyser	bad_save_user_regs
63984ad6884SPeter Tyser	bl	do_not_used
64084ad6884SPeter Tyser
64184ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
64284ad6884SPeter Tyser
64384ad6884SPeter Tyser	.align	5
64484ad6884SPeter Tyserirq:
64584ad6884SPeter Tyser	get_irq_stack
64684ad6884SPeter Tyser	irq_save_user_regs
64784ad6884SPeter Tyser	bl	do_irq
64884ad6884SPeter Tyser	irq_restore_user_regs
64984ad6884SPeter Tyser
65084ad6884SPeter Tyser	.align	5
65184ad6884SPeter Tyserfiq:
65284ad6884SPeter Tyser	get_fiq_stack
65384ad6884SPeter Tyser	irq_save_user_regs		/* someone ought to write a more    */
65484ad6884SPeter Tyser	bl	do_fiq			/* effiction fiq_save_user_regs	    */
65584ad6884SPeter Tyser	irq_restore_user_regs
65684ad6884SPeter Tyser
65784ad6884SPeter Tyser#else /* !CONFIG_USE_IRQ */
65884ad6884SPeter Tyser
65984ad6884SPeter Tyser	.align	5
66084ad6884SPeter Tyserirq:
66184ad6884SPeter Tyser	get_bad_stack
66284ad6884SPeter Tyser	bad_save_user_regs
66384ad6884SPeter Tyser	bl	do_irq
66484ad6884SPeter Tyser
66584ad6884SPeter Tyser	.align	5
66684ad6884SPeter Tyserfiq:
66784ad6884SPeter Tyser	get_bad_stack
66884ad6884SPeter Tyser	bad_save_user_regs
66984ad6884SPeter Tyser	bl	do_fiq
6705ab877b6SMarek Vasut#endif	/* CONFIG_PRELOADER */
67184ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
67284ad6884SPeter Tyser
67384ad6884SPeter Tyser/****************************************************************************/
67484ad6884SPeter Tyser/*									    */
67584ad6884SPeter Tyser/* Reset function: the PXA250 doesn't have a reset function, so we have to  */
67684ad6884SPeter Tyser/* perform a watchdog timeout for a soft reset.				    */
67784ad6884SPeter Tyser/*									    */
67884ad6884SPeter Tyser/****************************************************************************/
67984ad6884SPeter Tyser
68084ad6884SPeter Tyser	.align	5
68184ad6884SPeter Tyser.globl reset_cpu
68284ad6884SPeter Tyser
68384ad6884SPeter Tyser	/* FIXME: this code is PXA250 specific. How is this handled on	    */
68484ad6884SPeter Tyser	/*	  other XScale processors?				    */
68584ad6884SPeter Tyser
68684ad6884SPeter Tyserreset_cpu:
68784ad6884SPeter Tyser
68884ad6884SPeter Tyser	/* We set OWE:WME (watchdog enable) and wait until timeout happens  */
68984ad6884SPeter Tyser
69084ad6884SPeter Tyser	ldr	r0, OSTIMER_BASE
69184ad6884SPeter Tyser	ldr	r1, [r0, #OWER]
69284ad6884SPeter Tyser	orr	r1, r1, #0x0001			/* bit0: WME		    */
69384ad6884SPeter Tyser	str	r1, [r0, #OWER]
69484ad6884SPeter Tyser
69584ad6884SPeter Tyser	/* OS timer does only wrap every 1165 seconds, so we have to set    */
69684ad6884SPeter Tyser	/* the match register as well.					    */
69784ad6884SPeter Tyser
69884ad6884SPeter Tyser	ldr	r1, [r0, #OSCR]			/* read OS timer	    */
69984ad6884SPeter Tyser	add	r1, r1, #0x800			/* let OSMR3 match after    */
70084ad6884SPeter Tyser	add	r1, r1, #0x800			/* 4096*(1/3.6864MHz)=1ms   */
70184ad6884SPeter Tyser	str	r1, [r0, #OSMR3]
70284ad6884SPeter Tyser
70384ad6884SPeter Tyserreset_endless:
70484ad6884SPeter Tyser
70584ad6884SPeter Tyser	b	reset_endless
706