Merge mainline (v2.6.34-rc7)
[sfrench/cifs-2.6.git] / arch / arm / mm / cache-fa.S
1 /*
2  *  linux/arch/arm/mm/cache-fa.S
3  *
4  *  Copyright (C) 2005 Faraday Corp.
5  *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
6  *
7  * Based on cache-v4wb.S:
8  *  Copyright (C) 1997-2002 Russell king
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  *  Processors: FA520 FA526 FA626       
15  */
16 #include <linux/linkage.h>
17 #include <linux/init.h>
18 #include <asm/memory.h>
19 #include <asm/page.h>
20
21 #include "proc-macros.S"
22
23 /*
24  * The size of one data cache line.
25  */
26 #define CACHE_DLINESIZE 16
27
28 /*
29  * The total size of the data cache.
30  */
31 #ifdef CONFIG_ARCH_GEMINI
32 #define CACHE_DSIZE     8192
33 #else
34 #define CACHE_DSIZE     16384 
35 #endif 
36
37 /* FIXME: put optimal value here. Current one is just estimation */
38 #define CACHE_DLIMIT    (CACHE_DSIZE * 2)
39
40 /*
41  *      flush_user_cache_all()
42  *
43  *      Clean and invalidate all cache entries in a particular address
44  *      space.
45  */
46 ENTRY(fa_flush_user_cache_all)
47         /* FALLTHROUGH */
48 /*
49  *      flush_kern_cache_all()
50  *
51  *      Clean and invalidate the entire cache.
52  */
53 ENTRY(fa_flush_kern_cache_all)
54         mov     ip, #0
55         mov     r2, #VM_EXEC
56 __flush_whole_cache:
57         mcr     p15, 0, ip, c7, c14, 0          @ clean/invalidate D cache
58         tst     r2, #VM_EXEC
59         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
60         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
61         mcrne   p15, 0, ip, c7, c10, 4          @ drain write buffer
62         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
63         mov     pc, lr
64
65 /*
66  *      flush_user_cache_range(start, end, flags)
67  *
68  *      Invalidate a range of cache entries in the specified
69  *      address space.
70  *
71  *      - start - start address (inclusive, page aligned)
72  *      - end   - end address (exclusive, page aligned)
73  *      - flags - vma_area_struct flags describing address space
74  */
75 ENTRY(fa_flush_user_cache_range)
76         mov     ip, #0
77         sub     r3, r1, r0                      @ calculate total size
78         cmp     r3, #CACHE_DLIMIT               @ total size >= limit?
79         bhs     __flush_whole_cache             @ flush whole D cache
80
81 1:      tst     r2, #VM_EXEC
82         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I line
83         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
84         add     r0, r0, #CACHE_DLINESIZE
85         cmp     r0, r1
86         blo     1b
87         tst     r2, #VM_EXEC
88         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
89         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
90         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
91         mov     pc, lr
92
93 /*
94  *      coherent_kern_range(start, end)
95  *
96  *      Ensure coherency between the Icache and the Dcache in the
97  *      region described by start.  If you have non-snooping
98  *      Harvard caches, you need to implement this function.
99  *
100  *      - start  - virtual start address
101  *      - end    - virtual end address
102  */
103 ENTRY(fa_coherent_kern_range)
104         /* fall through */
105
106 /*
107  *      coherent_user_range(start, end)
108  *
109  *      Ensure coherency between the Icache and the Dcache in the
110  *      region described by start.  If you have non-snooping
111  *      Harvard caches, you need to implement this function.
112  *
113  *      - start  - virtual start address
114  *      - end    - virtual end address
115  */
116 ENTRY(fa_coherent_user_range)
117         bic     r0, r0, #CACHE_DLINESIZE - 1
118 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
119         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
120         add     r0, r0, #CACHE_DLINESIZE
121         cmp     r0, r1
122         blo     1b
123         mov     r0, #0
124         mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
125         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
126         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
127         mov     pc, lr
128
129 /*
130  *      flush_kern_dcache_area(void *addr, size_t size)
131  *
132  *      Ensure that the data held in the page kaddr is written back
133  *      to the page in question.
134  *
135  *      - addr  - kernel address
136  *      - size  - size of region
137  */
138 ENTRY(fa_flush_kern_dcache_area)
139         add     r1, r0, r1
140 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
141         add     r0, r0, #CACHE_DLINESIZE
142         cmp     r0, r1
143         blo     1b
144         mov     r0, #0
145         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
146         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
147         mov     pc, lr
148
149 /*
150  *      dma_inv_range(start, end)
151  *
152  *      Invalidate (discard) the specified virtual address range.
153  *      May not write back any entries.  If 'start' or 'end'
154  *      are not cache line aligned, those lines must be written
155  *      back.
156  *
157  *      - start  - virtual start address
158  *      - end    - virtual end address
159  */
160 fa_dma_inv_range:
161         tst     r0, #CACHE_DLINESIZE - 1
162         bic     r0, r0, #CACHE_DLINESIZE - 1
163         mcrne   p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
164         tst     r1, #CACHE_DLINESIZE - 1
165         bic     r1, r1, #CACHE_DLINESIZE - 1
166         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D entry
167 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
168         add     r0, r0, #CACHE_DLINESIZE
169         cmp     r0, r1
170         blo     1b
171         mov     r0, #0
172         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
173         mov     pc, lr
174
175 /*
176  *      dma_clean_range(start, end)
177  *
178  *      Clean (write back) the specified virtual address range.
179  *
180  *      - start  - virtual start address
181  *      - end    - virtual end address
182  */
183 fa_dma_clean_range:
184         bic     r0, r0, #CACHE_DLINESIZE - 1
185 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
186         add     r0, r0, #CACHE_DLINESIZE
187         cmp     r0, r1
188         blo     1b
189         mov     r0, #0  
190         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
191         mov     pc, lr
192
193 /*
194  *      dma_flush_range(start,end)
195  *      - start   - virtual start address of region
196  *      - end     - virtual end address of region
197  */
198 ENTRY(fa_dma_flush_range)
199         bic     r0, r0, #CACHE_DLINESIZE - 1
200 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
201         add     r0, r0, #CACHE_DLINESIZE
202         cmp     r0, r1
203         blo     1b
204         mov     r0, #0  
205         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
206         mov     pc, lr
207
208 /*
209  *      dma_map_area(start, size, dir)
210  *      - start - kernel virtual start address
211  *      - size  - size of region
212  *      - dir   - DMA direction
213  */
214 ENTRY(fa_dma_map_area)
215         add     r1, r1, r0
216         cmp     r2, #DMA_TO_DEVICE
217         beq     fa_dma_clean_range
218         bcs     fa_dma_inv_range
219         b       fa_dma_flush_range
220 ENDPROC(fa_dma_map_area)
221
222 /*
223  *      dma_unmap_area(start, size, dir)
224  *      - start - kernel virtual start address
225  *      - size  - size of region
226  *      - dir   - DMA direction
227  */
228 ENTRY(fa_dma_unmap_area)
229         mov     pc, lr
230 ENDPROC(fa_dma_unmap_area)
231
232         __INITDATA
233
234         .type   fa_cache_fns, #object
235 ENTRY(fa_cache_fns)
236         .long   fa_flush_kern_cache_all
237         .long   fa_flush_user_cache_all
238         .long   fa_flush_user_cache_range
239         .long   fa_coherent_kern_range
240         .long   fa_coherent_user_range
241         .long   fa_flush_kern_dcache_area
242         .long   fa_dma_map_area
243         .long   fa_dma_unmap_area
244         .long   fa_dma_flush_range
245         .size   fa_cache_fns, . - fa_cache_fns