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