i.MX31: Add a debug menu to play around with DVFS/DPTC settings for fun, testing...
[kugel-rb.git] / firmware / target / arm / crt0-pp.S
blob585455f821c547ccc4bfff2cef0431dd4749a910
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 #if defined(IPOD_VIDEO)
141     /* detect 32mb vs 64mb model */
142     /* we do this here because after SDRAM is remapped, we already assumed */
143     /* its size to be whatever we were compiled for. */
145     mov    r2, #0x12000000
146     mov    r3, #64
147     strb   r3, [r2, #-1]   /* first write 64 to last byte of first 32MB bank */
149     mov    r2, #0x14000000
150     mov    r3, #32
151     strb   r3, [r2, #-1]   /* now write 32 to last byte of second 32MB bank */
153     /* now the last word of the first 32MB bank tells you the RAM size */
154     /* since on a 32MB model both writes will touch the same actual location */
155     /* this is read later on in boot */
156 #endif
158     mov    r2, #0x40000000
159     ldr    r3, =remap_start
160     ldr    r4, =remap_end
162     and    r6, pc, #0xff000000 /* adjust for execute address */
163     orr    r3, r3, r6
164     orr    r4, r4, r6
166     /* copy the code to 0x40000000 */
168     ldr    r5, [r3], #4
169     str    r5, [r2], #4
170     cmp    r3, r4
171     blo    1b
173     ldr    r4, =MMAP_FLAGS
174     orr    r4, r4, r6      /* adjust for execute address */
175     ldr    r3, =MMAP_PHYS
176     ldr    r2, =MMAP_MASK  /* ldr is more flexible */
177     ldr    r1, =MMAP_LOG
178     mov    pc, #0x40000000 
180 remap_start:
181     str    r2, [r1]
182     str    r4, [r3]
183     ldr    r1, L_post_remap
184     bx     r1
185 L_post_remap:
186     .word remap_end
187 remap_end:
189     cmp    r0, #0x55
190     ldr    r4, =COP_CTRL
191     /* Wakeup co-processor to let it do remappings */
192     moveq  r3, #WAKE
193     /* Sleep us (co-processor) and wait for CPU to do kernel initialization */
194     movne  r3, #SLEEP
195     str    r3, [r4]
196     nop
197     nop
198     nop
200     /* Jump to co-processor init */
201     ldrne  pc, =cop_init
203 cpu_init:
204     /* Wait for COP to go to sleep before proceeding */
205     ldr    r4, =COP_STATUS
207     ldr    r3, [r4]
208     tst    r3, #COPSLEEPING
209     beq    1b
210     
211     /* Vectors and IRAM copy is done first since they are reclaimed for
212      * other uninitialized sections */
214     /* Copy exception handler code to address 0 */
215     ldr    r2, =_vectorsstart
216     ldr    r3, =_vectorsend
217     ldr    r4, =_vectorscopy
219     cmp    r3, r2
220     ldrhi  r5, [r4], #4
221     strhi  r5, [r2], #4
222     bhi    1b
223     
224     /* Copy the IRAM */
225     ldr    r2, =_iramcopy
226     ldr    r3, =_iramstart
227     ldr    r4, =_iramend
229     cmp    r4, r3
230     ldrhi  r5, [r2], #4
231     strhi  r5, [r3], #4
232     bhi    1b
234 #ifdef HAVE_INIT_ATTR
235     /* copy init code to codec buffer */
236     ldr    r2, =_initstart
237     ldr    r3, =_initend
238     ldr    r4, =_initcopy
241     cmp     r3, r2
242     ldrhi   r5, [r4], #4
243     strhi   r5, [r2], #4
244     bhi 1b
245 #endif
247     /* Zero out IBSS */
248     ldr    r2, =_iedata
249     ldr    r3, =_iend
250     mov    r4, #0
252     cmp    r3, r2
253     strhi  r4, [r2], #4
254     bhi    1b
256     /* Initialise bss section to zero */
257     ldr    r2, =_edata
258     ldr    r3, =_end
259     mov    r4, #0
261     cmp    r3, r2
262     strhi  r4, [r2], #4
263     bhi    1b
265     /* Load stack munge value */    
266     ldr    r4, =0xdeadbeef
268     /* Set up some stack and munge it with 0xdeadbeef */
269     ldr    r2, =stackbegin
270     ldr    sp, =stackend
272     cmp    sp, r2
273     strhi  r4, [r2], #4
274     bhi    1b
276 #if NUM_CORES > 1
277     /* Set up idle stack and munge it with 0xdeadbeef */
278     ldr    r2, =cpu_idlestackbegin
279     ldr    r3, =cpu_idlestackend
281     cmp    r3, r2
282     strhi  r4, [r2], #4
283     bhi    1b
284 #endif
286     /* Set up stack for IRQ mode */ 
287     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
288     ldr    sp, =irq_stack
289     /* Set up stack for FIQ mode */ 
290     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
291     ldr    sp, =fiq_stack
292     /* Let abort and undefined modes use IRQ stack */
293     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
294     ldr    sp, =irq_stack
295     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
296     ldr    sp, =irq_stack
298     /* Switch back to supervisor mode */
299     msr    cpsr_c, #0xd3
301     /* Delay waking the COP until thread initialization is complete unless dual-core
302        support is not enabled in which case the cop_main function does not perform
303        any kernel or thread initialization. It's just a trivial sleep loop. */
304 #if NUM_CORES == 1
305     ldr    r4, =COP_CTRL
306     mov    r3, #WAKE
307     str    r3, [r4]
308 #endif
310     ldr    pc, =main
311     /* main() should never return */
313 cop_init:
314 #if NUM_CORES > 1
315     /* Wait for CPU to go to sleep at the end of its kernel init */
316     ldr    r4, =CPU_STATUS
318     ldr    r3, [r4]
319     tst    r3, #CPUSLEEPING
320     beq    1b
321 #endif
323     /* Set up idle stack for COP and munge it with 0xdeadbeef */
324     ldr    sp, =cop_idlestackend
325     ldr    r2, =cop_idlestackbegin
326     ldr    r4, =0xdeadbeef
328     cmp    sp, r2
329     strhi  r4, [r2], #4
330     bhi    2b
332     /* Set up stack for IRQ mode */
333     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
334     ldr    sp, =cop_irq_stack
335     /* Set up stack for FIQ mode */
336     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
337     ldr    sp, =cop_fiq_stack
339     /* Let abort and undefined modes use IRQ stack */
340     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
341     ldr    sp, =cop_irq_stack
342     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
343     ldr    sp, =cop_irq_stack
345     /* Switch back to supervisor mode */
346     msr    cpsr_c, #0xd3
347     
348     /* Run cop_main() in apps/main.c */
349     ldr    pc, =cop_main
351 /* Exception handlers. Will be copied to address 0 after memory remapping */
352     .section .vectors,"aw"
353     ldr    pc, [pc, #24]
354     ldr    pc, [pc, #24]
355     ldr    pc, [pc, #24]
356     ldr    pc, [pc, #24]
357     ldr    pc, [pc, #24]
358     ldr    pc, [pc, #24]
359     ldr    pc, [pc, #24]
360     ldr    pc, [pc, #24]
362     /* Exception vectors */
363     .global vectors
364 vectors:
365     .word  start 
366     .word  undef_instr_handler
367     .word  software_int_handler
368     .word  prefetch_abort_handler
369     .word  data_abort_handler
370     .word  reserved_handler
371     .word  irq_handler
372     .word  fiq_handler
374     .text
376 /* All illegal exceptions call into UIE with exception address as first
377    parameter. This is calculated differently depending on which exception
378    we're in. Second parameter is exception number, used for a string lookup
379    in UIE.
380  */
381 undef_instr_handler:
382     sub    r0, lr, #4
383     mov    r1, #0
384     b      UIE
386 /* We run supervisor mode most of the time, and should never see a software
387    exception being thrown. Perhaps make it illegal and call UIE?
388  */
389 software_int_handler:
390 reserved_handler:
391     movs   pc, lr
392 prefetch_abort_handler:
393     sub    r0, lr, #4
394     mov    r1, #1
395     b      UIE
397 data_abort_handler:
398     sub    r0, lr, #8 
399     mov    r1, #2
400     b      UIE
402 /* Align stacks to cache line boundary */
403     .balign 32
404     
405 /* 256 words of IRQ stack */
406     .space 256*4
407 irq_stack:
409 /* 256 words of COP IRQ stack */
410     .space 256*4
411 cop_irq_stack:
413 /* 256 words of FIQ stack */
414     .space 256*4
415 fiq_stack:
417 /* We'll need this soon - just reserve the symbol */
418 #if 0
419 /* 256 words of COP FIQ stack */
420     .space 256*4
421 #endif
422 cop_fiq_stack: