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 <linux/cfi_types.h> 16#include <asm/assembler.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 */ 43SYM_TYPED_FUNC_START(fa_flush_icache_all) 44 mov r0, #0 45 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 46 ret lr 47SYM_FUNC_END(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 */ 55SYM_FUNC_ALIAS(fa_flush_user_cache_all, fa_flush_kern_cache_all) 56 57/* 58 * flush_kern_cache_all() 59 * 60 * Clean and invalidate the entire cache. 61 */ 62SYM_TYPED_FUNC_START(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 73SYM_FUNC_END(fa_flush_kern_cache_all) 74 75/* 76 * flush_user_cache_range(start, end, flags) 77 * 78 * Invalidate a range of cache entries in the specified 79 * address space. 80 * 81 * - start - start address (inclusive, page aligned) 82 * - end - end address (exclusive, page aligned) 83 * - flags - vma_area_struct flags describing address space 84 */ 85SYM_TYPED_FUNC_START(fa_flush_user_cache_range) 86 mov ip, #0 87 sub r3, r1, r0 @ calculate total size 88 cmp r3, #CACHE_DLIMIT @ total size >= limit? 89 bhs __flush_whole_cache @ flush whole D cache 90 911: tst r2, #VM_EXEC 92 mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line 93 mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 94 add r0, r0, #CACHE_DLINESIZE 95 cmp r0, r1 96 blo 1b 97 tst r2, #VM_EXEC 98 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 99 mcrne p15, 0, ip, c7, c10, 4 @ data write barrier 100 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 101 ret lr 102SYM_FUNC_END(fa_flush_user_cache_range) 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 */ 114SYM_TYPED_FUNC_START(fa_coherent_kern_range) 115#ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */ 116 b fa_coherent_user_range 117#endif 118SYM_FUNC_END(fa_coherent_kern_range) 119 120/* 121 * coherent_user_range(start, end) 122 * 123 * Ensure coherency between the Icache and the Dcache in the 124 * region described by start. If you have non-snooping 125 * Harvard caches, you need to implement this function. 126 * 127 * - start - virtual start address 128 * - end - virtual end address 129 */ 130SYM_TYPED_FUNC_START(fa_coherent_user_range) 131 bic r0, r0, #CACHE_DLINESIZE - 1 1321: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 133 mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 134 add r0, r0, #CACHE_DLINESIZE 135 cmp r0, r1 136 blo 1b 137 mov r0, #0 138 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 139 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 140 mcr p15, 0, r0, c7, c5, 4 @ prefetch flush 141 ret lr 142SYM_FUNC_END(fa_coherent_user_range) 143 144/* 145 * flush_kern_dcache_area(void *addr, size_t size) 146 * 147 * Ensure that the data held in the page kaddr is written back 148 * to the page in question. 149 * 150 * - addr - kernel address 151 * - size - size of region 152 */ 153SYM_TYPED_FUNC_START(fa_flush_kern_dcache_area) 154 add r1, r0, r1 1551: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 156 add r0, r0, #CACHE_DLINESIZE 157 cmp r0, r1 158 blo 1b 159 mov r0, #0 160 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 161 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 162 ret lr 163SYM_FUNC_END(fa_flush_kern_dcache_area) 164 165/* 166 * dma_inv_range(start, end) 167 * 168 * Invalidate (discard) the specified virtual address range. 169 * May not write back any entries. If 'start' or 'end' 170 * are not cache line aligned, those lines must be written 171 * back. 172 * 173 * - start - virtual start address 174 * - end - virtual end address 175 */ 176fa_dma_inv_range: 177 tst r0, #CACHE_DLINESIZE - 1 178 bic r0, r0, #CACHE_DLINESIZE - 1 179 mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 180 tst r1, #CACHE_DLINESIZE - 1 181 bic r1, r1, #CACHE_DLINESIZE - 1 182 mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry 1831: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 184 add r0, r0, #CACHE_DLINESIZE 185 cmp r0, r1 186 blo 1b 187 mov r0, #0 188 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 189 ret lr 190 191/* 192 * dma_clean_range(start, end) 193 * 194 * Clean (write back) the specified virtual address range. 195 * 196 * - start - virtual start address 197 * - end - virtual end address 198 */ 199fa_dma_clean_range: 200 bic r0, r0, #CACHE_DLINESIZE - 1 2011: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 202 add r0, r0, #CACHE_DLINESIZE 203 cmp r0, r1 204 blo 1b 205 mov r0, #0 206 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 207 ret lr 208 209/* 210 * dma_flush_range(start,end) 211 * - start - virtual start address of region 212 * - end - virtual end address of region 213 */ 214SYM_TYPED_FUNC_START(fa_dma_flush_range) 215 bic r0, r0, #CACHE_DLINESIZE - 1 2161: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 217 add r0, r0, #CACHE_DLINESIZE 218 cmp r0, r1 219 blo 1b 220 mov r0, #0 221 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 222 ret lr 223SYM_FUNC_END(fa_dma_flush_range) 224 225/* 226 * dma_map_area(start, size, dir) 227 * - start - kernel virtual start address 228 * - size - size of region 229 * - dir - DMA direction 230 */ 231SYM_TYPED_FUNC_START(fa_dma_map_area) 232 add r1, r1, r0 233 cmp r2, #DMA_TO_DEVICE 234 beq fa_dma_clean_range 235 bcs fa_dma_inv_range 236 b fa_dma_flush_range 237SYM_FUNC_END(fa_dma_map_area) 238 239/* 240 * dma_unmap_area(start, size, dir) 241 * - start - kernel virtual start address 242 * - size - size of region 243 * - dir - DMA direction 244 */ 245SYM_TYPED_FUNC_START(fa_dma_unmap_area) 246 ret lr 247SYM_FUNC_END(fa_dma_unmap_area) 248