Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / arm / mm / proc-v6.S
1 /*
2  *  linux/arch/arm/mm/proc-v6.S
3  *
4  *  Copyright (C) 2001 Deep Blue Solutions Ltd.
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  *  This is the "shell" of the ARMv6 processor support.
11  */
12 #include <linux/linkage.h>
13 #include <asm/assembler.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/hardware/arm_scu.h>
16 #include <asm/procinfo.h>
17 #include <asm/pgtable-hwdef.h>
18 #include <asm/pgtable.h>
19
20 #include "proc-macros.S"
21
22 #define D_CACHE_LINE_SIZE       32
23
24 #define TTB_C           (1 << 0)
25 #define TTB_S           (1 << 1)
26 #define TTB_IMP         (1 << 2)
27 #define TTB_RGN_NC      (0 << 3)
28 #define TTB_RGN_WBWA    (1 << 3)
29 #define TTB_RGN_WT      (2 << 3)
30 #define TTB_RGN_WB      (3 << 3)
31
32 ENTRY(cpu_v6_proc_init)
33         mov     pc, lr
34
35 ENTRY(cpu_v6_proc_fin)
36         stmfd   sp!, {lr}
37         cpsid   if                              @ disable interrupts
38         bl      v6_flush_kern_cache_all
39         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
40         bic     r0, r0, #0x1000                 @ ...i............
41         bic     r0, r0, #0x0006                 @ .............ca.
42         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
43         ldmfd   sp!, {pc}
44
45 /*
46  *      cpu_v6_reset(loc)
47  *
48  *      Perform a soft reset of the system.  Put the CPU into the
49  *      same state as it would be if it had been reset, and branch
50  *      to what would be the reset vector.
51  *
52  *      - loc   - location to jump to for soft reset
53  *
54  *      It is assumed that:
55  */
56         .align  5
57 ENTRY(cpu_v6_reset)
58         mov     pc, r0
59
60 /*
61  *      cpu_v6_do_idle()
62  *
63  *      Idle the processor (eg, wait for interrupt).
64  *
65  *      IRQs are already disabled.
66  */
67 ENTRY(cpu_v6_do_idle)
68         mcr     p15, 0, r1, c7, c0, 4           @ wait for interrupt
69         mov     pc, lr
70
71 ENTRY(cpu_v6_dcache_clean_area)
72 #ifndef TLB_CAN_READ_FROM_L1_CACHE
73 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
74         add     r0, r0, #D_CACHE_LINE_SIZE
75         subs    r1, r1, #D_CACHE_LINE_SIZE
76         bhi     1b
77 #endif
78         mov     pc, lr
79
80 /*
81  *      cpu_arm926_switch_mm(pgd_phys, tsk)
82  *
83  *      Set the translation table base pointer to be pgd_phys
84  *
85  *      - pgd_phys - physical address of new TTB
86  *
87  *      It is assumed that:
88  *      - we are not using split page tables
89  */
90 ENTRY(cpu_v6_switch_mm)
91         mov     r2, #0
92         ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
93 #ifdef CONFIG_SMP
94         orr     r0, r0, #TTB_RGN_WBWA|TTB_S     @ mark PTWs shared, outer cacheable
95 #endif
96         mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
97         mcr     p15, 0, r2, c7, c10, 4          @ drain write buffer
98         mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
99         mcr     p15, 0, r1, c13, c0, 1          @ set context ID
100         mov     pc, lr
101
102 /*
103  *      cpu_v6_set_pte(ptep, pte)
104  *
105  *      Set a level 2 translation table entry.
106  *
107  *      - ptep  - pointer to level 2 translation table entry
108  *                (hardware version is stored at -1024 bytes)
109  *      - pte   - PTE value to store
110  *
111  *      Permissions:
112  *        YUWD  APX AP1 AP0     SVC     User
113  *        0xxx   0   0   0      no acc  no acc
114  *        100x   1   0   1      r/o     no acc
115  *        10x0   1   0   1      r/o     no acc
116  *        1011   0   0   1      r/w     no acc
117  *        110x   0   1   0      r/w     r/o
118  *        11x0   0   1   0      r/w     r/o
119  *        1111   0   1   1      r/w     r/w
120  */
121 ENTRY(cpu_v6_set_pte)
122         str     r1, [r0], #-2048                @ linux version
123
124         bic     r2, r1, #0x000003f0
125         bic     r2, r2, #0x00000003
126         orr     r2, r2, #PTE_EXT_AP0 | 2
127
128         tst     r1, #L_PTE_WRITE
129         tstne   r1, #L_PTE_DIRTY
130         orreq   r2, r2, #PTE_EXT_APX
131
132         tst     r1, #L_PTE_USER
133         orrne   r2, r2, #PTE_EXT_AP1
134         tstne   r2, #PTE_EXT_APX
135         bicne   r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
136
137         tst     r1, #L_PTE_YOUNG
138         biceq   r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
139
140         tst     r1, #L_PTE_EXEC
141         orreq   r2, r2, #PTE_EXT_XN
142
143         tst     r1, #L_PTE_PRESENT
144         moveq   r2, #0
145
146         str     r2, [r0]
147         mcr     p15, 0, r0, c7, c10, 1 @ flush_pte
148         mov     pc, lr
149
150
151
152
153 cpu_v6_name:
154         .asciz  "Some Random V6 Processor"
155         .align
156
157         .section ".text.init", #alloc, #execinstr
158
159 /*
160  *      __v6_setup
161  *
162  *      Initialise TLB, Caches, and MMU state ready to switch the MMU
163  *      on.  Return in r0 the new CP15 C1 control register setting.
164  *
165  *      We automatically detect if we have a Harvard cache, and use the
166  *      Harvard cache control instructions insead of the unified cache
167  *      control instructions.
168  *
169  *      This should be able to cover all ARMv6 cores.
170  *
171  *      It is assumed that:
172  *      - cache type register is implemented
173  */
174 __v6_setup:
175 #ifdef CONFIG_SMP
176         /* Set up the SCU on core 0 only */
177         mrc     p15, 0, r0, c0, c0, 5           @ CPU core number
178         ands    r0, r0, #15
179         moveq   r0, #0x10000000 @ SCU_BASE
180         orreq   r0, r0, #0x00100000
181         ldreq   r5, [r0, #SCU_CTRL]
182         orreq   r5, r5, #1
183         streq   r5, [r0, #SCU_CTRL]
184
185 #ifndef CONFIG_CPU_DCACHE_DISABLE
186         mrc     p15, 0, r0, c1, c0, 1           @ Enable SMP/nAMP mode
187         orr     r0, r0, #0x20
188         mcr     p15, 0, r0, c1, c0, 1
189 #endif
190 #endif
191
192         mov     r0, #0
193         mcr     p15, 0, r0, c7, c14, 0          @ clean+invalidate D cache
194         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
195         mcr     p15, 0, r0, c7, c15, 0          @ clean+invalidate cache
196         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
197         mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
198         mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
199 #ifdef CONFIG_SMP
200         orr     r4, r4, #TTB_RGN_WBWA|TTB_S     @ mark PTWs shared, outer cacheable
201 #endif
202         mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
203 #ifdef CONFIG_VFP
204         mrc     p15, 0, r0, c1, c0, 2
205         orr     r0, r0, #(0xf << 20)
206         mcr     p15, 0, r0, c1, c0, 2           @ Enable full access to VFP
207 #endif
208         mrc     p15, 0, r0, c1, c0, 0           @ read control register
209         ldr     r5, v6_cr1_clear                @ get mask for bits to clear
210         bic     r0, r0, r5                      @ clear bits them
211         ldr     r5, v6_cr1_set                  @ get mask for bits to set
212         orr     r0, r0, r5                      @ set them
213         mov     pc, lr                          @ return to head.S:__ret
214
215         /*
216          *         V X F   I D LR
217          * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
218          * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
219          *         0 110       0011 1.00 .111 1101 < we want
220          */
221         .type   v6_cr1_clear, #object
222         .type   v6_cr1_set, #object
223 v6_cr1_clear:
224         .word   0x01e0fb7f
225 v6_cr1_set:
226         .word   0x00c0387d
227
228         .type   v6_processor_functions, #object
229 ENTRY(v6_processor_functions)
230         .word   v6_early_abort
231         .word   cpu_v6_proc_init
232         .word   cpu_v6_proc_fin
233         .word   cpu_v6_reset
234         .word   cpu_v6_do_idle
235         .word   cpu_v6_dcache_clean_area
236         .word   cpu_v6_switch_mm
237         .word   cpu_v6_set_pte
238         .size   v6_processor_functions, . - v6_processor_functions
239
240         .type   cpu_arch_name, #object
241 cpu_arch_name:
242         .asciz  "armv6"
243         .size   cpu_arch_name, . - cpu_arch_name
244
245         .type   cpu_elf_name, #object
246 cpu_elf_name:
247         .asciz  "v6"
248         .size   cpu_elf_name, . - cpu_elf_name
249         .align
250
251         .section ".proc.info.init", #alloc, #execinstr
252
253         /*
254          * Match any ARMv6 processor core.
255          */
256         .type   __v6_proc_info, #object
257 __v6_proc_info:
258         .long   0x0007b000
259         .long   0x0007f000
260         .long   PMD_TYPE_SECT | \
261                 PMD_SECT_BUFFERABLE | \
262                 PMD_SECT_CACHEABLE | \
263                 PMD_SECT_AP_WRITE | \
264                 PMD_SECT_AP_READ
265         b       __v6_setup
266         .long   cpu_arch_name
267         .long   cpu_elf_name
268         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
269         .long   cpu_v6_name
270         .long   v6_processor_functions
271         .long   v6wbi_tlb_fns
272         .long   v6_user_fns
273         .long   v6_cache_fns
274         .size   __v6_proc_info, . - __v6_proc_info