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