Reclaim .iram areas in DRAM by overlapping their load addresses with the uninitialize...
[kugel-rb.git] / firmware / target / arm / crt0-pp.S
blob210b5605605707db0f29d77d0b69a74ee4f637d1
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 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
187     
188     /* Vectors and IRAM copy is done first since they are reclaimed for
189      * other uninitialized sections */
191     /* Copy exception handler code to address 0 */
192     ldr    r2, =_vectorsstart
193     ldr    r3, =_vectorsend
194     ldr    r4, =_vectorscopy
196     cmp    r3, r2
197     ldrhi  r5, [r4], #4
198     strhi  r5, [r2], #4
199     bhi    1b
200     
201     /* Copy the IRAM */
202     ldr    r2, =_iramcopy
203     ldr    r3, =_iramstart
204     ldr    r4, =_iramend
206     cmp    r4, r3
207     ldrhi  r5, [r2], #4
208     strhi  r5, [r3], #4
209     bhi    1b
211     /* Zero out IBSS */
212     ldr    r2, =_iedata
213     ldr    r3, =_iend
214     mov    r4, #0
216     cmp    r3, r2
217     strhi  r4, [r2], #4
218     bhi    1b
220     /* Initialise bss section to zero */
221     ldr    r2, =_edata
222     ldr    r3, =_end
223     mov    r4, #0
225     cmp    r3, r2
226     strhi  r4, [r2], #4
227     bhi    1b
229     /* Load stack munge value */    
230     ldr    r4, =0xdeadbeef
232     /* Set up some stack and munge it with 0xdeadbeef */
233     ldr    r2, =stackbegin
234     ldr    sp, =stackend
236     cmp    sp, r2
237     strhi  r4, [r2], #4
238     bhi    1b
240 #if NUM_CORES > 1
241     /* Set up idle stack and munge it with 0xdeadbeef */
242     ldr    r2, =cpu_idlestackbegin
243     ldr    r3, =cpu_idlestackend
245     cmp    r3, r2
246     strhi  r4, [r2], #4
247     bhi    1b
248 #endif
250     /* Set up stack for IRQ mode */ 
251     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
252     ldr    sp, =irq_stack
253     /* Set up stack for FIQ mode */ 
254     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
255     ldr    sp, =fiq_stack
256     /* Let abort and undefined modes use IRQ stack */
257     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
258     ldr    sp, =irq_stack
259     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
260     ldr    sp, =irq_stack
262     /* Switch back to supervisor mode */
263     msr    cpsr_c, #0xd3
265     /* Delay waking the COP until thread initialization is complete unless dual-core
266        support is not enabled in which case the cop_main function does not perform
267        any kernel or thread initialization. It's just a trivial sleep loop. */
268 #if NUM_CORES == 1
269     ldr    r4, =COP_CTRL
270     mov    r3, #WAKE
271     str    r3, [r4]
272 #endif
274     bl     main
275     /* main() should never return */
277 cop_init:
278 #if NUM_CORES > 1
279     /* Wait for CPU to go to sleep at the end of its kernel init */
280     ldr    r4, =CPU_STATUS
282     ldr    r3, [r4]
283     tst    r3, #CPUSLEEPING
284     beq    1b
285 #endif
287     /* Set up idle stack for COP and munge it with 0xdeadbeef */
288     ldr    sp, =cop_idlestackend
289     ldr    r2, =cop_idlestackbegin
290     ldr    r4, =0xdeadbeef
292     cmp    sp, r2
293     strhi  r4, [r2], #4
294     bhi    2b
296     /* Set up stack for IRQ mode */
297     msr    cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */
298     ldr    sp, =cop_irq_stack
299     /* Set up stack for FIQ mode */
300     msr    cpsr_c, #0xd1 /* IRQ/FIQ disabled */
301     ldr    sp, =cop_fiq_stack
303     /* Let abort and undefined modes use IRQ stack */
304     msr    cpsr_c, #0xd7 /* IRQ/FIQ disabled */
305     ldr    sp, =cop_irq_stack
306     msr    cpsr_c, #0xdb /* IRQ/FIQ disabled */
307     ldr    sp, =cop_irq_stack
309     /* Switch back to supervisor mode */
310     msr    cpsr_c, #0xd3
311     
312     /* Run cop_main() in apps/main.c */
313     bl     cop_main
315 /* Exception handlers. Will be copied to address 0 after memory remapping */
316     .section .vectors,"aw"
317     ldr    pc, [pc, #24]
318     ldr    pc, [pc, #24]
319     ldr    pc, [pc, #24]
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]
326     /* Exception vectors */
327     .global vectors
328 vectors:
329     .word  start 
330     .word  undef_instr_handler
331     .word  software_int_handler
332     .word  prefetch_abort_handler
333     .word  data_abort_handler
334     .word  reserved_handler
335     .word  irq_handler
336     .word  fiq_handler
338     .text
340 /* All illegal exceptions call into UIE with exception address as first
341    parameter. This is calculated differently depending on which exception
342    we're in. Second parameter is exception number, used for a string lookup
343    in UIE.
344  */
345 undef_instr_handler:
346     mov    r0, lr
347     mov    r1, #0
348     b      UIE
350 /* We run supervisor mode most of the time, and should never see a software
351    exception being thrown. Perhaps make it illegal and call UIE?
352  */
353 software_int_handler:
354 reserved_handler:
355     movs   pc, lr
356 prefetch_abort_handler:
357     sub    r0, lr, #4
358     mov    r1, #1
359     b      UIE
361 data_abort_handler:
362     sub    r0, lr, #8 
363     mov    r1, #2
364     b      UIE
366 /* Align stacks to cache line boundary */
367     .balign 32
368     
369 /* 256 words of IRQ stack */
370     .space 256*4
371 irq_stack:
373 /* 256 words of COP IRQ stack */
374     .space 256*4
375 cop_irq_stack:
377 /* 256 words of FIQ stack */
378     .space 256*4
379 fiq_stack:
381 /* We'll need this soon - just reserve the symbol */
382 #if 0
383 /* 256 words of COP FIQ stack */
384     .space 256*4
385 #endif
386 cop_fiq_stack: