diff options
Diffstat (limited to 'firmware/target/arm/pp/crt0-pp502x-bl-usb.S')
-rw-r--r-- | firmware/target/arm/pp/crt0-pp502x-bl-usb.S | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/firmware/target/arm/pp/crt0-pp502x-bl-usb.S b/firmware/target/arm/pp/crt0-pp502x-bl-usb.S new file mode 100644 index 0000000000..7b0489b2a8 --- /dev/null +++ b/firmware/target/arm/pp/crt0-pp502x-bl-usb.S | |||
@@ -0,0 +1,367 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Linus Nielsen Feltzing | ||
11 | * Copyright (C) 2010 by Michael Sevakis | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #include "config.h" | ||
23 | #include "cpu.h" | ||
24 | |||
25 | /* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux | ||
26 | * loader | ||
27 | * | ||
28 | * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org) | ||
29 | * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org> | ||
30 | * | ||
31 | */ | ||
32 | .equ PROC_ID, 0x60000000 | ||
33 | .equ CPU_IDIS, 0x60004028 | ||
34 | .equ CPU_CTRL, 0x60007000 | ||
35 | .equ CPU_STATUS, 0x60007000 | ||
36 | .equ COP_IDIS, 0x60004038 | ||
37 | .equ COP_CTRL, 0x60007004 | ||
38 | .equ COP_STATUS, 0x60007004 | ||
39 | .equ CPU_SLEEPING,0x80000000 | ||
40 | .equ COP_SLEEPING,0x80000000 | ||
41 | .equ SLEEP, 0x80000000 | ||
42 | .equ WAKE, 0x00000000 | ||
43 | .equ MMAP_LOG, 0xf000f000 /* MMAP0 */ | ||
44 | .equ MMAP_PHYS, 0xf000f004 | ||
45 | .equ INT_VECT_TBL,0x6000f100 | ||
46 | .equ CACHE_CTRL, 0x6000c000 | ||
47 | .equ CACHE_ENAB, 0x1 | ||
48 | .equ CACHE_OP_COMMIT_DISCARD, 0x1 | ||
49 | .equ CACHE_OP_COMMIT , 0x0 | ||
50 | #if MEMORYSIZE > 32 | ||
51 | .equ MMAP_MASK, 0x00003c00 | ||
52 | #else | ||
53 | .equ MMAP_MASK, 0x00003e00 | ||
54 | #endif | ||
55 | .equ MMAP_FLAGS, 0x00000f84 | ||
56 | |||
57 | /* | ||
58 | * Entry point | ||
59 | */ | ||
60 | .section .init.text,"ax",%progbits | ||
61 | .global start | ||
62 | start: | ||
63 | b newstart | ||
64 | |||
65 | #ifdef IPOD_ARCH | ||
66 | .align 8 /* starts at 0x100 */ | ||
67 | .global boot_table | ||
68 | boot_table: | ||
69 | /* here comes the boot table, don't move its offset - preceding | ||
70 | code+data must stay <= 256 bytes */ | ||
71 | .space 400 | ||
72 | #else /* !IPOD_ARCH */ | ||
73 | /* (more than enough) space for exception vectors and mi4 magic */ | ||
74 | .space 68*4 | ||
75 | #endif /* IPOD_ARCH */ | ||
76 | |||
77 | newstart: | ||
78 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ | ||
79 | adr r4, start /* cache initial load address */ | ||
80 | |||
81 | /* Copy startup stub to IRAM since we need to both move the bootloader's | ||
82 | * location, which could overlap itself, and setup the memory mapper. */ | ||
83 | adr r0, start_stub_begin | ||
84 | mov r1, #0x40000000 | ||
85 | adr r2, start_stub_end | ||
86 | 1: | ||
87 | ldr r3, [r0], #4 | ||
88 | str r3, [r1], #4 | ||
89 | cmp r0, r2 | ||
90 | blo 1b | ||
91 | mov pc, #0x40000000 | ||
92 | |||
93 | start_stub_begin: | ||
94 | ldr r0, =PROC_ID | ||
95 | ldrb r0, [r0] | ||
96 | cmp r0, #0x55 | ||
97 | beq cpu | ||
98 | |||
99 | cop: | ||
100 | mov r0, #CACHE_OP_COMMIT_DISCARD | ||
101 | bl cache_operation | ||
102 | |||
103 | ldr r1, =COP_CTRL | ||
104 | mov r0, #SLEEP | ||
105 | |||
106 | /* sleep us (co-processor) while bootloader is copied */ | ||
107 | str r0, [r1] | ||
108 | nop | ||
109 | nop | ||
110 | nop | ||
111 | |||
112 | /* branch to final physical load address */ | ||
113 | ldr r2, =1f | ||
114 | and r4, r4, #0xfc000000 | ||
115 | add pc, r2, r4 | ||
116 | 1: | ||
117 | /* wait for bootloader to finish */ | ||
118 | str r0, [r1] | ||
119 | nop | ||
120 | nop | ||
121 | nop | ||
122 | |||
123 | /* branch to the address returned by main() */ | ||
124 | adr r0, startup_loc | ||
125 | ldr pc, [r0] | ||
126 | |||
127 | cpu: | ||
128 | /* wait for COP to sleep */ | ||
129 | ldr r1, =COP_STATUS | ||
130 | 1: | ||
131 | ldr r0, [r1] | ||
132 | tst r0, #COP_SLEEPING | ||
133 | beq 1b | ||
134 | |||
135 | mov r0, #CACHE_OP_COMMIT_DISCARD | ||
136 | bl cache_operation | ||
137 | |||
138 | /* move bootloader to the correct load address if needed */ | ||
139 | ldr r1, =_loadaddress | ||
140 | cmp r4, r1 | ||
141 | ldrne r2, =_loadaddressend | ||
142 | movne r0, r4 | ||
143 | sublo r3, r2, r1 /* size */ | ||
144 | addlo r0, r0, r3 /* initial load end addr */ | ||
145 | 1: /* lower to higher move - copy up */ | ||
146 | cmphi r2, r1 | ||
147 | ldrhi r3, [r0], #4 | ||
148 | strhi r3, [r1], #4 | ||
149 | bhi 1b | ||
150 | 1: /* higher to lower move - copy down */ | ||
151 | cmplo r1, r2 | ||
152 | ldrlo r3, [r0, #-4]! | ||
153 | strlo r3, [r2, #-4]! | ||
154 | blo 1b | ||
155 | |||
156 | mov r0, #CACHE_OP_COMMIT | ||
157 | bl cache_operation | ||
158 | |||
159 | and r4, r4, #0xfc000000 | ||
160 | |||
161 | ldr r0, =MMAP_FLAGS | ||
162 | orr r0, r0, r4 /* adjust for execute address */ | ||
163 | ldr r1, =MMAP_MASK | ||
164 | ldr r2, =MMAP_LOG | ||
165 | ldr r3, =MMAP_PHYS | ||
166 | str r1, [r2] /* MMAP_LOG = MMAP_MASK */ | ||
167 | str r0, [r3] /* MMAP_PHYS = MMAP_FLAGS | SDRAM base addr */ | ||
168 | |||
169 | /* wake the COP to jump it to the correct place */ | ||
170 | ldr r1, =COP_CTRL | ||
171 | mov r0, #WAKE | ||
172 | str r0, [r1] | ||
173 | |||
174 | /* wait for COP to halt then loading may proceed */ | ||
175 | ldr r1, =COP_STATUS | ||
176 | 1: | ||
177 | ldr r0, [r1] | ||
178 | tst r0, #COP_SLEEPING | ||
179 | beq 1b | ||
180 | |||
181 | ldr r0, =start_stub_end | ||
182 | add pc, r0, r4 | ||
183 | |||
184 | cache_operation: /* (bool commit_discard) */ | ||
185 | ldr r2, =CACHE_CTRL | ||
186 | ldr r1, [r2] | ||
187 | tst r1, #CACHE_ENAB | ||
188 | bxeq lr | ||
189 | cmp r0, #CACHE_OP_COMMIT | ||
190 | ldr r0, =0xf000f044 | ||
191 | ldr r1, [r0] | ||
192 | orrne r1, r1, #0x6 | ||
193 | orreq r1, r1, #0x2 | ||
194 | str r1, [r0] | ||
195 | 1: | ||
196 | ldr r1, [r2] | ||
197 | tst r1, #0x8000 | ||
198 | bne 1b | ||
199 | bx lr | ||
200 | .ltorg /* constants used in stub come with us to IRAM */ | ||
201 | start_stub_end: | ||
202 | /* now executing from final physical address */ | ||
203 | |||
204 | /* copy the vector addresses to the table */ | ||
205 | ldr r0, =INT_VECT_TBL | ||
206 | adr r1, vectorsstart | ||
207 | adr r2, vectorsend | ||
208 | 1: | ||
209 | cmp r2, r1 | ||
210 | ldrhi r3, [r1], #4 | ||
211 | strhi r3, [r0], #4 | ||
212 | bhi 1b | ||
213 | |||
214 | /* Copy the IRAM */ | ||
215 | ldr r0, =_iramcopy | ||
216 | ldr r1, =_iramstart | ||
217 | ldr r2, =_iramend | ||
218 | 1: | ||
219 | cmp r2, r1 | ||
220 | ldrhi r3, [r0], #4 | ||
221 | strhi r3, [r1], #4 | ||
222 | bhi 1b | ||
223 | |||
224 | mov r0, #0 | ||
225 | |||
226 | /* Zero out IBSS */ | ||
227 | ldr r1, =_iedata | ||
228 | ldr r2, =_iend | ||
229 | 1: | ||
230 | cmp r2, r1 | ||
231 | strhi r0, [r1], #4 | ||
232 | bhi 1b | ||
233 | |||
234 | /* Initialise bss/ncbss sections to zero */ | ||
235 | ldr r1, =_edata | ||
236 | ldr r2, =_end | ||
237 | 1: | ||
238 | cmp r2, r1 | ||
239 | strhi r0, [r1], #4 | ||
240 | bhi 1b | ||
241 | |||
242 | /* Set up stack for IRQ mode */ | ||
243 | msr cpsr_c, #0xd2 /* IRQ/FIQ disabled */ | ||
244 | ldr sp, =irq_stack | ||
245 | /* Let svc, abort and undefined modes use irq stack */ | ||
246 | msr cpsr_c, #0xd3 | ||
247 | ldr sp, =irq_stack | ||
248 | msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */ | ||
249 | ldr sp, =irq_stack | ||
250 | msr cpsr_c, #0xdb /* IRQ/FIQ disabled */ | ||
251 | ldr sp, =irq_stack | ||
252 | |||
253 | /* Switch back to sys mode */ | ||
254 | msr cpsr_c, #0xdf | ||
255 | |||
256 | /* Set up some stack and munge it with 0xdeadbeef */ | ||
257 | ldr r0, =0xdeadbeef | ||
258 | ldr r1, =stackbegin | ||
259 | ldr sp, =stackend | ||
260 | 1: | ||
261 | cmp sp, r1 | ||
262 | strhi r0, [r1], #4 | ||
263 | bhi 1b | ||
264 | |||
265 | /* execute the loader - this will load an image to 0x10000000 */ | ||
266 | ldr r0, =main | ||
267 | mov lr, pc | ||
268 | bx r0 | ||
269 | |||
270 | /* store actual startup location returned by main() */ | ||
271 | ldr r1, =startup_loc | ||
272 | str r0, [r1] | ||
273 | |||
274 | /* write back anything loaded + startup_loc */ | ||
275 | mov r0, #CACHE_OP_COMMIT | ||
276 | bl cache_operation | ||
277 | |||
278 | mov r0, #0 | ||
279 | |||
280 | /* disable memory mapper */ | ||
281 | ldr r1, =MMAP_LOG | ||
282 | ldr r2, =MMAP_PHYS | ||
283 | str r0, [r1] | ||
284 | str r0, [r2] | ||
285 | |||
286 | /* bring COP back to life */ | ||
287 | ldr r1, =COP_CTRL | ||
288 | mov r0, #WAKE | ||
289 | str r0, [r1] | ||
290 | |||
291 | /* after this point, r0-r3 are reserved for OF magic */ | ||
292 | |||
293 | #if defined(SANSA_C200) || defined(PHILIPS_HDD1630) | ||
294 | /* Magic for loading the c200 OF */ | ||
295 | ldr r0, =0xb00d10ad | ||
296 | mov r1, #0x700 | ||
297 | ldr r2, =0xfff0 | ||
298 | mov r3, #0x7 | ||
299 | #endif | ||
300 | |||
301 | #if defined(PHILIPS_HDD6330) | ||
302 | /* Magic for loading the HDD6XX0 OF */ | ||
303 | ldr r0, =0xb00d10ad | ||
304 | mov r1, #0x800 | ||
305 | ldr r2, =0xfff0 | ||
306 | mov r3, #0x7 | ||
307 | #endif | ||
308 | |||
309 | /* branch to the address returned by main() */ | ||
310 | adr r4, startup_loc | ||
311 | ldr pc, [r4] | ||
312 | |||
313 | startup_loc: | ||
314 | .word 0x00000000 | ||
315 | |||
316 | /* exception handlers: will be copied to local vector table */ | ||
317 | vectorsstart: | ||
318 | .word newstart | ||
319 | .word undef_instr_handler | ||
320 | .word software_int_handler | ||
321 | .word prefetch_abort_handler | ||
322 | .word data_abort_handler | ||
323 | .word reserved_handler | ||
324 | .word irq_handler | ||
325 | .word fiq_handler | ||
326 | vectorsend: | ||
327 | |||
328 | .text | ||
329 | |||
330 | /* All illegal exceptions call into UIE with exception address as first | ||
331 | parameter. This is calculated differently depending on which exception | ||
332 | we're in. Second parameter is exception number, used for a string lookup | ||
333 | in UIE. | ||
334 | */ | ||
335 | undef_instr_handler: | ||
336 | sub r0, lr, #4 | ||
337 | mov r1, #0 | ||
338 | b UIE | ||
339 | |||
340 | /* We run sys mode most of the time, and should never see a software | ||
341 | exception being thrown. Make it illegal and call UIE. | ||
342 | */ | ||
343 | software_int_handler: | ||
344 | reserved_handler: | ||
345 | sub r0, lr, #4 | ||
346 | mov r1, #4 | ||
347 | b UIE | ||
348 | |||
349 | prefetch_abort_handler: | ||
350 | sub r0, lr, #4 | ||
351 | mov r1, #1 | ||
352 | b UIE | ||
353 | |||
354 | data_abort_handler: | ||
355 | sub r0, lr, #8 | ||
356 | mov r1, #2 | ||
357 | b UIE | ||
358 | |||
359 | /* should never happen in the bootloader */ | ||
360 | fiq_handler: | ||
361 | subs pc, lr, #4 | ||
362 | |||
363 | /* 256 words of IRQ stack */ | ||
364 | .section .bss | ||
365 | .balign 16 | ||
366 | .space 256*4 | ||
367 | irq_stack: | ||