xref: /openbmc/u-boot/arch/arm/cpu/pxa/start.S (revision 84ad6884)
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 */
143*84ad6884SPeter Tyser	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
144*84ad6884SPeter Tyser
145*84ad6884SPeter Tyserclear_bss:
146*84ad6884SPeter Tyser	ldr	r0, _bss_start		/* find start of bss segment	    */
147*84ad6884SPeter Tyser	ldr	r1, _bss_end		/* stop here			    */
148*84ad6884SPeter Tyser	mov	r2, #0x00000000		/* clear			    */
149*84ad6884SPeter Tyser
150*84ad6884SPeter Tyserclbss_l:str	r2, [r0]		/* clear loop...		    */
151*84ad6884SPeter Tyser	add	r0, r0, #4
152*84ad6884SPeter Tyser	cmp	r0, r1
153*84ad6884SPeter Tyser	ble	clbss_l
154*84ad6884SPeter Tyser
155*84ad6884SPeter Tyser	ldr	pc, _start_armboot
156*84ad6884SPeter Tyser
157*84ad6884SPeter Tyser_start_armboot: .word start_armboot
158*84ad6884SPeter Tyser
159*84ad6884SPeter Tyser
160*84ad6884SPeter Tyser/****************************************************************************/
161*84ad6884SPeter Tyser/*									    */
162*84ad6884SPeter Tyser/* CPU_init_critical registers						    */
163*84ad6884SPeter Tyser/*									    */
164*84ad6884SPeter Tyser/* - setup important registers						    */
165*84ad6884SPeter Tyser/* - setup memory timing						    */
166*84ad6884SPeter Tyser/*									    */
167*84ad6884SPeter Tyser/****************************************************************************/
168*84ad6884SPeter Tyser/* mk@tbd: Fix this! */
169*84ad6884SPeter Tyser#undef RCSR
170*84ad6884SPeter Tyser#undef ICMR
171*84ad6884SPeter Tyser#undef OSMR3
172*84ad6884SPeter Tyser#undef OSCR
173*84ad6884SPeter Tyser#undef OWER
174*84ad6884SPeter Tyser#undef OIER
175*84ad6884SPeter Tyser#undef CCCR
176*84ad6884SPeter Tyser
177*84ad6884SPeter Tyser/* Interrupt-Controller base address					    */
178*84ad6884SPeter TyserIC_BASE:	   .word	   0x40d00000
179*84ad6884SPeter Tyser#define ICMR	0x04
180*84ad6884SPeter Tyser
181*84ad6884SPeter Tyser/* Reset-Controller */
182*84ad6884SPeter TyserRST_BASE:	.word	0x40f00030
183*84ad6884SPeter Tyser#define RCSR	0x00
184*84ad6884SPeter Tyser
185*84ad6884SPeter Tyser/* Operating System Timer */
186*84ad6884SPeter TyserOSTIMER_BASE:	.word	0x40a00000
187*84ad6884SPeter Tyser#define OSMR3	0x0C
188*84ad6884SPeter Tyser#define OSCR	0x10
189*84ad6884SPeter Tyser#define OWER	0x18
190*84ad6884SPeter Tyser#define OIER	0x1C
191*84ad6884SPeter Tyser
192*84ad6884SPeter Tyser/* Clock Manager Registers						    */
193*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
194*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
195*84ad6884SPeter Tyser#  error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!"
196*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */
197*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO
198*84ad6884SPeter Tyser#  define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1
199*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */
200*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
201*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
202*84ad6884SPeter TyserCC_BASE:	.word	0x41300000
203*84ad6884SPeter Tyser#define CCCR	0x00
204*84ad6884SPeter Tysercpuspeed:	.word	CONFIG_SYS_CPUSPEED
205*84ad6884SPeter Tyser#else /* !CONFIG_SYS_CPUSPEED */
206*84ad6884SPeter Tyser#error "You have to define CONFIG_SYS_CPUSPEED!!"
207*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
208*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
209*84ad6884SPeter Tyser
210*84ad6884SPeter Tyser	/* takes care the CP15 update has taken place */
211*84ad6884SPeter Tyser	.macro CPWAIT reg
212*84ad6884SPeter Tyser	mrc  p15,0,\reg,c2,c0,0
213*84ad6884SPeter Tyser	mov  \reg,\reg
214*84ad6884SPeter Tyser	sub  pc,pc,#4
215*84ad6884SPeter Tyser	.endm
216*84ad6884SPeter Tyser
217*84ad6884SPeter Tysercpu_init_crit:
218*84ad6884SPeter Tyser
219*84ad6884SPeter Tyser	/* mask all IRQs						    */
220*84ad6884SPeter Tyser#ifndef CONFIG_CPU_MONAHANS
221*84ad6884SPeter Tyser	ldr	r0, IC_BASE
222*84ad6884SPeter Tyser	mov	r1, #0x00
223*84ad6884SPeter Tyser	str	r1, [r0, #ICMR]
224*84ad6884SPeter Tyser#else /* CONFIG_CPU_MONAHANS */
225*84ad6884SPeter Tyser	/* Step 1 - Enable CP6 permission */
226*84ad6884SPeter Tyser	mrc	p15, 0, r1, c15, c1, 0	@ read CPAR
227*84ad6884SPeter Tyser	orr	r1, r1, #0x40
228*84ad6884SPeter Tyser		mcr	p15, 0, r1, c15, c1, 0
229*84ad6884SPeter Tyser	CPWAIT	r1
230*84ad6884SPeter Tyser
231*84ad6884SPeter Tyser	/* Step 2 - Mask ICMR & ICMR2 */
232*84ad6884SPeter Tyser	mov	r1, #0
233*84ad6884SPeter Tyser	mcr	p6, 0, r1, c1, c0, 0	@ ICMR
234*84ad6884SPeter Tyser	mcr	p6, 0, r1, c7, c0, 0	@ ICMR2
235*84ad6884SPeter Tyser
236*84ad6884SPeter Tyser	/* turn off all clocks but the ones we will definitly require */
237*84ad6884SPeter Tyser	ldr	r1, =CKENA
238*84ad6884SPeter Tyser	ldr	r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC)
239*84ad6884SPeter Tyser	str	r2, [r1]
240*84ad6884SPeter Tyser	ldr	r1, =CKENB
241*84ad6884SPeter Tyser	ldr	r2, =(CKENB_6_IRQ)
242*84ad6884SPeter Tyser	str	r2, [r1]
243*84ad6884SPeter Tyser#endif /* !CONFIG_CPU_MONAHANS */
244*84ad6884SPeter Tyser
245*84ad6884SPeter Tyser	/* set clock speed */
246*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS
247*84ad6884SPeter Tyser	ldr	r0, =ACCR
248*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))
249*84ad6884SPeter Tyser	str	r1, [r0]
250*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */
251*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED
252*84ad6884SPeter Tyser	ldr	r0, CC_BASE
253*84ad6884SPeter Tyser	ldr	r1, cpuspeed
254*84ad6884SPeter Tyser	str	r1, [r0, #CCCR]
255*84ad6884SPeter Tyser	mov	r0, #2
256*84ad6884SPeter Tyser	mcr	p14, 0, r0, c6, c0, 0
257*84ad6884SPeter Tyser
258*84ad6884SPeter Tysersetspeed_done:
259*84ad6884SPeter Tyser
260*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */
261*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */
262*84ad6884SPeter Tyser
263*84ad6884SPeter Tyser	/*
264*84ad6884SPeter Tyser	 * before relocating, we have to setup RAM timing
265*84ad6884SPeter Tyser	 * because memory timing is board-dependend, you will
266*84ad6884SPeter Tyser	 * find a lowlevel_init.S in your board directory.
267*84ad6884SPeter Tyser	 */
268*84ad6884SPeter Tyser	mov	ip,	lr
269*84ad6884SPeter Tyser	bl	lowlevel_init
270*84ad6884SPeter Tyser	mov	lr,	ip
271*84ad6884SPeter Tyser
272*84ad6884SPeter Tyser	/* Memory interfaces are working. Disable MMU and enable I-cache.   */
273*84ad6884SPeter Tyser	/* mk: hmm, this is not in the monahans docs, leave it now but
274*84ad6884SPeter Tyser	 *     check here if it doesn't work :-) */
275*84ad6884SPeter Tyser
276*84ad6884SPeter Tyser	ldr	r0, =0x2001		/* enable access to all coproc.	    */
277*84ad6884SPeter Tyser	mcr	p15, 0, r0, c15, c1, 0
278*84ad6884SPeter Tyser	CPWAIT r0
279*84ad6884SPeter Tyser
280*84ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c10, 4	/* drain the write & fill buffers   */
281*84ad6884SPeter Tyser	CPWAIT r0
282*84ad6884SPeter Tyser
283*84ad6884SPeter Tyser	mcr	p15, 0, r0, c7, c7, 0	/* flush Icache, Dcache and BTB	    */
284*84ad6884SPeter Tyser	CPWAIT r0
285*84ad6884SPeter Tyser
286*84ad6884SPeter Tyser	mcr	p15, 0, r0, c8, c7, 0	/* flush instuction and data TLBs   */
287*84ad6884SPeter Tyser	CPWAIT r0
288*84ad6884SPeter Tyser
289*84ad6884SPeter Tyser	/* Enable the Icache						    */
290*84ad6884SPeter Tyser/*
291*84ad6884SPeter Tyser	mrc	p15, 0, r0, c1, c0, 0
292*84ad6884SPeter Tyser	orr	r0, r0, #0x1800
293*84ad6884SPeter Tyser	mcr	p15, 0, r0, c1, c0, 0
294*84ad6884SPeter Tyser	CPWAIT
295*84ad6884SPeter Tyser*/
296*84ad6884SPeter Tyser	mov	pc, lr
297*84ad6884SPeter Tyser
298*84ad6884SPeter Tyser
299*84ad6884SPeter Tyser/****************************************************************************/
300*84ad6884SPeter Tyser/*									    */
301*84ad6884SPeter Tyser/* Interrupt handling							    */
302*84ad6884SPeter Tyser/*									    */
303*84ad6884SPeter Tyser/****************************************************************************/
304*84ad6884SPeter Tyser
305*84ad6884SPeter Tyser/* IRQ stack frame							    */
306*84ad6884SPeter Tyser
307*84ad6884SPeter Tyser#define S_FRAME_SIZE	72
308*84ad6884SPeter Tyser
309*84ad6884SPeter Tyser#define S_OLD_R0	68
310*84ad6884SPeter Tyser#define S_PSR		64
311*84ad6884SPeter Tyser#define S_PC		60
312*84ad6884SPeter Tyser#define S_LR		56
313*84ad6884SPeter Tyser#define S_SP		52
314*84ad6884SPeter Tyser
315*84ad6884SPeter Tyser#define S_IP		48
316*84ad6884SPeter Tyser#define S_FP		44
317*84ad6884SPeter Tyser#define S_R10		40
318*84ad6884SPeter Tyser#define S_R9		36
319*84ad6884SPeter Tyser#define S_R8		32
320*84ad6884SPeter Tyser#define S_R7		28
321*84ad6884SPeter Tyser#define S_R6		24
322*84ad6884SPeter Tyser#define S_R5		20
323*84ad6884SPeter Tyser#define S_R4		16
324*84ad6884SPeter Tyser#define S_R3		12
325*84ad6884SPeter Tyser#define S_R2		8
326*84ad6884SPeter Tyser#define S_R1		4
327*84ad6884SPeter Tyser#define S_R0		0
328*84ad6884SPeter Tyser
329*84ad6884SPeter Tyser#define MODE_SVC 0x13
330*84ad6884SPeter Tyser
331*84ad6884SPeter Tyser	/* use bad_save_user_regs for abort/prefetch/undef/swi ...	    */
332*84ad6884SPeter Tyser
333*84ad6884SPeter Tyser	.macro	bad_save_user_regs
334*84ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
335*84ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	    */
336*84ad6884SPeter Tyser	add	r8, sp, #S_PC
337*84ad6884SPeter Tyser
338*84ad6884SPeter Tyser	ldr	r2, _armboot_start
339*84ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
340*84ad6884SPeter Tyser	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
341*84ad6884SPeter Tyser	ldmia	r2, {r2 - r4}			/* get pc, cpsr, old_r0	    */
342*84ad6884SPeter Tyser	add	r0, sp, #S_FRAME_SIZE		/* restore sp_SVC	    */
343*84ad6884SPeter Tyser
344*84ad6884SPeter Tyser	add	r5, sp, #S_SP
345*84ad6884SPeter Tyser	mov	r1, lr
346*84ad6884SPeter Tyser	stmia	r5, {r0 - r4}			/* save sp_SVC, lr_SVC, pc, cpsr, old_r */
347*84ad6884SPeter Tyser	mov	r0, sp
348*84ad6884SPeter Tyser	.endm
349*84ad6884SPeter Tyser
350*84ad6884SPeter Tyser
351*84ad6884SPeter Tyser	/* use irq_save_user_regs / irq_restore_user_regs for		     */
352*84ad6884SPeter Tyser	/* IRQ/FIQ handling						     */
353*84ad6884SPeter Tyser
354*84ad6884SPeter Tyser	.macro	irq_save_user_regs
355*84ad6884SPeter Tyser	sub	sp, sp, #S_FRAME_SIZE
356*84ad6884SPeter Tyser	stmia	sp, {r0 - r12}			/* Calling r0-r12	     */
357*84ad6884SPeter Tyser	add	r8, sp, #S_PC
358*84ad6884SPeter Tyser	stmdb	r8, {sp, lr}^			/* Calling SP, LR	     */
359*84ad6884SPeter Tyser	str	lr, [r8, #0]			/* Save calling PC	     */
360*84ad6884SPeter Tyser	mrs	r6, spsr
361*84ad6884SPeter Tyser	str	r6, [r8, #4]			/* Save CPSR		     */
362*84ad6884SPeter Tyser	str	r0, [r8, #8]			/* Save OLD_R0		     */
363*84ad6884SPeter Tyser	mov	r0, sp
364*84ad6884SPeter Tyser	.endm
365*84ad6884SPeter Tyser
366*84ad6884SPeter Tyser	.macro	irq_restore_user_regs
367*84ad6884SPeter Tyser	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
368*84ad6884SPeter Tyser	mov	r0, r0
369*84ad6884SPeter Tyser	ldr	lr, [sp, #S_PC]			@ Get PC
370*84ad6884SPeter Tyser	add	sp, sp, #S_FRAME_SIZE
371*84ad6884SPeter Tyser	subs	pc, lr, #4			@ return & move spsr_svc into cpsr
372*84ad6884SPeter Tyser	.endm
373*84ad6884SPeter Tyser
374*84ad6884SPeter Tyser	.macro get_bad_stack
375*84ad6884SPeter Tyser	ldr	r13, _armboot_start		@ setup our mode stack
376*84ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
377*84ad6884SPeter Tyser	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
378*84ad6884SPeter Tyser
379*84ad6884SPeter Tyser	str	lr, [r13]			@ save caller lr / spsr
380*84ad6884SPeter Tyser	mrs	lr, spsr
381*84ad6884SPeter Tyser	str	lr, [r13, #4]
382*84ad6884SPeter Tyser
383*84ad6884SPeter Tyser	mov	r13, #MODE_SVC			@ prepare SVC-Mode
384*84ad6884SPeter Tyser	msr	spsr_c, r13
385*84ad6884SPeter Tyser	mov	lr, pc
386*84ad6884SPeter Tyser	movs	pc, lr
387*84ad6884SPeter Tyser	.endm
388*84ad6884SPeter Tyser
389*84ad6884SPeter Tyser	.macro get_irq_stack			@ setup IRQ stack
390*84ad6884SPeter Tyser	ldr	sp, IRQ_STACK_START
391*84ad6884SPeter Tyser	.endm
392*84ad6884SPeter Tyser
393*84ad6884SPeter Tyser	.macro get_fiq_stack			@ setup FIQ stack
394*84ad6884SPeter Tyser	ldr	sp, FIQ_STACK_START
395*84ad6884SPeter Tyser	.endm
396*84ad6884SPeter Tyser
397*84ad6884SPeter Tyser
398*84ad6884SPeter Tyser/****************************************************************************/
399*84ad6884SPeter Tyser/*									    */
400*84ad6884SPeter Tyser/* exception handlers							    */
401*84ad6884SPeter Tyser/*									    */
402*84ad6884SPeter Tyser/****************************************************************************/
403*84ad6884SPeter Tyser
404*84ad6884SPeter Tyser	.align	5
405*84ad6884SPeter Tyserundefined_instruction:
406*84ad6884SPeter Tyser	get_bad_stack
407*84ad6884SPeter Tyser	bad_save_user_regs
408*84ad6884SPeter Tyser	bl	do_undefined_instruction
409*84ad6884SPeter Tyser
410*84ad6884SPeter Tyser	.align	5
411*84ad6884SPeter Tysersoftware_interrupt:
412*84ad6884SPeter Tyser	get_bad_stack
413*84ad6884SPeter Tyser	bad_save_user_regs
414*84ad6884SPeter Tyser	bl	do_software_interrupt
415*84ad6884SPeter Tyser
416*84ad6884SPeter Tyser	.align	5
417*84ad6884SPeter Tyserprefetch_abort:
418*84ad6884SPeter Tyser	get_bad_stack
419*84ad6884SPeter Tyser	bad_save_user_regs
420*84ad6884SPeter Tyser	bl	do_prefetch_abort
421*84ad6884SPeter Tyser
422*84ad6884SPeter Tyser	.align	5
423*84ad6884SPeter Tyserdata_abort:
424*84ad6884SPeter Tyser	get_bad_stack
425*84ad6884SPeter Tyser	bad_save_user_regs
426*84ad6884SPeter Tyser	bl	do_data_abort
427*84ad6884SPeter Tyser
428*84ad6884SPeter Tyser	.align	5
429*84ad6884SPeter Tysernot_used:
430*84ad6884SPeter Tyser	get_bad_stack
431*84ad6884SPeter Tyser	bad_save_user_regs
432*84ad6884SPeter Tyser	bl	do_not_used
433*84ad6884SPeter Tyser
434*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ
435*84ad6884SPeter Tyser
436*84ad6884SPeter Tyser	.align	5
437*84ad6884SPeter Tyserirq:
438*84ad6884SPeter Tyser	get_irq_stack
439*84ad6884SPeter Tyser	irq_save_user_regs
440*84ad6884SPeter Tyser	bl	do_irq
441*84ad6884SPeter Tyser	irq_restore_user_regs
442*84ad6884SPeter Tyser
443*84ad6884SPeter Tyser	.align	5
444*84ad6884SPeter Tyserfiq:
445*84ad6884SPeter Tyser	get_fiq_stack
446*84ad6884SPeter Tyser	irq_save_user_regs		/* someone ought to write a more    */
447*84ad6884SPeter Tyser	bl	do_fiq			/* effiction fiq_save_user_regs	    */
448*84ad6884SPeter Tyser	irq_restore_user_regs
449*84ad6884SPeter Tyser
450*84ad6884SPeter Tyser#else /* !CONFIG_USE_IRQ */
451*84ad6884SPeter Tyser
452*84ad6884SPeter Tyser	.align	5
453*84ad6884SPeter Tyserirq:
454*84ad6884SPeter Tyser	get_bad_stack
455*84ad6884SPeter Tyser	bad_save_user_regs
456*84ad6884SPeter Tyser	bl	do_irq
457*84ad6884SPeter Tyser
458*84ad6884SPeter Tyser	.align	5
459*84ad6884SPeter Tyserfiq:
460*84ad6884SPeter Tyser	get_bad_stack
461*84ad6884SPeter Tyser	bad_save_user_regs
462*84ad6884SPeter Tyser	bl	do_fiq
463*84ad6884SPeter Tyser
464*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */
465*84ad6884SPeter Tyser
466*84ad6884SPeter Tyser/****************************************************************************/
467*84ad6884SPeter Tyser/*									    */
468*84ad6884SPeter Tyser/* Reset function: the PXA250 doesn't have a reset function, so we have to  */
469*84ad6884SPeter Tyser/* perform a watchdog timeout for a soft reset.				    */
470*84ad6884SPeter Tyser/*									    */
471*84ad6884SPeter Tyser/****************************************************************************/
472*84ad6884SPeter Tyser
473*84ad6884SPeter Tyser	.align	5
474*84ad6884SPeter Tyser.globl reset_cpu
475*84ad6884SPeter Tyser
476*84ad6884SPeter Tyser	/* FIXME: this code is PXA250 specific. How is this handled on	    */
477*84ad6884SPeter Tyser	/*	  other XScale processors?				    */
478*84ad6884SPeter Tyser
479*84ad6884SPeter Tyserreset_cpu:
480*84ad6884SPeter Tyser
481*84ad6884SPeter Tyser	/* We set OWE:WME (watchdog enable) and wait until timeout happens  */
482*84ad6884SPeter Tyser
483*84ad6884SPeter Tyser	ldr	r0, OSTIMER_BASE
484*84ad6884SPeter Tyser	ldr	r1, [r0, #OWER]
485*84ad6884SPeter Tyser	orr	r1, r1, #0x0001			/* bit0: WME		    */
486*84ad6884SPeter Tyser	str	r1, [r0, #OWER]
487*84ad6884SPeter Tyser
488*84ad6884SPeter Tyser	/* OS timer does only wrap every 1165 seconds, so we have to set    */
489*84ad6884SPeter Tyser	/* the match register as well.					    */
490*84ad6884SPeter Tyser
491*84ad6884SPeter Tyser	ldr	r1, [r0, #OSCR]			/* read OS timer	    */
492*84ad6884SPeter Tyser	add	r1, r1, #0x800			/* let OSMR3 match after    */
493*84ad6884SPeter Tyser	add	r1, r1, #0x800			/* 4096*(1/3.6864MHz)=1ms   */
494*84ad6884SPeter Tyser	str	r1, [r0, #OSMR3]
495*84ad6884SPeter Tyser
496*84ad6884SPeter Tyserreset_endless:
497*84ad6884SPeter Tyser
498*84ad6884SPeter Tyser	b	reset_endless
499