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