]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - arch/arm/mm/cache-v6.S
Merge branch 'x86-pat-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6.git] / arch / arm / mm / cache-v6.S
1 /*
2  *  linux/arch/arm/mm/cache-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 <linux/init.h>
14 #include <asm/assembler.h>
15 #include <asm/unwind.h>
16
17 #include "proc-macros.S"
18
19 #define HARVARD_CACHE
20 #define CACHE_LINE_SIZE         32
21 #define D_CACHE_LINE_SIZE       32
22 #define BTB_FLUSH_SIZE          8
23
24 #ifdef CONFIG_ARM_ERRATA_411920
25 /*
26  * Invalidate the entire I cache (this code is a workaround for the ARM1136
27  * erratum 411920 - Invalidate Instruction Cache operation can fail. This
28  * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
29  *
30  * Registers:
31  *   r0 - set to 0
32  *   r1 - corrupted
33  */
34 ENTRY(v6_icache_inval_all)
35         mov     r0, #0
36         mrs     r1, cpsr
37         cpsid   ifa                             @ disable interrupts
38         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
39         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
40         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
41         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
42         msr     cpsr_cx, r1                     @ restore interrupts
43         .rept   11                              @ ARM Ltd recommends at least
44         nop                                     @ 11 NOPs
45         .endr
46         mov     pc, lr
47 #endif
48
49 /*
50  *      v6_flush_cache_all()
51  *
52  *      Flush the entire cache.
53  *
54  *      It is assumed that:
55  */
56 ENTRY(v6_flush_kern_cache_all)
57         mov     r0, #0
58 #ifdef HARVARD_CACHE
59         mcr     p15, 0, r0, c7, c14, 0          @ D cache clean+invalidate
60 #ifndef CONFIG_ARM_ERRATA_411920
61         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
62 #else
63         b       v6_icache_inval_all
64 #endif
65 #else
66         mcr     p15, 0, r0, c7, c15, 0          @ Cache clean+invalidate
67 #endif
68         mov     pc, lr
69
70 /*
71  *      v6_flush_cache_all()
72  *
73  *      Flush all TLB entries in a particular address space
74  *
75  *      - mm    - mm_struct describing address space
76  */
77 ENTRY(v6_flush_user_cache_all)
78         /*FALLTHROUGH*/
79
80 /*
81  *      v6_flush_cache_range(start, end, flags)
82  *
83  *      Flush a range of TLB entries in the specified address space.
84  *
85  *      - start - start address (may not be aligned)
86  *      - end   - end address (exclusive, may not be aligned)
87  *      - flags - vm_area_struct flags describing address space
88  *
89  *      It is assumed that:
90  *      - we have a VIPT cache.
91  */
92 ENTRY(v6_flush_user_cache_range)
93         mov     pc, lr
94
95 /*
96  *      v6_coherent_kern_range(start,end)
97  *
98  *      Ensure that the I and D caches are coherent within specified
99  *      region.  This is typically used when code has been written to
100  *      a memory region, and will be executed.
101  *
102  *      - start   - virtual start address of region
103  *      - end     - virtual end address of region
104  *
105  *      It is assumed that:
106  *      - the Icache does not read data from the write buffer
107  */
108 ENTRY(v6_coherent_kern_range)
109         /* FALLTHROUGH */
110
111 /*
112  *      v6_coherent_user_range(start,end)
113  *
114  *      Ensure that the I and D caches are coherent within specified
115  *      region.  This is typically used when code has been written to
116  *      a memory region, and will be executed.
117  *
118  *      - start   - virtual start address of region
119  *      - end     - virtual end address of region
120  *
121  *      It is assumed that:
122  *      - the Icache does not read data from the write buffer
123  */
124 ENTRY(v6_coherent_user_range)
125  UNWIND(.fnstart                )
126 #ifdef HARVARD_CACHE
127         bic     r0, r0, #CACHE_LINE_SIZE - 1
128 1:
129  USER(  mcr     p15, 0, r0, c7, c10, 1  )       @ clean D line
130         add     r0, r0, #CACHE_LINE_SIZE
131 2:
132         cmp     r0, r1
133         blo     1b
134 #endif
135         mov     r0, #0
136 #ifdef HARVARD_CACHE
137         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
138 #ifndef CONFIG_ARM_ERRATA_411920
139         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
140 #else
141         b       v6_icache_inval_all
142 #endif
143 #else
144         mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
145 #endif
146         mov     pc, lr
147
148 /*
149  * Fault handling for the cache operation above. If the virtual address in r0
150  * isn't mapped, just try the next page.
151  */
152 9001:
153         mov     r0, r0, lsr #12
154         mov     r0, r0, lsl #12
155         add     r0, r0, #4096
156         b       2b
157  UNWIND(.fnend          )
158 ENDPROC(v6_coherent_user_range)
159 ENDPROC(v6_coherent_kern_range)
160
161 /*
162  *      v6_flush_kern_dcache_area(void *addr, size_t size)
163  *
164  *      Ensure that the data held in the page kaddr is written back
165  *      to the page in question.
166  *
167  *      - addr  - kernel address
168  *      - size  - region size
169  */
170 ENTRY(v6_flush_kern_dcache_area)
171         add     r1, r0, r1
172 1:
173 #ifdef HARVARD_CACHE
174         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
175 #else
176         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate unified line
177 #endif  
178         add     r0, r0, #D_CACHE_LINE_SIZE
179         cmp     r0, r1
180         blo     1b
181 #ifdef HARVARD_CACHE
182         mov     r0, #0
183         mcr     p15, 0, r0, c7, c10, 4
184 #endif
185         mov     pc, lr
186
187
188 /*
189  *      v6_dma_inv_range(start,end)
190  *
191  *      Invalidate the data cache within the specified region; we will
192  *      be performing a DMA operation in this region and we want to
193  *      purge old data in the cache.
194  *
195  *      - start   - virtual start address of region
196  *      - end     - virtual end address of region
197  */
198 v6_dma_inv_range:
199         tst     r0, #D_CACHE_LINE_SIZE - 1
200         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
201 #ifdef HARVARD_CACHE
202         mcrne   p15, 0, r0, c7, c10, 1          @ clean D line
203 #else
204         mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
205 #endif
206         tst     r1, #D_CACHE_LINE_SIZE - 1
207         bic     r1, r1, #D_CACHE_LINE_SIZE - 1
208 #ifdef HARVARD_CACHE
209         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
210 #else
211         mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
212 #endif
213 1:
214 #ifdef CONFIG_SMP
215         str     r0, [r0]                        @ write for ownership
216 #endif
217 #ifdef HARVARD_CACHE
218         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
219 #else
220         mcr     p15, 0, r0, c7, c7, 1           @ invalidate unified line
221 #endif
222         add     r0, r0, #D_CACHE_LINE_SIZE
223         cmp     r0, r1
224         blo     1b
225         mov     r0, #0
226         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
227         mov     pc, lr
228
229 /*
230  *      v6_dma_clean_range(start,end)
231  *      - start   - virtual start address of region
232  *      - end     - virtual end address of region
233  */
234 v6_dma_clean_range:
235         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
236 1:
237 #ifdef CONFIG_SMP
238         ldr     r2, [r0]                        @ read for ownership
239 #endif
240 #ifdef HARVARD_CACHE
241         mcr     p15, 0, r0, c7, c10, 1          @ clean D line
242 #else
243         mcr     p15, 0, r0, c7, c11, 1          @ clean unified line
244 #endif
245         add     r0, r0, #D_CACHE_LINE_SIZE
246         cmp     r0, r1
247         blo     1b
248         mov     r0, #0
249         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
250         mov     pc, lr
251
252 /*
253  *      v6_dma_flush_range(start,end)
254  *      - start   - virtual start address of region
255  *      - end     - virtual end address of region
256  */
257 ENTRY(v6_dma_flush_range)
258         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
259 1:
260 #ifdef CONFIG_SMP
261         ldr     r2, [r0]                        @ read for ownership
262         str     r2, [r0]                        @ write for ownership
263 #endif
264 #ifdef HARVARD_CACHE
265         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
266 #else
267         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate line
268 #endif
269         add     r0, r0, #D_CACHE_LINE_SIZE
270         cmp     r0, r1
271         blo     1b
272         mov     r0, #0
273         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
274         mov     pc, lr
275
276 /*
277  *      dma_map_area(start, size, dir)
278  *      - start - kernel virtual start address
279  *      - size  - size of region
280  *      - dir   - DMA direction
281  */
282 ENTRY(v6_dma_map_area)
283         add     r1, r1, r0
284         teq     r2, #DMA_FROM_DEVICE
285         beq     v6_dma_inv_range
286         teq     r2, #DMA_TO_DEVICE
287         beq     v6_dma_clean_range
288         b       v6_dma_flush_range
289 ENDPROC(v6_dma_map_area)
290
291 /*
292  *      dma_unmap_area(start, size, dir)
293  *      - start - kernel virtual start address
294  *      - size  - size of region
295  *      - dir   - DMA direction
296  */
297 ENTRY(v6_dma_unmap_area)
298         mov     pc, lr
299 ENDPROC(v6_dma_unmap_area)
300
301         __INITDATA
302
303         .type   v6_cache_fns, #object
304 ENTRY(v6_cache_fns)
305         .long   v6_flush_kern_cache_all
306         .long   v6_flush_user_cache_all
307         .long   v6_flush_user_cache_range
308         .long   v6_coherent_kern_range
309         .long   v6_coherent_user_range
310         .long   v6_flush_kern_dcache_area
311         .long   v6_dma_map_area
312         .long   v6_dma_unmap_area
313         .long   v6_dma_flush_range
314         .size   v6_cache_fns, . - v6_cache_fns