uboot-s3c2443.patch
[u-boot-openmoko/mini2440.git] / cpu / arm920t / start.S
blob8e49e384fd05c2bc4ac3f81827e41521aa4a132f
1 /*
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>
6  *  Copyright (c) 2002  Gary Jennejohn <gj@denx.de>
7  *
8  * S3C2410 NAND portions
9  *  Copyright (c) 2001  MIZI Research, Inc.
10  *  Copyright (c) 2006  OpenMoko, Inc. (Harald Welte <laforge@openmmoko.org>
11  *
12  * See file CREDITS for list of people who contributed to this
13  * project.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  */
32 #include <config.h>
33 #include <version.h>
34 #if defined(CONFIG_S3C2410)
35 #include <s3c2410.h>
36 #elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
37 #include <s3c2440.h>
38 #elif defined(CONFIG_S3C2443)
39 #include <s3c2443.h>
40 #endif
41 #include <status_led.h>
44  *************************************************************************
45  *
46  * Jump vector table as in table 3.1 in [1]
47  *
48  *************************************************************************
49  */
52 .globl _start
53 _start: b       start_code
54         ldr     pc, _undefined_instruction
55         ldr     pc, _software_interrupt
56         ldr     pc, _prefetch_abort
57         ldr     pc, _data_abort
58         ldr     pc, _not_used
59         ldr     pc, _irq
60         ldr     pc, _fiq
62 _undefined_instruction: .word undefined_instruction
63 _software_interrupt:    .word software_interrupt
64 _prefetch_abort:        .word prefetch_abort
65 _data_abort:            .word data_abort
66 _not_used:              .word not_used
67 _irq:                   .word irq
68 _fiq:                   .word fiq
70         .balignl 16,0xdeadbeef
74  *************************************************************************
75  *
76  * Startup Code (called from the ARM reset exception vector)
77  *
78  * do important init only if we don't start from memory!
79  * relocate armboot to ram
80  * setup stack
81  * jump to second stage
82  *
83  *************************************************************************
84  */
87 /* Must follow the .balign above, so we get a well-known address ! */
88 #ifdef CFG_PREBOOT_OVERRIDE
89 .globl  preboot_override
90 preboot_override:
91         .word   0
92 #endif
94 /* Must follow preboot_override , so we get a well-known address ! */
95 #ifdef CFG_ENV_OVERRIDE
96 .globl  env_override
97 env_override:
98         .word   0
99 #endif
101 #ifdef CONFIG_S3C2410_NAND_BOOT
102 .globl  booted_from_nand
103 booted_from_nand:
104         .word   0
105 _booted_from_nand:
106         .word   booted_from_nand
107 #endif /* CONFIG_S3C2410_NAND_BOOT */
109 _TEXT_BASE:
110         .word   TEXT_BASE
112 .globl _armboot_start
113 _armboot_start:
114         .word _start
117  * These are defined in the board-specific linker script.
118  */
119 .globl _bss_start
120 _bss_start:
121         .word __bss_start
123 .globl _bss_end
124 _bss_end:
125         .word _end
127 #ifdef CONFIG_USE_IRQ
128 /* IRQ stack memory (calculated at run-time) */
129 .globl IRQ_STACK_START
130 IRQ_STACK_START:
131         .word   0x0badc0de
133 /* IRQ stack memory (calculated at run-time) */
134 .globl FIQ_STACK_START
135 FIQ_STACK_START:
136         .word 0x0badc0de
137 #endif
141  * the actual start code
142  */
144 start_code:
145         /*
146          * set the cpu to SVC32 mode
147          */
148         mrs     r0,cpsr
149         bic     r0,r0,#0x1f
150         orr     r0,r0,#0xd3
151         msr     cpsr,r0
153         /* in case we run from the s3c24xx NAND stepping stone, the symbols
154          * for LED support are in lib_arm/board.o, i.e. outside of the
155          * steppingstone */
156 #ifndef CONFIG_S3C2410_NAND_BOOT
157         bl coloured_LED_init
158         bl red_LED_on
159 #endif
161 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
162         /*
163          * relocate exception table
164          */
165         ldr     r0, =_start
166         ldr     r1, =0x0
167         mov     r2, #16
168 copyex:
169         subs    r2, r2, #1
170         ldr     r3, [r0], #4
171         str     r3, [r1], #4
172         bne     copyex
173 #endif
175 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || \
176     defined(CONFIG_S3C2442) || defined(CONFIG_S3C2443)
177         /* turn off the watchdog */
179 # if defined(CONFIG_S3C2400)
180 #  define pWTCON                0x15300000
181 #  define INTMSK                0x14400008      /* Interupt-Controller base addresses */
182 #  define CLKDIVN       0x14800014      /* clock divisor register */
183 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
184 #  define pWTCON                0x53000000
185 #  define INTMSK                0x4A000008      /* Interupt-Controller base addresses */
186 #  define INTSUBMSK     0x4A00001C
187 #  define CLKDIVN       0x4C000014      /* clock divisor register */
188 # endif
190 #if defined(CONFIG_S3C2410)
191 # define INTSUBMSK_val  0x7ff
192 # define MPLLCON_val    ((0x90 << 12) + (0x7 << 4) + 0x0)       /* 202 MHz */
193 # define UPLLCON_val    ((0x78 << 12) + (0x2 << 4) + 0x3)
194 # define CLKDIVN_val    3 /* FCLK:HCLK:PCLK = 1:2:4 */
195 #elif defined(CONFIG_S3C2440)
196 # define INTSUBMSK_val  0xffff
197 #if (CONFIG_SYS_CLK_FREQ == 16934400)
198 # define MPLLCON_val    ((0x61 << 12) + (0x1 << 4) + 0x2)       /* 296.35 MHz */
199 # define UPLLCON_val    ((0x3c << 12) + (0x4 << 4) + 0x2)       /*  47.98 MHz */
200 #else if (CONFIG_SYS_CLK_FREQ == 12000000)
201 # define MPLLCON_val    ((0x44 << 12) + (0x1 << 4) + 0x1)       /* 304.00 MHz */
202 # define UPLLCON_val    ((0x38 << 12) + (0x2 << 4) + 0x2)       /*  48.00 MHz */
203 #endif
204 # define CLKDIVN_val    7 /* FCLK:HCLK:PCLK = 1:3:6 */
205 # define CAMDIVN        0x4C000018
206 #elif defined(CONFIG_S3C2442)
207 # define INTSUBMSK_val        0xffff
208 # if (CONFIG_SYS_CLK_FREQ == 12000000)
209 #  define MPLLCON_val ((142 << 12) + (7 << 4) + 1)
210 #  define UPLLCON_val   (( 88 << 12) + (8 << 4) + 2)
211 # elif (CONFIG_SYS_CLK_FREQ == 16934400)
212 #  define MPLLCON_val   ((181 << 12) + (14<< 4) + 1)
213 #  define UPLLCON_val   (( 26 << 12) + (4 << 4) + 1)
214 # endif
215 # define CLKDIVN_val  7 /* FCLK:HCLK:PCLK = 1:3:6 */
216 # define CAMDIVN      0x4C000018
217 #elif defined(CONFIG_S3C2443)
218 # define INTSUBMSK_val        0x1fffffff
219 # define EPLLCON_val  ((40 << 16) | (1 << 8) | (1))           /* 96 MHz */
220 # define MPLLCON_val  ((81 << 16) | (2 << 8) | (0))           /* 1068 MHz */
221 # define CLKDIV0_val  ((8 << 9) | (1 << 4) | (1 << 3) | (1 << 2)
222 #endif
224         ldr     r0, =pWTCON
225         mov     r1, #0x0
226         str     r1, [r0]
228         /*
229          * mask all IRQs by setting all bits in the INTMR - default
230          */
231         mov     r1, #0xffffffff
232         ldr     r0, =INTMSK
233         str     r1, [r0]
234 # if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
235      defined(CONFIG_S3C2443)
236         ldr     r1, =INTSUBMSK_val
237         ldr     r0, =INTSUBMSK
238         str     r1, [r0]
239 # endif
241 #if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
242         /* Make sure we get FCLK:HCLK:PCLK = 1:3:6 */
243         ldr     r0, =CAMDIVN
244         mov     r1, #0
245         str     r1, [r0]
246 #endif
248         /* Clock asynchronous mode */
249         mrc     p15, 0, r1, c1, c0, 0
250         orr     r1, r1, #0xc0000000
251         mcr     p15, 0, r1, c1, c0, 0
254 #if defined(CONFIG_S3C2443)
255 #define LOCKCON0        0x4c000000
256 #define LOCKCON1        0x4c000004
257 #define MPLLCON         0x4c000010
258 #define EPLLCON         0x4c000018
260         ldr     r0, =CLKDIV0
261         ldr     r1, =CLKDIV0_val
262         str     r1, [r0]
264         /* set safe (way too long) locktime for both PLLs */
265         ldr     r0, =LOCKCON0
266         mov     r1, #0xffffff
267         str     r1, [r0]
268         ldr     r0, =LOCKCON1
269         str     r1, [r0]
271         /* configure MPLL */
272         ldr     r0, =MPLLCON
273         ldr     r1, =MPLLCON_val
274         str     r1, [r0]
276         /* select MPLL clock out for SYSCLK */
277         ldr     r0, =CLKSRC
278         ldr     r1, [r0]
279         orr     r1, r1, #0x10
280         str     r1, [r0]
282 #if 0
283         /* configure EPLL */
284         ldr     r0, =EPLLCON
285         ldr     r1, =EPLLCON_val
286         str     r1, [r0]
287 #endif
290 #else /* i.e. 2440, 2410 and 2440 */
291 #define LOCKTIME        0x4c000000
292 #define UPLLCON         0x4c000008
294         ldr     r0, =LOCKTIME
295         mov     r1, #0xffffff
296         str     r1, [r0]
298         ldr     r0, =UPLLCON
299         ldr     r1, =UPLLCON_val
300         str     r1, [r0]
302         /* Page 7-19, seven nops between UPLL and MPLL */
303         nop
304         nop
305         nop
306         nop
307         nop
308         nop
309         nop
311         ldr     r1, =MPLLCON_val
312         str     r1, [r0, #-4]           /* MPLLCON */
314         /* FCLK:HCLK:PCLK = 1:2:4 */
315         ldr     r0, =CLKDIVN
316         mov     r1, #CLKDIVN_val
317         str     r1, [r0]
318 #endif
320 #if 1
321         /* enable uart */
322         ldr     r0, =0x4c00000c         /* clkcon */
323         ldr     r1, =0x7fff0            /* all clocks on */
324         str     r1, [r0]
326         /* gpio UART0 init */
327         ldr     r0, =0x56000070
328         mov     r1, #0xaa
329         str     r1, [r0]
331         /* init uart */
332         ldr     r0, =0x50000000
333         mov     r1, #0x03
334         str     r1, [r0]
335         ldr     r1, =0x245
336         str     r1, [r0, #0x04]
337         mov     r1, #0x01
338         str     r1, [r0, #0x08]
339         mov     r1, #0x00
340         str     r1, [r0, #0x0c]
341         mov     r1, #0x1a
342         str     r1, [r0, #0x28]
343 #endif
345 #endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 || CONFIG_S3C2442
346            CONFIG_S3C2443 */
348 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
349 #ifndef CONFIG_LL_INIT_NAND_ONLY
350         bl      cpu_init_crit
351 #endif
353 #if defined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410) || \
354     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
355     defined(CONFIG_S3C2443)
357 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
358         adr     r0, _start              /* r0 <- current position of code   */
360 #ifdef CONFIG_S3C2410_NAND_BOOT
361                                         /* are we running from NAND ?       */
362 #define BWSCON  0x48000000
363         ldr     r1, =BWSCON             /* Z = CPU booted from NAND         */
364         ldr     r1, [r1]
365         tst     r1, #6                  /* BWSCON[2:1] = OM[1:0]            */
366         teqeq   r0, #0                  /* Z &= running at address 0        */
367         beq     nand_load
368 #endif /* CONFIG_S3C2410_NAND_BOOT */
370 relocate:                               /* relocate U-Boot to RAM           */
371         teq     r0, #0                  /* running at address 0 ?           */
372         bleq    may_resume              /* yes -> do low-level setup        */
374         adr     r0, _start              /* the above may have clobbered r0  */
376         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
377         cmp     r0, r1                  /* don't reloc during debug         */
378         beq     done_relocate
380         ldr     r2, _armboot_start
381         ldr     r3, _bss_start
382         sub     r2, r3, r2              /* r2 <- size of armboot            */
383         add     r2, r0, r2              /* r2 <- source end address         */
385 copy_loop:
386         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
387         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
388         cmp     r0, r2                  /* until source end address [r2]    */
389         ble     copy_loop
390         mov     r0, #0                  /* flush v3/v4 cache */
391         mcr     p15, 0, r0, c7, c7, 0
392         ldr     pc, _done_relocate      /* jump to relocated code */
393 _done_relocate:
394         .word   done_relocate
396 #ifdef CONFIG_S3C2410_NAND_BOOT
397 nand_load:
398         bl      may_resume              /* low-level setup and resume */
400         @ reset NAND
401 #if defined(CONFIG_S3C2410)
402         mov     r1, #S3C2410_NAND_BASE
403         ldr     r2, =0xf842             @ initial value enable tacls=3,rph0=6,rph1=0
404         str     r2, [r1, #oNFCONF]
405         ldr     r2, [r1, #oNFCONF]
406         bic     r2, r2, #0x800          @ enable chip
407         str     r2, [r1, #oNFCONF]
408         mov     r2, #0xff               @ RESET command
409         strb    r2, [r1, #oNFCMD]
410         mov     r3, #0                  @ wait
411 1:      add     r3, r3, #0x1
412         cmp     r3, #0xa
413         blt     1b
414 2:      ldr     r2, [r1, #oNFSTAT]      @ wait ready
415         tst     r2, #0x1
416         beq     2b
417         ldr     r2, [r1, #oNFCONF]
418         orr     r2, r2, #0x800          @ disable chip
419         str     r2, [r1, #oNFCONF]
420 #elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
421         mov     r1, #S3C2440_NAND_BASE
422         ldr     r2, =0xfff0             @ initial value tacls=3,rph0=7,rph1=7
423         ldr     r3, [r1, #oNFCONF]
424         orr     r3, r3, r2
425         str     r3, [r1, #oNFCONF]
427         ldr     r3, [r1, #oNFCONT]
428         orr     r3, r3, #1              @ enable nand controller
429         str     r3, [r1, #oNFCONT]
430 #endif /* CONFIG_S3C2440 || CONFIG_S3C2442 */
432         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
433         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
434         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
435 #ifdef CONFIG_USE_IRQ
436         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
437 #endif
438         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
440         @ copy u-boot to RAM
441         ldr     r0, _TEXT_BASE
442         mov     r1, #0x0
443         mov     r2, #CFG_UBOOT_SIZE
444         bl      nand_read_ll
446         tst     r0, #0x0
447         beq     ok_nand_read
448 #ifdef CONFIG_DEBUG_LL
449 bad_nand_read:
450         ldr     r0, STR_FAIL
451         ldr     r1, SerBase
452         bl      PrintWord
453 1:      b       1b              @ infinite loop
454 #endif
456 ok_nand_read:
457 #ifdef CONFIG_DEBUG_LL
458         ldr     r0, STR_OK
459         ldr     r1, SerBase
460         bl      PrintWord
461 #endif
463         @ verify
464         mov     r0, #0
465         @ldr    r1, =0x33f00000
466         ldr     r1, _TEXT_BASE
467         mov     r2, #0x400      @ 4 bytes * 1024 = 4K-bytes
468 go_next:
469         ldr     r3, [r0], #4
470         ldr     r4, [r1], #4
471         teq     r3, r4
472         bne     notmatch
473         subs    r2, r2, #4
474         beq     done_nand_read
475         bne     go_next
476 notmatch:
477 #ifdef CONFIG_DEBUG_LL
478         sub     r0, r0, #4
479         ldr     r1, SerBase
480         bl      PrintHexWord
481         ldr     r0, STR_FAIL
482         ldr     r1, SerBase
483         bl      PrintWord
484 #endif
485 1:      b       1b
486 done_nand_read:
487         ldr     r0, _booted_from_nand
488         mov     r1, #1
489         strb    r1, [r0]
490 #endif /* CONFIG_S3C2410_NAND_BOOT */
491 done_relocate:
493 #if defined(CONFIG_USE_IRQ) && (defined(CONFIG_S3C2410) || \
494     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442))
495         /* In the case of the S3C2410, if we've somehow magically (JTAG, ...)
496            ended up in RAM, then that ram is mapped to 0x30000000 and not 0.
497            So we need to copy the interrupt vectors, etc.  */
499         mov     r0, #0
500         ldr     r1, _TEXT_BASE
501         mov     r2, #0x40
502 irqvec_cpy_next:
503         ldr     r3, [r1], #4
504         str     r3, [r0], #4
505         subs    r2, r2, #4
506         bne     irqvec_cpy_next
507 #endif /* CONFIG_USE_IRQ */
509 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
510 #endif
511         /* Set up the stack                                                 */
512 stack_setup:
513         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
514         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
515         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
516 #ifdef CONFIG_USE_IRQ
517         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
518 #endif
519         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
521 clear_bss:
522         ldr     r0, _bss_start          /* find start of bss segment        */
523         ldr     r1, _bss_end            /* stop here                        */
524         mov     r2, #0x00000000         /* clear                            */
526 clbss_l:str     r2, [r0]                /* clear loop...                    */
527         add     r0, r0, #4
528         cmp     r0, r1
529         ble     clbss_l
531         ldr     pc, _start_armboot
533 _start_armboot: .word start_armboot
537  *************************************************************************
539  * CPU_init_critical registers
541  * setup important registers
542  * setup memory timing
544  *************************************************************************
545  */
548 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
549 cpu_init_crit:
550         /*
551          * flush v4 I/D caches
552          */
553         mov     r0, #0
554         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
555         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
557         /*
558          * disable MMU stuff and caches
559          */
560         mrc     p15, 0, r0, c1, c0, 0
561         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
562         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
563         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
564         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
565         mcr     p15, 0, r0, c1, c0, 0
567         /*
568          * before relocating, we have to setup RAM timing
569          * because memory timing is board-dependend, you will
570          * find a lowlevel_init.S in your board directory.
571          */
572         mov     ip, lr
573 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
575 #else
576         bl      lowlevel_init
577 #endif
578         mov     lr, ip
579         mov     pc, lr
580 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
584  *************************************************************************
586  * may_resume
588  * Bring up memory and check if we're coming out of suspend.
590  *************************************************************************
591  */
594 may_resume:
595         mov     r10, lr                 /* we may call cpu_init_crit */
597         /* take sdram out of power down */
598         ldr     r0, =0x56000080         /* misccr */
599         ldr     r1, [ r0 ]
600         bic     r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
601         str     r1, [ r0 ]
603         /* ensure signals stabalise */
604         mov     r1, #128
605 1:      subs    r1, r1, #1
606         bpl     1b
608 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && defined(CONFIG_LL_INIT_NAND_ONLY)
609         bl      cpu_init_crit
610 #endif
611 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
612         /* ensure some refresh has happened */
613         ldr     r1, =0xfffff
614 1:      subs    r1, r1, #1
615         bpl     1b
617         /* test for resume */
618         ldr     r1, =0x560000B4         /* gstatus2 */
619         ldr     r0, [ r1 ]
620         tst     r0, #0x02               /* is this resume from power down */
621         ldrne   pc, [r1, #4]            /* gstatus3 */
622 #endif /* CONFIG_S3C2410 || CONFIG_S3C244 || CONFIG_S3C2442 */
623 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
625         mov     pc, r10
628  *************************************************************************
630  * Interrupt handling
632  *************************************************************************
633  */
636 @ IRQ stack frame.
638 #define S_FRAME_SIZE    72
640 #define S_OLD_R0        68
641 #define S_PSR           64
642 #define S_PC            60
643 #define S_LR            56
644 #define S_SP            52
646 #define S_IP            48
647 #define S_FP            44
648 #define S_R10           40
649 #define S_R9            36
650 #define S_R8            32
651 #define S_R7            28
652 #define S_R6            24
653 #define S_R5            20
654 #define S_R4            16
655 #define S_R3            12
656 #define S_R2            8
657 #define S_R1            4
658 #define S_R0            0
660 #define MODE_SVC 0x13
661 #define I_BIT    0x80
664  * use bad_save_user_regs for abort/prefetch/undef/swi ...
665  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
666  */
668         .macro  bad_save_user_regs
669         sub     sp, sp, #S_FRAME_SIZE
670         stmia   sp, {r0 - r12}                  @ Calling r0-r12
671         ldr     r2, _armboot_start
672         sub     r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
673         sub     r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
674         ldmia   r2, {r2 - r3}                   @ get pc, cpsr
675         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
677         add     r5, sp, #S_SP
678         mov     r1, lr
679         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
680         mov     r0, sp
681         .endm
683         .macro  irq_save_user_regs
684         sub     sp, sp, #S_FRAME_SIZE
685         stmia   sp, {r0 - r12}                  @ Calling r0-r12
686         add     r7, sp, #S_PC
687         stmdb   r7, {sp, lr}^                   @ Calling SP, LR
688         str     lr, [r7, #0]                    @ Save calling PC
689         mrs     r6, spsr
690         str     r6, [r7, #4]                    @ Save CPSR
691         str     r0, [r7, #8]                    @ Save OLD_R0
692         mov     r0, sp
693         .endm
695         .macro  irq_restore_user_regs
696         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
697         mov     r0, r0
698         ldr     lr, [sp, #S_PC]                 @ Get PC
699         add     sp, sp, #S_FRAME_SIZE
700         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
701         .endm
703         .macro get_bad_stack
704         ldr     r13, _armboot_start             @ setup our mode stack
705         sub     r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
706         sub     r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
708         str     lr, [r13]                       @ save caller lr / spsr
709         mrs     lr, spsr
710         str     lr, [r13, #4]
712         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
713         @ msr   spsr_c, r13
714         msr     spsr, r13
715         mov     lr, pc
716         movs    pc, lr
717         .endm
719         .macro get_irq_stack                    @ setup IRQ stack
720         ldr     sp, IRQ_STACK_START
721         .endm
723         .macro get_fiq_stack                    @ setup FIQ stack
724         ldr     sp, FIQ_STACK_START
725         .endm
728  * exception handlers
729  */
730         .align  5
731 undefined_instruction:
732         get_bad_stack
733         bad_save_user_regs
734         bl      do_undefined_instruction
736         .align  5
737 software_interrupt:
738         get_bad_stack
739         bad_save_user_regs
740         bl      do_software_interrupt
742         .align  5
743 prefetch_abort:
744         get_bad_stack
745         bad_save_user_regs
746         bl      do_prefetch_abort
748         .align  5
749 data_abort:
750         get_bad_stack
751         bad_save_user_regs
752         bl      do_data_abort
754         .align  5
755 not_used:
756         get_bad_stack
757         bad_save_user_regs
758         bl      do_not_used
760 #ifdef CONFIG_USE_IRQ
762         .align  5
763 irq:
764         get_irq_stack
765         irq_save_user_regs
766         bl      do_irq
767         irq_restore_user_regs
769         .align  5
770 fiq:
771         get_fiq_stack
772         /* someone ought to write a more effiction fiq_save_user_regs */
773         irq_save_user_regs
774         bl      do_fiq
775         irq_restore_user_regs
777 #else
779         .align  5
780 irq:
781         get_bad_stack
782         bad_save_user_regs
783         bl      do_irq
785         .align  5
786 fiq:
787         get_bad_stack
788         bad_save_user_regs
789         bl      do_fiq
791 #endif