Merge branch 'tc1100-wmi' into release
[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 ENTRY(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 ENTRY(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         __INITDATA
209
210         .type   fa_cache_fns, #object
211 ENTRY(fa_cache_fns)
212         .long   fa_flush_kern_cache_all
213         .long   fa_flush_user_cache_all
214         .long   fa_flush_user_cache_range
215         .long   fa_coherent_kern_range
216         .long   fa_coherent_user_range
217         .long   fa_flush_kern_dcache_area
218         .long   fa_dma_inv_range
219         .long   fa_dma_clean_range
220         .long   fa_dma_flush_range
221         .size   fa_cache_fns, . - fa_cache_fns