MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / arm / mm / cache-fa.S
blob9524d21a28f272b7050ffc6296b8bea25e05f473
1 /*
2  *  linux/arch/arm/mm/cache-fa.S
3  *
4  *  Copyright (C) 2005 Faraday Corp.
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  *  Processors: FA520 FA526 FA626       
11  * 03/31/2005 : Luke Lee created, modified from cache-v4wb.S
12  * 04/06/2005 : 1. Read CR0-1 and determine the cache size dynamically,
13  *                 to suit all Faraday CPU series
14  *              2. Fixed all functions
15  * 04/08/2005 : insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE
16  * 04/12/2005 : TODO: make this processor dependent or a self-modifying code to 
17  *              inline cache len/size info into the instructions, as reading cache 
18  *              size and len info in memory could cause another cache miss.
19  * 05/05/2005 : Modify fa_flush_user_cache_range to comply APCS.
20  * 05/19/2005 : Adjust for boundary conditions.
21  */
22 #include <linux/config.h>
23 #include <linux/linkage.h>
24 #include <linux/init.h>
25 #include <asm/hardware.h>
26 #include <asm/page.h>
27 #include "proc-macros.S"
29 #define CACHE_DLINESIZE    16
30 #define CACHE_DSIZE        16384
31 #define CACHE_ILINESIZE    16
32 #define CACHE_ISIZE        16384
35  *      initialize_cache_info()
36  *
37  *      Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to 
38  *      system register CR0-1
39  *      Destroyed register: r0, r1, r2, r3, ip
40  */
41         .align
42 ENTRY(fa_initialize_cache_info)
43         mov     r3, #1                          @ r3 always = 1
44         adr     ip, __fa_cache_ilen
45         
46         mrc     p15, 0, r0, c0, c0, 1
47         /* ILEN */
48         and     r1, r0, #3                      @ bits [1:0]
49         add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
50         mov     r2, r3, lsl r1                  @ r2 = 1<<r1
51         str     r2, [ip], #4
52         /* ISIZE */
53         mov     r1, r0, lsr #6                  @ bits [8:6]
54         and     r1, r1, #7
55         add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
56         mov     r2, r3, lsl r1
57         str     r2, [ip], #4
58         /* DLEN */
59         mov     r1, r0, lsr #12
60         and     r1, r1, #3                      @ bits [13:12]
61         add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
62         mov     r2, r3, lsl r1                  @ r2 = 1<<r1
63         str     r2, [ip], #4
64         /* DSIZE */
65         mov     r1, r0, lsr #18                 @ bits [20:18]
66         and     r1, r1, #7
67         add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
68         mov     r2, r3, lsl r1
69         str     r2, [ip]
70         mov     pc, lr
72         /* Warning : Do not change the order ! Successive codes depends on this */
73         .align
74         .globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
75 __fa_cache_ilen:
76         .word   0                               @ instruction cache line length
77 __fa_cache_isize:
78         .word   0                               @ instruction cache size
79 __fa_cache_dlen:
80         .word   0                               @ data cahce line length        
81 __fa_cache_dsize:
82         .word   0                               @ data cache size
85  *      flush_user_cache_all()
86  *
87  *      Clean and invalidate all cache entries in a particular address
88  *      space.
89  */
90 ENTRY(fa_flush_user_cache_all)
91         /* FALLTHROUGH */
93  *      flush_kern_cache_all()
94  *
95  *      Clean and invalidate the entire cache.
96  */
97 ENTRY(fa_flush_kern_cache_all)
98         mov     ip, #0
99         
100 #ifndef CONFIG_CPU_ICACHE_DISABLE
101         mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
102 #endif
103         
104 __flush_whole_cache:
105         
106 #ifndef CONFIG_CPU_DCACHE_DISABLE
107         mov     ip, #0
108 #  ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
109         mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
110 #  else
111         mcr     p15, 0, ip, c7,c14, 0           @ clean/invalidate D cache
112 #  endif
113 #endif /*CONFIG_CPU_DCACHE_DISABLE*/
114         
115 #ifndef CONFIG_CPU_FA_WB_DISABLE        
116         mcr     p15, 0, ip, c7, c10, 4          @ drain write buffer
117 #endif
118         
119 #ifdef CONFIG_CPU_FA_BTB
120         mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
121         nop
122         nop
123 #endif
124         
125         mov     pc, lr
128  *      flush_user_cache_range(start, end, flags)
130  *      Invalidate a range of cache entries in the specified
131  *      address space.
133  *      - start - start address (inclusive, page aligned)
134  *      - end   - end address (exclusive, page aligned)
135  *      - flags - vma_area_struct flags describing address space
136  */
137 ENTRY(fa_flush_user_cache_range)
138         mov     ip, #0
139         sub     r3, r1, r0                      @ calculate total size
140 #ifndef CONFIG_CPU_ICACHE_DISABLE
141         tst     r2, #VM_EXEC                    @ executable region?
142         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
143 #endif
145 #ifndef CONFIG_CPU_DCACHE_DISABLE       
146         cmp     r3, #CACHE_DSIZE                @ total size >= limit?
147         bhs     __flush_whole_cache             @ flush whole D cache
150         
151 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
152         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
153 #else
154         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
155 #endif
156         add     r0, r0, #CACHE_DLINESIZE
157         cmp     r0, r1
158         bls     1b
159 #endif  /* CONFIG_CPU_DCACHE_DISABLE */
160         
161 #ifndef CONFIG_CPU_FA_WB_DISABLE
162         tst     r2, #VM_EXEC
163         mcreq   p15, 0, r4, c7, c10, 4          @ drain write buffer
164 #endif
166 #ifdef CONFIG_CPU_FA_BTB
167         tst     r2, #VM_EXEC
168         mov     ip, #0
169         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
170         nop
171         nop
172 #endif
173         mov     pc, lr
176  *      flush_kern_dcache_page(void *page)
178  *      Ensure no D cache aliasing occurs, either with itself or
179  *      the I cache
181  *      - addr  - page aligned address
182  */
183 ENTRY(fa_flush_kern_dcache_page)
184         add     r1, r0, #PAGE_SZ
185         /* fall through */
188  *      coherent_kern_range(start, end)
190  *      Ensure coherency between the Icache and the Dcache in the
191  *      region described by start.  If you have non-snooping
192  *      Harvard caches, you need to implement this function.
194  *      - start  - virtual start address
195  *      - end    - virtual end address
196  */
197 ENTRY(fa_coherent_kern_range)
198         /* fall through */
201  *      coherent_user_range(start, end)
203  *      Ensure coherency between the Icache and the Dcache in the
204  *      region described by start.  If you have non-snooping
205  *      Harvard caches, you need to implement this function.
207  *      - start  - virtual start address
208  *      - end    - virtual end address
209  */
210 ENTRY(fa_coherent_user_range)
211         bic     r0, r0, #CACHE_DLINESIZE-1
213 #if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE))
215 #ifndef CONFIG_CPU_DCACHE_DISABLE       
216 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
217         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
218 #else
219         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
220 #endif
221 #endif /* CONFIG_CPU_DCACHE_DISABLE */
222         
223 #ifndef CONFIG_CPU_ICACHE_DISABLE
224         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
225 #endif
226         add     r0, r0, #CACHE_DLINESIZE
227         cmp     r0, r1
228         bls     1b                              @ Luke Lee 05/19/2005 blo->bls  
229 #endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
231         mov     ip, #0
232 #ifdef CONFIG_CPU_FA_BTB
233         mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
234         nop
235         nop
236 #endif
238 #ifndef CONFIG_CPU_FA_WB_DISABLE
239         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
240 #endif
241         
242         mov     pc, lr
245  *      dma_inv_range(start, end)
247  *      Invalidate (discard) the specified virtual address range.
248  *      May not write back any entries.  If 'start' or 'end'
249  *      are not cache line aligned, those lines must be written
250  *      back.
252  *      - start  - virtual start address
253  *      - end    - virtual end address
254  */
255 ENTRY(fa_dma_inv_range)
257 #ifndef CONFIG_CPU_DCACHE_DISABLE       
259 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
260         tst     r0, #CACHE_DLINESIZE -1
261         bic     r0, r0, #CACHE_DLINESIZE -1
262         mcrne   p15, 0, r0, c7, c10, 1          @ clean boundary D entry
263         mcr     p15, 0, r1, c7, c10, 1          @ clean boundary D entry
264 #else
265         bic     r0, r0, #CACHE_DLINESIZE -1     
266 #endif
267         
268 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
269         add     r0, r0, #CACHE_DLINESIZE
270         cmp     r0, r1
271         bls     1b                              @ Luke Lee 05/19/2005 blo->bls
272 #endif /* CONFIG_CPU_DCACHE_DISABLE */
274 #ifndef CONFIG_CPU_FA_WB_DISABLE
275         mov     r0, #0
276         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
277 #endif  
278         mov     pc, lr
281  *      dma_clean_range(start, end)
283  *      Clean (write back) the specified virtual address range.
285  *      - start  - virtual start address
286  *      - end    - virtual end address
287  */
288 ENTRY(fa_dma_clean_range)
290 #ifndef CONFIG_CPU_DCACHE_DISABLE       
292 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
293         bic     r0, r0, #CACHE_DLINESIZE - 1
294 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
295         add     r0, r0, #CACHE_DLINESIZE
296         cmp     r0, r1
297         bls     1b                              @ Luke Lee 05/19/2005 blo->bls
299 #endif
300 #endif /* CONFIG_CPU_DCACHE_DISABLE */
302 #ifndef CONFIG_CPU_FA_WB_DISABLE
303         mov     r0, #0  
304         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
305 #endif  
306         mov     pc, lr
309  *      dma_flush_range(start, end)
311  *      Clean and invalidate the specified virtual address range.
313  *      - start  - virtual start address
314  *      - end    - virtual end address
316  *      This is actually the same as fa_coherent_kern_range()
317  */
318         .globl  fa_dma_flush_range
319         .set    fa_dma_flush_range, fa_coherent_kern_range
321         __INITDATA
323         .type   fa_cache_fns, #object
324 ENTRY(fa_cache_fns)
325         .long   fa_flush_kern_cache_all
326         .long   fa_flush_user_cache_all
327         .long   fa_flush_user_cache_range
328         .long   fa_coherent_kern_range
329         .long   fa_coherent_user_range
330         .long   fa_flush_kern_dcache_page
331         .long   fa_dma_inv_range
332         .long   fa_dma_clean_range
333         .long   fa_dma_flush_range
334         .size   fa_cache_fns, . - fa_cache_fns