blob: 09ee815270a886387e30d1ee6419b24a7177ae48 [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*
2 * armboot - Startup Code for ARM920 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
Detlev Zundel792a09e2009-05-13 10:54:10 +02006 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
wdenkfe8c2802002-11-03 00:38:21 +00007 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
Wolfgang Denk9689ddc2009-07-27 10:06:39 +020027#include <common.h>
wdenkfe8c2802002-11-03 00:38:21 +000028#include <config.h>
wdenkfe8c2802002-11-03 00:38:21 +000029
30/*
31 *************************************************************************
32 *
33 * Jump vector table as in table 3.1 in [1]
34 *
35 *************************************************************************
36 */
37
38
39.globl _start
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +090040_start: b start_code
wdenkfe8c2802002-11-03 00:38:21 +000041 ldr pc, _undefined_instruction
42 ldr pc, _software_interrupt
43 ldr pc, _prefetch_abort
44 ldr pc, _data_abort
45 ldr pc, _not_used
46 ldr pc, _irq
47 ldr pc, _fiq
48
49_undefined_instruction: .word undefined_instruction
50_software_interrupt: .word software_interrupt
51_prefetch_abort: .word prefetch_abort
52_data_abort: .word data_abort
53_not_used: .word not_used
54_irq: .word irq
55_fiq: .word fiq
56
57 .balignl 16,0xdeadbeef
58
59
60/*
61 *************************************************************************
62 *
Peter Pearse80767a62007-09-05 16:04:41 +010063 * Startup Code (called from the ARM reset exception vector)
wdenkfe8c2802002-11-03 00:38:21 +000064 *
65 * do important init only if we don't start from memory!
66 * relocate armboot to ram
67 * setup stack
68 * jump to second stage
69 *
70 *************************************************************************
71 */
72
Heiko Schochercc7cdcb2010-09-17 13:10:43 +020073.globl _TEXT_BASE
wdenkfe8c2802002-11-03 00:38:21 +000074_TEXT_BASE:
75 .word TEXT_BASE
76
Heiko Schochercc7cdcb2010-09-17 13:10:43 +020077#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
wdenkfe8c2802002-11-03 00:38:21 +000078.globl _armboot_start
79_armboot_start:
80 .word _start
Heiko Schochercc7cdcb2010-09-17 13:10:43 +020081#endif
wdenkfe8c2802002-11-03 00:38:21 +000082
83/*
wdenkf6e20fc2004-02-08 19:38:38 +000084 * These are defined in the board-specific linker script.
wdenkfe8c2802002-11-03 00:38:21 +000085 */
wdenkf6e20fc2004-02-08 19:38:38 +000086.globl _bss_start
87_bss_start:
88 .word __bss_start
89
90.globl _bss_end
91_bss_end:
92 .word _end
wdenkfe8c2802002-11-03 00:38:21 +000093
wdenkfe8c2802002-11-03 00:38:21 +000094#ifdef CONFIG_USE_IRQ
95/* IRQ stack memory (calculated at run-time) */
96.globl IRQ_STACK_START
97IRQ_STACK_START:
98 .word 0x0badc0de
99
100/* IRQ stack memory (calculated at run-time) */
101.globl FIQ_STACK_START
102FIQ_STACK_START:
103 .word 0x0badc0de
104#endif
105
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200106#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
107/* IRQ stack memory (calculated at run-time) + 8 bytes */
108.globl IRQ_STACK_START_IN
109IRQ_STACK_START_IN:
110 .word 0x0badc0de
wdenkfe8c2802002-11-03 00:38:21 +0000111
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200112.globl _datarel_start
113_datarel_start:
114 .word __datarel_start
115
116.globl _datarelrolocal_start
117_datarelrolocal_start:
118 .word __datarelrolocal_start
119
120.globl _datarellocal_start
121_datarellocal_start:
122 .word __datarellocal_start
123
124.globl _datarelro_start
125_datarelro_start:
126 .word __datarelro_start
127
128.globl _got_start
129_got_start:
130 .word __got_start
131
132.globl _got_end
133_got_end:
134 .word __got_end
135
136/*
137 * the actual start code
138 */
139
140start_code:
141 /*
142 * set the cpu to SVC32 mode
143 */
144 mrs r0, cpsr
145 bic r0, r0, #0x1f
146 orr r0, r0, #0xd3
147 msr cpsr, r0
148
149 bl coloured_LED_init
150 bl red_LED_on
151
152#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
153 /*
154 * relocate exception table
155 */
156 ldr r0, =_start
157 ldr r1, =0x0
158 mov r2, #16
159copyex:
160 subs r2, r2, #1
161 ldr r3, [r0], #4
162 str r3, [r1], #4
163 bne copyex
164#endif
165
166#ifdef CONFIG_S3C24X0
167 /* turn off the watchdog */
168
169# if defined(CONFIG_S3C2400)
170# define pWTCON 0x15300000
171# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
172# define CLKDIVN 0x14800014 /* clock divisor register */
173#else
174# define pWTCON 0x53000000
175# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
176# define INTSUBMSK 0x4A00001C
177# define CLKDIVN 0x4C000014 /* clock divisor register */
178# endif
179
180 ldr r0, =pWTCON
181 mov r1, #0x0
182 str r1, [r0]
183
184 /*
185 * mask all IRQs by setting all bits in the INTMR - default
186 */
187 mov r1, #0xffffffff
188 ldr r0, =INTMSK
189 str r1, [r0]
190# if defined(CONFIG_S3C2410)
191 ldr r1, =0x3ff
192 ldr r0, =INTSUBMSK
193 str r1, [r0]
194# endif
195
196 /* FCLK:HCLK:PCLK = 1:2:4 */
197 /* default FCLK is 120 MHz ! */
198 ldr r0, =CLKDIVN
199 mov r1, #3
200 str r1, [r0]
201#endif /* CONFIG_S3C24X0 */
202
203 /*
204 * we do sys-critical inits only at reboot,
205 * not when booting from ram!
206 */
207#ifndef CONFIG_SKIP_LOWLEVEL_INIT
208 bl cpu_init_crit
209#endif
210
211/* Set stackpointer in internal RAM to call board_init_f */
212call_board_init_f:
213 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
214 ldr r0,=0x00000000
215 bl board_init_f
216
217/*------------------------------------------------------------------------------*/
218
219/*
220 * void relocate_code (addr_sp, gd, addr_moni)
221 *
222 * This "function" does not return, instead it continues in RAM
223 * after relocating the monitor code.
224 *
225 */
226 .globl relocate_code
227relocate_code:
228 mov r4, r0 /* save addr_sp */
229 mov r5, r1 /* save addr of gd */
230 mov r6, r2 /* save addr of destination */
231 mov r7, r2 /* save addr of destination */
232
233 /* Set up the stack */
234stack_setup:
235 mov sp, r4
236
237 adr r0, _start
238 ldr r2, _TEXT_BASE
239 ldr r3, _bss_start
240 sub r2, r3, r2 /* r2 <- size of armboot */
241 add r2, r0, r2 /* r2 <- source end address */
242 cmp r0, r6
243 beq clear_bss
244
245#ifndef CONFIG_SKIP_RELOCATE_UBOOT
246copy_loop:
247 ldmia r0!, {r9-r10} /* copy from source address [r0] */
248 stmia r6!, {r9-r10} /* copy to target address [r1] */
Albert Aribaudda90d4c2010-10-05 16:06:39 +0200249 cmp r0, r2 /* until source end address [r2] */
250 blo copy_loop
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200251
252#ifndef CONFIG_PRELOADER
253 /* fix got entries */
254 ldr r1, _TEXT_BASE /* Text base */
255 mov r0, r7 /* reloc addr */
256 ldr r2, _got_start /* addr in Flash */
257 ldr r3, _got_end /* addr in Flash */
258 sub r3, r3, r1
259 add r3, r3, r0
260 sub r2, r2, r1
261 add r2, r2, r0
262
263fixloop:
264 ldr r4, [r2]
265 sub r4, r4, r1
266 add r4, r4, r0
267 str r4, [r2]
268 add r2, r2, #4
269 cmp r2, r3
270 bne fixloop
271#endif
272#endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
273
274clear_bss:
275#ifndef CONFIG_PRELOADER
276 ldr r0, _bss_start
277 ldr r1, _bss_end
278 ldr r3, _TEXT_BASE /* Text base */
279 mov r4, r7 /* reloc addr */
280 sub r0, r0, r3
281 add r0, r0, r4
282 sub r1, r1, r3
283 add r1, r1, r4
284 mov r2, #0x00000000 /* clear */
285
286clbss_l:str r2, [r0] /* clear loop... */
287 add r0, r0, #4
288 cmp r0, r1
289 bne clbss_l
290
291 bl coloured_LED_init
292 bl red_LED_on
293#endif
294
295/*
296 * We are done. Do not return, instead branch to second part of board
297 * initialization, now running from RAM.
298 */
299#ifdef CONFIG_NAND_SPL
300 ldr pc, _nand_boot
301
302_nand_boot: .word nand_boot
303#else
304 ldr r0, _TEXT_BASE
305 ldr r2, _board_init_r
306 sub r2, r2, r0
307 add r2, r2, r7 /* position from board_init_r in RAM */
308 /* setup parameters for board_init_r */
309 mov r0, r5 /* gd_t */
310 mov r1, r7 /* dest_addr */
311 /* jump to it ... */
312 mov lr, r2
313 mov pc, lr
314
315_board_init_r: .word board_init_r
316#endif
317
318#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
wdenkfe8c2802002-11-03 00:38:21 +0000319/*
Peter Pearse80767a62007-09-05 16:04:41 +0100320 * the actual start code
wdenkfe8c2802002-11-03 00:38:21 +0000321 */
322
Peter Pearse80767a62007-09-05 16:04:41 +0100323start_code:
wdenkfe8c2802002-11-03 00:38:21 +0000324 /*
325 * set the cpu to SVC32 mode
326 */
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900327 mrs r0, cpsr
328 bic r0, r0, #0x1f
329 orr r0, r0, #0xd3
330 msr cpsr, r0
Peter Pearse80767a62007-09-05 16:04:41 +0100331
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900332 bl coloured_LED_init
333 bl red_LED_on
Peter Pearsed4fc6012007-08-14 10:10:52 +0100334
Jean-Christophe PLAGNIOL-VILLARDed3b18e2008-11-30 19:36:50 +0100335#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
Peter Pearsed4fc6012007-08-14 10:10:52 +0100336 /*
Peter Pearse80767a62007-09-05 16:04:41 +0100337 * relocate exception table
Peter Pearsed4fc6012007-08-14 10:10:52 +0100338 */
339 ldr r0, =_start
340 ldr r1, =0x0
341 mov r2, #16
342copyex:
343 subs r2, r2, #1
344 ldr r3, [r0], #4
345 str r3, [r1], #4
346 bne copyex
347#endif
348
kevin.morfitt@fearnside-systems.co.ukac678042009-11-17 18:30:34 +0900349#ifdef CONFIG_S3C24X0
Peter Pearse80767a62007-09-05 16:04:41 +0100350 /* turn off the watchdog */
351
352# if defined(CONFIG_S3C2400)
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900353# define pWTCON 0x15300000
354# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
Peter Pearse80767a62007-09-05 16:04:41 +0100355# define CLKDIVN 0x14800014 /* clock divisor register */
356#else
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900357# define pWTCON 0x53000000
358# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
Peter Pearse80767a62007-09-05 16:04:41 +0100359# define INTSUBMSK 0x4A00001C
360# define CLKDIVN 0x4C000014 /* clock divisor register */
361# endif
362
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900363 ldr r0, =pWTCON
364 mov r1, #0x0
365 str r1, [r0]
wdenkfe8c2802002-11-03 00:38:21 +0000366
367 /*
368 * mask all IRQs by setting all bits in the INTMR - default
369 */
370 mov r1, #0xffffffff
371 ldr r0, =INTMSK
372 str r1, [r0]
wdenk281e00a2004-08-01 22:48:16 +0000373# if defined(CONFIG_S3C2410)
wdenkfe8c2802002-11-03 00:38:21 +0000374 ldr r1, =0x3ff
375 ldr r0, =INTSUBMSK
376 str r1, [r0]
wdenk281e00a2004-08-01 22:48:16 +0000377# endif
wdenkfe8c2802002-11-03 00:38:21 +0000378
379 /* FCLK:HCLK:PCLK = 1:2:4 */
380 /* default FCLK is 120 MHz ! */
381 ldr r0, =CLKDIVN
382 mov r1, #3
383 str r1, [r0]
kevin.morfitt@fearnside-systems.co.ukac678042009-11-17 18:30:34 +0900384#endif /* CONFIG_S3C24X0 */
wdenkfe8c2802002-11-03 00:38:21 +0000385
386 /*
387 * we do sys-critical inits only at reboot,
388 * not when booting from ram!
389 */
wdenk8aa1a2d2005-04-04 12:44:11 +0000390#ifndef CONFIG_SKIP_LOWLEVEL_INIT
wdenkfe8c2802002-11-03 00:38:21 +0000391 bl cpu_init_crit
392#endif
393
wdenk8aa1a2d2005-04-04 12:44:11 +0000394#ifndef CONFIG_SKIP_RELOCATE_UBOOT
wdenka8c7c702003-12-06 19:49:23 +0000395relocate: /* relocate U-Boot to RAM */
396 adr r0, _start /* r0 <- current position of code */
397 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900398 cmp r0, r1 /* don't reloc during debug */
399 beq stack_setup
wdenka8c7c702003-12-06 19:49:23 +0000400
wdenkfe8c2802002-11-03 00:38:21 +0000401 ldr r2, _armboot_start
wdenkf6e20fc2004-02-08 19:38:38 +0000402 ldr r3, _bss_start
wdenka8c7c702003-12-06 19:49:23 +0000403 sub r2, r3, r2 /* r2 <- size of armboot */
404 add r2, r0, r2 /* r2 <- source end address */
wdenkfe8c2802002-11-03 00:38:21 +0000405
wdenkfe8c2802002-11-03 00:38:21 +0000406copy_loop:
wdenka8c7c702003-12-06 19:49:23 +0000407 ldmia r0!, {r3-r10} /* copy from source address [r0] */
408 stmia r1!, {r3-r10} /* copy to target address [r1] */
Albert Aribaudda90d4c2010-10-05 16:06:39 +0200409 cmp r0, r2 /* until source end address [r2] */
410 blo copy_loop
wdenk8aa1a2d2005-04-04 12:44:11 +0000411#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
Jens Scharsig80523522008-11-18 10:48:46 +0100412
wdenka8c7c702003-12-06 19:49:23 +0000413 /* Set up the stack */
414stack_setup:
415 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900416 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
417 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
wdenka8c7c702003-12-06 19:49:23 +0000418#ifdef CONFIG_USE_IRQ
419 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
420#endif
421 sub sp, r0, #12 /* leave 3 words for abort-stack */
Vitaly Kuzmichev1a27f7d2010-06-15 22:18:11 +0400422 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
wdenka8c7c702003-12-06 19:49:23 +0000423
wdenkf6e20fc2004-02-08 19:38:38 +0000424clear_bss:
425 ldr r0, _bss_start /* find start of bss segment */
wdenkf6e20fc2004-02-08 19:38:38 +0000426 ldr r1, _bss_end /* stop here */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200427 mov r2, #0x00000000 /* clear */
wdenkf6e20fc2004-02-08 19:38:38 +0000428
429clbss_l:str r2, [r0] /* clear loop... */
430 add r0, r0, #4
431 cmp r0, r1
Albert Aribaudda90d4c2010-10-05 16:06:39 +0200432 blo clbss_l
wdenkf6e20fc2004-02-08 19:38:38 +0000433
wdenkfe8c2802002-11-03 00:38:21 +0000434 ldr pc, _start_armboot
435
436_start_armboot: .word start_armboot
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200437#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
wdenkfe8c2802002-11-03 00:38:21 +0000438
439/*
440 *************************************************************************
441 *
442 * CPU_init_critical registers
443 *
444 * setup important registers
445 * setup memory timing
446 *
447 *************************************************************************
448 */
449
450
Wolfgang Denkdb28ddb2006-04-03 15:46:10 +0200451#ifndef CONFIG_SKIP_LOWLEVEL_INIT
wdenkfe8c2802002-11-03 00:38:21 +0000452cpu_init_crit:
453 /*
454 * flush v4 I/D caches
455 */
456 mov r0, #0
457 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
458 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
459
460 /*
461 * disable MMU stuff and caches
462 */
463 mrc p15, 0, r0, c1, c0, 0
464 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
465 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
466 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
467 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
468 mcr p15, 0, r0, c1, c0, 0
469
wdenkfe8c2802002-11-03 00:38:21 +0000470 /*
471 * before relocating, we have to setup RAM timing
472 * because memory timing is board-dependend, you will
wdenk400558b2005-04-02 23:52:25 +0000473 * find a lowlevel_init.S in your board directory.
wdenkfe8c2802002-11-03 00:38:21 +0000474 */
475 mov ip, lr
Peter Pearsed4fc6012007-08-14 10:10:52 +0100476
wdenk400558b2005-04-02 23:52:25 +0000477 bl lowlevel_init
Ulf Samuelssoncb82a532009-03-27 23:26:43 +0100478
wdenkfe8c2802002-11-03 00:38:21 +0000479 mov lr, ip
wdenkfe8c2802002-11-03 00:38:21 +0000480 mov pc, lr
Wolfgang Denkdb28ddb2006-04-03 15:46:10 +0200481#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
wdenkfe8c2802002-11-03 00:38:21 +0000482
wdenkfe8c2802002-11-03 00:38:21 +0000483/*
484 *************************************************************************
485 *
486 * Interrupt handling
487 *
488 *************************************************************************
489 */
490
491@
492@ IRQ stack frame.
493@
494#define S_FRAME_SIZE 72
495
496#define S_OLD_R0 68
497#define S_PSR 64
498#define S_PC 60
499#define S_LR 56
500#define S_SP 52
501
502#define S_IP 48
503#define S_FP 44
504#define S_R10 40
505#define S_R9 36
506#define S_R8 32
507#define S_R7 28
508#define S_R6 24
509#define S_R5 20
510#define S_R4 16
511#define S_R3 12
512#define S_R2 8
513#define S_R1 4
514#define S_R0 0
515
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900516#define MODE_SVC 0x13
517#define I_BIT 0x80
wdenkfe8c2802002-11-03 00:38:21 +0000518
519/*
520 * use bad_save_user_regs for abort/prefetch/undef/swi ...
521 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
522 */
523
524 .macro bad_save_user_regs
525 sub sp, sp, #S_FRAME_SIZE
526 stmia sp, {r0 - r12} @ Calling r0-r12
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200527#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
wdenkf6e20fc2004-02-08 19:38:38 +0000528 ldr r2, _armboot_start
Andrew Dyer6e1551a2008-09-12 02:20:46 +0200529 sub r2, r2, #(CONFIG_STACKSIZE)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200530 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900531 /* set base 2 words into abort stack */
532 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200533#else
534 ldr r2, IRQ_STACK_START_IN
535#endif
wdenkf07771c2003-05-28 08:06:31 +0000536 ldmia r2, {r2 - r3} @ get pc, cpsr
wdenkfe8c2802002-11-03 00:38:21 +0000537 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
538
539 add r5, sp, #S_SP
540 mov r1, lr
wdenkf07771c2003-05-28 08:06:31 +0000541 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
wdenkfe8c2802002-11-03 00:38:21 +0000542 mov r0, sp
543 .endm
544
545 .macro irq_save_user_regs
546 sub sp, sp, #S_FRAME_SIZE
547 stmia sp, {r0 - r12} @ Calling r0-r12
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900548 add r7, sp, #S_PC
549 stmdb r7, {sp, lr}^ @ Calling SP, LR
550 str lr, [r7, #0] @ Save calling PC
551 mrs r6, spsr
552 str r6, [r7, #4] @ Save CPSR
553 str r0, [r7, #8] @ Save OLD_R0
wdenkfe8c2802002-11-03 00:38:21 +0000554 mov r0, sp
555 .endm
556
557 .macro irq_restore_user_regs
558 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
559 mov r0, r0
560 ldr lr, [sp, #S_PC] @ Get PC
561 add sp, sp, #S_FRAME_SIZE
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900562 /* return & move spsr_svc into cpsr */
563 subs pc, lr, #4
wdenkfe8c2802002-11-03 00:38:21 +0000564 .endm
565
566 .macro get_bad_stack
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200567#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
wdenkf6e20fc2004-02-08 19:38:38 +0000568 ldr r13, _armboot_start @ setup our mode stack
Andrew Dyer6e1551a2008-09-12 02:20:46 +0200569 sub r13, r13, #(CONFIG_STACKSIZE)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200570 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900571 /* reserve a couple spots in abort stack */
572 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)
Heiko Schochercc7cdcb2010-09-17 13:10:43 +0200573#else
574 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
575#endif
wdenkfe8c2802002-11-03 00:38:21 +0000576
577 str lr, [r13] @ save caller lr / spsr
578 mrs lr, spsr
kevin.morfitt@fearnside-systems.co.ukd67cce22009-10-10 13:30:22 +0900579 str lr, [r13, #4]
wdenkfe8c2802002-11-03 00:38:21 +0000580
581 mov r13, #MODE_SVC @ prepare SVC-Mode
582 @ msr spsr_c, r13
583 msr spsr, r13
584 mov lr, pc
585 movs pc, lr
586 .endm
587
588 .macro get_irq_stack @ setup IRQ stack
589 ldr sp, IRQ_STACK_START
590 .endm
591
592 .macro get_fiq_stack @ setup FIQ stack
593 ldr sp, FIQ_STACK_START
594 .endm
595
596/*
597 * exception handlers
598 */
599 .align 5
600undefined_instruction:
601 get_bad_stack
602 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200603 bl do_undefined_instruction
wdenkfe8c2802002-11-03 00:38:21 +0000604
605 .align 5
606software_interrupt:
607 get_bad_stack
608 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200609 bl do_software_interrupt
wdenkfe8c2802002-11-03 00:38:21 +0000610
611 .align 5
612prefetch_abort:
613 get_bad_stack
614 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200615 bl do_prefetch_abort
wdenkfe8c2802002-11-03 00:38:21 +0000616
617 .align 5
618data_abort:
619 get_bad_stack
620 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200621 bl do_data_abort
wdenkfe8c2802002-11-03 00:38:21 +0000622
623 .align 5
624not_used:
625 get_bad_stack
626 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200627 bl do_not_used
wdenkfe8c2802002-11-03 00:38:21 +0000628
629#ifdef CONFIG_USE_IRQ
630
631 .align 5
632irq:
633 get_irq_stack
634 irq_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200635 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000636 irq_restore_user_regs
637
638 .align 5
639fiq:
640 get_fiq_stack
641 /* someone ought to write a more effiction fiq_save_user_regs */
642 irq_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200643 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000644 irq_restore_user_regs
645
646#else
647
648 .align 5
649irq:
650 get_bad_stack
651 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200652 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000653
654 .align 5
655fiq:
656 get_bad_stack
657 bad_save_user_regs
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200658 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000659
660#endif