xref: /openbmc/linux/arch/arm/mm/cache-v7.S (revision a2faac39)
1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
2bbe88886SCatalin Marinas/*
3bbe88886SCatalin Marinas *  linux/arch/arm/mm/cache-v7.S
4bbe88886SCatalin Marinas *
5bbe88886SCatalin Marinas *  Copyright (C) 2001 Deep Blue Solutions Ltd.
6bbe88886SCatalin Marinas *  Copyright (C) 2005 ARM Ltd.
7bbe88886SCatalin Marinas *
8bbe88886SCatalin Marinas *  This is the "shell" of the ARMv7 processor support.
9bbe88886SCatalin Marinas */
10bbe88886SCatalin Marinas#include <linux/linkage.h>
11bbe88886SCatalin Marinas#include <linux/init.h>
12bbe88886SCatalin Marinas#include <asm/assembler.h>
13c5102f59SWill Deacon#include <asm/errno.h>
1432cfb1b1SCatalin Marinas#include <asm/unwind.h>
151238c4fdSFlorian Fainelli#include <asm/hardware/cache-b15-rac.h>
16bbe88886SCatalin Marinas
17bbe88886SCatalin Marinas#include "proc-macros.S"
18bbe88886SCatalin Marinas
19*a2faac39SNick Desaulniers.arch armv7-a
20*a2faac39SNick Desaulniers
215f41f919SMarek Szyprowski#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND
225f41f919SMarek Szyprowski.globl icache_size
235f41f919SMarek Szyprowski	.data
245f41f919SMarek Szyprowski	.align	2
255f41f919SMarek Szyprowskiicache_size:
265f41f919SMarek Szyprowski	.long	64
275f41f919SMarek Szyprowski	.text
285f41f919SMarek Szyprowski#endif
29bbe88886SCatalin Marinas/*
30c08e20d2SDinh Nguyen * The secondary kernel init calls v7_flush_dcache_all before it enables
31c08e20d2SDinh Nguyen * the L1; however, the L1 comes out of reset in an undefined state, so
32c08e20d2SDinh Nguyen * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
33c08e20d2SDinh Nguyen * of cache lines with uninitialized data and uninitialized tags to get
34c08e20d2SDinh Nguyen * written out to memory, which does really unpleasant things to the main
35c08e20d2SDinh Nguyen * processor.  We fix this by performing an invalidate, rather than a
36c08e20d2SDinh Nguyen * clean + invalidate, before jumping into the kernel.
37c08e20d2SDinh Nguyen *
38f9e7a99fSArd Biesheuvel * This function needs to be called for both secondary cores startup and
39f9e7a99fSArd Biesheuvel * primary core resume procedures.
40c08e20d2SDinh Nguyen */
41c08e20d2SDinh NguyenENTRY(v7_invalidate_l1)
42c08e20d2SDinh Nguyen	mov	r0, #0
43c0e50736SArd Biesheuvel	mcr	p15, 2, r0, c0, c0, 0	@ select L1 data cache in CSSELR
44c0e50736SArd Biesheuvel	isb
45c0e50736SArd Biesheuvel	mrc	p15, 1, r0, c0, c0, 0	@ read cache geometry from CCSIDR
46c08e20d2SDinh Nguyen
47f9e7a99fSArd Biesheuvel	movw	r3, #0x3ff
48f9e7a99fSArd Biesheuvel	and	r3, r3, r0, lsr #3	@ 'Associativity' in CCSIDR[12:3]
49c08e20d2SDinh Nguyen	clz	r1, r3			@ WayShift
50f9e7a99fSArd Biesheuvel	mov	r2, #1
51f9e7a99fSArd Biesheuvel	mov	r3, r3, lsl r1		@ NumWays-1 shifted into bits [31:...]
52f9e7a99fSArd Biesheuvel	movs	r1, r2, lsl r1		@ #1 shifted left by same amount
53f9e7a99fSArd Biesheuvel	moveq	r1, #1			@ r1 needs value > 0 even if only 1 way
54f9e7a99fSArd Biesheuvel
55f9e7a99fSArd Biesheuvel	and	r2, r0, #0x7
56f9e7a99fSArd Biesheuvel	add	r2, r2, #4		@ SetShift
57f9e7a99fSArd Biesheuvel
5895731b8eSArd Biesheuvel1:	movw	ip, #0x7fff
5995731b8eSArd Biesheuvel	and	r0, ip, r0, lsr #13	@ 'NumSets' in CCSIDR[27:13]
60f9e7a99fSArd Biesheuvel
6195731b8eSArd Biesheuvel2:	mov	ip, r0, lsl r2		@ NumSet << SetShift
6295731b8eSArd Biesheuvel	orr	ip, ip, r3		@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
6395731b8eSArd Biesheuvel	mcr	p15, 0, ip, c7, c6, 2
64f9e7a99fSArd Biesheuvel	subs	r0, r0, #1		@ Set--
65f9e7a99fSArd Biesheuvel	bpl	2b
66f9e7a99fSArd Biesheuvel	subs	r3, r3, r1		@ Way--
67f9e7a99fSArd Biesheuvel	bcc	3f
68f9e7a99fSArd Biesheuvel	mrc	p15, 1, r0, c0, c0, 0	@ re-read cache geometry from CCSIDR
69f9e7a99fSArd Biesheuvel	b	1b
70f9e7a99fSArd Biesheuvel3:	dsb	st
71c08e20d2SDinh Nguyen	isb
726ebbf2ceSRussell King	ret	lr
73c08e20d2SDinh NguyenENDPROC(v7_invalidate_l1)
74c08e20d2SDinh Nguyen
75c08e20d2SDinh Nguyen/*
7681d11955STony Lindgren *	v7_flush_icache_all()
7781d11955STony Lindgren *
7881d11955STony Lindgren *	Flush the whole I-cache.
7981d11955STony Lindgren *
8081d11955STony Lindgren *	Registers:
8181d11955STony Lindgren *	r0 - set to 0
8281d11955STony Lindgren */
8381d11955STony LindgrenENTRY(v7_flush_icache_all)
8481d11955STony Lindgren	mov	r0, #0
8581d11955STony Lindgren	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)		@ invalidate I-cache inner shareable
8681d11955STony Lindgren	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)		@ I+BTB cache invalidate
876ebbf2ceSRussell King	ret	lr
8881d11955STony LindgrenENDPROC(v7_flush_icache_all)
8981d11955STony Lindgren
9081d11955STony Lindgren /*
91031bd879SLorenzo Pieralisi *     v7_flush_dcache_louis()
92031bd879SLorenzo Pieralisi *
93031bd879SLorenzo Pieralisi *     Flush the D-cache up to the Level of Unification Inner Shareable
94031bd879SLorenzo Pieralisi *
951f640552SArd Biesheuvel *     Corrupted registers: r0-r6, r9-r10
96031bd879SLorenzo Pieralisi */
97031bd879SLorenzo Pieralisi
98031bd879SLorenzo PieralisiENTRY(v7_flush_dcache_louis)
99031bd879SLorenzo Pieralisi	dmb					@ ensure ordering with previous memory accesses
100031bd879SLorenzo Pieralisi	mrc	p15, 1, r0, c0, c0, 1		@ read clidr, r0 = clidr
10147b8484eSRussell KingALT_SMP(mov	r3, r0, lsr #20)		@ move LoUIS into position
10247b8484eSRussell KingALT_UP(	mov	r3, r0, lsr #26)		@ move LoUU into position
10347b8484eSRussell King	ands	r3, r3, #7 << 1 		@ extract LoU*2 field from clidr
104d3cd451dSRussell King	bne	start_flush_levels		@ LoU != 0, start flushing
10569155794SJon Medhurst#ifdef CONFIG_ARM_ERRATA_643719
106d3cd451dSRussell KingALT_SMP(mrc	p15, 0, r2, c0, c0, 0)		@ read main ID register
107d3cd451dSRussell KingALT_UP(	ret	lr)				@ LoUU is zero, so nothing to do
108aaf4b5d9SRussell King	movw	r1, #:lower16:(0x410fc090 >> 4)	@ ID of ARM Cortex A9 r0p?
109aaf4b5d9SRussell King	movt	r1, #:upper16:(0x410fc090 >> 4)
110aaf4b5d9SRussell King	teq	r1, r2, lsr #4			@ test for errata affected core and if so...
111d3cd451dSRussell King	moveq	r3, #1 << 1			@   fix LoUIS value
112d3cd451dSRussell King	beq	start_flush_levels		@   start flushing cache levels
11369155794SJon Medhurst#endif
114d3cd451dSRussell King	ret	lr
115031bd879SLorenzo PieralisiENDPROC(v7_flush_dcache_louis)
116031bd879SLorenzo Pieralisi
117031bd879SLorenzo Pieralisi/*
118bbe88886SCatalin Marinas *	v7_flush_dcache_all()
119bbe88886SCatalin Marinas *
120bbe88886SCatalin Marinas *	Flush the whole D-cache.
121bbe88886SCatalin Marinas *
1221f640552SArd Biesheuvel *	Corrupted registers: r0-r6, r9-r10
123bbe88886SCatalin Marinas *
124bbe88886SCatalin Marinas *	- mm    - mm_struct describing address space
125bbe88886SCatalin Marinas */
126bbe88886SCatalin MarinasENTRY(v7_flush_dcache_all)
127c30c2f99SCatalin Marinas	dmb					@ ensure ordering with previous memory accesses
128bbe88886SCatalin Marinas	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
12947b8484eSRussell King	mov	r3, r0, lsr #23			@ move LoC into position
13047b8484eSRussell King	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
131bbe88886SCatalin Marinas	beq	finished			@ if loc is 0, then no need to clean
132cd8b24d9SRussell Kingstart_flush_levels:
133bbe88886SCatalin Marinas	mov	r10, #0				@ start clean at cache level 0
1343287be8cSLorenzo Pieralisiflush_levels:
135bbe88886SCatalin Marinas	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
136bbe88886SCatalin Marinas	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
137bbe88886SCatalin Marinas	and	r1, r1, #7			@ mask of the bits for current cache only
138bbe88886SCatalin Marinas	cmp	r1, #2				@ see what cache we have at this level
139bbe88886SCatalin Marinas	blt	skip				@ skip if no cache, or just i-cache
140e7289c6dSThomas Gleixner#ifdef CONFIG_PREEMPTION
1418e43a905SRabin Vincent	save_and_disable_irqs_notrace r9	@ make cssr&csidr read atomic
142b46c0f74SStephen Boyd#endif
143bbe88886SCatalin Marinas	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
144bbe88886SCatalin Marinas	isb					@ isb to sych the new cssr&csidr
145bbe88886SCatalin Marinas	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
146e7289c6dSThomas Gleixner#ifdef CONFIG_PREEMPTION
147b46c0f74SStephen Boyd	restore_irqs_notrace r9
148b46c0f74SStephen Boyd#endif
149bbe88886SCatalin Marinas	and	r2, r1, #7			@ extract the length of the cache lines
150bbe88886SCatalin Marinas	add	r2, r2, #4			@ add 4 (line length offset)
1515aca3708SRussell King	movw	r4, #0x3ff
152bbe88886SCatalin Marinas	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
153bbe88886SCatalin Marinas	clz	r5, r4				@ find bit position of way size increment
1541f640552SArd Biesheuvel	movw	r6, #0x7fff
1551f640552SArd Biesheuvel	and	r1, r6, r1, lsr #13		@ extract max number of the index size
1561f640552SArd Biesheuvel	mov	r6, #1
1571f640552SArd Biesheuvel	movne	r4, r4, lsl r5			@ # of ways shifted into bits [31:...]
1581f640552SArd Biesheuvel	movne	r6, r6, lsl r5			@ 1 shifted left by same amount
1593287be8cSLorenzo Pieralisiloop1:
1601f640552SArd Biesheuvel	mov	r9, r1				@ create working copy of max index
1613287be8cSLorenzo Pieralisiloop2:
1621f640552SArd Biesheuvel	mov	r5, r9, lsl r2			@ factor set number into r5
1631f640552SArd Biesheuvel	orr	r5, r5, r4			@ factor way number into r5
1641f640552SArd Biesheuvel	orr	r5, r5, r10			@ factor cache level into r5
1651f640552SArd Biesheuvel	mcr	p15, 0, r5, c7, c14, 2		@ clean & invalidate by set/way
16670f665feSLorenzo Pieralisi	subs	r9, r9, #1			@ decrement the index
167bbe88886SCatalin Marinas	bge	loop2
1681f640552SArd Biesheuvel	subs	r4, r4, r6			@ decrement the way
1691f640552SArd Biesheuvel	bcs	loop1
170bbe88886SCatalin Marinasskip:
171bbe88886SCatalin Marinas	add	r10, r10, #2			@ increment cache number
172bbe88886SCatalin Marinas	cmp	r3, r10
173779eb41cSBenjamin Gaignard#ifdef CONFIG_ARM_ERRATA_814220
174779eb41cSBenjamin Gaignard	dsb
175779eb41cSBenjamin Gaignard#endif
1763287be8cSLorenzo Pieralisi	bgt	flush_levels
177bbe88886SCatalin Marinasfinished:
17808a7e621SMasahiro Yamada	mov	r10, #0				@ switch back to cache level 0
179bbe88886SCatalin Marinas	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
1809581960aSWill Deacon	dsb	st
181bbe88886SCatalin Marinas	isb
1826ebbf2ceSRussell King	ret	lr
18393ed3970SCatalin MarinasENDPROC(v7_flush_dcache_all)
184bbe88886SCatalin Marinas
185bbe88886SCatalin Marinas/*
186bbe88886SCatalin Marinas *	v7_flush_cache_all()
187bbe88886SCatalin Marinas *
188bbe88886SCatalin Marinas *	Flush the entire cache system.
189bbe88886SCatalin Marinas *  The data cache flush is now achieved using atomic clean / invalidates
190bbe88886SCatalin Marinas *  working outwards from L1 cache. This is done using Set/Way based cache
19125985edcSLucas De Marchi *  maintenance instructions.
192bbe88886SCatalin Marinas *  The instruction cache can still be invalidated back to the point of
193bbe88886SCatalin Marinas *  unification in a single instruction.
194bbe88886SCatalin Marinas *
195bbe88886SCatalin Marinas */
196bbe88886SCatalin MarinasENTRY(v7_flush_kern_cache_all)
1971f640552SArd Biesheuvel	stmfd	sp!, {r4-r6, r9-r10, lr}
198bbe88886SCatalin Marinas	bl	v7_flush_dcache_all
199bbe88886SCatalin Marinas	mov	r0, #0
200f00ec48fSRussell King	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)	@ invalidate I-cache inner shareable
201f00ec48fSRussell King	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
2021f640552SArd Biesheuvel	ldmfd	sp!, {r4-r6, r9-r10, lr}
2036ebbf2ceSRussell King	ret	lr
20493ed3970SCatalin MarinasENDPROC(v7_flush_kern_cache_all)
205bbe88886SCatalin Marinas
206bbe88886SCatalin Marinas /*
207031bd879SLorenzo Pieralisi *     v7_flush_kern_cache_louis(void)
208031bd879SLorenzo Pieralisi *
209031bd879SLorenzo Pieralisi *     Flush the data cache up to Level of Unification Inner Shareable.
210031bd879SLorenzo Pieralisi *     Invalidate the I-cache to the point of unification.
211031bd879SLorenzo Pieralisi */
212031bd879SLorenzo PieralisiENTRY(v7_flush_kern_cache_louis)
2131f640552SArd Biesheuvel	stmfd	sp!, {r4-r6, r9-r10, lr}
214031bd879SLorenzo Pieralisi	bl	v7_flush_dcache_louis
215031bd879SLorenzo Pieralisi	mov	r0, #0
216031bd879SLorenzo Pieralisi	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)	@ invalidate I-cache inner shareable
217031bd879SLorenzo Pieralisi	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
2181f640552SArd Biesheuvel	ldmfd	sp!, {r4-r6, r9-r10, lr}
2196ebbf2ceSRussell King	ret	lr
220031bd879SLorenzo PieralisiENDPROC(v7_flush_kern_cache_louis)
221031bd879SLorenzo Pieralisi
222031bd879SLorenzo Pieralisi/*
223bbe88886SCatalin Marinas *	v7_flush_cache_all()
224bbe88886SCatalin Marinas *
225bbe88886SCatalin Marinas *	Flush all TLB entries in a particular address space
226bbe88886SCatalin Marinas *
227bbe88886SCatalin Marinas *	- mm    - mm_struct describing address space
228bbe88886SCatalin Marinas */
229bbe88886SCatalin MarinasENTRY(v7_flush_user_cache_all)
230bbe88886SCatalin Marinas	/*FALLTHROUGH*/
231bbe88886SCatalin Marinas
232bbe88886SCatalin Marinas/*
233bbe88886SCatalin Marinas *	v7_flush_cache_range(start, end, flags)
234bbe88886SCatalin Marinas *
235bbe88886SCatalin Marinas *	Flush a range of TLB entries in the specified address space.
236bbe88886SCatalin Marinas *
237bbe88886SCatalin Marinas *	- start - start address (may not be aligned)
238bbe88886SCatalin Marinas *	- end   - end address (exclusive, may not be aligned)
239bbe88886SCatalin Marinas *	- flags	- vm_area_struct flags describing address space
240bbe88886SCatalin Marinas *
241bbe88886SCatalin Marinas *	It is assumed that:
242bbe88886SCatalin Marinas *	- we have a VIPT cache.
243bbe88886SCatalin Marinas */
244bbe88886SCatalin MarinasENTRY(v7_flush_user_cache_range)
2456ebbf2ceSRussell King	ret	lr
24693ed3970SCatalin MarinasENDPROC(v7_flush_user_cache_all)
24793ed3970SCatalin MarinasENDPROC(v7_flush_user_cache_range)
248bbe88886SCatalin Marinas
249bbe88886SCatalin Marinas/*
250bbe88886SCatalin Marinas *	v7_coherent_kern_range(start,end)
251bbe88886SCatalin Marinas *
252bbe88886SCatalin Marinas *	Ensure that the I and D caches are coherent within specified
253bbe88886SCatalin Marinas *	region.  This is typically used when code has been written to
254bbe88886SCatalin Marinas *	a memory region, and will be executed.
255bbe88886SCatalin Marinas *
256bbe88886SCatalin Marinas *	- start   - virtual start address of region
257bbe88886SCatalin Marinas *	- end     - virtual end address of region
258bbe88886SCatalin Marinas *
259bbe88886SCatalin Marinas *	It is assumed that:
260bbe88886SCatalin Marinas *	- the Icache does not read data from the write buffer
261bbe88886SCatalin Marinas */
262bbe88886SCatalin MarinasENTRY(v7_coherent_kern_range)
263bbe88886SCatalin Marinas	/* FALLTHROUGH */
264bbe88886SCatalin Marinas
265bbe88886SCatalin Marinas/*
266bbe88886SCatalin Marinas *	v7_coherent_user_range(start,end)
267bbe88886SCatalin Marinas *
268bbe88886SCatalin Marinas *	Ensure that the I and D caches are coherent within specified
269bbe88886SCatalin Marinas *	region.  This is typically used when code has been written to
270bbe88886SCatalin Marinas *	a memory region, and will be executed.
271bbe88886SCatalin Marinas *
272bbe88886SCatalin Marinas *	- start   - virtual start address of region
273bbe88886SCatalin Marinas *	- end     - virtual end address of region
274bbe88886SCatalin Marinas *
275bbe88886SCatalin Marinas *	It is assumed that:
276bbe88886SCatalin Marinas *	- the Icache does not read data from the write buffer
277bbe88886SCatalin Marinas */
278bbe88886SCatalin MarinasENTRY(v7_coherent_user_range)
27932cfb1b1SCatalin Marinas UNWIND(.fnstart		)
280bbe88886SCatalin Marinas	dcache_line_size r2, r3
281bbe88886SCatalin Marinas	sub	r3, r2, #1
282da30e0acSCatalin Marinas	bic	r12, r0, r3
283f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
284f630c1bdSWill Deacon	ALT_SMP(W(dsb))
285f630c1bdSWill Deacon	ALT_UP(W(nop))
286f630c1bdSWill Deacon#endif
28732cfb1b1SCatalin Marinas1:
288da30e0acSCatalin Marinas USER(	mcr	p15, 0, r12, c7, c11, 1	)	@ clean D line to the point of unification
289da30e0acSCatalin Marinas	add	r12, r12, r2
290da30e0acSCatalin Marinas	cmp	r12, r1
291bbe88886SCatalin Marinas	blo	1b
2926abdd491SWill Deacon	dsb	ishst
2935f41f919SMarek Szyprowski#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND
2945f41f919SMarek Szyprowski	ldr	r3, =icache_size
2955f41f919SMarek Szyprowski	ldr	r2, [r3, #0]
2965f41f919SMarek Szyprowski#else
297da30e0acSCatalin Marinas	icache_line_size r2, r3
2985f41f919SMarek Szyprowski#endif
299da30e0acSCatalin Marinas	sub	r3, r2, #1
300da30e0acSCatalin Marinas	bic	r12, r0, r3
301da30e0acSCatalin Marinas2:
302da30e0acSCatalin Marinas USER(	mcr	p15, 0, r12, c7, c5, 1	)	@ invalidate I line
303da30e0acSCatalin Marinas	add	r12, r12, r2
304da30e0acSCatalin Marinas	cmp	r12, r1
305da30e0acSCatalin Marinas	blo	2b
306bbe88886SCatalin Marinas	mov	r0, #0
307f00ec48fSRussell King	ALT_SMP(mcr	p15, 0, r0, c7, c1, 6)	@ invalidate BTB Inner Shareable
308f00ec48fSRussell King	ALT_UP(mcr	p15, 0, r0, c7, c5, 6)	@ invalidate BTB
3096abdd491SWill Deacon	dsb	ishst
310bbe88886SCatalin Marinas	isb
3116ebbf2ceSRussell King	ret	lr
31232cfb1b1SCatalin Marinas
31332cfb1b1SCatalin Marinas/*
31432cfb1b1SCatalin Marinas * Fault handling for the cache operation above. If the virtual address in r0
315c5102f59SWill Deacon * isn't mapped, fail with -EFAULT.
31632cfb1b1SCatalin Marinas */
31732cfb1b1SCatalin Marinas9001:
3187253b85cSSimon Horman#ifdef CONFIG_ARM_ERRATA_775420
3197253b85cSSimon Horman	dsb
3207253b85cSSimon Horman#endif
321c5102f59SWill Deacon	mov	r0, #-EFAULT
3226ebbf2ceSRussell King	ret	lr
32332cfb1b1SCatalin Marinas UNWIND(.fnend		)
32493ed3970SCatalin MarinasENDPROC(v7_coherent_kern_range)
32593ed3970SCatalin MarinasENDPROC(v7_coherent_user_range)
326bbe88886SCatalin Marinas
327bbe88886SCatalin Marinas/*
3282c9b9c84SRussell King *	v7_flush_kern_dcache_area(void *addr, size_t size)
329bbe88886SCatalin Marinas *
330bbe88886SCatalin Marinas *	Ensure that the data held in the page kaddr is written back
331bbe88886SCatalin Marinas *	to the page in question.
332bbe88886SCatalin Marinas *
3332c9b9c84SRussell King *	- addr	- kernel address
3342c9b9c84SRussell King *	- size	- region size
335bbe88886SCatalin Marinas */
3362c9b9c84SRussell KingENTRY(v7_flush_kern_dcache_area)
337bbe88886SCatalin Marinas	dcache_line_size r2, r3
3382c9b9c84SRussell King	add	r1, r0, r1
339a248b13bSWill Deacon	sub	r3, r2, #1
340a248b13bSWill Deacon	bic	r0, r0, r3
341f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
342f630c1bdSWill Deacon	ALT_SMP(W(dsb))
343f630c1bdSWill Deacon	ALT_UP(W(nop))
344f630c1bdSWill Deacon#endif
345bbe88886SCatalin Marinas1:
346bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
347bbe88886SCatalin Marinas	add	r0, r0, r2
348bbe88886SCatalin Marinas	cmp	r0, r1
349bbe88886SCatalin Marinas	blo	1b
3509581960aSWill Deacon	dsb	st
3516ebbf2ceSRussell King	ret	lr
3522c9b9c84SRussell KingENDPROC(v7_flush_kern_dcache_area)
353bbe88886SCatalin Marinas
354bbe88886SCatalin Marinas/*
355bbe88886SCatalin Marinas *	v7_dma_inv_range(start,end)
356bbe88886SCatalin Marinas *
357bbe88886SCatalin Marinas *	Invalidate the data cache within the specified region; we will
358bbe88886SCatalin Marinas *	be performing a DMA operation in this region and we want to
359bbe88886SCatalin Marinas *	purge old data in the cache.
360bbe88886SCatalin Marinas *
361bbe88886SCatalin Marinas *	- start   - virtual start address of region
362bbe88886SCatalin Marinas *	- end     - virtual end address of region
363bbe88886SCatalin Marinas */
364702b94bfSRussell Kingv7_dma_inv_range:
365bbe88886SCatalin Marinas	dcache_line_size r2, r3
366bbe88886SCatalin Marinas	sub	r3, r2, #1
367bbe88886SCatalin Marinas	tst	r0, r3
368bbe88886SCatalin Marinas	bic	r0, r0, r3
369f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
370f630c1bdSWill Deacon	ALT_SMP(W(dsb))
371f630c1bdSWill Deacon	ALT_UP(W(nop))
372f630c1bdSWill Deacon#endif
373bbe88886SCatalin Marinas	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
374a1208f6aSChris Cole	addne	r0, r0, r2
375bbe88886SCatalin Marinas
376bbe88886SCatalin Marinas	tst	r1, r3
377bbe88886SCatalin Marinas	bic	r1, r1, r3
378bbe88886SCatalin Marinas	mcrne	p15, 0, r1, c7, c14, 1		@ clean & invalidate D / U line
379bbe88886SCatalin Marinas	cmp	r0, r1
380a1208f6aSChris Cole1:
381a1208f6aSChris Cole	mcrlo	p15, 0, r0, c7, c6, 1		@ invalidate D / U line
382a1208f6aSChris Cole	addlo	r0, r0, r2
383a1208f6aSChris Cole	cmplo	r0, r1
384bbe88886SCatalin Marinas	blo	1b
3859581960aSWill Deacon	dsb	st
3866ebbf2ceSRussell King	ret	lr
38793ed3970SCatalin MarinasENDPROC(v7_dma_inv_range)
388bbe88886SCatalin Marinas
389bbe88886SCatalin Marinas/*
390bbe88886SCatalin Marinas *	v7_dma_clean_range(start,end)
391bbe88886SCatalin Marinas *	- start   - virtual start address of region
392bbe88886SCatalin Marinas *	- end     - virtual end address of region
393bbe88886SCatalin Marinas */
394702b94bfSRussell Kingv7_dma_clean_range:
395bbe88886SCatalin Marinas	dcache_line_size r2, r3
396bbe88886SCatalin Marinas	sub	r3, r2, #1
397bbe88886SCatalin Marinas	bic	r0, r0, r3
398f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
399f630c1bdSWill Deacon	ALT_SMP(W(dsb))
400f630c1bdSWill Deacon	ALT_UP(W(nop))
401f630c1bdSWill Deacon#endif
402bbe88886SCatalin Marinas1:
403bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c10, 1		@ clean D / U line
404bbe88886SCatalin Marinas	add	r0, r0, r2
405bbe88886SCatalin Marinas	cmp	r0, r1
406bbe88886SCatalin Marinas	blo	1b
4079581960aSWill Deacon	dsb	st
4086ebbf2ceSRussell King	ret	lr
40993ed3970SCatalin MarinasENDPROC(v7_dma_clean_range)
410bbe88886SCatalin Marinas
411bbe88886SCatalin Marinas/*
412bbe88886SCatalin Marinas *	v7_dma_flush_range(start,end)
413bbe88886SCatalin Marinas *	- start   - virtual start address of region
414bbe88886SCatalin Marinas *	- end     - virtual end address of region
415bbe88886SCatalin Marinas */
416bbe88886SCatalin MarinasENTRY(v7_dma_flush_range)
417bbe88886SCatalin Marinas	dcache_line_size r2, r3
418bbe88886SCatalin Marinas	sub	r3, r2, #1
419bbe88886SCatalin Marinas	bic	r0, r0, r3
420f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
421f630c1bdSWill Deacon	ALT_SMP(W(dsb))
422f630c1bdSWill Deacon	ALT_UP(W(nop))
423f630c1bdSWill Deacon#endif
424bbe88886SCatalin Marinas1:
425bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
426bbe88886SCatalin Marinas	add	r0, r0, r2
427bbe88886SCatalin Marinas	cmp	r0, r1
428bbe88886SCatalin Marinas	blo	1b
4299581960aSWill Deacon	dsb	st
4306ebbf2ceSRussell King	ret	lr
43193ed3970SCatalin MarinasENDPROC(v7_dma_flush_range)
432bbe88886SCatalin Marinas
433a9c9147eSRussell King/*
434a9c9147eSRussell King *	dma_map_area(start, size, dir)
435a9c9147eSRussell King *	- start	- kernel virtual start address
436a9c9147eSRussell King *	- size	- size of region
437a9c9147eSRussell King *	- dir	- DMA direction
438a9c9147eSRussell King */
439a9c9147eSRussell KingENTRY(v7_dma_map_area)
440a9c9147eSRussell King	add	r1, r1, r0
4412ffe2da3SRussell King	teq	r2, #DMA_FROM_DEVICE
4422ffe2da3SRussell King	beq	v7_dma_inv_range
4432ffe2da3SRussell King	b	v7_dma_clean_range
444a9c9147eSRussell KingENDPROC(v7_dma_map_area)
445a9c9147eSRussell King
446a9c9147eSRussell King/*
447a9c9147eSRussell King *	dma_unmap_area(start, size, dir)
448a9c9147eSRussell King *	- start	- kernel virtual start address
449a9c9147eSRussell King *	- size	- size of region
450a9c9147eSRussell King *	- dir	- DMA direction
451a9c9147eSRussell King */
452a9c9147eSRussell KingENTRY(v7_dma_unmap_area)
4532ffe2da3SRussell King	add	r1, r1, r0
4542ffe2da3SRussell King	teq	r2, #DMA_TO_DEVICE
4552ffe2da3SRussell King	bne	v7_dma_inv_range
4566ebbf2ceSRussell King	ret	lr
457a9c9147eSRussell KingENDPROC(v7_dma_unmap_area)
458a9c9147eSRussell King
459bbe88886SCatalin Marinas	__INITDATA
460bbe88886SCatalin Marinas
461455a01ecSDave Martin	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
462455a01ecSDave Martin	define_cache_functions v7
4631238c4fdSFlorian Fainelli
4641238c4fdSFlorian Fainelli	/* The Broadcom Brahma-B15 read-ahead cache requires some modifications
4651238c4fdSFlorian Fainelli	 * to the v7_cache_fns, we only override the ones we need
4661238c4fdSFlorian Fainelli	 */
4671238c4fdSFlorian Fainelli#ifndef CONFIG_CACHE_B15_RAC
4681238c4fdSFlorian Fainelli	globl_equ	b15_flush_kern_cache_all,	v7_flush_kern_cache_all
4691238c4fdSFlorian Fainelli#endif
4701238c4fdSFlorian Fainelli	globl_equ	b15_flush_icache_all,		v7_flush_icache_all
4711238c4fdSFlorian Fainelli	globl_equ	b15_flush_kern_cache_louis,	v7_flush_kern_cache_louis
4721238c4fdSFlorian Fainelli	globl_equ	b15_flush_user_cache_all,	v7_flush_user_cache_all
4731238c4fdSFlorian Fainelli	globl_equ	b15_flush_user_cache_range,	v7_flush_user_cache_range
4741238c4fdSFlorian Fainelli	globl_equ	b15_coherent_kern_range,	v7_coherent_kern_range
4751238c4fdSFlorian Fainelli	globl_equ	b15_coherent_user_range,	v7_coherent_user_range
4761238c4fdSFlorian Fainelli	globl_equ	b15_flush_kern_dcache_area,	v7_flush_kern_dcache_area
4771238c4fdSFlorian Fainelli
4781238c4fdSFlorian Fainelli	globl_equ	b15_dma_map_area,		v7_dma_map_area
4791238c4fdSFlorian Fainelli	globl_equ	b15_dma_unmap_area,		v7_dma_unmap_area
4801238c4fdSFlorian Fainelli	globl_equ	b15_dma_flush_range,		v7_dma_flush_range
4811238c4fdSFlorian Fainelli
4821238c4fdSFlorian Fainelli	define_cache_functions b15
483