Hopefully fix FS#8506 (OF cant be loaded on some PP targets). also hopefully fixes...
[Rockbox.git] / firmware / target / arm / crt0-pp.S
blobdac666ca1cdedf26c91b2631fc0b80391bc3844d
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2002 by Linus Nielsen Feltzing
11  *
12  * All files in this archive are subject to the GNU General Public License.
13  * See the file COPYING in the source tree root for full license agreement.
14  *
15  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16  * KIND, either express or implied.
17  *
18  ****************************************************************************/
19 #include "config.h"
20 #include "cpu.h"
22     .section .init.text,"ax",%progbits
24     .global    start
25 start:
27 /* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux 
28  * loader
29  *
30  * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
31  * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
32  *
33  */
34 #if CONFIG_CPU == PP5002
35     .equ    PROC_ID,     0xc4000000
36     .equ    CPU_ICLR,    0xcf001028
37     .equ    CPU_CTRL,    0xcf004054
38     .equ    COP_ICLR,    0xcf001038
39     .equ    COP_CTRL,    0xcf004058
40     .equ    CPU_STATUS,  0xcf004050
41     .equ    COP_STATUS,  0xcf004050
42     .equ    IIS_CONFIG,  0xc0002500
43     .equ    SLEEP,       0x000000ca
44     .equ    WAKE,        0x000000ce
45     .equ    CPUSLEEPING, 0x00008000
46     .equ    COPSLEEPING, 0x00004000
47     .equ    CACHE_CTRL,  0xcf004024
48     .equ    MMAP_LOG,    0xf000f000 /* MMAP0 */
49     .equ    MMAP_PHYS,   0xf000f004
50 #if MEM > 32
51     .equ    MMAP_MASK,   0x00003c00
52 #else
53     .equ    MMAP_MASK,   0x00003e00
54 #endif
55     .equ    MMAP_FLAGS,  0x00003f84
56 #else
57     .equ    PROC_ID,     0x60000000
58     .equ    CPU_ICLR,    0x60004028
59     .equ    CPU_CTRL,    0x60007000
60     .equ    CPU_STATUS,  0x60007000
61     .equ    COP_ICLR,    0x60004038
62     .equ    COP_CTRL,    0x60007004
63     .equ    COP_STATUS,  0x60007004
64     .equ    IIS_CONFIG,  0x70002800
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 64*4 /* (more than enough) space for exception vectors and mi4 magic */
85 pad_skip:
86     /* Find out which processor we are - r0 should be preserved for the
87      * duration of the init to avoid constant reloading of the processor ID.
88      * For each stage, CPU proceeds first, then COP. 
89      */
90     ldr    r0, =PROC_ID
91     ldrb   r0, [r0]
93     /* We need to remap memory from wherever SDRAM is mapped natively, to
94        base address 0, so we can put our exception vectors there. We don't
95        want to do this remapping while executing from SDRAM, so we copy the
96        remapping code to IRAM, then execute from there. Hence, the following
97        code is compiled for address 0, but is currently executing at either
98        0x28000000 or 0x10000000, depending on chipset version. Do not use any
99        absolute addresses until remapping has been done. */
101     /* Cores are stepped though the init in turn: CPU then COP. The the remap
102        stage is completed by each core in turn and then the COP waits for the
103        CPU to finish initializing its kernel where the CPU will wake the COP
104        and wait for the COP to finish. This ensures no threading activity
105        starts until it is safe. */
106     cmp    r0, #0x55
107     
108     /* mask all interrupt sources before setting anything up */
109     ldreq  r2, =CPU_ICLR
110     ldrne  r2, =COP_ICLR    
111     mvn    r1, #0
112     str    r1, [r2]
114     /* put us (co-processor) to sleep and wait for CPU to remap */
115     ldrne  r2, =COP_CTRL
116     movne  r1, #SLEEP
117     strne  r1, [r2]
118     nop
119     nop
120     nop
122     /* wait for co-processor to sleep then CPU can begin its remapping */
123     ldreq  r2, =COP_STATUS
125     ldreq  r1, [r2]
126     tsteq  r1, #COPSLEEPING
127     beq    1b
129     /* disable cache and local interrupt vectors - it is really not desireable
130        to have them enabled here */
131     ldr    r2, =CACHE_CTRL
132     mov    r1, #0
133     str    r1, [r2]
135     mov    r2, #0x40000000
136     ldr    r3, =remap_start
137     ldr    r4, =remap_end
139     and    r6, pc, #0xff000000 /* adjust for execute address */
140     orr    r3, r3, r6
141     orr    r4, r4, r6
143     /* copy the code to 0x40000000 */
145     ldr    r5, [r3], #4
146     str    r5, [r2], #4
147     cmp    r3, r4
148     blo    1b
150     ldr    r4, =MMAP_FLAGS
151     orr    r4, r4, r6      /* adjust for execute address */
152     ldr    r3, =MMAP_PHYS
153     ldr    r2, =MMAP_MASK  /* ldr is more flexible */
154     ldr    r1, =MMAP_LOG
155     mov    pc, #0x40000000 
157 remap_start:
158     str    r2, [r1]
159     str    r4, [r3]
160     ldr    r1, L_post_remap
161     mov    pc, r1
162 L_post_remap:
163     .word remap_end
164 remap_end:
166     cmp    r0, #0x55
167     ldr    r4, =COP_CTRL
168     /* Wakeup co-processor to let it do remappings */
169     moveq  r3, #WAKE
170     /* Sleep us (co-processor) and wait for CPU to do kernel initialization */
171     movne  r3, #SLEEP
172     str    r3, [r4]
173     nop
174     nop
175     nop
177     /* Jump to co-processor init */
178     ldrne  pc, =cop_init
180 cpu_init:
181     /* Wait for COP to go to sleep before proceeding */
182     ldr    r4, =COP_STATUS
184     ldr    r3, [r4]
185     tst    r3, #COPSLEEPING
186     beq    1b
188     /* Copy exception handler code to address 0 */
189     ldr    r2, =_vectorsstart
190     ldr    r3, =_vectorsend
191     ldr    r4, =_vectorscopy
193     cmp    r3, r2
194     ldrhi  r5, [r4], #4
195     strhi  r5, [r2], #4
196     bhi    1b
198     /* Zero out IBSS */
199     ldr    r2, =_iedata
200     ldr    r3, =_iend
201     mov    r4, #0
203     cmp    r3, r2
204     strhi  r4, [r2], #4
205     bhi    1b
207     /* Copy the IRAM */
208     ldr    r2, =_iramcopy
209     ldr    r3, =_iramstart
210     ldr    r4, =_iramend
212     cmp    r4, r3
213     ldrhi  r5, [r2], #4
214     strhi  r5, [r3], #4
215     bhi    1b
217     /* Initialise bss section to zero */
218     ldr    r2, =_edata
219     ldr    r3, =_end
220     mov    r4, #0
222     cmp    r3, r2
223     strhi  r4, [r2], #4
224     bhi    1b
226     /* Load stack munge value */    
227     ldr    r4, =0xdeadbeef
229     /* Set up some stack and munge it with 0xdeadbeef */
230     ldr    r2, =stackbegin
231     ldr    sp, =stackend
233     cmp    sp, r2
234     strhi  r4, [r2], #4
235     bhi    1b
237 #if NUM_CORES > 1
238     /* Set up idle stack and munge it with 0xdeadbeef */
239     ldr    r2, =cpu_idlestackbegin
240     ldr    r3, =cpu_idlestackend
242     cmp    r3, r2
243     strhi  r4, [r2], #4
244     bhi    1b
245 #endif
247     /* Set up stack for IRQ mode */ 
248     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
249     ldr    sp, =irq_stack
250     /* Set up stack for FIQ mode */ 
251     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
252     ldr    sp, =fiq_stack
253     /* We'll load the banked FIQ mode registers with useful values here.
254        These values will be used in the FIQ handler in pcm-pp.c */
255     ldr    r10, =IIS_CONFIG
257     ldr    r11, =dma_play_data
259     /* Let abort and undefined modes use IRQ stack */
260     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
261     ldr    sp, =irq_stack
262     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
263     ldr    sp, =irq_stack
265     /* Switch back to supervisor mode */
266     msr    cpsr_c, #0xd3
268     /* Delay waking the COP until thread initialization is complete unless dual-core
269        support is not enabled in which case the cop_main function does not perform
270        any kernel or thread initialization. It's just a trivial sleep loop. */
271 #if NUM_CORES == 1
272     ldr    r4, =COP_CTRL
273     mov    r3, #WAKE
274     str    r3, [r4]
275 #endif
277     bl     main
278     /* main() should never return */
280 cop_init:
281 #if NUM_CORES > 1
282     /* Wait for CPU to go to sleep at the end of its kernel init */
283     ldr    r4, =CPU_STATUS
285     ldr    r3, [r4]
286     tst    r3, #CPUSLEEPING
287     beq    1b
288 #endif
290     /* Set up idle stack for COP and munge it with 0xdeadbeef */
291     ldr    sp, =cop_idlestackend
292     ldr    r2, =cop_idlestackbegin
293     ldr    r4, =0xdeadbeef
295     cmp    sp, r2
296     strhi  r4, [r2], #4
297     bhi    2b
299     /* Set up stack for IRQ mode */
300     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
301     ldr    sp, =cop_irq_stack
302     /* Set up stack for FIQ mode */
303     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
304     ldr    sp, =cop_fiq_stack
306     /* Let abort and undefined modes use IRQ stack */
307     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
308     ldr    sp, =cop_irq_stack
309     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
310     ldr    sp, =cop_irq_stack
312     /* Switch back to supervisor mode */
313     msr    cpsr_c, #0xd3
314     
315     /* Run cop_main() in apps/main.c */
316     bl     cop_main
318 /* Exception handlers. Will be copied to address 0 after memory remapping */
319     .section .vectors,"aw"
320     ldr    pc, [pc, #24]
321     ldr    pc, [pc, #24]
322     ldr    pc, [pc, #24]
323     ldr    pc, [pc, #24]
324     ldr    pc, [pc, #24]
325     ldr    pc, [pc, #24]
326     ldr    pc, [pc, #24]
327     ldr    pc, [pc, #24]
329     /* Exception vectors */
330     .global vectors
331 vectors:
332     .word  start 
333     .word  undef_instr_handler
334     .word  software_int_handler
335     .word  prefetch_abort_handler
336     .word  data_abort_handler
337     .word  reserved_handler
338     .word  irq_handler
339     .word  fiq_handler
341     .text
343 #ifndef STUB
344     .global irq
345     .global UIE
346 #endif
348 /* All illegal exceptions call into UIE with exception address as first
349    parameter. This is calculated differently depending on which exception
350    we're in. Second parameter is exception number, used for a string lookup
351    in UIE.
352  */
353 undef_instr_handler:
354     mov    r0, lr
355     mov    r1, #0
356     b      UIE
358 /* We run supervisor mode most of the time, and should never see a software
359    exception being thrown. Perhaps make it illegal and call UIE?
360  */
361 software_int_handler:
362 reserved_handler:
363     movs   pc, lr
364 prefetch_abort_handler:
365     sub    r0, lr, #4
366     mov    r1, #1
367     b      UIE
369 data_abort_handler:
370     sub    r0, lr, #8 
371     mov    r1, #2
372     b      UIE
374 irq_handler:
375 #ifndef STUB
376     stmfd  sp!, {r0-r3, r12, lr}
377     bl     irq
378     ldmfd  sp!, {r0-r3, r12, lr}
379 #endif
380     subs   pc, lr, #4
382 #ifdef STUB
383 UIE:
384     b UIE
385 #endif
387 /* Align stacks to cache line boundary */
388     .balign 32
389     
390 /* 256 words of IRQ stack */
391     .space 256*4
392 irq_stack:
394 /* 256 words of COP IRQ stack */
395     .space 256*4
396 cop_irq_stack:
398 /* 256 words of FIQ stack */
399     .space 256*4
400 fiq_stack:
402 /* We'll need this soon - just reserve the symbol */
403 #if 0
404 /* 256 words of COP FIQ stack */
405     .space 256*4
406 #endif
407 cop_fiq_stack: