2 * linux/arch/arm/mm/cache-fa.S
4 * Copyright (C) 2005 Faraday Corp.
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.
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.
22 #include <linux/config.h>
23 #include <linux/linkage.h>
24 #include <linux/init.h>
25 #include <asm/hardware.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()
37 * Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to
38 * system register CR0-1
39 * Destroyed register: r0, r1, r2, r3, ip
42 ENTRY(fa_initialize_cache_info)
43 mov r3, #1 @ r3 always = 1
44 adr ip, __fa_cache_ilen
46 mrc p15, 0, r0, c0, c0, 1
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
53 mov r1, r0, lsr #6 @ bits [8:6]
55 add r1, r1, #9 @ cache size is at least 512 bytes (2^9)
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
65 mov r1, r0, lsr #18 @ bits [20:18]
67 add r1, r1, #9 @ cache size is at least 512 bytes (2^9)
72 /* Warning : Do not change the order ! Successive codes depends on this */
74 .globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
76 .word 0 @ instruction cache line length
78 .word 0 @ instruction cache size
80 .word 0 @ data cahce line length
82 .word 0 @ data cache size
85 * flush_user_cache_all()
87 * Clean and invalidate all cache entries in a particular address
90 ENTRY(fa_flush_user_cache_all)
93 * flush_kern_cache_all()
95 * Clean and invalidate the entire cache.
97 ENTRY(fa_flush_kern_cache_all)
100 #ifndef CONFIG_CPU_ICACHE_DISABLE
101 mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
106 #ifndef CONFIG_CPU_DCACHE_DISABLE
108 # ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
109 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
111 mcr p15, 0, ip, c7,c14, 0 @ clean/invalidate D cache
113 #endif /*CONFIG_CPU_DCACHE_DISABLE*/
115 #ifndef CONFIG_CPU_FA_WB_DISABLE
116 mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
119 #ifdef CONFIG_CPU_FA_BTB
120 mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB
128 * flush_user_cache_range(start, end, flags)
130 * Invalidate a range of cache entries in the specified
133 * - start - start address (inclusive, page aligned)
134 * - end - end address (exclusive, page aligned)
135 * - flags - vma_area_struct flags describing address space
137 ENTRY(fa_flush_user_cache_range)
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
145 #ifndef CONFIG_CPU_DCACHE_DISABLE
146 cmp r3, #CACHE_DSIZE @ total size >= limit?
147 bhs __flush_whole_cache @ flush whole D cache
151 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
152 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
154 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
156 add r0, r0, #CACHE_DLINESIZE
159 #endif /* CONFIG_CPU_DCACHE_DISABLE */
161 #ifndef CONFIG_CPU_FA_WB_DISABLE
163 mcreq p15, 0, r4, c7, c10, 4 @ drain write buffer
166 #ifdef CONFIG_CPU_FA_BTB
169 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
176 * flush_kern_dcache_page(void *page)
178 * Ensure no D cache aliasing occurs, either with itself or
181 * - addr - page aligned address
183 ENTRY(fa_flush_kern_dcache_page)
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
197 ENTRY(fa_coherent_kern_range)
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
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
219 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
221 #endif /* CONFIG_CPU_DCACHE_DISABLE */
223 #ifndef CONFIG_CPU_ICACHE_DISABLE
224 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
226 add r0, r0, #CACHE_DLINESIZE
228 bls 1b @ Luke Lee 05/19/2005 blo->bls
229 #endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
232 #ifdef CONFIG_CPU_FA_BTB
233 mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB
238 #ifndef CONFIG_CPU_FA_WB_DISABLE
239 mcr p15, 0, ip, c7, c10, 4 @ drain WB
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
252 * - start - virtual start address
253 * - end - virtual end address
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
265 bic r0, r0, #CACHE_DLINESIZE -1
268 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
269 add r0, r0, #CACHE_DLINESIZE
271 bls 1b @ Luke Lee 05/19/2005 blo->bls
272 #endif /* CONFIG_CPU_DCACHE_DISABLE */
274 #ifndef CONFIG_CPU_FA_WB_DISABLE
276 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
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
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
297 bls 1b @ Luke Lee 05/19/2005 blo->bls
300 #endif /* CONFIG_CPU_DCACHE_DISABLE */
302 #ifndef CONFIG_CPU_FA_WB_DISABLE
304 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
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()
318 .globl fa_dma_flush_range
319 .set fa_dma_flush_range, fa_coherent_kern_range
323 .type fa_cache_fns, #object
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