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 <linux/cfi_types.h> 12#include <asm/assembler.h> 13#include <asm/errno.h> 14#include <asm/unwind.h> 15 16#include "proc-macros.S" 17 18#define HARVARD_CACHE 19#define CACHE_LINE_SIZE 32 20#define D_CACHE_LINE_SIZE 32 21#define BTB_FLUSH_SIZE 8 22 23.arch armv6 24 25/* 26 * v6_flush_icache_all() 27 * 28 * Flush the whole I-cache. 29 * 30 * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. 31 * This erratum is present in 1136, 1156 and 1176. It does not affect the 32 * MPCore. 33 * 34 * Registers: 35 * r0 - set to 0 36 * r1 - corrupted 37 */ 38SYM_TYPED_FUNC_START(v6_flush_icache_all) 39 mov r0, #0 40#ifdef CONFIG_ARM_ERRATA_411920 41 mrs r1, cpsr 42 cpsid ifa @ disable interrupts 43 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 44 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 45 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 46 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 47 msr cpsr_cx, r1 @ restore interrupts 48 .rept 11 @ ARM Ltd recommends at least 49 nop @ 11 NOPs 50 .endr 51#else 52 mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache 53#endif 54 ret lr 55SYM_FUNC_END(v6_flush_icache_all) 56 57/* 58 * v6_flush_cache_all() 59 * 60 * Flush the entire cache. 61 * 62 * It is assumed that: 63 */ 64SYM_TYPED_FUNC_START(v6_flush_kern_cache_all) 65 mov r0, #0 66#ifdef HARVARD_CACHE 67 mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate 68#ifndef CONFIG_ARM_ERRATA_411920 69 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 70#else 71 b v6_flush_icache_all 72#endif 73#else 74 mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate 75#endif 76 ret lr 77SYM_FUNC_END(v6_flush_kern_cache_all) 78 79/* 80 * v6_flush_cache_all() 81 * 82 * Flush all TLB entries in a particular address space 83 * 84 * - mm - mm_struct describing address space 85 */ 86SYM_TYPED_FUNC_START(v6_flush_user_cache_all) 87 ret lr 88SYM_FUNC_END(v6_flush_user_cache_all) 89 90/* 91 * v6_flush_cache_range(start, end, flags) 92 * 93 * Flush a range of TLB entries in the specified address space. 94 * 95 * - start - start address (may not be aligned) 96 * - end - end address (exclusive, may not be aligned) 97 * - flags - vm_area_struct flags describing address space 98 * 99 * It is assumed that: 100 * - we have a VIPT cache. 101 */ 102SYM_TYPED_FUNC_START(v6_flush_user_cache_range) 103 ret lr 104SYM_FUNC_END(v6_flush_user_cache_range) 105 106/* 107 * v6_coherent_kern_range(start,end) 108 * 109 * Ensure that the I and D caches are coherent within specified 110 * region. This is typically used when code has been written to 111 * a memory region, and will be executed. 112 * 113 * - start - virtual start address of region 114 * - end - virtual end address of region 115 * 116 * It is assumed that: 117 * - the Icache does not read data from the write buffer 118 */ 119SYM_TYPED_FUNC_START(v6_coherent_kern_range) 120#ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */ 121 b v6_coherent_user_range 122#endif 123SYM_FUNC_END(v6_coherent_kern_range) 124 125/* 126 * v6_coherent_user_range(start,end) 127 * 128 * Ensure that the I and D caches are coherent within specified 129 * region. This is typically used when code has been written to 130 * a memory region, and will be executed. 131 * 132 * - start - virtual start address of region 133 * - end - virtual end address of region 134 * 135 * It is assumed that: 136 * - the Icache does not read data from the write buffer 137 */ 138SYM_TYPED_FUNC_START(v6_coherent_user_range) 139 UNWIND(.fnstart ) 140#ifdef HARVARD_CACHE 141 bic r0, r0, #CACHE_LINE_SIZE - 1 1421: 143 USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line 144 add r0, r0, #CACHE_LINE_SIZE 145 cmp r0, r1 146 blo 1b 147#endif 148 mov r0, #0 149#ifdef HARVARD_CACHE 150 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 151#ifndef CONFIG_ARM_ERRATA_411920 152 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 153#else 154 b v6_flush_icache_all 155#endif 156#else 157 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 158#endif 159 ret lr 160 161/* 162 * Fault handling for the cache operation above. If the virtual address in r0 163 * isn't mapped, fail with -EFAULT. 164 */ 1659001: 166 mov r0, #-EFAULT 167 ret lr 168 UNWIND(.fnend ) 169SYM_FUNC_END(v6_coherent_user_range) 170 171/* 172 * v6_flush_kern_dcache_area(void *addr, size_t size) 173 * 174 * Ensure that the data held in the page kaddr is written back 175 * to the page in question. 176 * 177 * - addr - kernel address 178 * - size - region size 179 */ 180SYM_TYPED_FUNC_START(v6_flush_kern_dcache_area) 181 add r1, r0, r1 182 bic r0, r0, #D_CACHE_LINE_SIZE - 1 1831: 184#ifdef HARVARD_CACHE 185 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 186#else 187 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate unified line 188#endif 189 add r0, r0, #D_CACHE_LINE_SIZE 190 cmp r0, r1 191 blo 1b 192#ifdef HARVARD_CACHE 193 mov r0, #0 194 mcr p15, 0, r0, c7, c10, 4 195#endif 196 ret lr 197SYM_FUNC_END(v6_flush_kern_dcache_area) 198 199/* 200 * v6_dma_inv_range(start,end) 201 * 202 * Invalidate the data cache within the specified region; we will 203 * be performing a DMA operation in this region and we want to 204 * purge old data in the cache. 205 * 206 * - start - virtual start address of region 207 * - end - virtual end address of region 208 */ 209v6_dma_inv_range: 210 tst r0, #D_CACHE_LINE_SIZE - 1 211 bic r0, r0, #D_CACHE_LINE_SIZE - 1 212#ifdef HARVARD_CACHE 213 mcrne p15, 0, r0, c7, c10, 1 @ clean D line 214#else 215 mcrne p15, 0, r0, c7, c11, 1 @ clean unified line 216#endif 217 tst r1, #D_CACHE_LINE_SIZE - 1 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 blo 1b 233 mov r0, #0 234 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 235 ret lr 236 237/* 238 * v6_dma_clean_range(start,end) 239 * - start - virtual start address of region 240 * - end - virtual end address of region 241 */ 242v6_dma_clean_range: 243 bic r0, r0, #D_CACHE_LINE_SIZE - 1 2441: 245#ifdef HARVARD_CACHE 246 mcr p15, 0, r0, c7, c10, 1 @ clean D line 247#else 248 mcr p15, 0, r0, c7, c11, 1 @ clean unified line 249#endif 250 add r0, r0, #D_CACHE_LINE_SIZE 251 cmp r0, r1 252 blo 1b 253 mov r0, #0 254 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 255 ret lr 256 257/* 258 * v6_dma_flush_range(start,end) 259 * - start - virtual start address of region 260 * - end - virtual end address of region 261 */ 262SYM_TYPED_FUNC_START(v6_dma_flush_range) 263 bic r0, r0, #D_CACHE_LINE_SIZE - 1 2641: 265#ifdef HARVARD_CACHE 266 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 267#else 268 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate line 269#endif 270 add r0, r0, #D_CACHE_LINE_SIZE 271 cmp r0, r1 272 blo 1b 273 mov r0, #0 274 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 275 ret lr 276SYM_FUNC_END(v6_dma_flush_range) 277 278/* 279 * dma_map_area(start, size, dir) 280 * - start - kernel virtual start address 281 * - size - size of region 282 * - dir - DMA direction 283 */ 284SYM_TYPED_FUNC_START(v6_dma_map_area) 285 add r1, r1, r0 286 teq r2, #DMA_FROM_DEVICE 287 beq v6_dma_inv_range 288 b v6_dma_clean_range 289SYM_FUNC_END(v6_dma_map_area) 290 291/* 292 * dma_unmap_area(start, size, dir) 293 * - start - kernel virtual start address 294 * - size - size of region 295 * - dir - DMA direction 296 */ 297SYM_TYPED_FUNC_START(v6_dma_unmap_area) 298 add r1, r1, r0 299 teq r2, #DMA_TO_DEVICE 300 bne v6_dma_inv_range 301 ret lr 302SYM_FUNC_END(v6_dma_unmap_area) 303