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_icache_all() 42 * 43 * Unconditionally clean and invalidate the entire icache. 44 */ 45ENTRY(fa_flush_icache_all) 46 mov r0, #0 47 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 48 mov pc, lr 49ENDPROC(fa_flush_icache_all) 50 51/* 52 * flush_user_cache_all() 53 * 54 * Clean and invalidate all cache entries in a particular address 55 * space. 56 */ 57ENTRY(fa_flush_user_cache_all) 58 /* FALLTHROUGH */ 59/* 60 * flush_kern_cache_all() 61 * 62 * Clean and invalidate the entire cache. 63 */ 64ENTRY(fa_flush_kern_cache_all) 65 mov ip, #0 66 mov r2, #VM_EXEC 67__flush_whole_cache: 68 mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache 69 tst r2, #VM_EXEC 70 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 71 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 72 mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer 73 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 74 mov pc, lr 75 76/* 77 * flush_user_cache_range(start, end, flags) 78 * 79 * Invalidate a range of cache entries in the specified 80 * address space. 81 * 82 * - start - start address (inclusive, page aligned) 83 * - end - end address (exclusive, page aligned) 84 * - flags - vma_area_struct flags describing address space 85 */ 86ENTRY(fa_flush_user_cache_range) 87 mov ip, #0 88 sub r3, r1, r0 @ calculate total size 89 cmp r3, #CACHE_DLIMIT @ total size >= limit? 90 bhs __flush_whole_cache @ flush whole D cache 91 921: tst r2, #VM_EXEC 93 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line 94 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 95 add r0, r0, #CACHE_DLINESIZE 96 cmp r0, r1 97 blo 1b 98 tst r2, #VM_EXEC 99 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 100 mcrne p15, 0, ip, c7, c10, 4 @ data write barrier 101 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 102 mov pc, lr 103 104/* 105 * coherent_kern_range(start, end) 106 * 107 * Ensure coherency between the Icache and the Dcache in the 108 * region described by start. If you have non-snooping 109 * Harvard caches, you need to implement this function. 110 * 111 * - start - virtual start address 112 * - end - virtual end address 113 */ 114ENTRY(fa_coherent_kern_range) 115 /* fall through */ 116 117/* 118 * coherent_user_range(start, end) 119 * 120 * Ensure coherency between the Icache and the Dcache in the 121 * region described by start. If you have non-snooping 122 * Harvard caches, you need to implement this function. 123 * 124 * - start - virtual start address 125 * - end - virtual end address 126 */ 127ENTRY(fa_coherent_user_range) 128 bic r0, r0, #CACHE_DLINESIZE - 1 1291: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 130 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 131 add r0, r0, #CACHE_DLINESIZE 132 cmp r0, r1 133 blo 1b 134 mov r0, #0 135 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 136 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 137 mcr p15, 0, r0, c7, c5, 4 @ prefetch flush 138 mov pc, lr 139 140/* 141 * flush_kern_dcache_area(void *addr, size_t size) 142 * 143 * Ensure that the data held in the page kaddr is written back 144 * to the page in question. 145 * 146 * - addr - kernel address 147 * - size - size of region 148 */ 149ENTRY(fa_flush_kern_dcache_area) 150 add r1, r0, r1 1511: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 152 add r0, r0, #CACHE_DLINESIZE 153 cmp r0, r1 154 blo 1b 155 mov r0, #0 156 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 157 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 158 mov pc, lr 159 160/* 161 * dma_inv_range(start, end) 162 * 163 * Invalidate (discard) the specified virtual address range. 164 * May not write back any entries. If 'start' or 'end' 165 * are not cache line aligned, those lines must be written 166 * back. 167 * 168 * - start - virtual start address 169 * - end - virtual end address 170 */ 171fa_dma_inv_range: 172 tst r0, #CACHE_DLINESIZE - 1 173 bic r0, r0, #CACHE_DLINESIZE - 1 174 mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 175 tst r1, #CACHE_DLINESIZE - 1 176 bic r1, r1, #CACHE_DLINESIZE - 1 177 mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry 1781: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 179 add r0, r0, #CACHE_DLINESIZE 180 cmp r0, r1 181 blo 1b 182 mov r0, #0 183 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 184 mov pc, lr 185 186/* 187 * dma_clean_range(start, end) 188 * 189 * Clean (write back) the specified virtual address range. 190 * 191 * - start - virtual start address 192 * - end - virtual end address 193 */ 194fa_dma_clean_range: 195 bic r0, r0, #CACHE_DLINESIZE - 1 1961: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 197 add r0, r0, #CACHE_DLINESIZE 198 cmp r0, r1 199 blo 1b 200 mov r0, #0 201 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 202 mov pc, lr 203 204/* 205 * dma_flush_range(start,end) 206 * - start - virtual start address of region 207 * - end - virtual end address of region 208 */ 209ENTRY(fa_dma_flush_range) 210 bic r0, r0, #CACHE_DLINESIZE - 1 2111: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 212 add r0, r0, #CACHE_DLINESIZE 213 cmp r0, r1 214 blo 1b 215 mov r0, #0 216 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 217 mov pc, lr 218 219/* 220 * dma_map_area(start, size, dir) 221 * - start - kernel virtual start address 222 * - size - size of region 223 * - dir - DMA direction 224 */ 225ENTRY(fa_dma_map_area) 226 add r1, r1, r0 227 cmp r2, #DMA_TO_DEVICE 228 beq fa_dma_clean_range 229 bcs fa_dma_inv_range 230 b fa_dma_flush_range 231ENDPROC(fa_dma_map_area) 232 233/* 234 * dma_unmap_area(start, size, dir) 235 * - start - kernel virtual start address 236 * - size - size of region 237 * - dir - DMA direction 238 */ 239ENTRY(fa_dma_unmap_area) 240 mov pc, lr 241ENDPROC(fa_dma_unmap_area) 242 243 .globl fa_flush_kern_cache_louis 244 .equ fa_flush_kern_cache_louis, fa_flush_kern_cache_all 245 246 __INITDATA 247 248 @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 249 define_cache_functions fa 250