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