1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * linux/arch/arm/mm/cache-v6.S 4 * 5 * Copyright (C) 2001 Deep Blue Solutions Ltd. 6 * 7 * This is the "shell" of the ARMv6 processor support. 8 */ 9#include <linux/linkage.h> 10#include <linux/init.h> 11#include <asm/assembler.h> 12#include <asm/errno.h> 13#include <asm/unwind.h> 14 15#include "proc-macros.S" 16 17#define HARVARD_CACHE 18#define CACHE_LINE_SIZE 32 19#define D_CACHE_LINE_SIZE 32 20#define BTB_FLUSH_SIZE 8 21 22/* 23 * v6_flush_icache_all() 24 * 25 * Flush the whole I-cache. 26 * 27 * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. 28 * This erratum is present in 1136, 1156 and 1176. It does not affect the 29 * MPCore. 30 * 31 * Registers: 32 * r0 - set to 0 33 * r1 - corrupted 34 */ 35ENTRY(v6_flush_icache_all) 36 mov r0, #0 37#ifdef CONFIG_ARM_ERRATA_411920 38 mrs r1, cpsr 39 cpsid ifa @ disable interrupts 40 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 41 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 42 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 43 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 44 msr cpsr_cx, r1 @ restore interrupts 45 .rept 11 @ ARM Ltd recommends at least 46 nop @ 11 NOPs 47 .endr 48#else 49 mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache 50#endif 51 ret lr 52ENDPROC(v6_flush_icache_all) 53 54/* 55 * v6_flush_cache_all() 56 * 57 * Flush the entire cache. 58 * 59 * It is assumed that: 60 */ 61ENTRY(v6_flush_kern_cache_all) 62 mov r0, #0 63#ifdef HARVARD_CACHE 64 mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate 65#ifndef CONFIG_ARM_ERRATA_411920 66 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 67#else 68 b v6_flush_icache_all 69#endif 70#else 71 mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate 72#endif 73 ret lr 74 75/* 76 * v6_flush_cache_all() 77 * 78 * Flush all TLB entries in a particular address space 79 * 80 * - mm - mm_struct describing address space 81 */ 82ENTRY(v6_flush_user_cache_all) 83 /*FALLTHROUGH*/ 84 85/* 86 * v6_flush_cache_range(start, end, flags) 87 * 88 * Flush a range of TLB entries in the specified address space. 89 * 90 * - start - start address (may not be aligned) 91 * - end - end address (exclusive, may not be aligned) 92 * - flags - vm_area_struct flags describing address space 93 * 94 * It is assumed that: 95 * - we have a VIPT cache. 96 */ 97ENTRY(v6_flush_user_cache_range) 98 ret lr 99 100/* 101 * v6_coherent_kern_range(start,end) 102 * 103 * Ensure that the I and D caches are coherent within specified 104 * region. This is typically used when code has been written to 105 * a memory region, and will be executed. 106 * 107 * - start - virtual start address of region 108 * - end - virtual end address of region 109 * 110 * It is assumed that: 111 * - the Icache does not read data from the write buffer 112 */ 113ENTRY(v6_coherent_kern_range) 114 /* FALLTHROUGH */ 115 116/* 117 * v6_coherent_user_range(start,end) 118 * 119 * Ensure that the I and D caches are coherent within specified 120 * region. This is typically used when code has been written to 121 * a memory region, and will be executed. 122 * 123 * - start - virtual start address of region 124 * - end - virtual end address of region 125 * 126 * It is assumed that: 127 * - the Icache does not read data from the write buffer 128 */ 129ENTRY(v6_coherent_user_range) 130 UNWIND(.fnstart ) 131#ifdef HARVARD_CACHE 132 bic r0, r0, #CACHE_LINE_SIZE - 1 1331: 134 USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line 135 add r0, r0, #CACHE_LINE_SIZE 136 cmp r0, r1 137 blo 1b 138#endif 139 mov r0, #0 140#ifdef HARVARD_CACHE 141 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 142#ifndef CONFIG_ARM_ERRATA_411920 143 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 144#else 145 b v6_flush_icache_all 146#endif 147#else 148 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 149#endif 150 ret lr 151 152/* 153 * Fault handling for the cache operation above. If the virtual address in r0 154 * isn't mapped, fail with -EFAULT. 155 */ 1569001: 157 mov r0, #-EFAULT 158 ret lr 159 UNWIND(.fnend ) 160ENDPROC(v6_coherent_user_range) 161ENDPROC(v6_coherent_kern_range) 162 163/* 164 * v6_flush_kern_dcache_area(void *addr, size_t size) 165 * 166 * Ensure that the data held in the page kaddr is written back 167 * to the page in question. 168 * 169 * - addr - kernel address 170 * - size - region size 171 */ 172ENTRY(v6_flush_kern_dcache_area) 173 add r1, r0, r1 174 bic r0, r0, #D_CACHE_LINE_SIZE - 1 1751: 176#ifdef HARVARD_CACHE 177 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 178#else 179 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate unified line 180#endif 181 add r0, r0, #D_CACHE_LINE_SIZE 182 cmp r0, r1 183 blo 1b 184#ifdef HARVARD_CACHE 185 mov r0, #0 186 mcr p15, 0, r0, c7, c10, 4 187#endif 188 ret lr 189 190 191/* 192 * v6_dma_inv_range(start,end) 193 * 194 * Invalidate the data cache within the specified region; we will 195 * be performing a DMA operation in this region and we want to 196 * purge old data in the cache. 197 * 198 * - start - virtual start address of region 199 * - end - virtual end address of region 200 */ 201v6_dma_inv_range: 202#ifdef CONFIG_DMA_CACHE_RWFO 203 ldrb r2, [r0] @ read for ownership 204 strb r2, [r0] @ write for ownership 205#endif 206 tst r0, #D_CACHE_LINE_SIZE - 1 207 bic r0, r0, #D_CACHE_LINE_SIZE - 1 208#ifdef HARVARD_CACHE 209 mcrne p15, 0, r0, c7, c10, 1 @ clean D line 210#else 211 mcrne p15, 0, r0, c7, c11, 1 @ clean unified line 212#endif 213 tst r1, #D_CACHE_LINE_SIZE - 1 214#ifdef CONFIG_DMA_CACHE_RWFO 215 ldrbne r2, [r1, #-1] @ read for ownership 216 strbne r2, [r1, #-1] @ write for ownership 217#endif 218 bic r1, r1, #D_CACHE_LINE_SIZE - 1 219#ifdef HARVARD_CACHE 220 mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line 221#else 222 mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line 223#endif 2241: 225#ifdef HARVARD_CACHE 226 mcr p15, 0, r0, c7, c6, 1 @ invalidate D line 227#else 228 mcr p15, 0, r0, c7, c7, 1 @ invalidate unified line 229#endif 230 add r0, r0, #D_CACHE_LINE_SIZE 231 cmp r0, r1 232#ifdef CONFIG_DMA_CACHE_RWFO 233 ldrlo r2, [r0] @ read for ownership 234 strlo r2, [r0] @ write for ownership 235#endif 236 blo 1b 237 mov r0, #0 238 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 239 ret lr 240 241/* 242 * v6_dma_clean_range(start,end) 243 * - start - virtual start address of region 244 * - end - virtual end address of region 245 */ 246v6_dma_clean_range: 247 bic r0, r0, #D_CACHE_LINE_SIZE - 1 2481: 249#ifdef CONFIG_DMA_CACHE_RWFO 250 ldr r2, [r0] @ read for ownership 251#endif 252#ifdef HARVARD_CACHE 253 mcr p15, 0, r0, c7, c10, 1 @ clean D line 254#else 255 mcr p15, 0, r0, c7, c11, 1 @ clean unified line 256#endif 257 add r0, r0, #D_CACHE_LINE_SIZE 258 cmp r0, r1 259 blo 1b 260 mov r0, #0 261 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 262 ret lr 263 264/* 265 * v6_dma_flush_range(start,end) 266 * - start - virtual start address of region 267 * - end - virtual end address of region 268 */ 269ENTRY(v6_dma_flush_range) 270#ifdef CONFIG_DMA_CACHE_RWFO 271 ldrb r2, [r0] @ read for ownership 272 strb r2, [r0] @ write for ownership 273#endif 274 bic r0, r0, #D_CACHE_LINE_SIZE - 1 2751: 276#ifdef HARVARD_CACHE 277 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 278#else 279 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate line 280#endif 281 add r0, r0, #D_CACHE_LINE_SIZE 282 cmp r0, r1 283#ifdef CONFIG_DMA_CACHE_RWFO 284 ldrblo r2, [r0] @ read for ownership 285 strblo r2, [r0] @ write for ownership 286#endif 287 blo 1b 288 mov r0, #0 289 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 290 ret lr 291 292/* 293 * dma_map_area(start, size, dir) 294 * - start - kernel virtual start address 295 * - size - size of region 296 * - dir - DMA direction 297 */ 298ENTRY(v6_dma_map_area) 299 add r1, r1, r0 300 teq r2, #DMA_FROM_DEVICE 301 beq v6_dma_inv_range 302#ifndef CONFIG_DMA_CACHE_RWFO 303 b v6_dma_clean_range 304#else 305 teq r2, #DMA_TO_DEVICE 306 beq v6_dma_clean_range 307 b v6_dma_flush_range 308#endif 309ENDPROC(v6_dma_map_area) 310 311/* 312 * dma_unmap_area(start, size, dir) 313 * - start - kernel virtual start address 314 * - size - size of region 315 * - dir - DMA direction 316 */ 317ENTRY(v6_dma_unmap_area) 318#ifndef CONFIG_DMA_CACHE_RWFO 319 add r1, r1, r0 320 teq r2, #DMA_TO_DEVICE 321 bne v6_dma_inv_range 322#endif 323 ret lr 324ENDPROC(v6_dma_unmap_area) 325 326 .globl v6_flush_kern_cache_louis 327 .equ v6_flush_kern_cache_louis, v6_flush_kern_cache_all 328 329 __INITDATA 330 331 @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 332 define_cache_functions v6 333