Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[pandora-kernel.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_page(kaddr)
131  *
132  *      Ensure that the data held in the page kaddr is written back
133  *      to the page in question.
134  *
135  *      - kaddr   - kernel address (guaranteed to be page aligned)
136  */
137 ENTRY(fa_flush_kern_dcache_page)
138         add     r1, r0, #PAGE_SZ
139 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
140         add     r0, r0, #CACHE_DLINESIZE
141         cmp     r0, r1
142         blo     1b
143         mov     r0, #0
144         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
145         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
146         mov     pc, lr
147
148 /*
149  *      dma_inv_range(start, end)
150  *
151  *      Invalidate (discard) the specified virtual address range.
152  *      May not write back any entries.  If 'start' or 'end'
153  *      are not cache line aligned, those lines must be written
154  *      back.
155  *
156  *      - start  - virtual start address
157  *      - end    - virtual end address
158  */
159 ENTRY(fa_dma_inv_range)
160         tst     r0, #CACHE_DLINESIZE - 1
161         bic     r0, r0, #CACHE_DLINESIZE - 1
162         mcrne   p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
163         tst     r1, #CACHE_DLINESIZE - 1
164         bic     r1, r1, #CACHE_DLINESIZE - 1
165         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D entry
166 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
167         add     r0, r0, #CACHE_DLINESIZE
168         cmp     r0, r1
169         blo     1b
170         mov     r0, #0
171         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
172         mov     pc, lr
173
174 /*
175  *      dma_clean_range(start, end)
176  *
177  *      Clean (write back) the specified virtual address range.
178  *
179  *      - start  - virtual start address
180  *      - end    - virtual end address
181  */
182 ENTRY(fa_dma_clean_range)
183         bic     r0, r0, #CACHE_DLINESIZE - 1
184 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
185         add     r0, r0, #CACHE_DLINESIZE
186         cmp     r0, r1
187         blo     1b
188         mov     r0, #0  
189         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
190         mov     pc, lr
191
192 /*
193  *      dma_flush_range(start,end)
194  *      - start   - virtual start address of region
195  *      - end     - virtual end address of region
196  */
197 ENTRY(fa_dma_flush_range)
198         bic     r0, r0, #CACHE_DLINESIZE - 1
199 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
200         add     r0, r0, #CACHE_DLINESIZE
201         cmp     r0, r1
202         blo     1b
203         mov     r0, #0  
204         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
205         mov     pc, lr
206
207         __INITDATA
208
209         .type   fa_cache_fns, #object
210 ENTRY(fa_cache_fns)
211         .long   fa_flush_kern_cache_all
212         .long   fa_flush_user_cache_all
213         .long   fa_flush_user_cache_range
214         .long   fa_coherent_kern_range
215         .long   fa_coherent_user_range
216         .long   fa_flush_kern_dcache_page
217         .long   fa_dma_inv_range
218         .long   fa_dma_clean_range
219         .long   fa_dma_flush_range
220         .size   fa_cache_fns, . - fa_cache_fns