1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 228853ac8SPaulius Zaleckas/* 328853ac8SPaulius Zaleckas * linux/arch/arm/mm/cache-fa.S 428853ac8SPaulius Zaleckas * 528853ac8SPaulius Zaleckas * Copyright (C) 2005 Faraday Corp. 628853ac8SPaulius Zaleckas * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> 728853ac8SPaulius Zaleckas * 828853ac8SPaulius Zaleckas * Based on cache-v4wb.S: 928853ac8SPaulius Zaleckas * Copyright (C) 1997-2002 Russell king 1028853ac8SPaulius Zaleckas * 1128853ac8SPaulius Zaleckas * Processors: FA520 FA526 FA626 1228853ac8SPaulius Zaleckas */ 1328853ac8SPaulius Zaleckas#include <linux/linkage.h> 1428853ac8SPaulius Zaleckas#include <linux/init.h> 151036b895SLinus Walleij#include <linux/cfi_types.h> 166ebbf2ceSRussell King#include <asm/assembler.h> 1728853ac8SPaulius Zaleckas#include <asm/page.h> 1828853ac8SPaulius Zaleckas 1928853ac8SPaulius Zaleckas#include "proc-macros.S" 2028853ac8SPaulius Zaleckas 2128853ac8SPaulius Zaleckas/* 2228853ac8SPaulius Zaleckas * The size of one data cache line. 2328853ac8SPaulius Zaleckas */ 2428853ac8SPaulius Zaleckas#define CACHE_DLINESIZE 16 2528853ac8SPaulius Zaleckas 2628853ac8SPaulius Zaleckas/* 2728853ac8SPaulius Zaleckas * The total size of the data cache. 2828853ac8SPaulius Zaleckas */ 2928853ac8SPaulius Zaleckas#ifdef CONFIG_ARCH_GEMINI 3028853ac8SPaulius Zaleckas#define CACHE_DSIZE 8192 3128853ac8SPaulius Zaleckas#else 3228853ac8SPaulius Zaleckas#define CACHE_DSIZE 16384 3328853ac8SPaulius Zaleckas#endif 3428853ac8SPaulius Zaleckas 3528853ac8SPaulius Zaleckas/* FIXME: put optimal value here. Current one is just estimation */ 3628853ac8SPaulius Zaleckas#define CACHE_DLIMIT (CACHE_DSIZE * 2) 3728853ac8SPaulius Zaleckas 3828853ac8SPaulius Zaleckas/* 39c8c90860SMika Westerberg * flush_icache_all() 40c8c90860SMika Westerberg * 41c8c90860SMika Westerberg * Unconditionally clean and invalidate the entire icache. 42c8c90860SMika Westerberg */ 431036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_flush_icache_all) 44c8c90860SMika Westerberg mov r0, #0 45c8c90860SMika Westerberg mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 466ebbf2ceSRussell King ret lr 471036b895SLinus WalleijSYM_FUNC_END(fa_flush_icache_all) 48c8c90860SMika Westerberg 49c8c90860SMika Westerberg/* 5028853ac8SPaulius Zaleckas * flush_user_cache_all() 5128853ac8SPaulius Zaleckas * 5228853ac8SPaulius Zaleckas * Clean and invalidate all cache entries in a particular address 5328853ac8SPaulius Zaleckas * space. 5428853ac8SPaulius Zaleckas */ 552074beebSLinus WalleijSYM_FUNC_ALIAS(fa_flush_user_cache_all, fa_flush_kern_cache_all) 561036b895SLinus Walleij 5728853ac8SPaulius Zaleckas/* 5828853ac8SPaulius Zaleckas * flush_kern_cache_all() 5928853ac8SPaulius Zaleckas * 6028853ac8SPaulius Zaleckas * Clean and invalidate the entire cache. 6128853ac8SPaulius Zaleckas */ 621036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_flush_kern_cache_all) 6328853ac8SPaulius Zaleckas mov ip, #0 6428853ac8SPaulius Zaleckas mov r2, #VM_EXEC 6528853ac8SPaulius Zaleckas__flush_whole_cache: 6628853ac8SPaulius Zaleckas mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache 6728853ac8SPaulius Zaleckas tst r2, #VM_EXEC 6828853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache 6928853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 7028853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer 7128853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 726ebbf2ceSRussell King ret lr 731036b895SLinus WalleijSYM_FUNC_END(fa_flush_kern_cache_all) 7428853ac8SPaulius Zaleckas 7528853ac8SPaulius Zaleckas/* 7628853ac8SPaulius Zaleckas * flush_user_cache_range(start, end, flags) 7728853ac8SPaulius Zaleckas * 7828853ac8SPaulius Zaleckas * Invalidate a range of cache entries in the specified 7928853ac8SPaulius Zaleckas * address space. 8028853ac8SPaulius Zaleckas * 8128853ac8SPaulius Zaleckas * - start - start address (inclusive, page aligned) 8228853ac8SPaulius Zaleckas * - end - end address (exclusive, page aligned) 8328853ac8SPaulius Zaleckas * - flags - vma_area_struct flags describing address space 8428853ac8SPaulius Zaleckas */ 851036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_flush_user_cache_range) 8628853ac8SPaulius Zaleckas mov ip, #0 8728853ac8SPaulius Zaleckas sub r3, r1, r0 @ calculate total size 8828853ac8SPaulius Zaleckas cmp r3, #CACHE_DLIMIT @ total size >= limit? 8928853ac8SPaulius Zaleckas bhs __flush_whole_cache @ flush whole D cache 9028853ac8SPaulius Zaleckas 9128853ac8SPaulius Zaleckas1: tst r2, #VM_EXEC 9228853ac8SPaulius Zaleckas mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line 9328853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 9428853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 9528853ac8SPaulius Zaleckas cmp r0, r1 9628853ac8SPaulius Zaleckas blo 1b 9728853ac8SPaulius Zaleckas tst r2, #VM_EXEC 9828853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB 9928853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c10, 4 @ data write barrier 10028853ac8SPaulius Zaleckas mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush 1016ebbf2ceSRussell King ret lr 1021036b895SLinus WalleijSYM_FUNC_END(fa_flush_user_cache_range) 10328853ac8SPaulius Zaleckas 10428853ac8SPaulius Zaleckas/* 10528853ac8SPaulius Zaleckas * coherent_kern_range(start, end) 10628853ac8SPaulius Zaleckas * 10728853ac8SPaulius Zaleckas * Ensure coherency between the Icache and the Dcache in the 10828853ac8SPaulius Zaleckas * region described by start. If you have non-snooping 10928853ac8SPaulius Zaleckas * Harvard caches, you need to implement this function. 11028853ac8SPaulius Zaleckas * 11128853ac8SPaulius Zaleckas * - start - virtual start address 11228853ac8SPaulius Zaleckas * - end - virtual end address 11328853ac8SPaulius Zaleckas */ 1141036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_coherent_kern_range) 115*7b749aadSLinus Walleij#ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */ 1161036b895SLinus Walleij b fa_coherent_user_range 117*7b749aadSLinus Walleij#endif 1181036b895SLinus WalleijSYM_FUNC_END(fa_coherent_kern_range) 11928853ac8SPaulius Zaleckas 12028853ac8SPaulius Zaleckas/* 12128853ac8SPaulius Zaleckas * coherent_user_range(start, end) 12228853ac8SPaulius Zaleckas * 12328853ac8SPaulius Zaleckas * Ensure coherency between the Icache and the Dcache in the 12428853ac8SPaulius Zaleckas * region described by start. If you have non-snooping 12528853ac8SPaulius Zaleckas * Harvard caches, you need to implement this function. 12628853ac8SPaulius Zaleckas * 12728853ac8SPaulius Zaleckas * - start - virtual start address 12828853ac8SPaulius Zaleckas * - end - virtual end address 12928853ac8SPaulius Zaleckas */ 1301036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_coherent_user_range) 13128853ac8SPaulius Zaleckas bic r0, r0, #CACHE_DLINESIZE - 1 13228853ac8SPaulius Zaleckas1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry 13328853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry 13428853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 13528853ac8SPaulius Zaleckas cmp r0, r1 13628853ac8SPaulius Zaleckas blo 1b 13728853ac8SPaulius Zaleckas mov r0, #0 13828853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 13928853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 14028853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c5, 4 @ prefetch flush 1416ebbf2ceSRussell King ret lr 1421036b895SLinus WalleijSYM_FUNC_END(fa_coherent_user_range) 14328853ac8SPaulius Zaleckas 14428853ac8SPaulius Zaleckas/* 1452c9b9c84SRussell King * flush_kern_dcache_area(void *addr, size_t size) 14628853ac8SPaulius Zaleckas * 14728853ac8SPaulius Zaleckas * Ensure that the data held in the page kaddr is written back 14828853ac8SPaulius Zaleckas * to the page in question. 14928853ac8SPaulius Zaleckas * 1502c9b9c84SRussell King * - addr - kernel address 1512c9b9c84SRussell King * - size - size of region 15228853ac8SPaulius Zaleckas */ 1531036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_flush_kern_dcache_area) 1542c9b9c84SRussell King add r1, r0, r1 15528853ac8SPaulius Zaleckas1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 15628853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 15728853ac8SPaulius Zaleckas cmp r0, r1 15828853ac8SPaulius Zaleckas blo 1b 15928853ac8SPaulius Zaleckas mov r0, #0 16028853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache 16128853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 1626ebbf2ceSRussell King ret lr 1631036b895SLinus WalleijSYM_FUNC_END(fa_flush_kern_dcache_area) 16428853ac8SPaulius Zaleckas 16528853ac8SPaulius Zaleckas/* 16628853ac8SPaulius Zaleckas * dma_inv_range(start, end) 16728853ac8SPaulius Zaleckas * 16828853ac8SPaulius Zaleckas * Invalidate (discard) the specified virtual address range. 16928853ac8SPaulius Zaleckas * May not write back any entries. If 'start' or 'end' 17028853ac8SPaulius Zaleckas * are not cache line aligned, those lines must be written 17128853ac8SPaulius Zaleckas * back. 17228853ac8SPaulius Zaleckas * 17328853ac8SPaulius Zaleckas * - start - virtual start address 17428853ac8SPaulius Zaleckas * - end - virtual end address 17528853ac8SPaulius Zaleckas */ 176702b94bfSRussell Kingfa_dma_inv_range: 17728853ac8SPaulius Zaleckas tst r0, #CACHE_DLINESIZE - 1 17828853ac8SPaulius Zaleckas bic r0, r0, #CACHE_DLINESIZE - 1 17928853ac8SPaulius Zaleckas mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 18028853ac8SPaulius Zaleckas tst r1, #CACHE_DLINESIZE - 1 18128853ac8SPaulius Zaleckas bic r1, r1, #CACHE_DLINESIZE - 1 18228853ac8SPaulius Zaleckas mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry 18328853ac8SPaulius Zaleckas1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry 18428853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 18528853ac8SPaulius Zaleckas cmp r0, r1 18628853ac8SPaulius Zaleckas blo 1b 18728853ac8SPaulius Zaleckas mov r0, #0 18828853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 1896ebbf2ceSRussell King ret lr 19028853ac8SPaulius Zaleckas 19128853ac8SPaulius Zaleckas/* 19228853ac8SPaulius Zaleckas * dma_clean_range(start, end) 19328853ac8SPaulius Zaleckas * 19428853ac8SPaulius Zaleckas * Clean (write back) the specified virtual address range. 19528853ac8SPaulius Zaleckas * 19628853ac8SPaulius Zaleckas * - start - virtual start address 19728853ac8SPaulius Zaleckas * - end - virtual end address 19828853ac8SPaulius Zaleckas */ 199702b94bfSRussell Kingfa_dma_clean_range: 20028853ac8SPaulius Zaleckas bic r0, r0, #CACHE_DLINESIZE - 1 20128853ac8SPaulius Zaleckas1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 20228853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 20328853ac8SPaulius Zaleckas cmp r0, r1 20428853ac8SPaulius Zaleckas blo 1b 20528853ac8SPaulius Zaleckas mov r0, #0 20628853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 2076ebbf2ceSRussell King ret lr 20828853ac8SPaulius Zaleckas 20928853ac8SPaulius Zaleckas/* 21028853ac8SPaulius Zaleckas * dma_flush_range(start,end) 21128853ac8SPaulius Zaleckas * - start - virtual start address of region 21228853ac8SPaulius Zaleckas * - end - virtual end address of region 21328853ac8SPaulius Zaleckas */ 2141036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_dma_flush_range) 21528853ac8SPaulius Zaleckas bic r0, r0, #CACHE_DLINESIZE - 1 21628853ac8SPaulius Zaleckas1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry 21728853ac8SPaulius Zaleckas add r0, r0, #CACHE_DLINESIZE 21828853ac8SPaulius Zaleckas cmp r0, r1 21928853ac8SPaulius Zaleckas blo 1b 22028853ac8SPaulius Zaleckas mov r0, #0 22128853ac8SPaulius Zaleckas mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 2226ebbf2ceSRussell King ret lr 2231036b895SLinus WalleijSYM_FUNC_END(fa_dma_flush_range) 22428853ac8SPaulius Zaleckas 225a9c9147eSRussell King/* 226a9c9147eSRussell King * dma_map_area(start, size, dir) 227a9c9147eSRussell King * - start - kernel virtual start address 228a9c9147eSRussell King * - size - size of region 229a9c9147eSRussell King * - dir - DMA direction 230a9c9147eSRussell King */ 2311036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_dma_map_area) 232a9c9147eSRussell King add r1, r1, r0 233a9c9147eSRussell King cmp r2, #DMA_TO_DEVICE 234a9c9147eSRussell King beq fa_dma_clean_range 235a9c9147eSRussell King bcs fa_dma_inv_range 236a9c9147eSRussell King b fa_dma_flush_range 2371036b895SLinus WalleijSYM_FUNC_END(fa_dma_map_area) 238a9c9147eSRussell King 239a9c9147eSRussell King/* 240a9c9147eSRussell King * dma_unmap_area(start, size, dir) 241a9c9147eSRussell King * - start - kernel virtual start address 242a9c9147eSRussell King * - size - size of region 243a9c9147eSRussell King * - dir - DMA direction 244a9c9147eSRussell King */ 2451036b895SLinus WalleijSYM_TYPED_FUNC_START(fa_dma_unmap_area) 2466ebbf2ceSRussell King ret lr 2471036b895SLinus WalleijSYM_FUNC_END(fa_dma_unmap_area) 248