diff options
Diffstat (limited to 'firmware/target/arm/pp/crt0-pp.S')
-rw-r--r-- | firmware/target/arm/pp/crt0-pp.S | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/firmware/target/arm/pp/crt0-pp.S b/firmware/target/arm/pp/crt0-pp.S new file mode 100644 index 0000000000..5a9835a71f --- /dev/null +++ b/firmware/target/arm/pp/crt0-pp.S | |||
@@ -0,0 +1,430 @@ | |||
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" | ||
23 | |||
24 | .section .init.text,"ax",%progbits | ||
25 | |||
26 | .global start | ||
27 | start: | ||
28 | |||
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 MEMORYSIZE > 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 MEMORYSIZE > 32 | ||
73 | .equ MMAP_MASK, 0x00003c00 | ||
74 | #else | ||
75 | .equ MMAP_MASK, 0x00003e00 | ||
76 | #endif | ||
77 | .equ MMAP_FLAGS, 0x00000f84 | ||
78 | #endif | ||
79 | |||
80 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ | ||
81 | b pad_skip | ||
82 | |||
83 | .space 6*4 /* pad to offset 0x20 */ | ||
84 | |||
85 | .ascii "Rockbox" /* signature for bootloader checking osos */ | ||
86 | .byte 1 /* osos boot version, only 1 exists for now */ | ||
87 | |||
88 | .space 56*4 /* (more than enough) space for exception vectors and mi4 magic */ | ||
89 | |||
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] | ||
97 | |||
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. */ | ||
105 | |||
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] | ||
118 | |||
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 | ||
126 | |||
127 | /* wait for co-processor to sleep then CPU can begin its remapping */ | ||
128 | ldreq r2, =COP_STATUS | ||
129 | 1: | ||
130 | ldreq r1, [r2] | ||
131 | tsteq r1, #COPSLEEPING | ||
132 | beq 1b | ||
133 | |||
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] | ||
139 | |||
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. */ | ||
144 | |||
145 | mov r2, #0x12000000 | ||
146 | mov r3, #64 | ||
147 | strb r3, [r2, #-1] /* first write 64 to last byte of first 32MB bank */ | ||
148 | |||
149 | mov r2, #0x14000000 | ||
150 | mov r3, #32 | ||
151 | strb r3, [r2, #-1] /* now write 32 to last byte of second 32MB bank */ | ||
152 | |||
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 | ||
157 | |||
158 | mov r2, #0x40000000 | ||
159 | ldr r3, =remap_start | ||
160 | ldr r4, =remap_end | ||
161 | |||
162 | and r6, pc, #0xff000000 /* adjust for execute address */ | ||
163 | orr r3, r3, r6 | ||
164 | orr r4, r4, r6 | ||
165 | |||
166 | /* copy the code to 0x40000000 */ | ||
167 | 1: | ||
168 | ldr r5, [r3], #4 | ||
169 | str r5, [r2], #4 | ||
170 | cmp r3, r4 | ||
171 | blo 1b | ||
172 | |||
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 | ||
179 | |||
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: | ||
188 | |||
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 | ||
199 | |||
200 | /* Jump to co-processor init */ | ||
201 | ldrne pc, =cop_init | ||
202 | |||
203 | cpu_init: | ||
204 | /* Wait for COP to go to sleep before proceeding */ | ||
205 | ldr r4, =COP_STATUS | ||
206 | 1: | ||
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 */ | ||
213 | |||
214 | /* Copy exception handler code to address 0 */ | ||
215 | ldr r2, =_vectorsstart | ||
216 | ldr r3, =_vectorsend | ||
217 | ldr r4, =_vectorscopy | ||
218 | 1: | ||
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 | ||
228 | 1: | ||
229 | cmp r4, r3 | ||
230 | ldrhi r5, [r2], #4 | ||
231 | strhi r5, [r3], #4 | ||
232 | bhi 1b | ||
233 | |||
234 | #ifdef HAVE_INIT_ATTR | ||
235 | /* copy init code to codec buffer */ | ||
236 | ldr r2, =_initstart | ||
237 | ldr r3, =_initend | ||
238 | ldr r4, =_initcopy | ||
239 | |||
240 | 1: | ||
241 | cmp r3, r2 | ||
242 | ldrhi r5, [r4], #4 | ||
243 | strhi r5, [r2], #4 | ||
244 | bhi 1b | ||
245 | #endif | ||
246 | |||
247 | /* Zero out IBSS */ | ||
248 | ldr r2, =_iedata | ||
249 | ldr r3, =_iend | ||
250 | mov r4, #0 | ||
251 | 1: | ||
252 | cmp r3, r2 | ||
253 | strhi r4, [r2], #4 | ||
254 | bhi 1b | ||
255 | |||
256 | /* Initialise bss section to zero */ | ||
257 | ldr r2, =_edata | ||
258 | ldr r3, =_end | ||
259 | mov r4, #0 | ||
260 | 1: | ||
261 | cmp r3, r2 | ||
262 | strhi r4, [r2], #4 | ||
263 | bhi 1b | ||
264 | |||
265 | /* Load stack munge value */ | ||
266 | ldr r4, =0xdeadbeef | ||
267 | |||
268 | #if NUM_CORES > 1 | ||
269 | /* Set up idle stack and munge it with 0xdeadbeef */ | ||
270 | ldr r2, =cpu_idlestackbegin | ||
271 | ldr r3, =cpu_idlestackend | ||
272 | 1: | ||
273 | cmp r3, r2 | ||
274 | strhi r4, [r2], #4 | ||
275 | bhi 1b | ||
276 | #endif | ||
277 | |||
278 | /* Set up stack for IRQ mode */ | ||
279 | msr cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */ | ||
280 | ldr sp, =irq_stack | ||
281 | /* Set up stack for FIQ mode */ | ||
282 | msr cpsr_c, #0xd1 /* IRQ/FIQ disabled */ | ||
283 | ldr sp, =fiq_stack | ||
284 | |||
285 | /* Let svc, abort and undefined modes use irq stack */ | ||
286 | msr cpsr_c, #0xd3 /* IRQ/FIQ disabled */ | ||
287 | ldr sp, =irq_stack | ||
288 | msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */ | ||
289 | ldr sp, =irq_stack | ||
290 | msr cpsr_c, #0xdb /* IRQ/FIQ disabled */ | ||
291 | ldr sp, =irq_stack | ||
292 | |||
293 | /* Switch to sys mode */ | ||
294 | msr cpsr_c, #0xdf | ||
295 | |||
296 | /* Set up some stack and munge it with 0xdeadbeef */ | ||
297 | ldr r2, =stackbegin | ||
298 | ldr sp, =stackend | ||
299 | 1: | ||
300 | cmp sp, r2 | ||
301 | strhi r4, [r2], #4 | ||
302 | bhi 1b | ||
303 | |||
304 | /* Delay waking the COP until thread initialization is complete unless dual-core | ||
305 | support is not enabled in which case the cop_main function does not perform | ||
306 | any kernel or thread initialization. It's just a trivial sleep loop. */ | ||
307 | #if NUM_CORES == 1 | ||
308 | ldr r4, =COP_CTRL | ||
309 | mov r3, #WAKE | ||
310 | str r3, [r4] | ||
311 | #endif | ||
312 | |||
313 | ldr pc, =main | ||
314 | /* main() should never return */ | ||
315 | |||
316 | cop_init: | ||
317 | #if NUM_CORES > 1 | ||
318 | /* Wait for CPU to go to sleep at the end of its kernel init */ | ||
319 | ldr r4, =CPU_STATUS | ||
320 | 1: | ||
321 | ldr r3, [r4] | ||
322 | tst r3, #CPUSLEEPING | ||
323 | beq 1b | ||
324 | #endif | ||
325 | |||
326 | /* Set up stack for IRQ mode */ | ||
327 | msr cpsr_c, #0x92 /* IRQ disabled, FIQ enabled */ | ||
328 | ldr sp, =cop_irq_stack | ||
329 | /* Set up stack for FIQ mode */ | ||
330 | msr cpsr_c, #0xd1 /* IRQ/FIQ disabled */ | ||
331 | ldr sp, =cop_fiq_stack | ||
332 | |||
333 | /* Let svc, abort and undefined modes use irq stack */ | ||
334 | msr cpsr_c, #0xd3 /* IRQ/FIQ disabled */ | ||
335 | ldr sp, =cop_irq_stack | ||
336 | msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */ | ||
337 | ldr sp, =cop_irq_stack | ||
338 | msr cpsr_c, #0xdb /* IRQ/FIQ disabled */ | ||
339 | ldr sp, =cop_irq_stack | ||
340 | |||
341 | /* Switch to sys mode */ | ||
342 | msr cpsr_c, #0xdf | ||
343 | |||
344 | /* Set up idle stack for COP and munge it with 0xdeadbeef */ | ||
345 | ldr sp, =cop_idlestackend | ||
346 | ldr r2, =cop_idlestackbegin | ||
347 | ldr r4, =0xdeadbeef | ||
348 | 2: | ||
349 | cmp sp, r2 | ||
350 | strhi r4, [r2], #4 | ||
351 | bhi 2b | ||
352 | |||
353 | /* Run cop_main() in apps/main.c */ | ||
354 | ldr pc, =cop_main | ||
355 | |||
356 | /* Exception handlers. Will be copied to address 0 after memory remapping */ | ||
357 | .section .vectors,"aw" | ||
358 | ldr pc, [pc, #24] | ||
359 | ldr pc, [pc, #24] | ||
360 | ldr pc, [pc, #24] | ||
361 | ldr pc, [pc, #24] | ||
362 | ldr pc, [pc, #24] | ||
363 | ldr pc, [pc, #24] | ||
364 | ldr pc, [pc, #24] | ||
365 | ldr pc, [pc, #24] | ||
366 | |||
367 | /* Exception vectors */ | ||
368 | .global vectors | ||
369 | vectors: | ||
370 | .word start | ||
371 | .word undef_instr_handler | ||
372 | .word software_int_handler | ||
373 | .word prefetch_abort_handler | ||
374 | .word data_abort_handler | ||
375 | .word reserved_handler | ||
376 | .word irq_handler | ||
377 | .word fiq_handler | ||
378 | |||
379 | .text | ||
380 | |||
381 | /* All illegal exceptions call into UIE with exception address as first | ||
382 | parameter. This is calculated differently depending on which exception | ||
383 | we're in. Second parameter is exception number, used for a string lookup | ||
384 | in UIE. | ||
385 | */ | ||
386 | undef_instr_handler: | ||
387 | sub r0, lr, #4 | ||
388 | mov r1, #0 | ||
389 | b UIE | ||
390 | |||
391 | /* We run sys mode most of the time, and should never see a software | ||
392 | exception being thrown. Make it illegal and call UIE. | ||
393 | */ | ||
394 | software_int_handler: | ||
395 | reserved_handler: | ||
396 | sub r0, lr, #4 | ||
397 | mov r1, #4 | ||
398 | b UIE | ||
399 | |||
400 | prefetch_abort_handler: | ||
401 | sub r0, lr, #4 | ||
402 | mov r1, #1 | ||
403 | b UIE | ||
404 | |||
405 | data_abort_handler: | ||
406 | sub r0, lr, #8 | ||
407 | mov r1, #2 | ||
408 | b UIE | ||
409 | |||
410 | /* Align stacks to cache line boundary */ | ||
411 | .balign 32 | ||
412 | |||
413 | /* 256 words of IRQ stack */ | ||
414 | .space 256*4 | ||
415 | irq_stack: | ||
416 | |||
417 | /* 256 words of COP IRQ stack */ | ||
418 | .space 256*4 | ||
419 | cop_irq_stack: | ||
420 | |||
421 | /* 256 words of FIQ stack */ | ||
422 | .space 256*4 | ||
423 | fiq_stack: | ||
424 | |||
425 | /* We'll need this soon - just reserve the symbol */ | ||
426 | #if 0 | ||
427 | /* 256 words of COP FIQ stack */ | ||
428 | .space 256*4 | ||
429 | #endif | ||
430 | cop_fiq_stack: | ||