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#define CACHE_DLIMIT (CACHE_DSIZE * 2) 38 39/* 40 * flush_user_cache_all() 41 * 42 * Clean and invalidate all cache entries in a particular address 43 * space. 44 */ 45ENTRY(fa_flush_user_cache_all) 46 /* FALLTHROUGH */ 47/* 48 * flush_kern_cache_all() 49 * 50 * Clean and invalidate the entire cache. 51 */ 52ENTRY(fa_flush_kern_cache_all) 53 mov ip, #0 54 mov r2, #VM_EXEC 55__flush_whole_cache: 56 mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache 57 tst r2, #VM_EXEC 58 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 59 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 60 mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer 61 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 62 mov pc, lr 63 64/* 65 * flush_user_cache_range(start, end, flags) 66 * 67 * Invalidate a range of cache entries in the specified 68 * address space. 69 * 70 * - start - start address (inclusive, page aligned) 71 * - end - end address (exclusive, page aligned) 72 * - flags - vma_area_struct flags describing address space 73 */ 74ENTRY(fa_flush_user_cache_range) 75 mov ip, #0 76 sub r3, r1, r0 @ calculate total size 77 cmp r3, #CACHE_DLIMIT @ total size >= limit? 78 bhs __flush_whole_cache @ flush whole D cache 79 801: tst r2, #VM_EXEC 81 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line 82 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 83 add r0, r0, #CACHE_DLINESIZE 84 cmp r0, r1 85 blo 1b 86 tst r2, #VM_EXEC 87 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 88 mcrne p15, 0, ip, c7, c10, 4 @ data write barrier 89 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 90 mov pc, lr 91 92/* 93 * coherent_kern_range(start, end) 94 * 95 * Ensure coherency between the Icache and the Dcache in the 96 * region described by start. If you have non-snooping 97 * Harvard caches, you need to implement this function. 98 * 99 * - start - virtual start address 100 * - end - virtual end address 101 */ 102ENTRY(fa_coherent_kern_range) 103 /* fall through */ 104 105/* 106 * coherent_user_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_user_range) 116 bic r0, r0, #CACHE_DLINESIZE - 1 1171: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 118 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 119 add r0, r0, #CACHE_DLINESIZE 120 cmp r0, r1 121 blo 1b 122 mov r0, #0 123 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 124 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 125 mcr p15, 0, r0, c7, c5, 4 @ prefetch flush 126 mov pc, lr 127 128/* 129 * flush_kern_dcache_area(void *addr, size_t size) 130 * 131 * Ensure that the data held in the page kaddr is written back 132 * to the page in question. 133 * 134 * - addr - kernel address 135 * - size - size of region 136 */ 137ENTRY(fa_flush_kern_dcache_area) 138 add r1, r0, r1 1391: 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 */ 159fa_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 1661: 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 */ 182fa_dma_clean_range: 183 bic r0, r0, #CACHE_DLINESIZE - 1 1841: 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 */ 197ENTRY(fa_dma_flush_range) 198 bic r0, r0, #CACHE_DLINESIZE - 1 1991: 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/* 208 * dma_map_area(start, size, dir) 209 * - start - kernel virtual start address 210 * - size - size of region 211 * - dir - DMA direction 212 */ 213ENTRY(fa_dma_map_area) 214 add r1, r1, r0 215 cmp r2, #DMA_TO_DEVICE 216 beq fa_dma_clean_range 217 bcs fa_dma_inv_range 218 b fa_dma_flush_range 219ENDPROC(fa_dma_map_area) 220 221/* 222 * dma_unmap_area(start, size, dir) 223 * - start - kernel virtual start address 224 * - size - size of region 225 * - dir - DMA direction 226 */ 227ENTRY(fa_dma_unmap_area) 228 mov pc, lr 229ENDPROC(fa_dma_unmap_area) 230 231 __INITDATA 232 233 .type fa_cache_fns, #object 234ENTRY(fa_cache_fns) 235 .long fa_flush_kern_cache_all 236 .long fa_flush_user_cache_all 237 .long fa_flush_user_cache_range 238 .long fa_coherent_kern_range 239 .long fa_coherent_user_range 240 .long fa_flush_kern_dcache_area 241 .long fa_dma_map_area 242 .long fa_dma_unmap_area 243 .long fa_dma_flush_range 244 .size fa_cache_fns, . - fa_cache_fns 245