xref: /openbmc/u-boot/arch/arm/cpu/pxa/start.S (revision 1a27f7d9)
1*84ad6884SPeter Tyser/*
2*84ad6884SPeter Tyser *  armboot - Startup Code for XScale
3*84ad6884SPeter Tyser *
4*84ad6884SPeter Tyser *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
5*84ad6884SPeter Tyser *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6*84ad6884SPeter Tyser *  Copyright (C) 2000	Wolfgang Denk <wd@denx.de>
7*84ad6884SPeter Tyser *  Copyright (C) 2001	Alex Zuepke <azu@sysgo.de>
8*84ad6884SPeter Tyser *  Copyright (C) 2002	Kyle Harris <kharris@nexus-tech.net>
9*84ad6884SPeter Tyser *  Copyright (C) 2003	Robert Schwebel <r.schwebel@pengutronix.de>
10*84ad6884SPeter Tyser *  Copyright (C) 2003	Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
11*84ad6884SPeter Tyser *
12*84ad6884SPeter Tyser * See file CREDITS for list of people who contributed to this
13*84ad6884SPeter Tyser * project.
14*84ad6884SPeter Tyser *
15*84ad6884SPeter Tyser * This program is free software; you can redistribute it and/or
16*84ad6884SPeter Tyser * modify it under the terms of the GNU General Public License as
17*84ad6884SPeter Tyser * published by the Free Software Foundation; either version 2 of
18*84ad6884SPeter Tyser * the License, or (at your option) any later version.
19*84ad6884SPeter Tyser *
20*84ad6884SPeter Tyser * This program is distributed in the hope that it will be useful,
21*84ad6884SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of
22*84ad6884SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
23*84ad6884SPeter Tyser * GNU General Public License for more details.
24*84ad6884SPeter Tyser *
25*84ad6884SPeter Tyser * You should have received a copy of the GNU General Public License
26*84ad6884SPeter Tyser * along with this program; if not, write to the Free Software
27*84ad6884SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28*84ad6884SPeter Tyser * MA 02111-1307 USA
29*84ad6884SPeter Tyser */
30*84ad6884SPeter Tyser
31*84ad6884SPeter Tyser#include <config.h>
32*84ad6884SPeter Tyser#include <version.h>
33*84ad6884SPeter Tyser#include <asm/arch/pxa-regs.h>
34*84ad6884SPeter Tyser
35*84ad6884SPeter Tyser.globl _start
36*84ad6884SPeter Tyser_start: b	reset
37*84ad6884SPeter Tyser	ldr	pc, _undefined_instruction
38*84ad6884SPeter Tyser	ldr	pc, _software_interrupt
39*84ad6884SPeter Tyser	ldr	pc, _prefetch_abort
40*84ad6884SPeter Tyser	ldr	pc, _data_abort
41*84ad6884SPeter Tyser	ldr	pc, _not_used
42*84ad6884SPeter Tyser	ldr	pc, _irq
43*84ad6884SPeter Tyser	ldr	pc, _fiq
44*84ad6884SPeter Tyser
45*84ad6884SPeter Tyser_undefined_instruction: .word undefined_instruction
46*84ad6884SPeter Tyser_software_interrupt:	.word software_interrupt
47*84ad6884SPeter Tyser_prefetch_abort:	.word prefetch_abort
48*84ad6884SPeter Tyser_data_abort:		.word data_abort
49*84ad6884SPeter Tyser_not_used:		.word not_used
50*84ad6884SPeter Tyser_irq:			.word irq
51*84ad6884SPeter Tyser_fiq:			.word fiq
52*84ad6884SPeter Tyser
53*84ad6884SPeter Tyser	.balignl 16,0xdeadbeef
54*84ad6884SPeter Tyser
55*84ad6884SPeter Tyser
56*84ad6884SPeter Tyser/*
57*84ad6884SPeter Tyser * Startup Code (reset vector)
58*84ad6884SPeter Tyser *
59*84ad6884SPeter Tyser * do important init only if we don't start from RAM!
60*84ad6884SPeter Tyser * - relocate armboot to RAM
61*84ad6884SPeter Tyser * - setup stack
62*84ad6884SPeter Tyser * - jump to second stage
63*84ad6884SPeter Tyser */
64*84ad6884SPeter Tyser
65*84ad6884SPeter Tyser_TEXT_BASE:
66*84ad6884SPeter Tyser	.word	TEXT_BASE
67*84ad6884SPeter Tyser
68*84ad6884SPeter Tyser.globl _armboot_start
69*84ad6884SPeter Tyser_armboot_start:
70*84ad6884SPeter Tyser	.word _start
71*84ad6884SPeter Tyser
72*84ad6884SPeter Tyser/*
73*84ad6884SPeter Tyser * These are defined in the board-specific linker script.
74*84ad6884SPeter Tyser */
75*84ad6884SPeter Tyser.globl _bss_start
76*84ad6884SPeter Tyser_bss_start:
77*84ad6884SPeter Tyser	.word __bss_start
78*84ad6884SPeter Tyser
79*84ad6884SPeter Tyser.globl _bss_end
80*84ad6884SPeter Tyser_bss_end:
81*84ad6884SPeter Tyser	.word _end
82*84ad6884SPeter Tyser
83*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
84*84ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */
85*84ad6884SPeter Tyser.globl IRQ_STACK_START
86*84ad6884SPeter TyserIRQ_STACK_START:
87*84ad6884SPeter Tyser	.word	0x0badc0de
88*84ad6884SPeter Tyser
89*84ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */
90*84ad6884SPeter Tyser.globl FIQ_STACK_START
91*84ad6884SPeter TyserFIQ_STACK_START:
92*84ad6884SPeter Tyser	.word 0x0badc0de
93*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
94*84ad6884SPeter Tyser
95*84ad6884SPeter Tyser
96*84ad6884SPeter Tyser/****************************************************************************/
97*84ad6884SPeter Tyser/*									    */
98*84ad6884SPeter Tyser/* the actual reset code						    */
99*84ad6884SPeter Tyser/*									    */
100*84ad6884SPeter Tyser/****************************************************************************/
101*84ad6884SPeter Tyser
102*84ad6884SPeter Tyserreset:
103*84ad6884SPeter Tyser	mrs	r0,cpsr			/* set the CPU to SVC32 mode	    */
104*84ad6884SPeter Tyser	bic	r0,r0,#0x1f		/* (superviser mode, M=10011)	    */
105*84ad6884SPeter Tyser	orr	r0,r0,#0x13
106*84ad6884SPeter Tyser	msr	cpsr,r0
107*84ad6884SPeter Tyser
108*84ad6884SPeter Tyser	/*
109*84ad6884SPeter Tyser	 * we do sys-critical inits only at reboot,
110*84ad6884SPeter Tyser	 * not when booting from RAM!
111*84ad6884SPeter Tyser	 */
112*84ad6884SPeter Tyser#ifndef CONFIG_SKIP_LOWLEVEL_INIT
113*84ad6884SPeter Tyser	bl	cpu_init_crit		/* we do sys-critical inits	    */
114*84ad6884SPeter Tyser#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
115*84ad6884SPeter Tyser
116*84ad6884SPeter Tyser#ifndef CONFIG_SKIP_RELOCATE_UBOOT
117*84ad6884SPeter Tyserrelocate:				/* relocate U-Boot to RAM	    */
118*84ad6884SPeter Tyser	adr	r0, _start		/* r0 <- current position of code   */
119*84ad6884SPeter Tyser	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
120*84ad6884SPeter Tyser	cmp	r0, r1			/* don't reloc during debug	    */
121*84ad6884SPeter Tyser	beq	stack_setup
122*84ad6884SPeter Tyser
123*84ad6884SPeter Tyser	ldr	r2, _armboot_start
124*84ad6884SPeter Tyser	ldr	r3, _bss_start
125*84ad6884SPeter Tyser	sub	r2, r3, r2		/* r2 <- size of armboot	    */
126*84ad6884SPeter Tyser	add	r2, r0, r2		/* r2 <- source end address	    */
127*84ad6884SPeter Tyser
128*84ad6884SPeter Tysercopy_loop:
129*84ad6884SPeter Tyser	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
130*84ad6884SPeter Tyser	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
131*84ad6884SPeter Tyser	cmp	r0, r2			/* until source end address [r2]    */
132*84ad6884SPeter Tyser	ble	copy_loop
133*84ad6884SPeter Tyser#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */
134*84ad6884SPeter Tyser
135*84ad6884SPeter Tyser	/* Set up the stack						    */
136*84ad6884SPeter Tyserstack_setup:
137*84ad6884SPeter Tyser	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
138*84ad6884SPeter Tyser	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area			    */
139*84ad6884SPeter Tyser	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo			    */
140*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
141*84ad6884SPeter Tyser	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
142*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
1431a27f7d9SVitaly Kuzmichev	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
1441a27f7d9SVitaly Kuzmichev	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
145*84ad6884SPeter Tyser
146*84ad6884SPeter Tyserclear_bss:
147*84ad6884SPeter Tyser	ldr	r0, _bss_start		/* find start of bss segment	    */
148*84ad6884SPeter Tyser	ldr	r1, _bss_end		/* stop here			    */
149*84ad6884SPeter Tyser	mov	r2, #0x00000000		/* clear			    */
150*84ad6884SPeter Tyser
151*84ad6884SPeter Tyserclbss_l:str	r2, [r0]		/* clear loop...		    */
152*84ad6884SPeter Tyser	add	r0, r0, #4
153*84ad6884SPeter Tyser	cmp	r0, r1
154*84ad6884SPeter Tyser	ble	clbss_l
155*84ad6884SPeter Tyser
156*84ad6884SPeter Tyser	ldr	pc, _start_armboot
157*84ad6884SPeter Tyser
158*84ad6884SPeter Tyser_start_armboot: .word start_armboot
159*84ad6884SPeter Tyser
160*84ad6884SPeter Tyser
161*84ad6884SPeter Tyser/****************************************************************************/
162*84ad6884SPeter Tyser/*									    */
163*84ad6884SPeter Tyser/* CPU_init_critical registers						    */
164*84ad6884SPeter Tyser/*									    */
165*84ad6884SPeter Tyser/* - setup important registers						    */
166*84ad6884SPeter Tyser/* - setup memory timing						    */
167*84ad6884SPeter Tyser/*									    */
168*84ad6884SPeter Tyser/****************************************************************************/
169*84ad6884SPeter Tyser/* mk@tbd: Fix this! */
170*84ad6884SPeter Tyser#undef RCSR
171*84ad6884SPeter Tyser#undef ICMR
172*84ad6884SPeter Tyser#undef OSMR3
173*84ad6884SPeter Tyser#undef OSCR
174*84ad6884SPeter Tyser#undef OWER
175*84ad6884SPeter Tyser#undef OIER
176*84ad6884SPeter Tyser#undef CCCR
177*84ad6884SPeter Tyser
178*84ad6884SPeter Tyser/* Interrupt-Controller base address					    */
179*84ad6884SPeter TyserIC_BASE:	   .word	   0x40d00000
180*84ad6884SPeter Tyser#define ICMR	0x04
181*84ad6884SPeter Tyser
182*84ad6884SPeter Tyser/* Reset-Controller */
183*84ad6884SPeter TyserRST_BASE:	.word	0x40f00030
184*84ad6884SPeter Tyser#define RCSR	0x00
185*84ad6884SPeter Tyser
186*84ad6884SPeter Tyser/* Operating System Timer */
187*84ad6884SPeter TyserOSTIMER_BASE:	.word	0x40a00000
188*84ad6884SPeter Tyser#define OSMR3	0x0C
189*84ad6884SPeter Tyser#define OSCR	0x10
190*84ad6884SPeter Tyser#define OWER	0x18
191*84ad6884SPeter Tyser#define OIER	0x1C
192*84ad6884SPeter Tyser
193*84ad6884SPeter Tyser/* Clock Manager Registers						    */
194*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
195*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
196*84ad6884SPeter Tyser#  error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!"
197*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */
198*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO
199*84ad6884SPeter Tyser#  define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1
200*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */
201*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
202*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
203*84ad6884SPeter TyserCC_BASE:	.word	0x41300000
204*84ad6884SPeter Tyser#define CCCR	0x00
205*84ad6884SPeter Tysercpuspeed:	.word	CONFIG_SYS_CPUSPEED
206*84ad6884SPeter Tyser#else /* !CONFIG_SYS_CPUSPEED */
207*84ad6884SPeter Tyser#error "You have to define CONFIG_SYS_CPUSPEED!!"
208*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
209*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
210*84ad6884SPeter Tyser
211*84ad6884SPeter Tyser	/* takes care the CP15 update has taken place */
212*84ad6884SPeter Tyser	.macro CPWAIT reg
213*84ad6884SPeter Tyser	mrc  p15,0,\reg,c2,c0,0
214*84ad6884SPeter Tyser	mov  \reg,\reg
215*84ad6884SPeter Tyser	sub  pc,pc,#4
216*84ad6884SPeter Tyser	.endm
217*84ad6884SPeter Tyser
218*84ad6884SPeter Tysercpu_init_crit:
219*84ad6884SPeter Tyser
220*84ad6884SPeter Tyser	/* mask all IRQs						    */
221*84ad6884SPeter Tyser#ifndef CONFIG_CPU_MONAHANS
222*84ad6884SPeter Tyser	ldr	r0, IC_BASE
223*84ad6884SPeter Tyser	mov	r1, #0x00
224*84ad6884SPeter Tyser	str	r1, [r0, #ICMR]
225*84ad6884SPeter Tyser#else /* CONFIG_CPU_MONAHANS */
226*84ad6884SPeter Tyser	/* Step 1 - Enable CP6 permission */
227*84ad6884SPeter Tyser	mrc	p15, 0, r1, c15, c1, 0	@ read CPAR
228*84ad6884SPeter Tyser	orr	r1, r1, #0x40
229*84ad6884SPeter Tyser		mcr	p15, 0, r1, c15, c1, 0
230*84ad6884SPeter Tyser	CPWAIT	r1
231*84ad6884SPeter Tyser
232*84ad6884SPeter Tyser	/* Step 2 - Mask ICMR & ICMR2 */
233*84ad6884SPeter Tyser	mov	r1, #0
234*84ad6884SPeter Tyser	mcr	p6, 0, r1, c1, c0, 0	@ ICMR
235*84ad6884SPeter Tyser	mcr	p6, 0, r1, c7, c0, 0	@ ICMR2
236*84ad6884SPeter Tyser
237*84ad6884SPeter Tyser	/* turn off all clocks but the ones we will definitly require */
238*84ad6884SPeter Tyser	ldr	r1, =CKENA
239*84ad6884SPeter Tyser	ldr	r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC)
240*84ad6884SPeter Tyser	str	r2, [r1]
241*84ad6884SPeter Tyser	ldr	r1, =CKENB
242*84ad6884SPeter Tyser	ldr	r2, =(CKENB_6_IRQ)
243*84ad6884SPeter Tyser	str	r2, [r1]
244*84ad6884SPeter Tyser#endif /* !CONFIG_CPU_MONAHANS */
245*84ad6884SPeter Tyser
246*84ad6884SPeter Tyser	/* set clock speed */
247*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
248*84ad6884SPeter Tyser	ldr	r0, =ACCR
249*84ad6884SPeter Tyser	ldr	r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK))
250*84ad6884SPeter Tyser	str	r1, [r0]
251*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
252*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
253*84ad6884SPeter Tyser	ldr	r0, CC_BASE
254*84ad6884SPeter Tyser	ldr	r1, cpuspeed
255*84ad6884SPeter Tyser	str	r1, [r0, #CCCR]
256*84ad6884SPeter Tyser	mov	r0, #2
257*84ad6884SPeter Tyser	mcr	p14, 0, r0, c6, c0, 0
258*84ad6884SPeter Tyser
259*84ad6884SPeter Tysersetspeed_done:
260*84ad6884SPeter Tyser
261*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
262*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
263*84ad6884SPeter Tyser
264*84ad6884SPeter Tyser	/*
265*84ad6884SPeter Tyser	 * before relocating, we have to setup RAM timing
266*84ad6884SPeter Tyser	 * because memory timing is board-dependend, you will
267*84ad6884SPeter Tyser	 * find a lowlevel_init.S in your board directory.
268*84ad6884SPeter Tyser	 */
269*84ad6884SPeter Tyser	mov	ip,	lr
270*84ad6884SPeter Tyser	bl	lowlevel_init
271*84ad6884SPeter Tyser	mov	lr,	ip
272*84ad6884SPeter Tyser
273*84ad6884SPeter Tyser	/* Memory interfaces are working. Disable MMU and enable I-cache.   */
274*84ad6884SPeter Tyser	/* mk: hmm, this is not in the monahans docs, leave it now but
275*84ad6884SPeter Tyser	 *     check here if it doesn't work :-) */
276*84ad6884SPeter Tyser
277*84ad6884SPeter Tyser	ldr	r0, =0x2001		/* enable access to all coproc.	    */
278*84ad6884SPeter Tyser	mcr	p15, 0, r0, c15, c1, 0
279*84ad6884SPeter Tyser	CPWAIT r0
280*84ad6884SPeter Tyser
281*84ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c10, 4	/* drain the write & fill buffers   */
282*84ad6884SPeter Tyser	CPWAIT r0
283*84ad6884SPeter Tyser
284*84ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c7, 0	/* flush Icache, Dcache and BTB	    */
285*84ad6884SPeter Tyser	CPWAIT r0
286*84ad6884SPeter Tyser
287*84ad6884SPeter Tyser	mcr	p15, 0, r0, c8, c7, 0	/* flush instuction and data TLBs   */
288*84ad6884SPeter Tyser	CPWAIT r0
289*84ad6884SPeter Tyser
290*84ad6884SPeter Tyser	/* Enable the Icache						    */
291*84ad6884SPeter Tyser/*
292*84ad6884SPeter Tyser	mrc	p15, 0, r0, c1, c0, 0
293*84ad6884SPeter Tyser	orr	r0, r0, #0x1800
294*84ad6884SPeter Tyser	mcr	p15, 0, r0, c1, c0, 0
295*84ad6884SPeter Tyser	CPWAIT
296*84ad6884SPeter Tyser*/
297*84ad6884SPeter Tyser	mov	pc, lr
298*84ad6884SPeter Tyser
299*84ad6884SPeter Tyser
300*84ad6884SPeter Tyser/****************************************************************************/
301*84ad6884SPeter Tyser/*									    */
302*84ad6884SPeter Tyser/* Interrupt handling							    */
303*84ad6884SPeter Tyser/*									    */
304*84ad6884SPeter Tyser/****************************************************************************/
305*84ad6884SPeter Tyser
306*84ad6884SPeter Tyser/* IRQ stack frame							    */
307*84ad6884SPeter Tyser
308*84ad6884SPeter Tyser#define S_FRAME_SIZE	72
309*84ad6884SPeter Tyser
310*84ad6884SPeter Tyser#define S_OLD_R0	68
311*84ad6884SPeter Tyser#define S_PSR		64
312*84ad6884SPeter Tyser#define S_PC		60
313*84ad6884SPeter Tyser#define S_LR		56
314*84ad6884SPeter Tyser#define S_SP		52
315*84ad6884SPeter Tyser
316*84ad6884SPeter Tyser#define S_IP		48
317*84ad6884SPeter Tyser#define S_FP		44
318*84ad6884SPeter Tyser#define S_R10		40
319*84ad6884SPeter Tyser#define S_R9		36
320*84ad6884SPeter Tyser#define S_R8		32
321*84ad6884SPeter Tyser#define S_R7		28
322*84ad6884SPeter Tyser#define S_R6		24
323*84ad6884SPeter Tyser#define S_R5		20
324*84ad6884SPeter Tyser#define S_R4		16
325*84ad6884SPeter Tyser#define S_R3		12
326*84ad6884SPeter Tyser#define S_R2		8
327*84ad6884SPeter Tyser#define S_R1		4
328*84ad6884SPeter Tyser#define S_R0		0
329*84ad6884SPeter Tyser
330*84ad6884SPeter Tyser#define MODE_SVC 0x13
331*84ad6884SPeter Tyser
332*84ad6884SPeter Tyser	/* use bad_save_user_regs for abort/prefetch/undef/swi ...	    */
333*84ad6884SPeter Tyser
334*84ad6884SPeter Tyser	.macro	bad_save_user_regs
335*84ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
336*84ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	    */
337*84ad6884SPeter Tyser	add	r8, sp, #S_PC
338*84ad6884SPeter Tyser
339*84ad6884SPeter Tyser	ldr	r2, _armboot_start
340*84ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
341*84ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
342*84ad6884SPeter Tyser	ldmia	r2, {r2 - r4}			/* get pc, cpsr, old_r0	    */
343*84ad6884SPeter Tyser	add	r0, sp, #S_FRAME_SIZE		/* restore sp_SVC	    */
344*84ad6884SPeter Tyser
345*84ad6884SPeter Tyser	add	r5, sp, #S_SP
346*84ad6884SPeter Tyser	mov	r1, lr
347*84ad6884SPeter Tyser	stmia	r5, {r0 - r4}			/* save sp_SVC, lr_SVC, pc, cpsr, old_r */
348*84ad6884SPeter Tyser	mov	r0, sp
349*84ad6884SPeter Tyser	.endm
350*84ad6884SPeter Tyser
351*84ad6884SPeter Tyser
352*84ad6884SPeter Tyser	/* use irq_save_user_regs / irq_restore_user_regs for		     */
353*84ad6884SPeter Tyser	/* IRQ/FIQ handling						     */
354*84ad6884SPeter Tyser
355*84ad6884SPeter Tyser	.macro	irq_save_user_regs
356*84ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
357*84ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	     */
358*84ad6884SPeter Tyser	add	r8, sp, #S_PC
359*84ad6884SPeter Tyser	stmdb	r8, {sp, lr}^			/* Calling SP, LR	     */
360*84ad6884SPeter Tyser	str	lr, [r8, #0]			/* Save calling PC	     */
361*84ad6884SPeter Tyser	mrs	r6, spsr
362*84ad6884SPeter Tyser	str	r6, [r8, #4]			/* Save CPSR		     */
363*84ad6884SPeter Tyser	str	r0, [r8, #8]			/* Save OLD_R0		     */
364*84ad6884SPeter Tyser	mov	r0, sp
365*84ad6884SPeter Tyser	.endm
366*84ad6884SPeter Tyser
367*84ad6884SPeter Tyser	.macro	irq_restore_user_regs
368*84ad6884SPeter Tyser	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
369*84ad6884SPeter Tyser	mov	r0, r0
370*84ad6884SPeter Tyser	ldr	lr, [sp, #S_PC]			@ Get PC
371*84ad6884SPeter Tyser	add	sp, sp, #S_FRAME_SIZE
372*84ad6884SPeter Tyser	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
373*84ad6884SPeter Tyser	.endm
374*84ad6884SPeter Tyser
375*84ad6884SPeter Tyser	.macro get_bad_stack
376*84ad6884SPeter Tyser	ldr	r13, _armboot_start		@ setup our mode stack
377*84ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
378*84ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
379*84ad6884SPeter Tyser
380*84ad6884SPeter Tyser	str	lr, [r13]			@ save caller lr / spsr
381*84ad6884SPeter Tyser	mrs	lr, spsr
382*84ad6884SPeter Tyser	str	lr, [r13, #4]
383*84ad6884SPeter Tyser
384*84ad6884SPeter Tyser	mov	r13, #MODE_SVC			@ prepare SVC-Mode
385*84ad6884SPeter Tyser	msr	spsr_c, r13
386*84ad6884SPeter Tyser	mov	lr, pc
387*84ad6884SPeter Tyser	movs	pc, lr
388*84ad6884SPeter Tyser	.endm
389*84ad6884SPeter Tyser
390*84ad6884SPeter Tyser	.macro get_irq_stack			@ setup IRQ stack
391*84ad6884SPeter Tyser	ldr	sp, IRQ_STACK_START
392*84ad6884SPeter Tyser	.endm
393*84ad6884SPeter Tyser
394*84ad6884SPeter Tyser	.macro get_fiq_stack			@ setup FIQ stack
395*84ad6884SPeter Tyser	ldr	sp, FIQ_STACK_START
396*84ad6884SPeter Tyser	.endm
397*84ad6884SPeter Tyser
398*84ad6884SPeter Tyser
399*84ad6884SPeter Tyser/****************************************************************************/
400*84ad6884SPeter Tyser/*									    */
401*84ad6884SPeter Tyser/* exception handlers							    */
402*84ad6884SPeter Tyser/*									    */
403*84ad6884SPeter Tyser/****************************************************************************/
404*84ad6884SPeter Tyser
405*84ad6884SPeter Tyser	.align	5
406*84ad6884SPeter Tyserundefined_instruction:
407*84ad6884SPeter Tyser	get_bad_stack
408*84ad6884SPeter Tyser	bad_save_user_regs
409*84ad6884SPeter Tyser	bl	do_undefined_instruction
410*84ad6884SPeter Tyser
411*84ad6884SPeter Tyser	.align	5
412*84ad6884SPeter Tysersoftware_interrupt:
413*84ad6884SPeter Tyser	get_bad_stack
414*84ad6884SPeter Tyser	bad_save_user_regs
415*84ad6884SPeter Tyser	bl	do_software_interrupt
416*84ad6884SPeter Tyser
417*84ad6884SPeter Tyser	.align	5
418*84ad6884SPeter Tyserprefetch_abort:
419*84ad6884SPeter Tyser	get_bad_stack
420*84ad6884SPeter Tyser	bad_save_user_regs
421*84ad6884SPeter Tyser	bl	do_prefetch_abort
422*84ad6884SPeter Tyser
423*84ad6884SPeter Tyser	.align	5
424*84ad6884SPeter Tyserdata_abort:
425*84ad6884SPeter Tyser	get_bad_stack
426*84ad6884SPeter Tyser	bad_save_user_regs
427*84ad6884SPeter Tyser	bl	do_data_abort
428*84ad6884SPeter Tyser
429*84ad6884SPeter Tyser	.align	5
430*84ad6884SPeter Tysernot_used:
431*84ad6884SPeter Tyser	get_bad_stack
432*84ad6884SPeter Tyser	bad_save_user_regs
433*84ad6884SPeter Tyser	bl	do_not_used
434*84ad6884SPeter Tyser
435*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
436*84ad6884SPeter Tyser
437*84ad6884SPeter Tyser	.align	5
438*84ad6884SPeter Tyserirq:
439*84ad6884SPeter Tyser	get_irq_stack
440*84ad6884SPeter Tyser	irq_save_user_regs
441*84ad6884SPeter Tyser	bl	do_irq
442*84ad6884SPeter Tyser	irq_restore_user_regs
443*84ad6884SPeter Tyser
444*84ad6884SPeter Tyser	.align	5
445*84ad6884SPeter Tyserfiq:
446*84ad6884SPeter Tyser	get_fiq_stack
447*84ad6884SPeter Tyser	irq_save_user_regs		/* someone ought to write a more    */
448*84ad6884SPeter Tyser	bl	do_fiq			/* effiction fiq_save_user_regs	    */
449*84ad6884SPeter Tyser	irq_restore_user_regs
450*84ad6884SPeter Tyser
451*84ad6884SPeter Tyser#else /* !CONFIG_USE_IRQ */
452*84ad6884SPeter Tyser
453*84ad6884SPeter Tyser	.align	5
454*84ad6884SPeter Tyserirq:
455*84ad6884SPeter Tyser	get_bad_stack
456*84ad6884SPeter Tyser	bad_save_user_regs
457*84ad6884SPeter Tyser	bl	do_irq
458*84ad6884SPeter Tyser
459*84ad6884SPeter Tyser	.align	5
460*84ad6884SPeter Tyserfiq:
461*84ad6884SPeter Tyser	get_bad_stack
462*84ad6884SPeter Tyser	bad_save_user_regs
463*84ad6884SPeter Tyser	bl	do_fiq
464*84ad6884SPeter Tyser
465*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
466*84ad6884SPeter Tyser
467*84ad6884SPeter Tyser/****************************************************************************/
468*84ad6884SPeter Tyser/*									    */
469*84ad6884SPeter Tyser/* Reset function: the PXA250 doesn't have a reset function, so we have to  */
470*84ad6884SPeter Tyser/* perform a watchdog timeout for a soft reset.				    */
471*84ad6884SPeter Tyser/*									    */
472*84ad6884SPeter Tyser/****************************************************************************/
473*84ad6884SPeter Tyser
474*84ad6884SPeter Tyser	.align	5
475*84ad6884SPeter Tyser.globl reset_cpu
476*84ad6884SPeter Tyser
477*84ad6884SPeter Tyser	/* FIXME: this code is PXA250 specific. How is this handled on	    */
478*84ad6884SPeter Tyser	/*	  other XScale processors?				    */
479*84ad6884SPeter Tyser
480*84ad6884SPeter Tyserreset_cpu:
481*84ad6884SPeter Tyser
482*84ad6884SPeter Tyser	/* We set OWE:WME (watchdog enable) and wait until timeout happens  */
483*84ad6884SPeter Tyser
484*84ad6884SPeter Tyser	ldr	r0, OSTIMER_BASE
485*84ad6884SPeter Tyser	ldr	r1, [r0, #OWER]
486*84ad6884SPeter Tyser	orr	r1, r1, #0x0001			/* bit0: WME		    */
487*84ad6884SPeter Tyser	str	r1, [r0, #OWER]
488*84ad6884SPeter Tyser
489*84ad6884SPeter Tyser	/* OS timer does only wrap every 1165 seconds, so we have to set    */
490*84ad6884SPeter Tyser	/* the match register as well.					    */
491*84ad6884SPeter Tyser
492*84ad6884SPeter Tyser	ldr	r1, [r0, #OSCR]			/* read OS timer	    */
493*84ad6884SPeter Tyser	add	r1, r1, #0x800			/* let OSMR3 match after    */
494*84ad6884SPeter Tyser	add	r1, r1, #0x800			/* 4096*(1/3.6864MHz)=1ms   */
495*84ad6884SPeter Tyser	str	r1, [r0, #OSMR3]
496*84ad6884SPeter Tyser
497*84ad6884SPeter Tyserreset_endless:
498*84ad6884SPeter Tyser
499*84ad6884SPeter Tyser	b	reset_endless
500