Fix include problem
[kugel-rb.git] / firmware / target / arm / crt0-pp.S
blob31bf3d6e7114c928aecdba320c7106f8953a8ef5
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2002 by Linus Nielsen Feltzing
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18  * KIND, either express or implied.
19  *
20  ****************************************************************************/
21 #include "config.h"
22 #include "cpu.h"
24     .section .init.text,"ax",%progbits
26     .global    start
27 start:
29 /* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux 
30  * loader
31  *
32  * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
33  * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
34  *
35  */
36 #if CONFIG_CPU == PP5002
37     .equ    PROC_ID,     0xc4000000
38     .equ    CPU_ICLR,    0xcf001028
39     .equ    CPU_CTRL,    0xcf004054
40     .equ    COP_ICLR,    0xcf001038
41     .equ    COP_CTRL,    0xcf004058
42     .equ    CPU_STATUS,  0xcf004050
43     .equ    COP_STATUS,  0xcf004050
44     .equ    SLEEP,       0x000000ca
45     .equ    WAKE,        0x000000ce
46     .equ    CPUSLEEPING, 0x00008000
47     .equ    COPSLEEPING, 0x00004000
48     .equ    CACHE_CTRL,  0xcf004024
49     .equ    MMAP_LOG,    0xf000f000 /* MMAP0 */
50     .equ    MMAP_PHYS,   0xf000f004
51 #if MEM > 32
52     .equ    MMAP_MASK,   0x00003c00
53 #else
54     .equ    MMAP_MASK,   0x00003e00
55 #endif
56     .equ    MMAP_FLAGS,  0x00003f84
57 #else
58     .equ    PROC_ID,     0x60000000
59     .equ    CPU_ICLR,    0x60004028
60     .equ    CPU_CTRL,    0x60007000
61     .equ    CPU_STATUS,  0x60007000
62     .equ    COP_ICLR,    0x60004038
63     .equ    COP_CTRL,    0x60007004
64     .equ    COP_STATUS,  0x60007004
65     .equ    SLEEP,       0x80000000
66     .equ    WAKE,        0x00000000
67     .equ    CPUSLEEPING, 0x80000000
68     .equ    COPSLEEPING, 0x80000000    
69     .equ    CACHE_CTRL,  0x6000c000
70     .equ    MMAP_LOG,    0xf000f000 /* MMAP0 */
71     .equ    MMAP_PHYS,   0xf000f004
72 #if MEM > 32
73     .equ    MMAP_MASK,   0x00003c00
74 #else
75     .equ    MMAP_MASK,   0x00003e00
76 #endif
77     .equ    MMAP_FLAGS,  0x00000f84
78 #endif
80     msr    cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
81     b      pad_skip
83 .space 6*4  /* pad to offset 0x20 */
85     .ascii "Rockbox"    /* signature for bootloader checking osos */
86     .byte 1             /* osos boot version, only 1 exists for now */
88 .space 56*4 /* (more than enough) space for exception vectors and mi4 magic */
90 pad_skip:
91     /* Find out which processor we are - r0 should be preserved for the
92      * duration of the init to avoid constant reloading of the processor ID.
93      * For each stage, CPU proceeds first, then COP. 
94      */
95     ldr    r0, =PROC_ID
96     ldrb   r0, [r0]
98     /* We need to remap memory from wherever SDRAM is mapped natively, to
99        base address 0, so we can put our exception vectors there. We don't
100        want to do this remapping while executing from SDRAM, so we copy the
101        remapping code to IRAM, then execute from there. Hence, the following
102        code is compiled for address 0, but is currently executing at either
103        0x28000000 or 0x10000000, depending on chipset version. Do not use any
104        absolute addresses until remapping has been done. */
106     /* Cores are stepped though the init in turn: CPU then COP. The the remap
107        stage is completed by each core in turn and then the COP waits for the
108        CPU to finish initializing its kernel where the CPU will wake the COP
109        and wait for the COP to finish. This ensures no threading activity
110        starts until it is safe. */
111     cmp    r0, #0x55
112     
113     /* mask all interrupt sources before setting anything up */
114     ldreq  r2, =CPU_ICLR
115     ldrne  r2, =COP_ICLR    
116     mvn    r1, #0
117     str    r1, [r2]
119     /* put us (co-processor) to sleep and wait for CPU to remap */
120     ldrne  r2, =COP_CTRL
121     movne  r1, #SLEEP
122     strne  r1, [r2]
123     nop
124     nop
125     nop
127     /* wait for co-processor to sleep then CPU can begin its remapping */
128     ldreq  r2, =COP_STATUS
130     ldreq  r1, [r2]
131     tsteq  r1, #COPSLEEPING
132     beq    1b
134     /* disable cache and local interrupt vectors - it is really not desireable
135        to have them enabled here */
136     ldr    r2, =CACHE_CTRL
137     mov    r1, #0
138     str    r1, [r2]
140     mov    r2, #0x40000000
141     ldr    r3, =remap_start
142     ldr    r4, =remap_end
144     and    r6, pc, #0xff000000 /* adjust for execute address */
145     orr    r3, r3, r6
146     orr    r4, r4, r6
148     /* copy the code to 0x40000000 */
150     ldr    r5, [r3], #4
151     str    r5, [r2], #4
152     cmp    r3, r4
153     blo    1b
155     ldr    r4, =MMAP_FLAGS
156     orr    r4, r4, r6      /* adjust for execute address */
157     ldr    r3, =MMAP_PHYS
158     ldr    r2, =MMAP_MASK  /* ldr is more flexible */
159     ldr    r1, =MMAP_LOG
160     mov    pc, #0x40000000 
162 remap_start:
163     str    r2, [r1]
164     str    r4, [r3]
165     ldr    r1, L_post_remap
166     mov    pc, r1
167 L_post_remap:
168     .word remap_end
169 remap_end:
171     cmp    r0, #0x55
172     ldr    r4, =COP_CTRL
173     /* Wakeup co-processor to let it do remappings */
174     moveq  r3, #WAKE
175     /* Sleep us (co-processor) and wait for CPU to do kernel initialization */
176     movne  r3, #SLEEP
177     str    r3, [r4]
178     nop
179     nop
180     nop
182     /* Jump to co-processor init */
183     ldrne  pc, =cop_init
185 cpu_init:
186     /* Wait for COP to go to sleep before proceeding */
187     ldr    r4, =COP_STATUS
189     ldr    r3, [r4]
190     tst    r3, #COPSLEEPING
191     beq    1b
192     
193     /* Vectors and IRAM copy is done first since they are reclaimed for
194      * other uninitialized sections */
196     /* Copy exception handler code to address 0 */
197     ldr    r2, =_vectorsstart
198     ldr    r3, =_vectorsend
199     ldr    r4, =_vectorscopy
201     cmp    r3, r2
202     ldrhi  r5, [r4], #4
203     strhi  r5, [r2], #4
204     bhi    1b
205     
206     /* Copy the IRAM */
207     ldr    r2, =_iramcopy
208     ldr    r3, =_iramstart
209     ldr    r4, =_iramend
211     cmp    r4, r3
212     ldrhi  r5, [r2], #4
213     strhi  r5, [r3], #4
214     bhi    1b
216 #ifdef HAVE_INIT_ATTR
217     /* copy init code to codec buffer */
218     ldr    r2, =_initstart
219     ldr    r3, =_initend
220     ldr    r4, =_initcopy
223     cmp     r3, r2
224     ldrhi   r5, [r4], #4
225     strhi   r5, [r2], #4
226     bhi 1b
227 #endif
229     /* Zero out IBSS */
230     ldr    r2, =_iedata
231     ldr    r3, =_iend
232     mov    r4, #0
234     cmp    r3, r2
235     strhi  r4, [r2], #4
236     bhi    1b
238     /* Initialise bss section to zero */
239     ldr    r2, =_edata
240     ldr    r3, =_end
241     mov    r4, #0
243     cmp    r3, r2
244     strhi  r4, [r2], #4
245     bhi    1b
247     /* Load stack munge value */    
248     ldr    r4, =0xdeadbeef
250     /* Set up some stack and munge it with 0xdeadbeef */
251     ldr    r2, =stackbegin
252     ldr    sp, =stackend
254     cmp    sp, r2
255     strhi  r4, [r2], #4
256     bhi    1b
258 #if NUM_CORES > 1
259     /* Set up idle stack and munge it with 0xdeadbeef */
260     ldr    r2, =cpu_idlestackbegin
261     ldr    r3, =cpu_idlestackend
263     cmp    r3, r2
264     strhi  r4, [r2], #4
265     bhi    1b
266 #endif
268     /* Set up stack for IRQ mode */ 
269     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
270     ldr    sp, =irq_stack
271     /* Set up stack for FIQ mode */ 
272     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
273     ldr    sp, =fiq_stack
274     /* Let abort and undefined modes use IRQ stack */
275     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
276     ldr    sp, =irq_stack
277     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
278     ldr    sp, =irq_stack
280     /* Switch back to supervisor mode */
281     msr    cpsr_c, #0xd3
283     /* Delay waking the COP until thread initialization is complete unless dual-core
284        support is not enabled in which case the cop_main function does not perform
285        any kernel or thread initialization. It's just a trivial sleep loop. */
286 #if NUM_CORES == 1
287     ldr    r4, =COP_CTRL
288     mov    r3, #WAKE
289     str    r3, [r4]
290 #endif
292     ldr    pc, =main
293     /* main() should never return */
295 cop_init:
296 #if NUM_CORES > 1
297     /* Wait for CPU to go to sleep at the end of its kernel init */
298     ldr    r4, =CPU_STATUS
300     ldr    r3, [r4]
301     tst    r3, #CPUSLEEPING
302     beq    1b
303 #endif
305     /* Set up idle stack for COP and munge it with 0xdeadbeef */
306     ldr    sp, =cop_idlestackend
307     ldr    r2, =cop_idlestackbegin
308     ldr    r4, =0xdeadbeef
310     cmp    sp, r2
311     strhi  r4, [r2], #4
312     bhi    2b
314     /* Set up stack for IRQ mode */
315     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
316     ldr    sp, =cop_irq_stack
317     /* Set up stack for FIQ mode */
318     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
319     ldr    sp, =cop_fiq_stack
321     /* Let abort and undefined modes use IRQ stack */
322     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
323     ldr    sp, =cop_irq_stack
324     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
325     ldr    sp, =cop_irq_stack
327     /* Switch back to supervisor mode */
328     msr    cpsr_c, #0xd3
329     
330     /* Run cop_main() in apps/main.c */
331     ldr    pc, =cop_main
333 /* Exception handlers. Will be copied to address 0 after memory remapping */
334     .section .vectors,"aw"
335     ldr    pc, [pc, #24]
336     ldr    pc, [pc, #24]
337     ldr    pc, [pc, #24]
338     ldr    pc, [pc, #24]
339     ldr    pc, [pc, #24]
340     ldr    pc, [pc, #24]
341     ldr    pc, [pc, #24]
342     ldr    pc, [pc, #24]
344     /* Exception vectors */
345     .global vectors
346 vectors:
347     .word  start 
348     .word  undef_instr_handler
349     .word  software_int_handler
350     .word  prefetch_abort_handler
351     .word  data_abort_handler
352     .word  reserved_handler
353     .word  irq_handler
354     .word  fiq_handler
356     .text
358 /* All illegal exceptions call into UIE with exception address as first
359    parameter. This is calculated differently depending on which exception
360    we're in. Second parameter is exception number, used for a string lookup
361    in UIE.
362  */
363 undef_instr_handler:
364     sub    r0, lr, #4
365     mov    r1, #0
366     b      UIE
368 /* We run supervisor mode most of the time, and should never see a software
369    exception being thrown. Perhaps make it illegal and call UIE?
370  */
371 software_int_handler:
372 reserved_handler:
373     movs   pc, lr
374 prefetch_abort_handler:
375     sub    r0, lr, #4
376     mov    r1, #1
377     b      UIE
379 data_abort_handler:
380     sub    r0, lr, #8 
381     mov    r1, #2
382     b      UIE
384 /* Align stacks to cache line boundary */
385     .balign 32
386     
387 /* 256 words of IRQ stack */
388     .space 256*4
389 irq_stack:
391 /* 256 words of COP IRQ stack */
392     .space 256*4
393 cop_irq_stack:
395 /* 256 words of FIQ stack */
396     .space 256*4
397 fiq_stack:
399 /* We'll need this soon - just reserve the symbol */
400 #if 0
401 /* 256 words of COP FIQ stack */
402     .space 256*4
403 #endif
404 cop_fiq_stack: