1*d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 21da177e4SLinus Torvalds/* 31da177e4SLinus Torvalds * linux/arch/arm/mm/cache-v4wb.S 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1997-2002 Russell king 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds#include <linux/linkage.h> 81da177e4SLinus Torvalds#include <linux/init.h> 96ebbf2ceSRussell King#include <asm/assembler.h> 101da177e4SLinus Torvalds#include <asm/page.h> 111da177e4SLinus Torvalds#include "proc-macros.S" 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds/* 141da177e4SLinus Torvalds * The size of one data cache line. 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds#define CACHE_DLINESIZE 32 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds/* 191da177e4SLinus Torvalds * The total size of the data cache. 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds#if defined(CONFIG_CPU_SA110) 221da177e4SLinus Torvalds# define CACHE_DSIZE 16384 231da177e4SLinus Torvalds#elif defined(CONFIG_CPU_SA1100) 241da177e4SLinus Torvalds# define CACHE_DSIZE 8192 251da177e4SLinus Torvalds#else 261da177e4SLinus Torvalds# error Unknown cache size 271da177e4SLinus Torvalds#endif 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds/* 301da177e4SLinus Torvalds * This is the size at which it becomes more efficient to 311da177e4SLinus Torvalds * clean the whole cache, rather than using the individual 3225985edcSLucas De Marchi * cache line maintenance instructions. 331da177e4SLinus Torvalds * 341da177e4SLinus Torvalds * Size Clean (ticks) Dirty (ticks) 351da177e4SLinus Torvalds * 4096 21 20 21 53 55 54 361da177e4SLinus Torvalds * 8192 40 41 40 106 100 102 371da177e4SLinus Torvalds * 16384 77 77 76 140 140 138 381da177e4SLinus Torvalds * 32768 150 149 150 214 216 212 <--- 391da177e4SLinus Torvalds * 65536 296 297 296 351 358 361 401da177e4SLinus Torvalds * 131072 591 591 591 656 657 651 411da177e4SLinus Torvalds * Whole 132 136 132 221 217 207 <--- 421da177e4SLinus Torvalds */ 431da177e4SLinus Torvalds#define CACHE_DLIMIT (CACHE_DSIZE * 4) 441da177e4SLinus Torvalds 4595f3df6bSRussell King .data 461abd3502SRussell King .align 2 4795f3df6bSRussell Kingflush_base: 4895f3df6bSRussell King .long FLUSH_BASE 4995f3df6bSRussell King .text 5095f3df6bSRussell King 511da177e4SLinus Torvalds/* 52c8c90860SMika Westerberg * flush_icache_all() 53c8c90860SMika Westerberg * 54c8c90860SMika Westerberg * Unconditionally clean and invalidate the entire icache. 55c8c90860SMika Westerberg */ 56c8c90860SMika WesterbergENTRY(v4wb_flush_icache_all) 57c8c90860SMika Westerberg mov r0, #0 58c8c90860SMika Westerberg mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 596ebbf2ceSRussell King ret lr 60c8c90860SMika WesterbergENDPROC(v4wb_flush_icache_all) 61c8c90860SMika Westerberg 62c8c90860SMika Westerberg/* 631da177e4SLinus Torvalds * flush_user_cache_all() 641da177e4SLinus Torvalds * 651da177e4SLinus Torvalds * Clean and invalidate all cache entries in a particular address 661da177e4SLinus Torvalds * space. 671da177e4SLinus Torvalds */ 681da177e4SLinus TorvaldsENTRY(v4wb_flush_user_cache_all) 691da177e4SLinus Torvalds /* FALLTHROUGH */ 701da177e4SLinus Torvalds/* 711da177e4SLinus Torvalds * flush_kern_cache_all() 721da177e4SLinus Torvalds * 731da177e4SLinus Torvalds * Clean and invalidate the entire cache. 741da177e4SLinus Torvalds */ 751da177e4SLinus TorvaldsENTRY(v4wb_flush_kern_cache_all) 761da177e4SLinus Torvalds mov ip, #0 771da177e4SLinus Torvalds mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache 781da177e4SLinus Torvalds__flush_whole_cache: 7995f3df6bSRussell King ldr r3, =flush_base 8095f3df6bSRussell King ldr r1, [r3, #0] 8195f3df6bSRussell King eor r1, r1, #CACHE_DSIZE 8295f3df6bSRussell King str r1, [r3, #0] 8395f3df6bSRussell King add r2, r1, #CACHE_DSIZE 8495f3df6bSRussell King1: ldr r3, [r1], #32 8595f3df6bSRussell King cmp r1, r2 861da177e4SLinus Torvalds blo 1b 8795f3df6bSRussell King#ifdef FLUSH_BASE_MINICACHE 8895f3df6bSRussell King add r2, r2, #FLUSH_BASE_MINICACHE - FLUSH_BASE 8995f3df6bSRussell King sub r1, r2, #512 @ only 512 bytes 9095f3df6bSRussell King1: ldr r3, [r1], #32 9195f3df6bSRussell King cmp r1, r2 9295f3df6bSRussell King blo 1b 9395f3df6bSRussell King#endif 941da177e4SLinus Torvalds mcr p15, 0, ip, c7, c10, 4 @ drain write buffer 956ebbf2ceSRussell King ret lr 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds/* 981da177e4SLinus Torvalds * flush_user_cache_range(start, end, flags) 991da177e4SLinus Torvalds * 1001da177e4SLinus Torvalds * Invalidate a range of cache entries in the specified 1011da177e4SLinus Torvalds * address space. 1021da177e4SLinus Torvalds * 1031da177e4SLinus Torvalds * - start - start address (inclusive, page aligned) 1041da177e4SLinus Torvalds * - end - end address (exclusive, page aligned) 1051da177e4SLinus Torvalds * - flags - vma_area_struct flags describing address space 1061da177e4SLinus Torvalds */ 1071da177e4SLinus TorvaldsENTRY(v4wb_flush_user_cache_range) 10895f3df6bSRussell King mov ip, #0 1091da177e4SLinus Torvalds sub r3, r1, r0 @ calculate total size 1101da177e4SLinus Torvalds tst r2, #VM_EXEC @ executable region? 1111da177e4SLinus Torvalds mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds cmp r3, #CACHE_DLIMIT @ total size >= limit? 1141da177e4SLinus Torvalds bhs __flush_whole_cache @ flush whole D cache 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 1171da177e4SLinus Torvalds mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 1181da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 1191da177e4SLinus Torvalds cmp r0, r1 1201da177e4SLinus Torvalds blo 1b 1211da177e4SLinus Torvalds tst r2, #VM_EXEC 1221da177e4SLinus Torvalds mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer 1236ebbf2ceSRussell King ret lr 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds/* 1262c9b9c84SRussell King * flush_kern_dcache_area(void *addr, size_t size) 1271da177e4SLinus Torvalds * 1281da177e4SLinus Torvalds * Ensure no D cache aliasing occurs, either with itself or 1291da177e4SLinus Torvalds * the I cache 1301da177e4SLinus Torvalds * 1312c9b9c84SRussell King * - addr - kernel address 1322c9b9c84SRussell King * - size - region size 1331da177e4SLinus Torvalds */ 1342c9b9c84SRussell KingENTRY(v4wb_flush_kern_dcache_area) 1352c9b9c84SRussell King add r1, r0, r1 1361da177e4SLinus Torvalds /* fall through */ 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds/* 1391da177e4SLinus Torvalds * coherent_kern_range(start, end) 1401da177e4SLinus Torvalds * 1411da177e4SLinus Torvalds * Ensure coherency between the Icache and the Dcache in the 1421da177e4SLinus Torvalds * region described by start. If you have non-snooping 1431da177e4SLinus Torvalds * Harvard caches, you need to implement this function. 1441da177e4SLinus Torvalds * 1451da177e4SLinus Torvalds * - start - virtual start address 1461da177e4SLinus Torvalds * - end - virtual end address 1471da177e4SLinus Torvalds */ 1481da177e4SLinus TorvaldsENTRY(v4wb_coherent_kern_range) 1491da177e4SLinus Torvalds /* fall through */ 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds/* 1521da177e4SLinus Torvalds * coherent_user_range(start, end) 1531da177e4SLinus Torvalds * 1541da177e4SLinus Torvalds * Ensure coherency between the Icache and the Dcache in the 1551da177e4SLinus Torvalds * region described by start. If you have non-snooping 1561da177e4SLinus Torvalds * Harvard caches, you need to implement this function. 1571da177e4SLinus Torvalds * 1581da177e4SLinus Torvalds * - start - virtual start address 1591da177e4SLinus Torvalds * - end - virtual end address 1601da177e4SLinus Torvalds */ 1611da177e4SLinus TorvaldsENTRY(v4wb_coherent_user_range) 1621da177e4SLinus Torvalds bic r0, r0, #CACHE_DLINESIZE - 1 1631da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 1641da177e4SLinus Torvalds mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 1651da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 1661da177e4SLinus Torvalds cmp r0, r1 1671da177e4SLinus Torvalds blo 1b 168c5102f59SWill Deacon mov r0, #0 169c5102f59SWill Deacon mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 170c5102f59SWill Deacon mcr p15, 0, r0, c7, c10, 4 @ drain WB 1716ebbf2ceSRussell King ret lr 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds/* 1751da177e4SLinus Torvalds * dma_inv_range(start, end) 1761da177e4SLinus Torvalds * 1771da177e4SLinus Torvalds * Invalidate (discard) the specified virtual address range. 1781da177e4SLinus Torvalds * May not write back any entries. If 'start' or 'end' 1791da177e4SLinus Torvalds * are not cache line aligned, those lines must be written 1801da177e4SLinus Torvalds * back. 1811da177e4SLinus Torvalds * 1821da177e4SLinus Torvalds * - start - virtual start address 1831da177e4SLinus Torvalds * - end - virtual end address 1841da177e4SLinus Torvalds */ 185702b94bfSRussell Kingv4wb_dma_inv_range: 1861da177e4SLinus Torvalds tst r0, #CACHE_DLINESIZE - 1 1871da177e4SLinus Torvalds bic r0, r0, #CACHE_DLINESIZE - 1 1881da177e4SLinus Torvalds mcrne p15, 0, r0, c7, c10, 1 @ clean D entry 1891da177e4SLinus Torvalds tst r1, #CACHE_DLINESIZE - 1 1901da177e4SLinus Torvalds mcrne p15, 0, r1, c7, c10, 1 @ clean D entry 1911da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 1921da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 1931da177e4SLinus Torvalds cmp r0, r1 1941da177e4SLinus Torvalds blo 1b 1951da177e4SLinus Torvalds mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 1966ebbf2ceSRussell King ret lr 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds/* 1991da177e4SLinus Torvalds * dma_clean_range(start, end) 2001da177e4SLinus Torvalds * 2011da177e4SLinus Torvalds * Clean (write back) the specified virtual address range. 2021da177e4SLinus Torvalds * 2031da177e4SLinus Torvalds * - start - virtual start address 2041da177e4SLinus Torvalds * - end - virtual end address 2051da177e4SLinus Torvalds */ 206702b94bfSRussell Kingv4wb_dma_clean_range: 2071da177e4SLinus Torvalds bic r0, r0, #CACHE_DLINESIZE - 1 2081da177e4SLinus Torvalds1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 2091da177e4SLinus Torvalds add r0, r0, #CACHE_DLINESIZE 2101da177e4SLinus Torvalds cmp r0, r1 2111da177e4SLinus Torvalds blo 1b 2121da177e4SLinus Torvalds mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 2136ebbf2ceSRussell King ret lr 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds/* 2161da177e4SLinus Torvalds * dma_flush_range(start, end) 2171da177e4SLinus Torvalds * 2181da177e4SLinus Torvalds * Clean and invalidate the specified virtual address range. 2191da177e4SLinus Torvalds * 2201da177e4SLinus Torvalds * - start - virtual start address 2211da177e4SLinus Torvalds * - end - virtual end address 2221da177e4SLinus Torvalds * 2231da177e4SLinus Torvalds * This is actually the same as v4wb_coherent_kern_range() 2241da177e4SLinus Torvalds */ 2251da177e4SLinus Torvalds .globl v4wb_dma_flush_range 2261da177e4SLinus Torvalds .set v4wb_dma_flush_range, v4wb_coherent_kern_range 2271da177e4SLinus Torvalds 228a9c9147eSRussell King/* 229a9c9147eSRussell King * dma_map_area(start, size, dir) 230a9c9147eSRussell King * - start - kernel virtual start address 231a9c9147eSRussell King * - size - size of region 232a9c9147eSRussell King * - dir - DMA direction 233a9c9147eSRussell King */ 234a9c9147eSRussell KingENTRY(v4wb_dma_map_area) 235a9c9147eSRussell King add r1, r1, r0 236a9c9147eSRussell King cmp r2, #DMA_TO_DEVICE 237a9c9147eSRussell King beq v4wb_dma_clean_range 238a9c9147eSRussell King bcs v4wb_dma_inv_range 239a9c9147eSRussell King b v4wb_dma_flush_range 240a9c9147eSRussell KingENDPROC(v4wb_dma_map_area) 241a9c9147eSRussell King 242a9c9147eSRussell King/* 243a9c9147eSRussell King * dma_unmap_area(start, size, dir) 244a9c9147eSRussell King * - start - kernel virtual start address 245a9c9147eSRussell King * - size - size of region 246a9c9147eSRussell King * - dir - DMA direction 247a9c9147eSRussell King */ 248a9c9147eSRussell KingENTRY(v4wb_dma_unmap_area) 2496ebbf2ceSRussell King ret lr 250a9c9147eSRussell KingENDPROC(v4wb_dma_unmap_area) 251a9c9147eSRussell King 252031bd879SLorenzo Pieralisi .globl v4wb_flush_kern_cache_louis 253031bd879SLorenzo Pieralisi .equ v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all 254031bd879SLorenzo Pieralisi 2551da177e4SLinus Torvalds __INITDATA 2561da177e4SLinus Torvalds 257eec95e56SDave Martin @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) 258eec95e56SDave Martin define_cache_functions v4wb 259