FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / firmware / target / arm / crt0-pp.S
blobbd1fc035c9549c3f6a4868692efe7f49b1400a2c
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     /* Zero out IBSS */
217     ldr    r2, =_iedata
218     ldr    r3, =_iend
219     mov    r4, #0
221     cmp    r3, r2
222     strhi  r4, [r2], #4
223     bhi    1b
225     /* Initialise bss section to zero */
226     ldr    r2, =_edata
227     ldr    r3, =_end
228     mov    r4, #0
230     cmp    r3, r2
231     strhi  r4, [r2], #4
232     bhi    1b
234     /* Load stack munge value */    
235     ldr    r4, =0xdeadbeef
237     /* Set up some stack and munge it with 0xdeadbeef */
238     ldr    r2, =stackbegin
239     ldr    sp, =stackend
241     cmp    sp, r2
242     strhi  r4, [r2], #4
243     bhi    1b
245 #if NUM_CORES > 1
246     /* Set up idle stack and munge it with 0xdeadbeef */
247     ldr    r2, =cpu_idlestackbegin
248     ldr    r3, =cpu_idlestackend
250     cmp    r3, r2
251     strhi  r4, [r2], #4
252     bhi    1b
253 #endif
255     /* Set up stack for IRQ mode */ 
256     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
257     ldr    sp, =irq_stack
258     /* Set up stack for FIQ mode */ 
259     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
260     ldr    sp, =fiq_stack
261     /* Let abort and undefined modes use IRQ stack */
262     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
263     ldr    sp, =irq_stack
264     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
265     ldr    sp, =irq_stack
267     /* Switch back to supervisor mode */
268     msr    cpsr_c, #0xd3
270     /* Delay waking the COP until thread initialization is complete unless dual-core
271        support is not enabled in which case the cop_main function does not perform
272        any kernel or thread initialization. It's just a trivial sleep loop. */
273 #if NUM_CORES == 1
274     ldr    r4, =COP_CTRL
275     mov    r3, #WAKE
276     str    r3, [r4]
277 #endif
279     bl     main
280     /* main() should never return */
282 cop_init:
283 #if NUM_CORES > 1
284     /* Wait for CPU to go to sleep at the end of its kernel init */
285     ldr    r4, =CPU_STATUS
287     ldr    r3, [r4]
288     tst    r3, #CPUSLEEPING
289     beq    1b
290 #endif
292     /* Set up idle stack for COP and munge it with 0xdeadbeef */
293     ldr    sp, =cop_idlestackend
294     ldr    r2, =cop_idlestackbegin
295     ldr    r4, =0xdeadbeef
297     cmp    sp, r2
298     strhi  r4, [r2], #4
299     bhi    2b
301     /* Set up stack for IRQ mode */
302     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
303     ldr    sp, =cop_irq_stack
304     /* Set up stack for FIQ mode */
305     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
306     ldr    sp, =cop_fiq_stack
308     /* Let abort and undefined modes use IRQ stack */
309     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
310     ldr    sp, =cop_irq_stack
311     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
312     ldr    sp, =cop_irq_stack
314     /* Switch back to supervisor mode */
315     msr    cpsr_c, #0xd3
316     
317     /* Run cop_main() in apps/main.c */
318     bl     cop_main
320 /* Exception handlers. Will be copied to address 0 after memory remapping */
321     .section .vectors,"aw"
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]
328     ldr    pc, [pc, #24]
329     ldr    pc, [pc, #24]
331     /* Exception vectors */
332     .global vectors
333 vectors:
334     .word  start 
335     .word  undef_instr_handler
336     .word  software_int_handler
337     .word  prefetch_abort_handler
338     .word  data_abort_handler
339     .word  reserved_handler
340     .word  irq_handler
341     .word  fiq_handler
343     .text
345 /* All illegal exceptions call into UIE with exception address as first
346    parameter. This is calculated differently depending on which exception
347    we're in. Second parameter is exception number, used for a string lookup
348    in UIE.
349  */
350 undef_instr_handler:
351     mov    r0, lr
352     mov    r1, #0
353     b      UIE
355 /* We run supervisor mode most of the time, and should never see a software
356    exception being thrown. Perhaps make it illegal and call UIE?
357  */
358 software_int_handler:
359 reserved_handler:
360     movs   pc, lr
361 prefetch_abort_handler:
362     sub    r0, lr, #4
363     mov    r1, #1
364     b      UIE
366 data_abort_handler:
367     sub    r0, lr, #8 
368     mov    r1, #2
369     b      UIE
371 /* Align stacks to cache line boundary */
372     .balign 32
373     
374 /* 256 words of IRQ stack */
375     .space 256*4
376 irq_stack:
378 /* 256 words of COP IRQ stack */
379     .space 256*4
380 cop_irq_stack:
382 /* 256 words of FIQ stack */
383     .space 256*4
384 fiq_stack:
386 /* We'll need this soon - just reserve the symbol */
387 #if 0
388 /* 256 words of COP FIQ stack */
389     .space 256*4
390 #endif
391 cop_fiq_stack: