1*d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 21da177e4SLinus Torvalds/* 31da177e4SLinus Torvalds * linux/arch/arm/mm/cache-v4wt.S 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1997-2002 Russell king 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * ARMv4 write through cache operations support. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * We assume that the write buffer is not enabled. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds#include <linux/linkage.h> 121da177e4SLinus Torvalds#include <linux/init.h> 136ebbf2ceSRussell King#include <asm/assembler.h> 141da177e4SLinus Torvalds#include <asm/page.h> 151da177e4SLinus Torvalds#include "proc-macros.S" 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds/* 181da177e4SLinus Torvalds * The size of one data cache line. 191da177e4SLinus Torvalds */ 201da177e4SLinus Torvalds#define CACHE_DLINESIZE 32 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds/* 231da177e4SLinus Torvalds * The number of data cache segments. 241da177e4SLinus Torvalds */ 251da177e4SLinus Torvalds#define CACHE_DSEGMENTS 8 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds/* 281da177e4SLinus Torvalds * The number of lines in a cache segment. 291da177e4SLinus Torvalds */ 301da177e4SLinus Torvalds#define CACHE_DENTRIES 64 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds/* 331da177e4SLinus Torvalds * This is the size at which it becomes more efficient to 341da177e4SLinus Torvalds * clean the whole cache, rather than using the individual 3525985edcSLucas De Marchi * cache line maintenance instructions. 361da177e4SLinus Torvalds * 371da177e4SLinus Torvalds * *** This needs benchmarking 381da177e4SLinus Torvalds */ 391da177e4SLinus Torvalds#define CACHE_DLIMIT 16384 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds/* 42c8c90860SMika Westerberg * flush_icache_all() 43c8c90860SMika Westerberg * 44c8c90860SMika Westerberg * Unconditionally clean and invalidate the entire icache. 45c8c90860SMika Westerberg */ 46c8c90860SMika WesterbergENTRY(v4wt_flush_icache_all) 47c8c90860SMika Westerberg mov r0, #0 48c8c90860SMika Westerberg mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 496ebbf2ceSRussell King ret lr 50c8c90860SMika WesterbergENDPROC(v4wt_flush_icache_all) 51c8c90860SMika Westerberg 52c8c90860SMika Westerberg/* 531da177e4SLinus Torvalds * flush_user_cache_all() 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * Invalidate all cache entries in a particular address 561da177e4SLinus Torvalds * space. 571da177e4SLinus Torvalds */ 581da177e4SLinus TorvaldsENTRY(v4wt_flush_user_cache_all) 591da177e4SLinus Torvalds /* FALLTHROUGH */ 601da177e4SLinus Torvalds/* 611da177e4SLinus Torvalds * flush_kern_cache_all() 621da177e4SLinus Torvalds * 631da177e4SLinus Torvalds * Clean and invalidate the entire cache. 641da177e4SLinus Torvalds */ 651da177e4SLinus TorvaldsENTRY(v4wt_flush_kern_cache_all) 661da177e4SLinus Torvalds mov r2, #VM_EXEC 671da177e4SLinus Torvalds mov ip, #0 681da177e4SLinus Torvalds__flush_whole_cache: 691da177e4SLinus Torvalds tst r2, #VM_EXEC 701da177e4SLinus Torvalds mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 711da177e4SLinus Torvalds mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache 726ebbf2ceSRussell King ret lr 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds/* 751da177e4SLinus Torvalds * flush_user_cache_range(start, end, flags) 761da177e4SLinus Torvalds * 771da177e4SLinus Torvalds * Clean and invalidate a range of cache entries in the specified 781da177e4SLinus Torvalds * address space. 791da177e4SLinus Torvalds * 801da177e4SLinus Torvalds * - start - start address (inclusive, page aligned) 811da177e4SLinus Torvalds * - end - end address (exclusive, page aligned) 821da177e4SLinus Torvalds * - flags - vma_area_struct flags describing address space 831da177e4SLinus Torvalds */ 841da177e4SLinus TorvaldsENTRY(v4wt_flush_user_cache_range) 851da177e4SLinus Torvalds sub r3, r1, r0 @ calculate total size 861da177e4SLinus Torvalds cmp r3, #CACHE_DLIMIT 871da177e4SLinus Torvalds bhs __flush_whole_cache 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 901da177e4SLinus Torvalds tst r2, #VM_EXEC 911da177e4SLinus Torvalds mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry 921da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 931da177e4SLinus Torvalds cmp r0, r1 941da177e4SLinus Torvalds blo 1b 956ebbf2ceSRussell King ret lr 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds/* 981da177e4SLinus Torvalds * coherent_kern_range(start, end) 991da177e4SLinus Torvalds * 1001da177e4SLinus Torvalds * Ensure coherency between the Icache and the Dcache in the 1011da177e4SLinus Torvalds * region described by start. If you have non-snooping 1021da177e4SLinus Torvalds * Harvard caches, you need to implement this function. 1031da177e4SLinus Torvalds * 1041da177e4SLinus Torvalds * - start - virtual start address 1051da177e4SLinus Torvalds * - end - virtual end address 1061da177e4SLinus Torvalds */ 1071da177e4SLinus TorvaldsENTRY(v4wt_coherent_kern_range) 1081da177e4SLinus Torvalds /* FALLTRHOUGH */ 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds/* 1111da177e4SLinus Torvalds * coherent_user_range(start, end) 1121da177e4SLinus Torvalds * 1131da177e4SLinus Torvalds * Ensure coherency between the Icache and the Dcache in the 1141da177e4SLinus Torvalds * region described by start. If you have non-snooping 1151da177e4SLinus Torvalds * Harvard caches, you need to implement this function. 1161da177e4SLinus Torvalds * 1171da177e4SLinus Torvalds * - start - virtual start address 1181da177e4SLinus Torvalds * - end - virtual end address 1191da177e4SLinus Torvalds */ 1201da177e4SLinus TorvaldsENTRY(v4wt_coherent_user_range) 1211da177e4SLinus Torvalds bic r0, r0, #CACHE_DLINESIZE - 1 1221da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 1231da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 1241da177e4SLinus Torvalds cmp r0, r1 1251da177e4SLinus Torvalds blo 1b 126c5102f59SWill Deacon mov r0, #0 1276ebbf2ceSRussell King ret lr 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds/* 1302c9b9c84SRussell King * flush_kern_dcache_area(void *addr, size_t size) 1311da177e4SLinus Torvalds * 1321da177e4SLinus Torvalds * Ensure no D cache aliasing occurs, either with itself or 1331da177e4SLinus Torvalds * the I cache 1341da177e4SLinus Torvalds * 1352c9b9c84SRussell King * - addr - kernel address 1362c9b9c84SRussell King * - size - region size 1371da177e4SLinus Torvalds */ 1382c9b9c84SRussell KingENTRY(v4wt_flush_kern_dcache_area) 1391da177e4SLinus Torvalds mov r2, #0 1401da177e4SLinus Torvalds mcr p15, 0, r2, c7, c5, 0 @ invalidate I cache 1412c9b9c84SRussell King add r1, r0, r1 1421da177e4SLinus Torvalds /* fallthrough */ 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds/* 1451da177e4SLinus Torvalds * dma_inv_range(start, end) 1461da177e4SLinus Torvalds * 1471da177e4SLinus Torvalds * Invalidate (discard) the specified virtual address range. 1481da177e4SLinus Torvalds * May not write back any entries. If 'start' or 'end' 1491da177e4SLinus Torvalds * are not cache line aligned, those lines must be written 1501da177e4SLinus Torvalds * back. 1511da177e4SLinus Torvalds * 1521da177e4SLinus Torvalds * - start - virtual start address 1531da177e4SLinus Torvalds * - end - virtual end address 1541da177e4SLinus Torvalds */ 155702b94bfSRussell Kingv4wt_dma_inv_range: 1561da177e4SLinus Torvalds bic r0, r0, #CACHE_DLINESIZE - 1 1571da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 1581da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 1591da177e4SLinus Torvalds cmp r0, r1 1601da177e4SLinus Torvalds blo 1b 1616ebbf2ceSRussell King ret lr 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds/* 1641da177e4SLinus Torvalds * dma_flush_range(start, end) 1651da177e4SLinus Torvalds * 1661da177e4SLinus Torvalds * Clean and invalidate the specified virtual address range. 1671da177e4SLinus Torvalds * 1681da177e4SLinus Torvalds * - start - virtual start address 1691da177e4SLinus Torvalds * - end - virtual end address 1701da177e4SLinus Torvalds */ 1711da177e4SLinus Torvalds .globl v4wt_dma_flush_range 1721da177e4SLinus Torvalds .equ v4wt_dma_flush_range, v4wt_dma_inv_range 1731da177e4SLinus Torvalds 174a9c9147eSRussell King/* 175a9c9147eSRussell King * dma_unmap_area(start, size, dir) 176a9c9147eSRussell King * - start - kernel virtual start address 177a9c9147eSRussell King * - size - size of region 178a9c9147eSRussell King * - dir - DMA direction 179a9c9147eSRussell King */ 180a9c9147eSRussell KingENTRY(v4wt_dma_unmap_area) 181a9c9147eSRussell King add r1, r1, r0 182a9c9147eSRussell King teq r2, #DMA_TO_DEVICE 183a9c9147eSRussell King bne v4wt_dma_inv_range 184a9c9147eSRussell King /* FALLTHROUGH */ 185a9c9147eSRussell King 186a9c9147eSRussell King/* 187a9c9147eSRussell King * dma_map_area(start, size, dir) 188a9c9147eSRussell King * - start - kernel virtual start address 189a9c9147eSRussell King * - size - size of region 190a9c9147eSRussell King * - dir - DMA direction 191a9c9147eSRussell King */ 192a9c9147eSRussell KingENTRY(v4wt_dma_map_area) 1936ebbf2ceSRussell King ret lr 194a9c9147eSRussell KingENDPROC(v4wt_dma_unmap_area) 195a9c9147eSRussell KingENDPROC(v4wt_dma_map_area) 196a9c9147eSRussell King 197031bd879SLorenzo Pieralisi .globl v4wt_flush_kern_cache_louis 198031bd879SLorenzo Pieralisi .equ v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all 199031bd879SLorenzo Pieralisi 2001da177e4SLinus Torvalds __INITDATA 2011da177e4SLinus Torvalds 202d5b5b2e2SDave Martin @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 203d5b5b2e2SDave Martin define_cache_functions v4wt 204