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