MINI2440: Remove the extraneous PLL config at startup
[u-boot-openmoko/mini2440.git] / cpu / arm920t / start.S
blobd1000268e92ccc3db370fde4f92aae9f1dc6b3a8
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
299 #else /* i.e. 2440, 2410 and 2440 */
301 #ifndef CONFIG_MINI2440 /* cpu_init_crit is called right afterward */
302 #define LOCKTIME        0x4c000000
303 #define UPLLCON         0x4c000008
305         ldr     r0, =LOCKTIME
306         mov     r1, #0xffffff
307         str     r1, [r0]
309         ldr     r0, =UPLLCON
310         ldr     r1, =UPLLCON_val
311         str     r1, [r0]
313         /* Page 7-19, seven nops between UPLL and MPLL */
314         nop
315         nop
316         nop
317         nop
318         nop
319         nop
320         nop
322         ldr     r1, =MPLLCON_val
323         str     r1, [r0, #-4]           /* MPLLCON */
325         /* FCLK:HCLK:PCLK */
326         ldr     r0, =CLKDIVN
327         mov     r1, #CLKDIVN_val
328         str     r1, [r0]
329 #endif
331 #if 1
332         /* enable uart */
333         ldr     r0, =0x4c00000c         /* clkcon */
334         ldr     r1, =0x7fff0            /* all clocks on */
335         str     r1, [r0]
337         /* gpio UART0 init */
338         ldr     r0, =0x56000070
339         mov     r1, #0xaa
340         str     r1, [r0]
342         /* init uart */
343         ldr     r0, =0x50000000
344         mov     r1, #0x03
345         str     r1, [r0]
346         ldr     r1, =0x245
347         str     r1, [r0, #0x04]
348         mov     r1, #0x01
349         str     r1, [r0, #0x08]
350         mov     r1, #0x00
351         str     r1, [r0, #0x0c]
352         mov     r1, #0x1a
353         str     r1, [r0, #0x28]
354 #endif
355 #endif /* ! CONFIG_MINI2440 */
357 #endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 || CONFIG_S3C2442
358            CONFIG_S3C2443 */
360 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
361 #ifndef CONFIG_LL_INIT_NAND_ONLY
362         bl      cpu_init_crit
363 #endif
365 #if defined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410) || \
366     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
367     defined(CONFIG_S3C2443)
369 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
370         adr     r0, _start              /* r0 <- current position of code   */
372 #ifdef CONFIG_S3C2410_NAND_BOOT
373                                         /* are we running from NAND ?       */
374 #define BWSCON  0x48000000
375         ldr     r1, =BWSCON             /* Z = CPU booted from NAND         */
376         ldr     r1, [r1]
377         tst     r1, #6                  /* BWSCON[2:1] = OM[1:0]            */
378         teqeq   r0, #0                  /* Z &= running at address 0        */
379         beq     nand_load
380 #endif /* CONFIG_S3C2410_NAND_BOOT */
382 relocate:                               /* relocate U-Boot to RAM           */
383         teq     r0, #0                  /* running at address 0 ?           */
384         bleq    may_resume              /* yes -> do low-level setup        */
386         adr     r0, _start              /* the above may have clobbered r0  */
388         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
389         cmp     r0, r1                  /* don't reloc during debug         */
390         beq     done_relocate
392         ldr     r2, _armboot_start
393         ldr     r3, _bss_start
394         sub     r2, r3, r2              /* r2 <- size of armboot            */
395         add     r2, r0, r2              /* r2 <- source end address         */
397 copy_loop:
398         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
399         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
400         cmp     r0, r2                  /* until source end address [r2]    */
401         ble     copy_loop
403 #ifndef CFG_NO_FLASH
404         ldr     r0, _end_if_0           /* are we booting from NOR ? */
405         cmp     r0, r2
406         ldreq   r0, _booted_from_nor    /* remember that we've booted from  */
407         moveq   r1, #1                  /* NOR                              */
408         streqb  r1, [r0]
409 #endif /* !CFG_NO_FLASH */
411         mov     r0, #0                  /* flush v3/v4 cache */
412         mcr     p15, 0, r0, c7, c7, 0
413         ldr     pc, _done_relocate      /* jump to relocated code */
414 _done_relocate:
415         .word   done_relocate
417 #ifdef CONFIG_S3C2410_NAND_BOOT
418 nand_load:
419         bl      may_resume              /* low-level setup and resume */
421         @ reset NAND
422 #if defined(CONFIG_S3C2410)
423         mov     r1, #S3C2410_NAND_BASE
424         ldr     r2, =0xf842             @ initial value enable tacls=3,rph0=6,rph1=0
425         str     r2, [r1, #oNFCONF]
426         ldr     r2, [r1, #oNFCONF]
427         bic     r2, r2, #0x800          @ enable chip
428         str     r2, [r1, #oNFCONF]
429         mov     r2, #0xff               @ RESET command
430         strb    r2, [r1, #oNFCMD]
431         mov     r3, #0                  @ wait
432 1:      add     r3, r3, #0x1
433         cmp     r3, #0xa
434         blt     1b
435 2:      ldr     r2, [r1, #oNFSTAT]      @ wait ready
436         tst     r2, #0x1
437         beq     2b
438         ldr     r2, [r1, #oNFCONF]
439         orr     r2, r2, #0x800          @ disable chip
440         str     r2, [r1, #oNFCONF]
441 #elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
442         mov     r1, #S3C2440_NAND_BASE
443         ldr     r2, =0xfff0             @ initial value tacls=3,rph0=7,rph1=7
444         ldr     r3, [r1, #oNFCONF]
445         orr     r3, r3, r2
446         str     r3, [r1, #oNFCONF]
448         ldr     r3, [r1, #oNFCONT]
449         orr     r3, r3, #1              @ enable nand controller
450         str     r3, [r1, #oNFCONT]
451 #endif /* CONFIG_S3C2440 || CONFIG_S3C2442 */
453         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
454         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
455         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
456 #ifdef CONFIG_USE_IRQ
457         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
458 #endif
459         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
461         @ copy u-boot to RAM
462         ldr     r0, _TEXT_BASE
463         mov     r1, #0x0
464         mov     r2, #CFG_UBOOT_SIZE
465         bl      nand_read_ll
467         tst     r0, #0x0
468         beq     ok_nand_read
469 #ifdef CONFIG_DEBUG_LL
470 bad_nand_read:
471         ldr     r0, STR_FAIL
472         ldr     r1, SerBase
473         bl      PrintWord
474 1:      b       1b              @ infinite loop
475 #endif
477 ok_nand_read:
478 #ifdef CONFIG_DEBUG_LL
479         ldr     r0, STR_OK
480         ldr     r1, SerBase
481         bl      PrintWord
482 #endif
484         @ verify
485         mov     r0, #0
486         @ldr    r1, =0x33f00000
487         ldr     r1, _TEXT_BASE
488         mov     r2, #0x400      @ 4 bytes * 1024 = 4K-bytes
489 go_next:
490         ldr     r3, [r0], #4
491         ldr     r4, [r1], #4
492         teq     r3, r4
493         bne     notmatch
494         subs    r2, r2, #4
495         beq     done_nand_read
496         bne     go_next
497 notmatch:
498 #ifdef CONFIG_DEBUG_LL
499         sub     r0, r0, #4
500         ldr     r1, SerBase
501         bl      PrintHexWord
502         ldr     r0, STR_FAIL
503         ldr     r1, SerBase
504         bl      PrintWord
505 #endif
506 1:      b       1b
507 done_nand_read:
508         ldr     r0, _booted_from_nand
509         mov     r1, #1
510         strb    r1, [r0]
511 #endif /* CONFIG_S3C2410_NAND_BOOT */
512 done_relocate:
514 #if defined(CONFIG_USE_IRQ) && (defined(CONFIG_S3C2410) || \
515     defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442))
516         /* In the case of the S3C2410, if we've somehow magically (JTAG, ...)
517            ended up in RAM, then that ram is mapped to 0x30000000 and not 0.
518            So we need to copy the interrupt vectors, etc.  */
520         mov     r0, #0
521         ldr     r1, _TEXT_BASE
522         mov     r2, #0x40
523 irqvec_cpy_next:
524         ldr     r3, [r1], #4
525         str     r3, [r0], #4
526         subs    r2, r2, #4
527         bne     irqvec_cpy_next
528 #endif /* CONFIG_USE_IRQ */
530 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
531 #endif
532         /* Set up the stack                                                 */
533 stack_setup:
534         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
535         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
536         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
537 #ifdef CONFIG_USE_IRQ
538         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
539 #endif
540         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
542 clear_bss:
543         ldr     r0, _bss_start          /* find start of bss segment        */
544         ldr     r1, _bss_end            /* stop here                        */
545         mov     r2, #0x00000000         /* clear                            */
547 clbss_l:str     r2, [r0]                /* clear loop...                    */
548         add     r0, r0, #4
549         cmp     r0, r1
550         ble     clbss_l
552         ldr     pc, _start_armboot
554 _start_armboot: .word start_armboot
558  *************************************************************************
560  * CPU_init_critical registers
562  * setup important registers
563  * setup memory timing
565  *************************************************************************
566  */
569 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
570 cpu_init_crit:
571         /*
572          * flush v4 I/D caches
573          */
574         mov     r0, #0
575         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
576         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
578         /*
579          * disable MMU stuff and caches
580          */
581         mrc     p15, 0, r0, c1, c0, 0
582         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
583         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
584         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
585         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
586         mcr     p15, 0, r0, c1, c0, 0
588         /*
589          * before relocating, we have to setup RAM timing
590          * because memory timing is board-dependend, you will
591          * find a lowlevel_init.S in your board directory.
592          */
593         mov     ip, lr
594 #if     defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
596 #else
597         bl      lowlevel_init
598 #endif
599         mov     lr, ip
600         mov     pc, lr
601 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
605  *************************************************************************
607  * may_resume
609  * Bring up memory and check if we're coming out of suspend.
611  *************************************************************************
612  */
615 may_resume:
616         mov     r10, lr                 /* we may call cpu_init_crit */
618         /* take sdram out of power down */
619         ldr     r0, =0x56000080         /* misccr */
620         ldr     r1, [ r0 ]
621         bic     r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
622         str     r1, [ r0 ]
624         /* ensure signals stabalise */
625         mov     r1, #128
626 1:      subs    r1, r1, #1
627         bpl     1b
629 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && defined(CONFIG_LL_INIT_NAND_ONLY)
630         bl      cpu_init_crit
631 #endif
632 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
633         /* ensure some refresh has happened */
634         ldr     r1, =0xfffff
635 1:      subs    r1, r1, #1
636         bpl     1b
638         /* capture full EINT situation into gstatus 4 */
640         ldr     r0, =0x4A000000 /* SRCPND */
641         ldr     r1, [ r0 ]
642         and     r1, r1, #0xf
644         ldr     r0, =0x560000BC /* gstatus4 */
645         str     r1, [ r0 ]
647         ldr     r0, =0x560000A8 /* EINTPEND */
648         ldr     r1, [ r0 ]
649         ldr     r0, =0xfff0
650         and     r1, r1, r0
651         ldr     r0, =0x560000BC /* gstatus4 */
652         ldr     r0, [ r0 ]
653         orr     r1, r1, r0
654         ldr     r0, =0x560000BC /* gstatus4 */
655         str     r1, [ r0 ]
657         /* test for resume */
659         ldr     r1, =0x560000B4         /* gstatus2 */
660         ldr     r0, [ r1 ]
661         tst     r0, #0x02               /* is this resume from power down */
662                                         /* well, if it was, we are going to jump to
663                                          * whatever address we stashed in gstatus3,
664                                          * and gstatus4 will hold the wake interrupt
665                                          * source for the OS to look at
666                                          */
667         ldrne   pc, [r1, #4]
668 #endif /* CONFIG_S3C2410 || CONFIG_S3C244 || CONFIG_S3C2442 */
669 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
671         mov     pc, r10
674  *************************************************************************
676  * Interrupt handling
678  *************************************************************************
679  */
682 @ IRQ stack frame.
684 #define S_FRAME_SIZE    72
686 #define S_OLD_R0        68
687 #define S_PSR           64
688 #define S_PC            60
689 #define S_LR            56
690 #define S_SP            52
692 #define S_IP            48
693 #define S_FP            44
694 #define S_R10           40
695 #define S_R9            36
696 #define S_R8            32
697 #define S_R7            28
698 #define S_R6            24
699 #define S_R5            20
700 #define S_R4            16
701 #define S_R3            12
702 #define S_R2            8
703 #define S_R1            4
704 #define S_R0            0
706 #define MODE_SVC 0x13
707 #define I_BIT    0x80
710  * use bad_save_user_regs for abort/prefetch/undef/swi ...
711  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
712  */
714         .macro  bad_save_user_regs
715         sub     sp, sp, #S_FRAME_SIZE
716         stmia   sp, {r0 - r12}                  @ Calling r0-r12
717         ldr     r2, _armboot_start
718         sub     r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
719         sub     r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
720         ldmia   r2, {r2 - r3}                   @ get pc, cpsr
721         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
723         add     r5, sp, #S_SP
724         mov     r1, lr
725         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
726         mov     r0, sp
727         .endm
729         .macro  irq_save_user_regs
730         sub     sp, sp, #S_FRAME_SIZE
731         stmia   sp, {r0 - r12}                  @ Calling r0-r12
732         add     r7, sp, #S_PC
733         stmdb   r7, {sp, lr}^                   @ Calling SP, LR
734         str     lr, [r7, #0]                    @ Save calling PC
735         mrs     r6, spsr
736         str     r6, [r7, #4]                    @ Save CPSR
737         str     r0, [r7, #8]                    @ Save OLD_R0
738         mov     r0, sp
739         .endm
741         .macro  irq_restore_user_regs
742         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
743         mov     r0, r0
744         ldr     lr, [sp, #S_PC]                 @ Get PC
745         add     sp, sp, #S_FRAME_SIZE
746         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
747         .endm
749         .macro get_bad_stack
750         ldr     r13, _armboot_start             @ setup our mode stack
751         sub     r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
752         sub     r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
754         str     lr, [r13]                       @ save caller lr / spsr
755         mrs     lr, spsr
756         str     lr, [r13, #4]
758         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
759         @ msr   spsr_c, r13
760         msr     spsr, r13
761         mov     lr, pc
762         movs    pc, lr
763         .endm
765         .macro get_irq_stack                    @ setup IRQ stack
766         ldr     sp, IRQ_STACK_START
767         .endm
769         .macro get_fiq_stack                    @ setup FIQ stack
770         ldr     sp, FIQ_STACK_START
771         .endm
774  * exception handlers
775  */
776         .align  5
777 undefined_instruction:
778         get_bad_stack
779         bad_save_user_regs
780         bl      do_undefined_instruction
782         .align  5
783 software_interrupt:
784         get_bad_stack
785         bad_save_user_regs
786         bl      do_software_interrupt
788         .align  5
789 prefetch_abort:
790         get_bad_stack
791         bad_save_user_regs
792         bl      do_prefetch_abort
794         .align  5
795 data_abort:
796         get_bad_stack
797         bad_save_user_regs
798         bl      do_data_abort
800         .align  5
801 not_used:
802         get_bad_stack
803         bad_save_user_regs
804         bl      do_not_used
806 #ifdef CONFIG_USE_IRQ
808         .align  5
809 irq:
810         get_irq_stack
811         irq_save_user_regs
812         bl      do_irq
813         irq_restore_user_regs
815         .align  5
816 fiq:
817         get_fiq_stack
818         /* someone ought to write a more effiction fiq_save_user_regs */
819         irq_save_user_regs
820         bl      do_fiq
821         irq_restore_user_regs
823 #else
825         .align  5
826 irq:
827         get_bad_stack
828         bad_save_user_regs
829         bl      do_irq
831         .align  5
832 fiq:
833         get_bad_stack
834         bad_save_user_regs
835         bl      do_fiq
837 #endif