MINI2440: Updated early nand loader
[u-boot-openmoko/mini2440.git] / cpu / arm920t / start.S
blobad2d703401846dcc98c4ce67834d74604b686ac3
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 #ifndef CFG_NO_FLASH
110 .globl booted_from_nor
111 booted_from_nor:
112         .word   0
113 _booted_from_nor:
114         .word   booted_from_nor
115 _end_if_0:
116         .word   __bss_start-_start
117 #endif /* !CFG_NO_FLASH */
119 _TEXT_BASE:
120         .word   TEXT_BASE
122 .globl _armboot_start
123 _armboot_start:
124         .word _start
127  * These are defined in the board-specific linker script.
128  */
129 .globl _bss_start
130 _bss_start:
131         .word __bss_start
133 .globl _bss_end
134 _bss_end:
135         .word _end
137 #ifdef CONFIG_USE_IRQ
138 /* IRQ stack memory (calculated at run-time) */
139 .globl IRQ_STACK_START
140 IRQ_STACK_START:
141         .word   0x0badc0de
143 /* IRQ stack memory (calculated at run-time) */
144 .globl FIQ_STACK_START
145 FIQ_STACK_START:
146         .word 0x0badc0de
147 #endif
151  * the actual start code
152  */
154 start_code:
155         /*
156          * set the cpu to SVC32 mode
157          */
158         mrs     r0,cpsr
159         bic     r0,r0,#0x1f
160         orr     r0,r0,#0xd3
161         msr     cpsr,r0
163         /* in case we run from the s3c24xx NAND stepping stone, the symbols
164          * for LED support are in lib_arm/board.o, i.e. outside of the
165          * steppingstone */
166 #ifndef CONFIG_S3C2410_NAND_BOOT
167         bl coloured_LED_init
168         bl red_LED_on
169 #endif
171 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
172         /*
173          * relocate exception table
174          */
175         ldr     r0, =_start
176         ldr     r1, =0x0
177         mov     r2, #16
178 copyex:
179         subs    r2, r2, #1
180         ldr     r3, [r0], #4
181         str     r3, [r1], #4
182         bne     copyex
183 #endif
185 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || \
186     defined(CONFIG_S3C2442) || defined(CONFIG_S3C2443)
187         /* turn off the watchdog */
189 # if defined(CONFIG_S3C2400)
190 #  define pWTCON                0x15300000
191 #  define INTMSK                0x14400008      /* Interupt-Controller base addresses */
192 #  define CLKDIVN       0x14800014      /* clock divisor register */
193 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
194 #  define pWTCON                0x53000000
195 #  define INTMSK                0x4A000008      /* Interupt-Controller base addresses */
196 #  define INTSUBMSK     0x4A00001C
197 #  define CLKDIVN       0x4C000014      /* clock divisor register */
198 # endif
200 #if defined(CONFIG_S3C2410)
201 # define INTSUBMSK_val  0x7ff
202 # define MPLLCON_val    ((0x90 << 12) + (0x7 << 4) + 0x0)       /* 202 MHz */
203 # define UPLLCON_val    ((0x78 << 12) + (0x2 << 4) + 0x3)
204 # define CLKDIVN_val    3 /* FCLK:HCLK:PCLK = 1:2:4 */
205 #elif defined(CONFIG_S3C2440)
206 # define INTSUBMSK_val  0xffff
207 #if (CONFIG_SYS_CLK_FREQ == 16934400)
208 # define MPLLCON_val    ((0x61 << 12) + (0x1 << 4) + 0x2)       /* 296.35 MHz */
209 # define UPLLCON_val    ((0x3c << 12) + (0x4 << 4) + 0x2)       /*  47.98 MHz */
210 #elif (CONFIG_SYS_CLK_FREQ == 12000000)
211 # define MPLLCON_val    ((0x44 << 12) + (0x1 << 4) + 0x1)       /* 304.00 MHz */
212 # define UPLLCON_val    ((0x38 << 12) + (0x2 << 4) + 0x2)       /*  48.00 MHz */
213 #endif
214 # define CLKDIVN_val    7 /* FCLK:HCLK:PCLK = 1:3:6 */
215 # define CAMDIVN        0x4C000018
216 #elif defined(CONFIG_S3C2442)
217 # define INTSUBMSK_val        0xffff
218 # if (CONFIG_SYS_CLK_FREQ == 12000000)
219 #  define MPLLCON_val ((142 << 12) + (7 << 4) + 1)
220 #  define UPLLCON_val   (( 88 << 12) + (4 << 4) + 2)
221 # elif (CONFIG_SYS_CLK_FREQ == 16934400)
222 #  define MPLLCON_val   ((181 << 12) + (14<< 4) + 1)
223 #  define UPLLCON_val   (( 26 << 12) + (4 << 4) + 1)
224 # endif
225 # define CLKDIVN_val  7 /* FCLK:HCLK:PCLK = 1:3:6 */
226 # define CAMDIVN      0x4C000018
227 #elif defined(CONFIG_S3C2443)
228 # define INTSUBMSK_val        0x1fffffff
229 # define EPLLCON_val  ((40 << 16) | (1 << 8) | (1))           /* 96 MHz */
230 # define MPLLCON_val  ((81 << 16) | (2 << 8) | (0))           /* 1068 MHz */
231 # define CLKDIV0_val  ((8 << 9) | (1 << 4) | (1 << 3) | (1 << 2)
232 #endif
234         ldr     r0, =pWTCON
235         mov     r1, #0x0
236         str     r1, [r0]
238         /*
239          * mask all IRQs by setting all bits in the INTMR - default
240          */
241         mov     r1, #0xffffffff
242         ldr     r0, =INTMSK
243         str     r1, [r0]
244 # if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
245      defined(CONFIG_S3C2443)
246         ldr     r1, =INTSUBMSK_val
247         ldr     r0, =INTSUBMSK
248         str     r1, [r0]
249 # endif
251 #if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
252         /* Make sure we get FCLK:HCLK:PCLK */
253         ldr     r0, =CAMDIVN
254         mov     r1, #0
255         str     r1, [r0]
256 #endif
258         /* Clock asynchronous mode */
259         mrc     p15, 0, r1, c1, c0, 0
260         orr     r1, r1, #0xc0000000
261         mcr     p15, 0, r1, c1, c0, 0
264 #if defined(CONFIG_S3C2443)
265 #define LOCKCON0        0x4c000000
266 #define LOCKCON1        0x4c000004
267 #define MPLLCON         0x4c000010
268 #define EPLLCON         0x4c000018
270         ldr     r0, =CLKDIV0
271         ldr     r1, =CLKDIV0_val
272         str     r1, [r0]
274         /* set safe (way too long) locktime for both PLLs */
275         ldr     r0, =LOCKCON0
276         mov     r1, #0xffffff
277         str     r1, [r0]
278         ldr     r0, =LOCKCON1
279         str     r1, [r0]
281         /* configure MPLL */
282         ldr     r0, =MPLLCON
283         ldr     r1, =MPLLCON_val
284         str     r1, [r0]
286         /* select MPLL clock out for SYSCLK */
287         ldr     r0, =CLKSRC
288         ldr     r1, [r0]
289         orr     r1, r1, #0x10
290         str     r1, [r0]
292 #if 0
293         /* configure EPLL */
294         ldr     r0, =EPLLCON
295         ldr     r1, =EPLLCON_val
296         str     r1, [r0]
297 #endif
300 #else /* i.e. 2440, 2410 and 2440 */
301 #define LOCKTIME        0x4c000000
302 #define UPLLCON         0x4c000008
304         ldr     r0, =LOCKTIME
305         mov     r1, #0xffffff
306         str     r1, [r0]
308         ldr     r0, =UPLLCON
309         ldr     r1, =UPLLCON_val
310         str     r1, [r0]
312         /* Page 7-19, seven nops between UPLL and MPLL */
313         nop
314         nop
315         nop
316         nop
317         nop
318         nop
319         nop
321         ldr     r1, =MPLLCON_val
322         str     r1, [r0, #-4]           /* MPLLCON */
324         /* FCLK:HCLK:PCLK */
325         ldr     r0, =CLKDIVN
326         mov     r1, #CLKDIVN_val
327         str     r1, [r0]
328 #endif
330 #if 1
331         /* enable uart */
332         ldr     r0, =0x4c00000c         /* clkcon */
333         ldr     r1, =0x7fff0            /* all clocks on */
334         str     r1, [r0]
336         /* gpio UART0 init */
337         ldr     r0, =0x56000070
338         mov     r1, #0xaa
339         str     r1, [r0]
341         /* init uart */
342         ldr     r0, =0x50000000
343         mov     r1, #0x03
344         str     r1, [r0]
345         ldr     r1, =0x245
346         str     r1, [r0, #0x04]
347         mov     r1, #0x01
348         str     r1, [r0, #0x08]
349         mov     r1, #0x00
350         str     r1, [r0, #0x0c]
351         mov     r1, #0x1a
352         str     r1, [r0, #0x28]
353 #endif
355 #endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 || CONFIG_S3C2442
356            CONFIG_S3C2443 */
358 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
359 #ifndef CONFIG_LL_INIT_NAND_ONLY
360         bl      cpu_init_crit
361 #endif
363 #if defined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410) || \
364     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
365     defined(CONFIG_S3C2443)
367 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
368         adr     r0, _start              /* r0 <- current position of code   */
370 #ifdef CONFIG_S3C2410_NAND_BOOT
371                                         /* are we running from NAND ?       */
372 #define BWSCON  0x48000000
373         ldr     r1, =BWSCON             /* Z = CPU booted from NAND         */
374         ldr     r1, [r1]
375         tst     r1, #6                  /* BWSCON[2:1] = OM[1:0]            */
376         teqeq   r0, #0                  /* Z &= running at address 0        */
377         beq     nand_load
378 #endif /* CONFIG_S3C2410_NAND_BOOT */
380 relocate:                               /* relocate U-Boot to RAM           */
381         teq     r0, #0                  /* running at address 0 ?           */
382         bleq    may_resume              /* yes -> do low-level setup        */
384         adr     r0, _start              /* the above may have clobbered r0  */
386         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
387         cmp     r0, r1                  /* don't reloc during debug         */
388         beq     done_relocate
390         ldr     r2, _armboot_start
391         ldr     r3, _bss_start
392         sub     r2, r3, r2              /* r2 <- size of armboot            */
393         add     r2, r0, r2              /* r2 <- source end address         */
395 copy_loop:
396         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
397         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
398         cmp     r0, r2                  /* until source end address [r2]    */
399         ble     copy_loop
401 #ifndef CFG_NO_FLASH
402         ldr     r0, _end_if_0           /* are we booting from NOR ? */
403         cmp     r0, r2
404         ldreq   r0, _booted_from_nor    /* remember that we've booted from  */
405         moveq   r1, #1                  /* NOR                              */
406         streqb  r1, [r0]
407 #endif /* !CFG_NO_FLASH */
409         mov     r0, #0                  /* flush v3/v4 cache */
410         mcr     p15, 0, r0, c7, c7, 0
411         ldr     pc, _done_relocate      /* jump to relocated code */
412 _done_relocate:
413         .word   done_relocate
415 #ifdef CONFIG_S3C2410_NAND_BOOT
416 nand_load:
417         bl      may_resume              /* low-level setup and resume */
419         @ reset NAND
420 #if defined(CONFIG_S3C2410)
421         mov     r1, #S3C2410_NAND_BASE
422         ldr     r2, =0xf842             @ initial value enable tacls=3,rph0=6,rph1=0
423         str     r2, [r1, #oNFCONF]
424         ldr     r2, [r1, #oNFCONF]
425         bic     r2, r2, #0x800          @ enable chip
426         str     r2, [r1, #oNFCONF]
427         mov     r2, #0xff               @ RESET command
428         strb    r2, [r1, #oNFCMD]
429         mov     r3, #0                  @ wait
430 1:      add     r3, r3, #0x1
431         cmp     r3, #0xa
432         blt     1b
433 2:      ldr     r2, [r1, #oNFSTAT]      @ wait ready
434         tst     r2, #0x1
435         beq     2b
436         ldr     r2, [r1, #oNFCONF]
437         orr     r2, r2, #0x800          @ disable chip
438         str     r2, [r1, #oNFCONF]
439 #elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
440         mov     r1, #S3C2440_NAND_BASE
441         ldr     r2, =0xfff0             @ initial value tacls=3,rph0=7,rph1=7
442         ldr     r3, [r1, #oNFCONF]
443         orr     r3, r3, r2
444         str     r3, [r1, #oNFCONF]
446         ldr     r3, [r1, #oNFCONT]
447         orr     r3, r3, #1              @ enable nand controller
448         str     r3, [r1, #oNFCONT]
449 #endif /* CONFIG_S3C2440 || CONFIG_S3C2442 */
451         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
452         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
453         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
454 #ifdef CONFIG_USE_IRQ
455         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
456 #endif
457         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
459         @ copy u-boot to RAM
460         ldr     r0, _TEXT_BASE
461         mov     r1, #0x0
462         mov     r2, #CFG_UBOOT_SIZE
463         bl      nand_read_ll
465         tst     r0, #0x0
466         beq     ok_nand_read
467 #ifdef CONFIG_DEBUG_LL
468 bad_nand_read:
469         ldr     r0, STR_FAIL
470         ldr     r1, SerBase
471         bl      PrintWord
472 1:      b       1b              @ infinite loop
473 #endif
475 ok_nand_read:
476 #ifdef CONFIG_DEBUG_LL
477         ldr     r0, STR_OK
478         ldr     r1, SerBase
479         bl      PrintWord
480 #endif
482         @ verify
483         mov     r0, #0
484         @ldr    r1, =0x33f00000
485         ldr     r1, _TEXT_BASE
486         mov     r2, #0x400      @ 4 bytes * 1024 = 4K-bytes
487 go_next:
488         ldr     r3, [r0], #4
489         ldr     r4, [r1], #4
490         teq     r3, r4
491         bne     notmatch
492         subs    r2, r2, #4
493         beq     done_nand_read
494         bne     go_next
495 notmatch:
496 #ifdef CONFIG_DEBUG_LL
497         sub     r0, r0, #4
498         ldr     r1, SerBase
499         bl      PrintHexWord
500         ldr     r0, STR_FAIL
501         ldr     r1, SerBase
502         bl      PrintWord
503 #endif
504 1:      b       1b
505 done_nand_read:
506         ldr     r0, _booted_from_nand
507         mov     r1, #1
508         strb    r1, [r0]
509 #endif /* CONFIG_S3C2410_NAND_BOOT */
510 done_relocate:
512 #if defined(CONFIG_USE_IRQ) && (defined(CONFIG_S3C2410) || \
513     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442))
514         /* In the case of the S3C2410, if we've somehow magically (JTAG, ...)
515            ended up in RAM, then that ram is mapped to 0x30000000 and not 0.
516            So we need to copy the interrupt vectors, etc.  */
518         mov     r0, #0
519         ldr     r1, _TEXT_BASE
520         mov     r2, #0x40
521 irqvec_cpy_next:
522         ldr     r3, [r1], #4
523         str     r3, [r0], #4
524         subs    r2, r2, #4
525         bne     irqvec_cpy_next
526 #endif /* CONFIG_USE_IRQ */
528 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
529 #endif
530         /* Set up the stack                                                 */
531 stack_setup:
532         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
533         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
534         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
535 #ifdef CONFIG_USE_IRQ
536         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
537 #endif
538         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
540 clear_bss:
541         ldr     r0, _bss_start          /* find start of bss segment        */
542         ldr     r1, _bss_end            /* stop here                        */
543         mov     r2, #0x00000000         /* clear                            */
545 clbss_l:str     r2, [r0]                /* clear loop...                    */
546         add     r0, r0, #4
547         cmp     r0, r1
548         ble     clbss_l
550         ldr     pc, _start_armboot
552 _start_armboot: .word start_armboot
556  *************************************************************************
558  * CPU_init_critical registers
560  * setup important registers
561  * setup memory timing
563  *************************************************************************
564  */
567 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
568 cpu_init_crit:
569         /*
570          * flush v4 I/D caches
571          */
572         mov     r0, #0
573         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
574         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
576         /*
577          * disable MMU stuff and caches
578          */
579         mrc     p15, 0, r0, c1, c0, 0
580         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
581         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
582         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
583         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
584         mcr     p15, 0, r0, c1, c0, 0
586         /*
587          * before relocating, we have to setup RAM timing
588          * because memory timing is board-dependend, you will
589          * find a lowlevel_init.S in your board directory.
590          */
591         mov     ip, lr
592 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
594 #else
595         bl      lowlevel_init
596 #endif
597         mov     lr, ip
598         mov     pc, lr
599 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
603  *************************************************************************
605  * may_resume
607  * Bring up memory and check if we're coming out of suspend.
609  *************************************************************************
610  */
613 may_resume:
614         mov     r10, lr                 /* we may call cpu_init_crit */
616         /* take sdram out of power down */
617         ldr     r0, =0x56000080         /* misccr */
618         ldr     r1, [ r0 ]
619         bic     r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
620         str     r1, [ r0 ]
622         /* ensure signals stabalise */
623         mov     r1, #128
624 1:      subs    r1, r1, #1
625         bpl     1b
627 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && defined(CONFIG_LL_INIT_NAND_ONLY)
628         bl      cpu_init_crit
629 #endif
630 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
631         /* ensure some refresh has happened */
632         ldr     r1, =0xfffff
633 1:      subs    r1, r1, #1
634         bpl     1b
636         /* capture full EINT situation into gstatus 4 */
638         ldr     r0, =0x4A000000 /* SRCPND */
639         ldr     r1, [ r0 ]
640         and     r1, r1, #0xf
642         ldr     r0, =0x560000BC /* gstatus4 */
643         str     r1, [ r0 ]
645         ldr     r0, =0x560000A8 /* EINTPEND */
646         ldr     r1, [ r0 ]
647         ldr     r0, =0xfff0
648         and     r1, r1, r0
649         ldr     r0, =0x560000BC /* gstatus4 */
650         ldr     r0, [ r0 ]
651         orr     r1, r1, r0
652         ldr     r0, =0x560000BC /* gstatus4 */
653         str     r1, [ r0 ]
655         /* test for resume */
657         ldr     r1, =0x560000B4         /* gstatus2 */
658         ldr     r0, [ r1 ]
659         tst     r0, #0x02               /* is this resume from power down */
660                                         /* well, if it was, we are going to jump to
661                                          * whatever address we stashed in gstatus3,
662                                          * and gstatus4 will hold the wake interrupt
663                                          * source for the OS to look at
664                                          */
665         ldrne   pc, [r1, #4]
666 #endif /* CONFIG_S3C2410 || CONFIG_S3C244 || CONFIG_S3C2442 */
667 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
669         mov     pc, r10
672  *************************************************************************
674  * Interrupt handling
676  *************************************************************************
677  */
680 @ IRQ stack frame.
682 #define S_FRAME_SIZE    72
684 #define S_OLD_R0        68
685 #define S_PSR           64
686 #define S_PC            60
687 #define S_LR            56
688 #define S_SP            52
690 #define S_IP            48
691 #define S_FP            44
692 #define S_R10           40
693 #define S_R9            36
694 #define S_R8            32
695 #define S_R7            28
696 #define S_R6            24
697 #define S_R5            20
698 #define S_R4            16
699 #define S_R3            12
700 #define S_R2            8
701 #define S_R1            4
702 #define S_R0            0
704 #define MODE_SVC 0x13
705 #define I_BIT    0x80
708  * use bad_save_user_regs for abort/prefetch/undef/swi ...
709  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
710  */
712         .macro  bad_save_user_regs
713         sub     sp, sp, #S_FRAME_SIZE
714         stmia   sp, {r0 - r12}                  @ Calling r0-r12
715         ldr     r2, _armboot_start
716         sub     r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
717         sub     r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
718         ldmia   r2, {r2 - r3}                   @ get pc, cpsr
719         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
721         add     r5, sp, #S_SP
722         mov     r1, lr
723         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
724         mov     r0, sp
725         .endm
727         .macro  irq_save_user_regs
728         sub     sp, sp, #S_FRAME_SIZE
729         stmia   sp, {r0 - r12}                  @ Calling r0-r12
730         add     r7, sp, #S_PC
731         stmdb   r7, {sp, lr}^                   @ Calling SP, LR
732         str     lr, [r7, #0]                    @ Save calling PC
733         mrs     r6, spsr
734         str     r6, [r7, #4]                    @ Save CPSR
735         str     r0, [r7, #8]                    @ Save OLD_R0
736         mov     r0, sp
737         .endm
739         .macro  irq_restore_user_regs
740         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
741         mov     r0, r0
742         ldr     lr, [sp, #S_PC]                 @ Get PC
743         add     sp, sp, #S_FRAME_SIZE
744         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
745         .endm
747         .macro get_bad_stack
748         ldr     r13, _armboot_start             @ setup our mode stack
749         sub     r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
750         sub     r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
752         str     lr, [r13]                       @ save caller lr / spsr
753         mrs     lr, spsr
754         str     lr, [r13, #4]
756         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
757         @ msr   spsr_c, r13
758         msr     spsr, r13
759         mov     lr, pc
760         movs    pc, lr
761         .endm
763         .macro get_irq_stack                    @ setup IRQ stack
764         ldr     sp, IRQ_STACK_START
765         .endm
767         .macro get_fiq_stack                    @ setup FIQ stack
768         ldr     sp, FIQ_STACK_START
769         .endm
772  * exception handlers
773  */
774         .align  5
775 undefined_instruction:
776         get_bad_stack
777         bad_save_user_regs
778         bl      do_undefined_instruction
780         .align  5
781 software_interrupt:
782         get_bad_stack
783         bad_save_user_regs
784         bl      do_software_interrupt
786         .align  5
787 prefetch_abort:
788         get_bad_stack
789         bad_save_user_regs
790         bl      do_prefetch_abort
792         .align  5
793 data_abort:
794         get_bad_stack
795         bad_save_user_regs
796         bl      do_data_abort
798         .align  5
799 not_used:
800         get_bad_stack
801         bad_save_user_regs
802         bl      do_not_used
804 #ifdef CONFIG_USE_IRQ
806         .align  5
807 irq:
808         get_irq_stack
809         irq_save_user_regs
810         bl      do_irq
811         irq_restore_user_regs
813         .align  5
814 fiq:
815         get_fiq_stack
816         /* someone ought to write a more effiction fiq_save_user_regs */
817         irq_save_user_regs
818         bl      do_fiq
819         irq_restore_user_regs
821 #else
823         .align  5
824 irq:
825         get_bad_stack
826         bad_save_user_regs
827         bl      do_irq
829         .align  5
830 fiq:
831         get_bad_stack
832         bad_save_user_regs
833         bl      do_fiq
835 #endif