diff options
Diffstat (limited to 'arch/arm/boot/compressed/head.S')
-rw-r--r-- | arch/arm/boot/compressed/head.S | 786 |
1 files changed, 786 insertions, 0 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S new file mode 100644 index 00000000000..c0e7aff3dec --- /dev/null +++ b/arch/arm/boot/compressed/head.S | |||
@@ -0,0 +1,786 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head.S | ||
3 | * | ||
4 | * Copyright (C) 1996-2002 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/config.h> | ||
11 | #include <linux/linkage.h> | ||
12 | |||
13 | /* | ||
14 | * Debugging stuff | ||
15 | * | ||
16 | * Note that these macros must not contain any code which is not | ||
17 | * 100% relocatable. Any attempt to do so will result in a crash. | ||
18 | * Please select one of the following when turning on debugging. | ||
19 | */ | ||
20 | #ifdef DEBUG | ||
21 | #if defined(CONFIG_DEBUG_DC21285_PORT) | ||
22 | .macro loadsp, rb | ||
23 | mov \rb, #0x42000000 | ||
24 | .endm | ||
25 | .macro writeb, rb | ||
26 | str \rb, [r3, #0x160] | ||
27 | .endm | ||
28 | #elif defined(CONFIG_DEBUG_ICEDCC) | ||
29 | .macro loadsp, rb | ||
30 | .endm | ||
31 | .macro writeb, rb | ||
32 | mcr p14, 0, \rb, c0, c1, 0 | ||
33 | .endm | ||
34 | #elif defined(CONFIG_FOOTBRIDGE) | ||
35 | .macro loadsp, rb | ||
36 | mov \rb, #0x7c000000 | ||
37 | .endm | ||
38 | .macro writeb, rb | ||
39 | strb \rb, [r3, #0x3f8] | ||
40 | .endm | ||
41 | #elif defined(CONFIG_ARCH_RPC) | ||
42 | .macro loadsp, rb | ||
43 | mov \rb, #0x03000000 | ||
44 | orr \rb, \rb, #0x00010000 | ||
45 | .endm | ||
46 | .macro writeb, rb | ||
47 | strb \rb, [r3, #0x3f8 << 2] | ||
48 | .endm | ||
49 | #elif defined(CONFIG_ARCH_INTEGRATOR) | ||
50 | .macro loadsp, rb | ||
51 | mov \rb, #0x16000000 | ||
52 | .endm | ||
53 | .macro writeb, rb | ||
54 | strb \rb, [r3, #0] | ||
55 | .endm | ||
56 | #elif defined(CONFIG_ARCH_PXA) /* Xscale-type */ | ||
57 | .macro loadsp, rb | ||
58 | mov \rb, #0x40000000 | ||
59 | orr \rb, \rb, #0x00100000 | ||
60 | .endm | ||
61 | .macro writeb, rb | ||
62 | strb \rb, [r3, #0] | ||
63 | .endm | ||
64 | #elif defined(CONFIG_ARCH_SA1100) | ||
65 | .macro loadsp, rb | ||
66 | mov \rb, #0x80000000 @ physical base address | ||
67 | # if defined(CONFIG_DEBUG_LL_SER3) | ||
68 | add \rb, \rb, #0x00050000 @ Ser3 | ||
69 | # else | ||
70 | add \rb, \rb, #0x00010000 @ Ser1 | ||
71 | # endif | ||
72 | .endm | ||
73 | .macro writeb, rb | ||
74 | str \rb, [r3, #0x14] @ UTDR | ||
75 | .endm | ||
76 | #elif defined(CONFIG_ARCH_IXP4XX) | ||
77 | .macro loadsp, rb | ||
78 | mov \rb, #0xc8000000 | ||
79 | .endm | ||
80 | .macro writeb, rb | ||
81 | str \rb, [r3, #0] | ||
82 | #elif defined(CONFIG_ARCH_IXP2000) | ||
83 | .macro loadsp, rb | ||
84 | mov \rb, #0xc0000000 | ||
85 | orr \rb, \rb, #0x00030000 | ||
86 | .endm | ||
87 | .macro writeb, rb | ||
88 | str \rb, [r3, #0] | ||
89 | .endm | ||
90 | #elif defined(CONFIG_ARCH_LH7A40X) | ||
91 | .macro loadsp, rb | ||
92 | ldr \rb, =0x80000700 @ UART2 UARTBASE | ||
93 | .endm | ||
94 | .macro writeb, rb | ||
95 | strb \rb, [r3, #0] | ||
96 | .endm | ||
97 | #elif defined(CONFIG_ARCH_OMAP) | ||
98 | .macro loadsp, rb | ||
99 | mov \rb, #0xff000000 @ physical base address | ||
100 | add \rb, \rb, #0x00fb0000 | ||
101 | #if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) | ||
102 | add \rb, \rb, #0x00000800 | ||
103 | #endif | ||
104 | #ifdef CONFIG_OMAP_LL_DEBUG_UART3 | ||
105 | add \rb, \rb, #0x00009000 | ||
106 | #endif | ||
107 | .endm | ||
108 | .macro writeb, rb | ||
109 | strb \rb, [r3] | ||
110 | .endm | ||
111 | #elif defined(CONFIG_ARCH_IOP331) | ||
112 | .macro loadsp, rb | ||
113 | mov \rb, #0xff000000 | ||
114 | orr \rb, \rb, #0x00ff0000 | ||
115 | orr \rb, \rb, #0x0000f700 @ location of the UART | ||
116 | .endm | ||
117 | .macro writeb, rb | ||
118 | str \rb, [r3, #0] | ||
119 | .endm | ||
120 | #elif defined(CONFIG_ARCH_S3C2410) | ||
121 | .macro loadsp, rb | ||
122 | mov \rb, #0x50000000 | ||
123 | add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT | ||
124 | .endm | ||
125 | .macro writeb, rb | ||
126 | strb \rb, [r3, #0x20] | ||
127 | .endm | ||
128 | #else | ||
129 | #error no serial architecture defined | ||
130 | #endif | ||
131 | #endif | ||
132 | |||
133 | .macro kputc,val | ||
134 | mov r0, \val | ||
135 | bl putc | ||
136 | .endm | ||
137 | |||
138 | .macro kphex,val,len | ||
139 | mov r0, \val | ||
140 | mov r1, #\len | ||
141 | bl phex | ||
142 | .endm | ||
143 | |||
144 | .macro debug_reloc_start | ||
145 | #ifdef DEBUG | ||
146 | kputc #'\n' | ||
147 | kphex r6, 8 /* processor id */ | ||
148 | kputc #':' | ||
149 | kphex r7, 8 /* architecture id */ | ||
150 | kputc #':' | ||
151 | mrc p15, 0, r0, c1, c0 | ||
152 | kphex r0, 8 /* control reg */ | ||
153 | kputc #'\n' | ||
154 | kphex r5, 8 /* decompressed kernel start */ | ||
155 | kputc #'-' | ||
156 | kphex r8, 8 /* decompressed kernel end */ | ||
157 | kputc #'>' | ||
158 | kphex r4, 8 /* kernel execution address */ | ||
159 | kputc #'\n' | ||
160 | #endif | ||
161 | .endm | ||
162 | |||
163 | .macro debug_reloc_end | ||
164 | #ifdef DEBUG | ||
165 | kphex r5, 8 /* end of kernel */ | ||
166 | kputc #'\n' | ||
167 | mov r0, r4 | ||
168 | bl memdump /* dump 256 bytes at start of kernel */ | ||
169 | #endif | ||
170 | .endm | ||
171 | |||
172 | .section ".start", #alloc, #execinstr | ||
173 | /* | ||
174 | * sort out different calling conventions | ||
175 | */ | ||
176 | .align | ||
177 | start: | ||
178 | .type start,#function | ||
179 | .rept 8 | ||
180 | mov r0, r0 | ||
181 | .endr | ||
182 | |||
183 | b 1f | ||
184 | .word 0x016f2818 @ Magic numbers to help the loader | ||
185 | .word start @ absolute load/run zImage address | ||
186 | .word _edata @ zImage end address | ||
187 | 1: mov r7, r1 @ save architecture ID | ||
188 | mov r8, #0 @ save r0 | ||
189 | |||
190 | #ifndef __ARM_ARCH_2__ | ||
191 | /* | ||
192 | * Booting from Angel - need to enter SVC mode and disable | ||
193 | * FIQs/IRQs (numeric definitions from angel arm.h source). | ||
194 | * We only do this if we were in user mode on entry. | ||
195 | */ | ||
196 | mrs r2, cpsr @ get current mode | ||
197 | tst r2, #3 @ not user? | ||
198 | bne not_angel | ||
199 | mov r0, #0x17 @ angel_SWIreason_EnterSVC | ||
200 | swi 0x123456 @ angel_SWI_ARM | ||
201 | not_angel: | ||
202 | mrs r2, cpsr @ turn off interrupts to | ||
203 | orr r2, r2, #0xc0 @ prevent angel from running | ||
204 | msr cpsr_c, r2 | ||
205 | #else | ||
206 | teqp pc, #0x0c000003 @ turn off interrupts | ||
207 | #endif | ||
208 | |||
209 | /* | ||
210 | * Note that some cache flushing and other stuff may | ||
211 | * be needed here - is there an Angel SWI call for this? | ||
212 | */ | ||
213 | |||
214 | /* | ||
215 | * some architecture specific code can be inserted | ||
216 | * by the linker here, but it should preserve r7 and r8. | ||
217 | */ | ||
218 | |||
219 | .text | ||
220 | adr r0, LC0 | ||
221 | ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} | ||
222 | subs r0, r0, r1 @ calculate the delta offset | ||
223 | |||
224 | @ if delta is zero, we are | ||
225 | beq not_relocated @ running at the address we | ||
226 | @ were linked at. | ||
227 | |||
228 | /* | ||
229 | * We're running at a different address. We need to fix | ||
230 | * up various pointers: | ||
231 | * r5 - zImage base address | ||
232 | * r6 - GOT start | ||
233 | * ip - GOT end | ||
234 | */ | ||
235 | add r5, r5, r0 | ||
236 | add r6, r6, r0 | ||
237 | add ip, ip, r0 | ||
238 | |||
239 | #ifndef CONFIG_ZBOOT_ROM | ||
240 | /* | ||
241 | * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, | ||
242 | * we need to fix up pointers into the BSS region. | ||
243 | * r2 - BSS start | ||
244 | * r3 - BSS end | ||
245 | * sp - stack pointer | ||
246 | */ | ||
247 | add r2, r2, r0 | ||
248 | add r3, r3, r0 | ||
249 | add sp, sp, r0 | ||
250 | |||
251 | /* | ||
252 | * Relocate all entries in the GOT table. | ||
253 | */ | ||
254 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | ||
255 | add r1, r1, r0 @ table. This fixes up the | ||
256 | str r1, [r6], #4 @ C references. | ||
257 | cmp r6, ip | ||
258 | blo 1b | ||
259 | #else | ||
260 | |||
261 | /* | ||
262 | * Relocate entries in the GOT table. We only relocate | ||
263 | * the entries that are outside the (relocated) BSS region. | ||
264 | */ | ||
265 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | ||
266 | cmp r1, r2 @ entry < bss_start || | ||
267 | cmphs r3, r1 @ _end < entry | ||
268 | addlo r1, r1, r0 @ table. This fixes up the | ||
269 | str r1, [r6], #4 @ C references. | ||
270 | cmp r6, ip | ||
271 | blo 1b | ||
272 | #endif | ||
273 | |||
274 | not_relocated: mov r0, #0 | ||
275 | 1: str r0, [r2], #4 @ clear bss | ||
276 | str r0, [r2], #4 | ||
277 | str r0, [r2], #4 | ||
278 | str r0, [r2], #4 | ||
279 | cmp r2, r3 | ||
280 | blo 1b | ||
281 | |||
282 | /* | ||
283 | * The C runtime environment should now be setup | ||
284 | * sufficiently. Turn the cache on, set up some | ||
285 | * pointers, and start decompressing. | ||
286 | */ | ||
287 | bl cache_on | ||
288 | |||
289 | mov r1, sp @ malloc space above stack | ||
290 | add r2, sp, #0x10000 @ 64k max | ||
291 | |||
292 | /* | ||
293 | * Check to see if we will overwrite ourselves. | ||
294 | * r4 = final kernel address | ||
295 | * r5 = start of this image | ||
296 | * r2 = end of malloc space (and therefore this image) | ||
297 | * We basically want: | ||
298 | * r4 >= r2 -> OK | ||
299 | * r4 + image length <= r5 -> OK | ||
300 | */ | ||
301 | cmp r4, r2 | ||
302 | bhs wont_overwrite | ||
303 | add r0, r4, #4096*1024 @ 4MB largest kernel size | ||
304 | cmp r0, r5 | ||
305 | bls wont_overwrite | ||
306 | |||
307 | mov r5, r2 @ decompress after malloc space | ||
308 | mov r0, r5 | ||
309 | mov r3, r7 | ||
310 | bl decompress_kernel | ||
311 | |||
312 | add r0, r0, #127 | ||
313 | bic r0, r0, #127 @ align the kernel length | ||
314 | /* | ||
315 | * r0 = decompressed kernel length | ||
316 | * r1-r3 = unused | ||
317 | * r4 = kernel execution address | ||
318 | * r5 = decompressed kernel start | ||
319 | * r6 = processor ID | ||
320 | * r7 = architecture ID | ||
321 | * r8-r14 = unused | ||
322 | */ | ||
323 | add r1, r5, r0 @ end of decompressed kernel | ||
324 | adr r2, reloc_start | ||
325 | ldr r3, LC1 | ||
326 | add r3, r2, r3 | ||
327 | 1: ldmia r2!, {r8 - r13} @ copy relocation code | ||
328 | stmia r1!, {r8 - r13} | ||
329 | ldmia r2!, {r8 - r13} | ||
330 | stmia r1!, {r8 - r13} | ||
331 | cmp r2, r3 | ||
332 | blo 1b | ||
333 | |||
334 | bl cache_clean_flush | ||
335 | add pc, r5, r0 @ call relocation code | ||
336 | |||
337 | /* | ||
338 | * We're not in danger of overwriting ourselves. Do this the simple way. | ||
339 | * | ||
340 | * r4 = kernel execution address | ||
341 | * r7 = architecture ID | ||
342 | */ | ||
343 | wont_overwrite: mov r0, r4 | ||
344 | mov r3, r7 | ||
345 | bl decompress_kernel | ||
346 | b call_kernel | ||
347 | |||
348 | .type LC0, #object | ||
349 | LC0: .word LC0 @ r1 | ||
350 | .word __bss_start @ r2 | ||
351 | .word _end @ r3 | ||
352 | .word zreladdr @ r4 | ||
353 | .word _start @ r5 | ||
354 | .word _got_start @ r6 | ||
355 | .word _got_end @ ip | ||
356 | .word user_stack+4096 @ sp | ||
357 | LC1: .word reloc_end - reloc_start | ||
358 | .size LC0, . - LC0 | ||
359 | |||
360 | #ifdef CONFIG_ARCH_RPC | ||
361 | .globl params | ||
362 | params: ldr r0, =params_phys | ||
363 | mov pc, lr | ||
364 | .ltorg | ||
365 | .align | ||
366 | #endif | ||
367 | |||
368 | /* | ||
369 | * Turn on the cache. We need to setup some page tables so that we | ||
370 | * can have both the I and D caches on. | ||
371 | * | ||
372 | * We place the page tables 16k down from the kernel execution address, | ||
373 | * and we hope that nothing else is using it. If we're using it, we | ||
374 | * will go pop! | ||
375 | * | ||
376 | * On entry, | ||
377 | * r4 = kernel execution address | ||
378 | * r6 = processor ID | ||
379 | * r7 = architecture number | ||
380 | * r8 = run-time address of "start" | ||
381 | * On exit, | ||
382 | * r1, r2, r3, r8, r9, r12 corrupted | ||
383 | * This routine must preserve: | ||
384 | * r4, r5, r6, r7 | ||
385 | */ | ||
386 | .align 5 | ||
387 | cache_on: mov r3, #8 @ cache_on function | ||
388 | b call_cache_fn | ||
389 | |||
390 | __setup_mmu: sub r3, r4, #16384 @ Page directory size | ||
391 | bic r3, r3, #0xff @ Align the pointer | ||
392 | bic r3, r3, #0x3f00 | ||
393 | /* | ||
394 | * Initialise the page tables, turning on the cacheable and bufferable | ||
395 | * bits for the RAM area only. | ||
396 | */ | ||
397 | mov r0, r3 | ||
398 | mov r8, r0, lsr #18 | ||
399 | mov r8, r8, lsl #18 @ start of RAM | ||
400 | add r9, r8, #0x10000000 @ a reasonable RAM size | ||
401 | mov r1, #0x12 | ||
402 | orr r1, r1, #3 << 10 | ||
403 | add r2, r3, #16384 | ||
404 | 1: cmp r1, r8 @ if virt > start of RAM | ||
405 | orrhs r1, r1, #0x0c @ set cacheable, bufferable | ||
406 | cmp r1, r9 @ if virt > end of RAM | ||
407 | bichs r1, r1, #0x0c @ clear cacheable, bufferable | ||
408 | str r1, [r0], #4 @ 1:1 mapping | ||
409 | add r1, r1, #1048576 | ||
410 | teq r0, r2 | ||
411 | bne 1b | ||
412 | /* | ||
413 | * If ever we are running from Flash, then we surely want the cache | ||
414 | * to be enabled also for our execution instance... We map 2MB of it | ||
415 | * so there is no map overlap problem for up to 1 MB compressed kernel. | ||
416 | * If the execution is in RAM then we would only be duplicating the above. | ||
417 | */ | ||
418 | mov r1, #0x1e | ||
419 | orr r1, r1, #3 << 10 | ||
420 | mov r2, pc, lsr #20 | ||
421 | orr r1, r1, r2, lsl #20 | ||
422 | add r0, r3, r2, lsl #2 | ||
423 | str r1, [r0], #4 | ||
424 | add r1, r1, #1048576 | ||
425 | str r1, [r0] | ||
426 | mov pc, lr | ||
427 | |||
428 | __armv4_cache_on: | ||
429 | mov r12, lr | ||
430 | bl __setup_mmu | ||
431 | mov r0, #0 | ||
432 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
433 | mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs | ||
434 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
435 | orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement | ||
436 | orr r0, r0, #0x0030 | ||
437 | bl __common_cache_on | ||
438 | mov r0, #0 | ||
439 | mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs | ||
440 | mov pc, r12 | ||
441 | |||
442 | __arm6_cache_on: | ||
443 | mov r12, lr | ||
444 | bl __setup_mmu | ||
445 | mov r0, #0 | ||
446 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
447 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
448 | mov r0, #0x30 | ||
449 | bl __common_cache_on | ||
450 | mov r0, #0 | ||
451 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
452 | mov pc, r12 | ||
453 | |||
454 | __common_cache_on: | ||
455 | #ifndef DEBUG | ||
456 | orr r0, r0, #0x000d @ Write buffer, mmu | ||
457 | #endif | ||
458 | mov r1, #-1 | ||
459 | mcr p15, 0, r3, c2, c0, 0 @ load page table pointer | ||
460 | mcr p15, 0, r1, c3, c0, 0 @ load domain access control | ||
461 | mcr p15, 0, r0, c1, c0, 0 @ load control register | ||
462 | mov pc, lr | ||
463 | |||
464 | /* | ||
465 | * All code following this line is relocatable. It is relocated by | ||
466 | * the above code to the end of the decompressed kernel image and | ||
467 | * executed there. During this time, we have no stacks. | ||
468 | * | ||
469 | * r0 = decompressed kernel length | ||
470 | * r1-r3 = unused | ||
471 | * r4 = kernel execution address | ||
472 | * r5 = decompressed kernel start | ||
473 | * r6 = processor ID | ||
474 | * r7 = architecture ID | ||
475 | * r8-r14 = unused | ||
476 | */ | ||
477 | .align 5 | ||
478 | reloc_start: add r8, r5, r0 | ||
479 | debug_reloc_start | ||
480 | mov r1, r4 | ||
481 | 1: | ||
482 | .rept 4 | ||
483 | ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel | ||
484 | stmia r1!, {r0, r2, r3, r9 - r13} | ||
485 | .endr | ||
486 | |||
487 | cmp r5, r8 | ||
488 | blo 1b | ||
489 | debug_reloc_end | ||
490 | |||
491 | call_kernel: bl cache_clean_flush | ||
492 | bl cache_off | ||
493 | mov r0, #0 | ||
494 | mov r1, r7 @ restore architecture number | ||
495 | mov pc, r4 @ call kernel | ||
496 | |||
497 | /* | ||
498 | * Here follow the relocatable cache support functions for the | ||
499 | * various processors. This is a generic hook for locating an | ||
500 | * entry and jumping to an instruction at the specified offset | ||
501 | * from the start of the block. Please note this is all position | ||
502 | * independent code. | ||
503 | * | ||
504 | * r1 = corrupted | ||
505 | * r2 = corrupted | ||
506 | * r3 = block offset | ||
507 | * r6 = corrupted | ||
508 | * r12 = corrupted | ||
509 | */ | ||
510 | |||
511 | call_cache_fn: adr r12, proc_types | ||
512 | mrc p15, 0, r6, c0, c0 @ get processor ID | ||
513 | 1: ldr r1, [r12, #0] @ get value | ||
514 | ldr r2, [r12, #4] @ get mask | ||
515 | eor r1, r1, r6 @ (real ^ match) | ||
516 | tst r1, r2 @ & mask | ||
517 | addeq pc, r12, r3 @ call cache function | ||
518 | add r12, r12, #4*5 | ||
519 | b 1b | ||
520 | |||
521 | /* | ||
522 | * Table for cache operations. This is basically: | ||
523 | * - CPU ID match | ||
524 | * - CPU ID mask | ||
525 | * - 'cache on' method instruction | ||
526 | * - 'cache off' method instruction | ||
527 | * - 'cache flush' method instruction | ||
528 | * | ||
529 | * We match an entry using: ((real_id ^ match) & mask) == 0 | ||
530 | * | ||
531 | * Writethrough caches generally only need 'on' and 'off' | ||
532 | * methods. Writeback caches _must_ have the flush method | ||
533 | * defined. | ||
534 | */ | ||
535 | .type proc_types,#object | ||
536 | proc_types: | ||
537 | .word 0x41560600 @ ARM6/610 | ||
538 | .word 0xffffffe0 | ||
539 | b __arm6_cache_off @ works, but slow | ||
540 | b __arm6_cache_off | ||
541 | mov pc, lr | ||
542 | @ b __arm6_cache_on @ untested | ||
543 | @ b __arm6_cache_off | ||
544 | @ b __armv3_cache_flush | ||
545 | |||
546 | .word 0x00000000 @ old ARM ID | ||
547 | .word 0x0000f000 | ||
548 | mov pc, lr | ||
549 | mov pc, lr | ||
550 | mov pc, lr | ||
551 | |||
552 | .word 0x41007000 @ ARM7/710 | ||
553 | .word 0xfff8fe00 | ||
554 | b __arm7_cache_off | ||
555 | b __arm7_cache_off | ||
556 | mov pc, lr | ||
557 | |||
558 | .word 0x41807200 @ ARM720T (writethrough) | ||
559 | .word 0xffffff00 | ||
560 | b __armv4_cache_on | ||
561 | b __armv4_cache_off | ||
562 | mov pc, lr | ||
563 | |||
564 | .word 0x00007000 @ ARM7 IDs | ||
565 | .word 0x0000f000 | ||
566 | mov pc, lr | ||
567 | mov pc, lr | ||
568 | mov pc, lr | ||
569 | |||
570 | @ Everything from here on will be the new ID system. | ||
571 | |||
572 | .word 0x4401a100 @ sa110 / sa1100 | ||
573 | .word 0xffffffe0 | ||
574 | b __armv4_cache_on | ||
575 | b __armv4_cache_off | ||
576 | b __armv4_cache_flush | ||
577 | |||
578 | .word 0x6901b110 @ sa1110 | ||
579 | .word 0xfffffff0 | ||
580 | b __armv4_cache_on | ||
581 | b __armv4_cache_off | ||
582 | b __armv4_cache_flush | ||
583 | |||
584 | @ These match on the architecture ID | ||
585 | |||
586 | .word 0x00020000 @ ARMv4T | ||
587 | .word 0x000f0000 | ||
588 | b __armv4_cache_on | ||
589 | b __armv4_cache_off | ||
590 | b __armv4_cache_flush | ||
591 | |||
592 | .word 0x00050000 @ ARMv5TE | ||
593 | .word 0x000f0000 | ||
594 | b __armv4_cache_on | ||
595 | b __armv4_cache_off | ||
596 | b __armv4_cache_flush | ||
597 | |||
598 | .word 0x00060000 @ ARMv5TEJ | ||
599 | .word 0x000f0000 | ||
600 | b __armv4_cache_on | ||
601 | b __armv4_cache_off | ||
602 | b __armv4_cache_flush | ||
603 | |||
604 | .word 0x00070000 @ ARMv6 | ||
605 | .word 0x000f0000 | ||
606 | b __armv4_cache_on | ||
607 | b __armv4_cache_off | ||
608 | b __armv6_cache_flush | ||
609 | |||
610 | .word 0 @ unrecognised type | ||
611 | .word 0 | ||
612 | mov pc, lr | ||
613 | mov pc, lr | ||
614 | mov pc, lr | ||
615 | |||
616 | .size proc_types, . - proc_types | ||
617 | |||
618 | /* | ||
619 | * Turn off the Cache and MMU. ARMv3 does not support | ||
620 | * reading the control register, but ARMv4 does. | ||
621 | * | ||
622 | * On entry, r6 = processor ID | ||
623 | * On exit, r0, r1, r2, r3, r12 corrupted | ||
624 | * This routine must preserve: r4, r6, r7 | ||
625 | */ | ||
626 | .align 5 | ||
627 | cache_off: mov r3, #12 @ cache_off function | ||
628 | b call_cache_fn | ||
629 | |||
630 | __armv4_cache_off: | ||
631 | mrc p15, 0, r0, c1, c0 | ||
632 | bic r0, r0, #0x000d | ||
633 | mcr p15, 0, r0, c1, c0 @ turn MMU and cache off | ||
634 | mov r0, #0 | ||
635 | mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 | ||
636 | mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 | ||
637 | mov pc, lr | ||
638 | |||
639 | __arm6_cache_off: | ||
640 | mov r0, #0x00000030 @ ARM6 control reg. | ||
641 | b __armv3_cache_off | ||
642 | |||
643 | __arm7_cache_off: | ||
644 | mov r0, #0x00000070 @ ARM7 control reg. | ||
645 | b __armv3_cache_off | ||
646 | |||
647 | __armv3_cache_off: | ||
648 | mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off | ||
649 | mov r0, #0 | ||
650 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
651 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
652 | mov pc, lr | ||
653 | |||
654 | /* | ||
655 | * Clean and flush the cache to maintain consistency. | ||
656 | * | ||
657 | * On entry, | ||
658 | * r6 = processor ID | ||
659 | * On exit, | ||
660 | * r1, r2, r3, r11, r12 corrupted | ||
661 | * This routine must preserve: | ||
662 | * r0, r4, r5, r6, r7 | ||
663 | */ | ||
664 | .align 5 | ||
665 | cache_clean_flush: | ||
666 | mov r3, #16 | ||
667 | b call_cache_fn | ||
668 | |||
669 | __armv6_cache_flush: | ||
670 | mov r1, #0 | ||
671 | mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D | ||
672 | mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB | ||
673 | mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified | ||
674 | mcr p15, 0, r1, c7, c10, 4 @ drain WB | ||
675 | mov pc, lr | ||
676 | |||
677 | __armv4_cache_flush: | ||
678 | mov r2, #64*1024 @ default: 32K dcache size (*2) | ||
679 | mov r11, #32 @ default: 32 byte line size | ||
680 | mrc p15, 0, r3, c0, c0, 1 @ read cache type | ||
681 | teq r3, r6 @ cache ID register present? | ||
682 | beq no_cache_id | ||
683 | mov r1, r3, lsr #18 | ||
684 | and r1, r1, #7 | ||
685 | mov r2, #1024 | ||
686 | mov r2, r2, lsl r1 @ base dcache size *2 | ||
687 | tst r3, #1 << 14 @ test M bit | ||
688 | addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 | ||
689 | mov r3, r3, lsr #12 | ||
690 | and r3, r3, #3 | ||
691 | mov r11, #8 | ||
692 | mov r11, r11, lsl r3 @ cache line size in bytes | ||
693 | no_cache_id: | ||
694 | bic r1, pc, #63 @ align to longest cache line | ||
695 | add r2, r1, r2 | ||
696 | 1: ldr r3, [r1], r11 @ s/w flush D cache | ||
697 | teq r1, r2 | ||
698 | bne 1b | ||
699 | |||
700 | mcr p15, 0, r1, c7, c5, 0 @ flush I cache | ||
701 | mcr p15, 0, r1, c7, c6, 0 @ flush D cache | ||
702 | mcr p15, 0, r1, c7, c10, 4 @ drain WB | ||
703 | mov pc, lr | ||
704 | |||
705 | __armv3_cache_flush: | ||
706 | mov r1, #0 | ||
707 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
708 | mov pc, lr | ||
709 | |||
710 | /* | ||
711 | * Various debugging routines for printing hex characters and | ||
712 | * memory, which again must be relocatable. | ||
713 | */ | ||
714 | #ifdef DEBUG | ||
715 | .type phexbuf,#object | ||
716 | phexbuf: .space 12 | ||
717 | .size phexbuf, . - phexbuf | ||
718 | |||
719 | phex: adr r3, phexbuf | ||
720 | mov r2, #0 | ||
721 | strb r2, [r3, r1] | ||
722 | 1: subs r1, r1, #1 | ||
723 | movmi r0, r3 | ||
724 | bmi puts | ||
725 | and r2, r0, #15 | ||
726 | mov r0, r0, lsr #4 | ||
727 | cmp r2, #10 | ||
728 | addge r2, r2, #7 | ||
729 | add r2, r2, #'0' | ||
730 | strb r2, [r3, r1] | ||
731 | b 1b | ||
732 | |||
733 | puts: loadsp r3 | ||
734 | 1: ldrb r2, [r0], #1 | ||
735 | teq r2, #0 | ||
736 | moveq pc, lr | ||
737 | 2: writeb r2 | ||
738 | mov r1, #0x00020000 | ||
739 | 3: subs r1, r1, #1 | ||
740 | bne 3b | ||
741 | teq r2, #'\n' | ||
742 | moveq r2, #'\r' | ||
743 | beq 2b | ||
744 | teq r0, #0 | ||
745 | bne 1b | ||
746 | mov pc, lr | ||
747 | putc: | ||
748 | mov r2, r0 | ||
749 | mov r0, #0 | ||
750 | loadsp r3 | ||
751 | b 2b | ||
752 | |||
753 | memdump: mov r12, r0 | ||
754 | mov r10, lr | ||
755 | mov r11, #0 | ||
756 | 2: mov r0, r11, lsl #2 | ||
757 | add r0, r0, r12 | ||
758 | mov r1, #8 | ||
759 | bl phex | ||
760 | mov r0, #':' | ||
761 | bl putc | ||
762 | 1: mov r0, #' ' | ||
763 | bl putc | ||
764 | ldr r0, [r12, r11, lsl #2] | ||
765 | mov r1, #8 | ||
766 | bl phex | ||
767 | and r0, r11, #7 | ||
768 | teq r0, #3 | ||
769 | moveq r0, #' ' | ||
770 | bleq putc | ||
771 | and r0, r11, #7 | ||
772 | add r11, r11, #1 | ||
773 | teq r0, #7 | ||
774 | bne 1b | ||
775 | mov r0, #'\n' | ||
776 | bl putc | ||
777 | cmp r11, #64 | ||
778 | blt 2b | ||
779 | mov pc, r10 | ||
780 | #endif | ||
781 | |||
782 | reloc_end: | ||
783 | |||
784 | .align | ||
785 | .section ".stack", "w" | ||
786 | user_stack: .space 4096 | ||