Root/
1 | /* |
2 | * linux/arch/arm/kernel/head-common.S |
3 | * |
4 | * Copyright (C) 1994-2002 Russell King |
5 | * Copyright (c) 2003 ARM Limited |
6 | * All Rights Reserved |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. |
11 | * |
12 | */ |
13 | |
14 | #define ATAG_CORE 0x54410001 |
15 | #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) |
16 | #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) |
17 | |
18 | /* |
19 | * Exception handling. Something went wrong and we can't proceed. We |
20 | * ought to tell the user, but since we don't have any guarantee that |
21 | * we're even running on the right architecture, we do virtually nothing. |
22 | * |
23 | * If CONFIG_DEBUG_LL is set we try to print out something about the error |
24 | * and hope for the best (useful if bootloader fails to pass a proper |
25 | * machine ID for example). |
26 | */ |
27 | __HEAD |
28 | __error_a: |
29 | #ifdef CONFIG_DEBUG_LL |
30 | mov r4, r1 @ preserve machine ID |
31 | adr r0, str_a1 |
32 | bl printascii |
33 | mov r0, r4 |
34 | bl printhex8 |
35 | adr r0, str_a2 |
36 | bl printascii |
37 | adr r3, __lookup_machine_type_data |
38 | ldmia r3, {r4, r5, r6} @ get machine desc list |
39 | sub r4, r3, r4 @ get offset between virt&phys |
40 | add r5, r5, r4 @ convert virt addresses to |
41 | add r6, r6, r4 @ physical address space |
42 | 1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type |
43 | bl printhex8 |
44 | mov r0, #'\t' |
45 | bl printch |
46 | ldr r0, [r5, #MACHINFO_NAME] @ get machine name |
47 | add r0, r0, r4 |
48 | bl printascii |
49 | mov r0, #'\n' |
50 | bl printch |
51 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc |
52 | cmp r5, r6 |
53 | blo 1b |
54 | adr r0, str_a3 |
55 | bl printascii |
56 | b __error |
57 | ENDPROC(__error_a) |
58 | |
59 | str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" |
60 | str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" |
61 | str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" |
62 | .align |
63 | #endif |
64 | |
65 | /* |
66 | * Lookup machine architecture in the linker-build list of architectures. |
67 | * Note that we can't use the absolute addresses for the __arch_info |
68 | * lists since we aren't running with the MMU on (and therefore, we are |
69 | * not in the correct address space). We have to calculate the offset. |
70 | * |
71 | * r1 = machine architecture number |
72 | * Returns: |
73 | * r3, r4, r6 corrupted |
74 | * r5 = mach_info pointer in physical address space |
75 | */ |
76 | __lookup_machine_type: |
77 | adr r3, __lookup_machine_type_data |
78 | ldmia r3, {r4, r5, r6} |
79 | sub r3, r3, r4 @ get offset between virt&phys |
80 | add r5, r5, r3 @ convert virt addresses to |
81 | add r6, r6, r3 @ physical address space |
82 | 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type |
83 | teq r3, r1 @ matches loader number? |
84 | beq 2f @ found |
85 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc |
86 | cmp r5, r6 |
87 | blo 1b |
88 | mov r5, #0 @ unknown machine |
89 | 2: mov pc, lr |
90 | ENDPROC(__lookup_machine_type) |
91 | |
92 | /* |
93 | * Look in arch/arm/kernel/arch.[ch] for information about the |
94 | * __arch_info structures. |
95 | */ |
96 | .align 2 |
97 | .type __lookup_machine_type_data, %object |
98 | __lookup_machine_type_data: |
99 | .long . |
100 | .long __arch_info_begin |
101 | .long __arch_info_end |
102 | .size __lookup_machine_type_data, . - __lookup_machine_type_data |
103 | |
104 | /* Determine validity of the r2 atags pointer. The heuristic requires |
105 | * that the pointer be aligned, in the first 16k of physical RAM and |
106 | * that the ATAG_CORE marker is first and present. Future revisions |
107 | * of this function may be more lenient with the physical address and |
108 | * may also be able to move the ATAGS block if necessary. |
109 | * |
110 | * r8 = machinfo |
111 | * |
112 | * Returns: |
113 | * r2 either valid atags pointer, or zero |
114 | * r5, r6 corrupted |
115 | */ |
116 | __vet_atags: |
117 | tst r2, #0x3 @ aligned? |
118 | bne 1f |
119 | |
120 | ldr r5, [r2, #0] @ is first tag ATAG_CORE? |
121 | cmp r5, #ATAG_CORE_SIZE |
122 | cmpne r5, #ATAG_CORE_SIZE_EMPTY |
123 | bne 1f |
124 | ldr r5, [r2, #4] |
125 | ldr r6, =ATAG_CORE |
126 | cmp r5, r6 |
127 | bne 1f |
128 | |
129 | mov pc, lr @ atag pointer is ok |
130 | |
131 | 1: mov r2, #0 |
132 | mov pc, lr |
133 | ENDPROC(__vet_atags) |
134 | |
135 | /* |
136 | * The following fragment of code is executed with the MMU on in MMU mode, |
137 | * and uses absolute addresses; this is not position independent. |
138 | * |
139 | * r0 = cp#15 control register |
140 | * r1 = machine ID |
141 | * r2 = atags pointer |
142 | * r9 = processor ID |
143 | */ |
144 | __INIT |
145 | __mmap_switched: |
146 | adr r3, __mmap_switched_data |
147 | |
148 | ldmia r3!, {r4, r5, r6, r7} |
149 | cmp r4, r5 @ Copy data segment if needed |
150 | 1: cmpne r5, r6 |
151 | ldrne fp, [r4], #4 |
152 | strne fp, [r5], #4 |
153 | bne 1b |
154 | |
155 | mov fp, #0 @ Clear BSS (and zero fp) |
156 | 1: cmp r6, r7 |
157 | strcc fp, [r6],#4 |
158 | bcc 1b |
159 | |
160 | ARM( ldmia r3, {r4, r5, r6, r7, sp}) |
161 | THUMB( ldmia r3, {r4, r5, r6, r7} ) |
162 | THUMB( ldr sp, [r3, #16] ) |
163 | str r9, [r4] @ Save processor ID |
164 | str r1, [r5] @ Save machine type |
165 | str r2, [r6] @ Save atags pointer |
166 | bic r4, r0, #CR_A @ Clear 'A' bit |
167 | stmia r7, {r0, r4} @ Save control register values |
168 | b start_kernel |
169 | ENDPROC(__mmap_switched) |
170 | |
171 | .align 2 |
172 | .type __mmap_switched_data, %object |
173 | __mmap_switched_data: |
174 | .long __data_loc @ r4 |
175 | .long _sdata @ r5 |
176 | .long __bss_start @ r6 |
177 | .long _end @ r7 |
178 | .long processor_id @ r4 |
179 | .long __machine_arch_type @ r5 |
180 | .long __atags_pointer @ r6 |
181 | .long cr_alignment @ r7 |
182 | .long init_thread_union + THREAD_START_SP @ sp |
183 | .size __mmap_switched_data, . - __mmap_switched_data |
184 | |
185 | /* |
186 | * This provides a C-API version of __lookup_machine_type |
187 | */ |
188 | ENTRY(lookup_machine_type) |
189 | stmfd sp!, {r4 - r6, lr} |
190 | mov r1, r0 |
191 | bl __lookup_machine_type |
192 | mov r0, r5 |
193 | ldmfd sp!, {r4 - r6, pc} |
194 | ENDPROC(lookup_machine_type) |
195 | |
196 | /* |
197 | * This provides a C-API version of __lookup_processor_type |
198 | */ |
199 | ENTRY(lookup_processor_type) |
200 | stmfd sp!, {r4 - r6, r9, lr} |
201 | mov r9, r0 |
202 | bl __lookup_processor_type |
203 | mov r0, r5 |
204 | ldmfd sp!, {r4 - r6, r9, pc} |
205 | ENDPROC(lookup_processor_type) |
206 | |
207 | /* |
208 | * Read processor ID register (CP#15, CR0), and look up in the linker-built |
209 | * supported processor list. Note that we can't use the absolute addresses |
210 | * for the __proc_info lists since we aren't running with the MMU on |
211 | * (and therefore, we are not in the correct address space). We have to |
212 | * calculate the offset. |
213 | * |
214 | * r9 = cpuid |
215 | * Returns: |
216 | * r3, r4, r6 corrupted |
217 | * r5 = proc_info pointer in physical address space |
218 | * r9 = cpuid (preserved) |
219 | */ |
220 | __CPUINIT |
221 | __lookup_processor_type: |
222 | adr r3, __lookup_processor_type_data |
223 | ldmia r3, {r4 - r6} |
224 | sub r3, r3, r4 @ get offset between virt&phys |
225 | add r5, r5, r3 @ convert virt addresses to |
226 | add r6, r6, r3 @ physical address space |
227 | 1: ldmia r5, {r3, r4} @ value, mask |
228 | and r4, r4, r9 @ mask wanted bits |
229 | teq r3, r4 |
230 | beq 2f |
231 | add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) |
232 | cmp r5, r6 |
233 | blo 1b |
234 | mov r5, #0 @ unknown processor |
235 | 2: mov pc, lr |
236 | ENDPROC(__lookup_processor_type) |
237 | |
238 | /* |
239 | * Look in <asm/procinfo.h> for information about the __proc_info structure. |
240 | */ |
241 | .align 2 |
242 | .type __lookup_processor_type_data, %object |
243 | __lookup_processor_type_data: |
244 | .long . |
245 | .long __proc_info_begin |
246 | .long __proc_info_end |
247 | .size __lookup_processor_type_data, . - __lookup_processor_type_data |
248 | |
249 | __error_p: |
250 | #ifdef CONFIG_DEBUG_LL |
251 | adr r0, str_p1 |
252 | bl printascii |
253 | mov r0, r9 |
254 | bl printhex8 |
255 | adr r0, str_p2 |
256 | bl printascii |
257 | b __error |
258 | str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" |
259 | str_p2: .asciz ").\n" |
260 | .align |
261 | #endif |
262 | ENDPROC(__error_p) |
263 | |
264 | __error: |
265 | #ifdef CONFIG_ARCH_RPC |
266 | /* |
267 | * Turn the screen red on a error - RiscPC only. |
268 | */ |
269 | mov r0, #0x02000000 |
270 | mov r3, #0x11 |
271 | orr r3, r3, r3, lsl #8 |
272 | orr r3, r3, r3, lsl #16 |
273 | str r3, [r0], #4 |
274 | str r3, [r0], #4 |
275 | str r3, [r0], #4 |
276 | str r3, [r0], #4 |
277 | #endif |
278 | 1: mov r0, r0 |
279 | b 1b |
280 | ENDPROC(__error) |
281 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9