MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / arm / kernel / head.S
blob741c1ab1eb5c67be6bc522846810592fef2ec0df
1 /*
2  *  linux/arch/arm/kernel/head-armv.S
3  *
4  *  Copyright (C) 1994-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  *  Kernel startup code for all 32-bit CPUs
11  */
12 #include <linux/config.h>
13 #include <linux/linkage.h>
14 #include <linux/init.h>
16 #include <asm/assembler.h>
17 #include <asm/mach-types.h>
18 #include <asm/procinfo.h>
19 #include <asm/ptrace.h>
20 #include <asm/constants.h>
23  * We place the page tables 16K below TEXTADDR.  Therefore, we must make sure
24  * that TEXTADDR is correctly set.  Currently, we expect the least significant
25  * 16 bits to be 0x8000, but we could probably relax this restriction to
26  * TEXTADDR > PAGE_OFFSET + 0x4000
27  *
28  * Note that swapper_pg_dir is the virtual address of the page tables, and
29  * pgtbl gives us a position-independent reference to these tables.  We can
30  * do this because stext == TEXTADDR
31  *
32  * swapper_pg_dir, pgtbl and krnladr are all closely related.
33  */
34 #if (TEXTADDR & 0xffff) != 0x8000
35 #error TEXTADDR must start at 0xXXXX8000
36 #endif
38         .globl  swapper_pg_dir
39         .equ    swapper_pg_dir, TEXTADDR - 0x4000
41         .macro  pgtbl, reg
42         adr     \reg, stext
43         sub     \reg, \reg, #0x4000
44         .endm
45 #if 0   /* just for debug used. add by Victor Yu. 07-17-2007 */
46         .macro  show_value, reg
47         ldr     r7, =0x98200000
48         mov     r3, #8
49 1:      and     r8, \reg, #0xf0000000
50         mov     r8, r8, LSR #28
51         cmp     r8, #10
52         addge   r8, r8, #87
53         addlt   r8, r8, #'0'
54         strb    r8, [r7]
55         mov     \reg, \reg, LSL #4
56         sub     r3, r3, #1
57         cmp     r3, #0
58         bgt     1b
59         mov     r8, #'\n'
60         strb    r8, [r7]
61         .endm
62 #endif
65  * Since the page table is closely related to the kernel start address, we
66  * can convert the page table base address to the base address of the section
67  * containing both.
68  */
69         .macro  krnladr, rd, pgtable
70         bic     \rd, \pgtable, #0x000ff000
71         .endm
74  * Kernel startup entry point.
75  * ---------------------------
76  *
77  * This is normally called from the decompressor code.  The requirements
78  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
79  * r1 = machine nr.
80  *
81  * This code is mostly position independent, so if you link the kernel at
82  * 0xc0008000, you call this at __pa(0xc0008000).
83  *
84  * See linux/arch/arm/tools/mach-types for the complete list of machine
85  * numbers for r1.
86  *
87  * We're trying to keep crap to a minimum; DO NOT add any machine specific
88  * crap here - that's what the boot loader (or in extreme, well justified
89  * circumstances, zImage) is for.
90  */
91         __INIT
92         .type   stext, #function
93 ENTRY(stext)
94 #if 0   /* mask by Victor Yu. 11-11-2005, do it on arch/arm/boot/compressed/head-cpe.S */
95         mov     r1, #MACH_TYPE_MOXACPU & 0xff
96         orr     r1, r1, #MACH_TYPE_MOXACPU & 0xff00
97 #endif
98 #if 0   /* just debug used. add by Victor Yu. 07-17-2007 */
99         ldr     r9, =0x90200000
100         ldr     r4, [r9]
101         show_value      r4      @0
102         ldr     r4, [r9, #4]
103         show_value      r4      @4
104 #endif
105 #if 0   /* just debug used. add by Victor Yu. 07-17-2007 */
106         ldr     r9, =0x90300000
107         ldr     r8, =0x00633922
108         str     r8, [r9]
109         ldr     r8, =0x00480410
110         str     r8, [r9, #4]
111 #endif
113         mov     r12, r0
114         mov     r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC   @ make sure svc mode
115         msr     cpsr_c, r0                      @ and all irqs disabled
116         bl      __lookup_processor_type
117         teq     r10, #0                         @ invalid processor?
118         moveq   r0, #'p'                        @ yes, error 'p'
119         beq     __error
120         bl      __lookup_architecture_type
121         teq     r7, #0                          @ invalid architecture?
122         moveq   r0, #'a'                        @ yes, error 'a'
123         beq     __error
124         bl      __create_page_tables
126         /*
127          * The following calls CPU specific code in a position independent
128          * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
129          * xxx_proc_info structure selected by __lookup_architecture_type
130          * above.  On return, the CPU will be ready for the MMU to be
131          * turned on, and r0 will hold the CPU control register value.
132          */
133         adr     lr, __turn_mmu_on               @ return (PIC) address
134         add     pc, r10, #12
136         .type   __switch_data, %object
137 __switch_data:
138         .long   __mmap_switched
139         .long   __bss_start                     @ r4
140         .long   _end                            @ r5
141         .long   processor_id                    @ r6
142         .long   __machine_arch_type             @ r7
143         .long   cr_alignment                    @ r8
144         .long   init_thread_union+8192          @ sp
147  * Enable the MMU.  This completely changes the structure of the visible
148  * memory space.  You will not be able to trace execution through this.
149  * If you have an enquiry about this, *please* check the linux-arm-kernel
150  * mailing list archives BEFORE sending another post to the list.
151  */
152         .align  5
153         .type   __turn_mmu_on, %function
154 __turn_mmu_on:
155         ldr     lr, __switch_data
156 #ifdef CONFIG_ALIGNMENT_TRAP
157         orr     r0, r0, #2                      @ ...........A.
158 #endif
159         mcr     p15, 0, r0, c1, c0, 0           @ write control reg
160         mrc     p15, 0, r3, c0, c0, 0           @ read id reg
161 #if 0   /* mask by Victor Yu. 06-13-2005 */
162         mov     r3, r3
163         mov     r3, r3
164 #else   /* add by Victor Yu. 06-13-2005 */
165         mov     ip, #0
166         mcr     p15, 0, ip, c7, c5, 4           @ flush prefetch instruction    
167 #endif
168         mov     pc, lr
171  * The following fragment of code is executed with the MMU on, and uses
172  * absolute addresses; this is not position independent.
174  *  r0  = processor control register
175  *  r1  = machine ID
176  *  r9  = processor ID
177  *  r12 = value of r0 when kernel was called (currently always zero)
178  */
179         .align  5
180 __mmap_switched:
181         adr     r3, __switch_data + 4
182         ldmia   r3, {r4, r5, r6, r7, r8, sp}
183         mov     fp, #0                          @ Clear BSS (and zero fp)
184 1:      cmp     r4, r5
185         strcc   fp, [r4],#4
186         bcc     1b
187         str     r9, [r6]                        @ Save processor ID
188         str     r1, [r7]                        @ Save machine type
189         bic     r2, r0, #2                      @ Clear 'A' bit
190         stmia   r8, {r0, r2}                    @ Save control register values
191         b       start_kernel
194  * Setup the initial page tables.  We only setup the barest
195  * amount which are required to get the kernel running, which
196  * generally means mapping in the kernel code.
198  * We only map in 4MB of RAM, which should be sufficient in
199  * all cases.
201  * r5 = physical address of start of RAM
202  * r6 = physical IO address
203  * r7 = byte offset into page tables for IO
204  * r8 = page table flags
205  */
206 __create_page_tables:
207         pgtbl   r4                              @ page table address
209         /*
210          * Clear the 16K level 1 swapper page table
211          */
212         mov     r0, r4
213         mov     r3, #0
214         add     r2, r0, #0x4000
215 1:      str     r3, [r0], #4
216         str     r3, [r0], #4
217         str     r3, [r0], #4
218         str     r3, [r0], #4
219         teq     r0, r2
220         bne     1b
222         /*
223          * Create identity mapping for first MB of kernel to
224          * cater for the MMU enable.  This identity mapping
225          * will be removed by paging_init()
226          */
227         krnladr r2, r4                          @ start of kernel
228         add     r3, r8, r2                      @ flags + kernel base
229         str     r3, [r4, r2, lsr #18]           @ identity mapping
231         /*
232          * Now setup the pagetables for our kernel direct
233          * mapped region.  We round TEXTADDR down to the
234          * nearest megabyte boundary.
235          */
236         add     r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
237         bic     r2, r3, #0x00f00000
238         str     r2, [r0]                        @ PAGE_OFFSET + 0MB
239         add     r0, r0, #(TEXTADDR & 0x00f00000) >> 18
240         str     r3, [r0], #4                    @ KERNEL + 0MB
241         add     r3, r3, #1 << 20
242         str     r3, [r0], #4                    @ KERNEL + 1MB
243         add     r3, r3, #1 << 20
244         str     r3, [r0], #4                    @ KERNEL + 2MB
245         add     r3, r3, #1 << 20
246         str     r3, [r0], #4                    @ KERNEL + 3MB
248         bic     r8, r8, #0x0c                   @ turn off cacheable
249                                                 @ and bufferable bits
250 #ifdef CONFIG_DEBUG_LL
251         /*
252          * Map in IO space for serial debugging.
253          * This allows debug messages to be output
254          * via a serial console before paging_init.
255          */
256         add     r0, r4, r7
257         rsb     r3, r7, #0x4000                 @ PTRS_PER_PGD*sizeof(long)
258         cmp     r3, #0x0800
259         addge   r2, r0, #0x0800
260         addlt   r2, r0, r3
261         orr     r3, r6, r8
262 1:      str     r3, [r0], #4
263         add     r3, r3, #1 << 20
264         teq     r0, r2
265         bne     1b
266 #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
267         /*
268          * If we're using the NetWinder, we need to map in
269          * the 16550-type serial port for the debug messages
270          */
271         teq     r1, #MACH_TYPE_NETWINDER
272         teqne   r1, #MACH_TYPE_CATS
273         bne     1f
274         add     r0, r4, #0x3fc0                 @ ff000000
275         mov     r3, #0x7c000000
276         orr     r3, r3, r8
277         str     r3, [r0], #4
278         add     r3, r3, #1 << 20
279         str     r3, [r0], #4
281 #endif
282 #endif
283 #ifdef CONFIG_ARCH_RPC
284         /*
285          * Map in screen at 0x02000000 & SCREEN2_BASE
286          * Similar reasons here - for debug.  This is
287          * only for Acorn RiscPC architectures.
288          */
289         add     r0, r4, #0x80                   @ 02000000
290         mov     r3, #0x02000000
291         orr     r3, r3, r8
292         str     r3, [r0]
293         add     r0, r4, #0x3600                 @ d8000000
294         str     r3, [r0]
295 #endif
296         mov     pc, lr
301  * Exception handling.  Something went wrong and we can't proceed.  We
302  * ought to tell the user, but since we don't have any guarantee that
303  * we're even running on the right architecture, we do virtually nothing.
305  * r0 = ascii error character:
306  *      a = invalid architecture
307  *      p = invalid processor
308  *      i = invalid calling convention
310  * Generally, only serious errors cause this.
311  */
312 __error:
313 #ifdef CONFIG_DEBUG_LL
314         mov     r8, r0                          @ preserve r0
315         adr     r0, err_str
316         bl      printascii
317         mov     r0, r8
318         bl      printch
319 #endif
320 #ifdef CONFIG_ARCH_RPC
322  * Turn the screen red on a error - RiscPC only.
323  */
324         mov     r0, #0x02000000
325         mov     r3, #0x11
326         orr     r3, r3, r3, lsl #8
327         orr     r3, r3, r3, lsl #16
328         str     r3, [r0], #4
329         str     r3, [r0], #4
330         str     r3, [r0], #4
331         str     r3, [r0], #4
332 #endif
333 1:      mov     r0, r0
334         b       1b
336 #ifdef CONFIG_DEBUG_LL
337 err_str:
338         .asciz  "\nError: "
339         .align
340 #endif
343  * Read processor ID register (CP#15, CR0), and look up in the linker-built
344  * supported processor list.  Note that we can't use the absolute addresses
345  * for the __proc_info lists since we aren't running with the MMU on
346  * (and therefore, we are not in the correct address space).  We have to
347  * calculate the offset.
349  * Returns:
350  *      r5, r6, r7 corrupted
351  *      r8  = page table flags
352  *      r9  = processor ID
353  *      r10 = pointer to processor structure
354  */
355 __lookup_processor_type:
356         adr     r5, 2f
357         ldmia   r5, {r7, r9, r10}
358         sub     r5, r5, r10                     @ convert addresses
359         add     r7, r7, r5                      @ to our address space
360         add     r10, r9, r5
361         mrc     p15, 0, r9, c0, c0              @ get processor id
362 1:      ldmia   r10, {r5, r6, r8}               @ value, mask, mmuflags
363         and     r6, r6, r9                      @ mask wanted bits
364         teq     r5, r6
365         moveq   pc, lr
366         add     r10, r10, #PROC_INFO_SZ         @ sizeof(proc_info_list)
367         cmp     r10, r7
368         blt     1b
369         mov     r10, #0                         @ unknown processor
370         mov     pc, lr
373  * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
374  * more information about the __proc_info and __arch_info structures.
375  */
376 2:      .long   __proc_info_end
377         .long   __proc_info_begin
378         .long   2b
379         .long   __arch_info_begin
380         .long   __arch_info_end
383  * Lookup machine architecture in the linker-build list of architectures.
384  * Note that we can't use the absolute addresses for the __arch_info
385  * lists since we aren't running with the MMU on (and therefore, we are
386  * not in the correct address space).  We have to calculate the offset.
388  *  r1 = machine architecture number
389  * Returns:
390  *  r2, r3, r4 corrupted
391  *  r5 = physical start address of RAM
392  *  r6 = physical address of IO
393  *  r7 = byte offset into page tables for IO
394  */
395 __lookup_architecture_type:
396         adr     r4, 2b
397         ldmia   r4, {r2, r3, r5, r6, r7}        @ throw away r2, r3
398         sub     r5, r4, r5                      @ convert addresses
399         add     r4, r6, r5                      @ to our address space
400         add     r7, r7, r5
401 1:      ldr     r5, [r4]                        @ get machine type
402         teq     r5, r1                          @ matches loader number?
403         beq     2f                              @ found
404         add     r4, r4, #SIZEOF_MACHINE_DESC    @ next machine_desc
405         cmp     r4, r7
406         blt     1b
407         mov     r7, #0                          @ unknown architecture
408         mov     pc, lr
409 2:      ldmib   r4, {r5, r6, r7}                @ found, get results
410         mov     pc, lr