xref: /openbmc/linux/arch/arm/mm/cache-v4wt.S (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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