xref: /openbmc/linux/arch/arm/mm/cache-v7.S (revision d3cd451d)
1bbe88886SCatalin Marinas/*
2bbe88886SCatalin Marinas *  linux/arch/arm/mm/cache-v7.S
3bbe88886SCatalin Marinas *
4bbe88886SCatalin Marinas *  Copyright (C) 2001 Deep Blue Solutions Ltd.
5bbe88886SCatalin Marinas *  Copyright (C) 2005 ARM Ltd.
6bbe88886SCatalin Marinas *
7bbe88886SCatalin Marinas * This program is free software; you can redistribute it and/or modify
8bbe88886SCatalin Marinas * it under the terms of the GNU General Public License version 2 as
9bbe88886SCatalin Marinas * published by the Free Software Foundation.
10bbe88886SCatalin Marinas *
11bbe88886SCatalin Marinas *  This is the "shell" of the ARMv7 processor support.
12bbe88886SCatalin Marinas */
13bbe88886SCatalin Marinas#include <linux/linkage.h>
14bbe88886SCatalin Marinas#include <linux/init.h>
15bbe88886SCatalin Marinas#include <asm/assembler.h>
16c5102f59SWill Deacon#include <asm/errno.h>
1732cfb1b1SCatalin Marinas#include <asm/unwind.h>
18bbe88886SCatalin Marinas
19bbe88886SCatalin Marinas#include "proc-macros.S"
20bbe88886SCatalin Marinas
21bbe88886SCatalin Marinas/*
22c08e20d2SDinh Nguyen * The secondary kernel init calls v7_flush_dcache_all before it enables
23c08e20d2SDinh Nguyen * the L1; however, the L1 comes out of reset in an undefined state, so
24c08e20d2SDinh Nguyen * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
25c08e20d2SDinh Nguyen * of cache lines with uninitialized data and uninitialized tags to get
26c08e20d2SDinh Nguyen * written out to memory, which does really unpleasant things to the main
27c08e20d2SDinh Nguyen * processor.  We fix this by performing an invalidate, rather than a
28c08e20d2SDinh Nguyen * clean + invalidate, before jumping into the kernel.
29c08e20d2SDinh Nguyen *
30c08e20d2SDinh Nguyen * This function is cloned from arch/arm/mach-tegra/headsmp.S, and needs
31c08e20d2SDinh Nguyen * to be called for both secondary cores startup and primary core resume
32c08e20d2SDinh Nguyen * procedures.
33c08e20d2SDinh Nguyen */
34c08e20d2SDinh NguyenENTRY(v7_invalidate_l1)
35c08e20d2SDinh Nguyen       mov     r0, #0
36c08e20d2SDinh Nguyen       mcr     p15, 2, r0, c0, c0, 0
37c08e20d2SDinh Nguyen       mrc     p15, 1, r0, c0, c0, 0
38c08e20d2SDinh Nguyen
395aca3708SRussell King       movw    r1, #0x7fff
40c08e20d2SDinh Nguyen       and     r2, r1, r0, lsr #13
41c08e20d2SDinh Nguyen
425aca3708SRussell King       movw    r1, #0x3ff
43c08e20d2SDinh Nguyen
44c08e20d2SDinh Nguyen       and     r3, r1, r0, lsr #3      @ NumWays - 1
45c08e20d2SDinh Nguyen       add     r2, r2, #1              @ NumSets
46c08e20d2SDinh Nguyen
47c08e20d2SDinh Nguyen       and     r0, r0, #0x7
48c08e20d2SDinh Nguyen       add     r0, r0, #4      @ SetShift
49c08e20d2SDinh Nguyen
50c08e20d2SDinh Nguyen       clz     r1, r3          @ WayShift
51c08e20d2SDinh Nguyen       add     r4, r3, #1      @ NumWays
52c08e20d2SDinh Nguyen1:     sub     r2, r2, #1      @ NumSets--
53c08e20d2SDinh Nguyen       mov     r3, r4          @ Temp = NumWays
54c08e20d2SDinh Nguyen2:     subs    r3, r3, #1      @ Temp--
55c08e20d2SDinh Nguyen       mov     r5, r3, lsl r1
56c08e20d2SDinh Nguyen       mov     r6, r2, lsl r0
57c08e20d2SDinh Nguyen       orr     r5, r5, r6      @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
58c08e20d2SDinh Nguyen       mcr     p15, 0, r5, c7, c6, 2
59c08e20d2SDinh Nguyen       bgt     2b
60c08e20d2SDinh Nguyen       cmp     r2, #0
61c08e20d2SDinh Nguyen       bgt     1b
629581960aSWill Deacon       dsb     st
63c08e20d2SDinh Nguyen       isb
646ebbf2ceSRussell King       ret     lr
65c08e20d2SDinh NguyenENDPROC(v7_invalidate_l1)
66c08e20d2SDinh Nguyen
67c08e20d2SDinh Nguyen/*
6881d11955STony Lindgren *	v7_flush_icache_all()
6981d11955STony Lindgren *
7081d11955STony Lindgren *	Flush the whole I-cache.
7181d11955STony Lindgren *
7281d11955STony Lindgren *	Registers:
7381d11955STony Lindgren *	r0 - set to 0
7481d11955STony Lindgren */
7581d11955STony LindgrenENTRY(v7_flush_icache_all)
7681d11955STony Lindgren	mov	r0, #0
7781d11955STony Lindgren	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)		@ invalidate I-cache inner shareable
7881d11955STony Lindgren	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)		@ I+BTB cache invalidate
796ebbf2ceSRussell King	ret	lr
8081d11955STony LindgrenENDPROC(v7_flush_icache_all)
8181d11955STony Lindgren
8281d11955STony Lindgren /*
83031bd879SLorenzo Pieralisi *     v7_flush_dcache_louis()
84031bd879SLorenzo Pieralisi *
85031bd879SLorenzo Pieralisi *     Flush the D-cache up to the Level of Unification Inner Shareable
86031bd879SLorenzo Pieralisi *
87031bd879SLorenzo Pieralisi *     Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
88031bd879SLorenzo Pieralisi */
89031bd879SLorenzo Pieralisi
90031bd879SLorenzo PieralisiENTRY(v7_flush_dcache_louis)
91031bd879SLorenzo Pieralisi	dmb					@ ensure ordering with previous memory accesses
92031bd879SLorenzo Pieralisi	mrc	p15, 1, r0, c0, c0, 1		@ read clidr, r0 = clidr
9347b8484eSRussell KingALT_SMP(mov	r3, r0, lsr #20)		@ move LoUIS into position
9447b8484eSRussell KingALT_UP(	mov	r3, r0, lsr #26)		@ move LoUU into position
9547b8484eSRussell King	ands	r3, r3, #7 << 1 		@ extract LoU*2 field from clidr
96d3cd451dSRussell King	bne	start_flush_levels		@ LoU != 0, start flushing
9769155794SJon Medhurst#ifdef CONFIG_ARM_ERRATA_643719
98d3cd451dSRussell KingALT_SMP(mrc	p15, 0, r2, c0, c0, 0)		@ read main ID register
99d3cd451dSRussell KingALT_UP(	ret	lr)				@ LoUU is zero, so nothing to do
100d3cd451dSRussell King	movw	r1, #:lower16:0x410fc090	@ ID of ARM Cortex A9 r0p?
101d3cd451dSRussell King	movt	r1, #:upper16:0x410fc090
102d3cd451dSRussell King	bic	r2, r2, #0x0000000f             @ clear minor revision number
103d3cd451dSRussell King	teq	r2, r1                          @ test for errata affected core and if so...
104d3cd451dSRussell King	moveq	r3, #1 << 1			@   fix LoUIS value
105d3cd451dSRussell King	beq	start_flush_levels		@   start flushing cache levels
10669155794SJon Medhurst#endif
107d3cd451dSRussell King	ret	lr
108031bd879SLorenzo PieralisiENDPROC(v7_flush_dcache_louis)
109031bd879SLorenzo Pieralisi
110031bd879SLorenzo Pieralisi/*
111bbe88886SCatalin Marinas *	v7_flush_dcache_all()
112bbe88886SCatalin Marinas *
113bbe88886SCatalin Marinas *	Flush the whole D-cache.
114bbe88886SCatalin Marinas *
115347c8b70SCatalin Marinas *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
116bbe88886SCatalin Marinas *
117bbe88886SCatalin Marinas *	- mm    - mm_struct describing address space
118bbe88886SCatalin Marinas */
119bbe88886SCatalin MarinasENTRY(v7_flush_dcache_all)
120c30c2f99SCatalin Marinas	dmb					@ ensure ordering with previous memory accesses
121bbe88886SCatalin Marinas	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
12247b8484eSRussell King	mov	r3, r0, lsr #23			@ move LoC into position
12347b8484eSRussell King	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
124bbe88886SCatalin Marinas	beq	finished			@ if loc is 0, then no need to clean
125cd8b24d9SRussell Kingstart_flush_levels:
126bbe88886SCatalin Marinas	mov	r10, #0				@ start clean at cache level 0
1273287be8cSLorenzo Pieralisiflush_levels:
128bbe88886SCatalin Marinas	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
129bbe88886SCatalin Marinas	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
130bbe88886SCatalin Marinas	and	r1, r1, #7			@ mask of the bits for current cache only
131bbe88886SCatalin Marinas	cmp	r1, #2				@ see what cache we have at this level
132bbe88886SCatalin Marinas	blt	skip				@ skip if no cache, or just i-cache
133b46c0f74SStephen Boyd#ifdef CONFIG_PREEMPT
1348e43a905SRabin Vincent	save_and_disable_irqs_notrace r9	@ make cssr&csidr read atomic
135b46c0f74SStephen Boyd#endif
136bbe88886SCatalin Marinas	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
137bbe88886SCatalin Marinas	isb					@ isb to sych the new cssr&csidr
138bbe88886SCatalin Marinas	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
139b46c0f74SStephen Boyd#ifdef CONFIG_PREEMPT
140b46c0f74SStephen Boyd	restore_irqs_notrace r9
141b46c0f74SStephen Boyd#endif
142bbe88886SCatalin Marinas	and	r2, r1, #7			@ extract the length of the cache lines
143bbe88886SCatalin Marinas	add	r2, r2, #4			@ add 4 (line length offset)
1445aca3708SRussell King	movw	r4, #0x3ff
145bbe88886SCatalin Marinas	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
146bbe88886SCatalin Marinas	clz	r5, r4				@ find bit position of way size increment
1475aca3708SRussell King	movw	r7, #0x7fff
148bbe88886SCatalin Marinas	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
1493287be8cSLorenzo Pieralisiloop1:
15070f665feSLorenzo Pieralisi	mov	r9, r7				@ create working copy of max index
1513287be8cSLorenzo Pieralisiloop2:
15270f665feSLorenzo Pieralisi ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
15370f665feSLorenzo Pieralisi THUMB(	lsl	r6, r4, r5		)
154347c8b70SCatalin Marinas THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
15570f665feSLorenzo Pieralisi ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
15670f665feSLorenzo Pieralisi THUMB(	lsl	r6, r9, r2		)
157347c8b70SCatalin Marinas THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
158bbe88886SCatalin Marinas	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
15970f665feSLorenzo Pieralisi	subs	r9, r9, #1			@ decrement the index
160bbe88886SCatalin Marinas	bge	loop2
16170f665feSLorenzo Pieralisi	subs	r4, r4, #1			@ decrement the way
1623287be8cSLorenzo Pieralisi	bge	loop1
163bbe88886SCatalin Marinasskip:
164bbe88886SCatalin Marinas	add	r10, r10, #2			@ increment cache number
165bbe88886SCatalin Marinas	cmp	r3, r10
1663287be8cSLorenzo Pieralisi	bgt	flush_levels
167bbe88886SCatalin Marinasfinished:
168bbe88886SCatalin Marinas	mov	r10, #0				@ swith back to cache level 0
169bbe88886SCatalin Marinas	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
1709581960aSWill Deacon	dsb	st
171bbe88886SCatalin Marinas	isb
1726ebbf2ceSRussell King	ret	lr
17393ed3970SCatalin MarinasENDPROC(v7_flush_dcache_all)
174bbe88886SCatalin Marinas
175bbe88886SCatalin Marinas/*
176bbe88886SCatalin Marinas *	v7_flush_cache_all()
177bbe88886SCatalin Marinas *
178bbe88886SCatalin Marinas *	Flush the entire cache system.
179bbe88886SCatalin Marinas *  The data cache flush is now achieved using atomic clean / invalidates
180bbe88886SCatalin Marinas *  working outwards from L1 cache. This is done using Set/Way based cache
18125985edcSLucas De Marchi *  maintenance instructions.
182bbe88886SCatalin Marinas *  The instruction cache can still be invalidated back to the point of
183bbe88886SCatalin Marinas *  unification in a single instruction.
184bbe88886SCatalin Marinas *
185bbe88886SCatalin Marinas */
186bbe88886SCatalin MarinasENTRY(v7_flush_kern_cache_all)
187347c8b70SCatalin Marinas ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
188347c8b70SCatalin Marinas THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
189bbe88886SCatalin Marinas	bl	v7_flush_dcache_all
190bbe88886SCatalin Marinas	mov	r0, #0
191f00ec48fSRussell King	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)	@ invalidate I-cache inner shareable
192f00ec48fSRussell King	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
193347c8b70SCatalin Marinas ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
194347c8b70SCatalin Marinas THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
1956ebbf2ceSRussell King	ret	lr
19693ed3970SCatalin MarinasENDPROC(v7_flush_kern_cache_all)
197bbe88886SCatalin Marinas
198bbe88886SCatalin Marinas /*
199031bd879SLorenzo Pieralisi *     v7_flush_kern_cache_louis(void)
200031bd879SLorenzo Pieralisi *
201031bd879SLorenzo Pieralisi *     Flush the data cache up to Level of Unification Inner Shareable.
202031bd879SLorenzo Pieralisi *     Invalidate the I-cache to the point of unification.
203031bd879SLorenzo Pieralisi */
204031bd879SLorenzo PieralisiENTRY(v7_flush_kern_cache_louis)
205031bd879SLorenzo Pieralisi ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
206031bd879SLorenzo Pieralisi THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
207031bd879SLorenzo Pieralisi	bl	v7_flush_dcache_louis
208031bd879SLorenzo Pieralisi	mov	r0, #0
209031bd879SLorenzo Pieralisi	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)	@ invalidate I-cache inner shareable
210031bd879SLorenzo Pieralisi	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
211031bd879SLorenzo Pieralisi ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
212031bd879SLorenzo Pieralisi THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
2136ebbf2ceSRussell King	ret	lr
214031bd879SLorenzo PieralisiENDPROC(v7_flush_kern_cache_louis)
215031bd879SLorenzo Pieralisi
216031bd879SLorenzo Pieralisi/*
217bbe88886SCatalin Marinas *	v7_flush_cache_all()
218bbe88886SCatalin Marinas *
219bbe88886SCatalin Marinas *	Flush all TLB entries in a particular address space
220bbe88886SCatalin Marinas *
221bbe88886SCatalin Marinas *	- mm    - mm_struct describing address space
222bbe88886SCatalin Marinas */
223bbe88886SCatalin MarinasENTRY(v7_flush_user_cache_all)
224bbe88886SCatalin Marinas	/*FALLTHROUGH*/
225bbe88886SCatalin Marinas
226bbe88886SCatalin Marinas/*
227bbe88886SCatalin Marinas *	v7_flush_cache_range(start, end, flags)
228bbe88886SCatalin Marinas *
229bbe88886SCatalin Marinas *	Flush a range of TLB entries in the specified address space.
230bbe88886SCatalin Marinas *
231bbe88886SCatalin Marinas *	- start - start address (may not be aligned)
232bbe88886SCatalin Marinas *	- end   - end address (exclusive, may not be aligned)
233bbe88886SCatalin Marinas *	- flags	- vm_area_struct flags describing address space
234bbe88886SCatalin Marinas *
235bbe88886SCatalin Marinas *	It is assumed that:
236bbe88886SCatalin Marinas *	- we have a VIPT cache.
237bbe88886SCatalin Marinas */
238bbe88886SCatalin MarinasENTRY(v7_flush_user_cache_range)
2396ebbf2ceSRussell King	ret	lr
24093ed3970SCatalin MarinasENDPROC(v7_flush_user_cache_all)
24193ed3970SCatalin MarinasENDPROC(v7_flush_user_cache_range)
242bbe88886SCatalin Marinas
243bbe88886SCatalin Marinas/*
244bbe88886SCatalin Marinas *	v7_coherent_kern_range(start,end)
245bbe88886SCatalin Marinas *
246bbe88886SCatalin Marinas *	Ensure that the I and D caches are coherent within specified
247bbe88886SCatalin Marinas *	region.  This is typically used when code has been written to
248bbe88886SCatalin Marinas *	a memory region, and will be executed.
249bbe88886SCatalin Marinas *
250bbe88886SCatalin Marinas *	- start   - virtual start address of region
251bbe88886SCatalin Marinas *	- end     - virtual end address of region
252bbe88886SCatalin Marinas *
253bbe88886SCatalin Marinas *	It is assumed that:
254bbe88886SCatalin Marinas *	- the Icache does not read data from the write buffer
255bbe88886SCatalin Marinas */
256bbe88886SCatalin MarinasENTRY(v7_coherent_kern_range)
257bbe88886SCatalin Marinas	/* FALLTHROUGH */
258bbe88886SCatalin Marinas
259bbe88886SCatalin Marinas/*
260bbe88886SCatalin Marinas *	v7_coherent_user_range(start,end)
261bbe88886SCatalin Marinas *
262bbe88886SCatalin Marinas *	Ensure that the I and D caches are coherent within specified
263bbe88886SCatalin Marinas *	region.  This is typically used when code has been written to
264bbe88886SCatalin Marinas *	a memory region, and will be executed.
265bbe88886SCatalin Marinas *
266bbe88886SCatalin Marinas *	- start   - virtual start address of region
267bbe88886SCatalin Marinas *	- end     - virtual end address of region
268bbe88886SCatalin Marinas *
269bbe88886SCatalin Marinas *	It is assumed that:
270bbe88886SCatalin Marinas *	- the Icache does not read data from the write buffer
271bbe88886SCatalin Marinas */
272bbe88886SCatalin MarinasENTRY(v7_coherent_user_range)
27332cfb1b1SCatalin Marinas UNWIND(.fnstart		)
274bbe88886SCatalin Marinas	dcache_line_size r2, r3
275bbe88886SCatalin Marinas	sub	r3, r2, #1
276da30e0acSCatalin Marinas	bic	r12, r0, r3
277f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
278f630c1bdSWill Deacon	ALT_SMP(W(dsb))
279f630c1bdSWill Deacon	ALT_UP(W(nop))
280f630c1bdSWill Deacon#endif
28132cfb1b1SCatalin Marinas1:
282da30e0acSCatalin Marinas USER(	mcr	p15, 0, r12, c7, c11, 1	)	@ clean D line to the point of unification
283da30e0acSCatalin Marinas	add	r12, r12, r2
284da30e0acSCatalin Marinas	cmp	r12, r1
285bbe88886SCatalin Marinas	blo	1b
2866abdd491SWill Deacon	dsb	ishst
287da30e0acSCatalin Marinas	icache_line_size r2, r3
288da30e0acSCatalin Marinas	sub	r3, r2, #1
289da30e0acSCatalin Marinas	bic	r12, r0, r3
290da30e0acSCatalin Marinas2:
291da30e0acSCatalin Marinas USER(	mcr	p15, 0, r12, c7, c5, 1	)	@ invalidate I line
292da30e0acSCatalin Marinas	add	r12, r12, r2
293da30e0acSCatalin Marinas	cmp	r12, r1
294da30e0acSCatalin Marinas	blo	2b
295bbe88886SCatalin Marinas	mov	r0, #0
296f00ec48fSRussell King	ALT_SMP(mcr	p15, 0, r0, c7, c1, 6)	@ invalidate BTB Inner Shareable
297f00ec48fSRussell King	ALT_UP(mcr	p15, 0, r0, c7, c5, 6)	@ invalidate BTB
2986abdd491SWill Deacon	dsb	ishst
299bbe88886SCatalin Marinas	isb
3006ebbf2ceSRussell King	ret	lr
30132cfb1b1SCatalin Marinas
30232cfb1b1SCatalin Marinas/*
30332cfb1b1SCatalin Marinas * Fault handling for the cache operation above. If the virtual address in r0
304c5102f59SWill Deacon * isn't mapped, fail with -EFAULT.
30532cfb1b1SCatalin Marinas */
30632cfb1b1SCatalin Marinas9001:
3077253b85cSSimon Horman#ifdef CONFIG_ARM_ERRATA_775420
3087253b85cSSimon Horman	dsb
3097253b85cSSimon Horman#endif
310c5102f59SWill Deacon	mov	r0, #-EFAULT
3116ebbf2ceSRussell King	ret	lr
31232cfb1b1SCatalin Marinas UNWIND(.fnend		)
31393ed3970SCatalin MarinasENDPROC(v7_coherent_kern_range)
31493ed3970SCatalin MarinasENDPROC(v7_coherent_user_range)
315bbe88886SCatalin Marinas
316bbe88886SCatalin Marinas/*
3172c9b9c84SRussell King *	v7_flush_kern_dcache_area(void *addr, size_t size)
318bbe88886SCatalin Marinas *
319bbe88886SCatalin Marinas *	Ensure that the data held in the page kaddr is written back
320bbe88886SCatalin Marinas *	to the page in question.
321bbe88886SCatalin Marinas *
3222c9b9c84SRussell King *	- addr	- kernel address
3232c9b9c84SRussell King *	- size	- region size
324bbe88886SCatalin Marinas */
3252c9b9c84SRussell KingENTRY(v7_flush_kern_dcache_area)
326bbe88886SCatalin Marinas	dcache_line_size r2, r3
3272c9b9c84SRussell King	add	r1, r0, r1
328a248b13bSWill Deacon	sub	r3, r2, #1
329a248b13bSWill Deacon	bic	r0, r0, r3
330f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
331f630c1bdSWill Deacon	ALT_SMP(W(dsb))
332f630c1bdSWill Deacon	ALT_UP(W(nop))
333f630c1bdSWill Deacon#endif
334bbe88886SCatalin Marinas1:
335bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
336bbe88886SCatalin Marinas	add	r0, r0, r2
337bbe88886SCatalin Marinas	cmp	r0, r1
338bbe88886SCatalin Marinas	blo	1b
3399581960aSWill Deacon	dsb	st
3406ebbf2ceSRussell King	ret	lr
3412c9b9c84SRussell KingENDPROC(v7_flush_kern_dcache_area)
342bbe88886SCatalin Marinas
343bbe88886SCatalin Marinas/*
344bbe88886SCatalin Marinas *	v7_dma_inv_range(start,end)
345bbe88886SCatalin Marinas *
346bbe88886SCatalin Marinas *	Invalidate the data cache within the specified region; we will
347bbe88886SCatalin Marinas *	be performing a DMA operation in this region and we want to
348bbe88886SCatalin Marinas *	purge old data in the cache.
349bbe88886SCatalin Marinas *
350bbe88886SCatalin Marinas *	- start   - virtual start address of region
351bbe88886SCatalin Marinas *	- end     - virtual end address of region
352bbe88886SCatalin Marinas */
353702b94bfSRussell Kingv7_dma_inv_range:
354bbe88886SCatalin Marinas	dcache_line_size r2, r3
355bbe88886SCatalin Marinas	sub	r3, r2, #1
356bbe88886SCatalin Marinas	tst	r0, r3
357bbe88886SCatalin Marinas	bic	r0, r0, r3
358f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
359f630c1bdSWill Deacon	ALT_SMP(W(dsb))
360f630c1bdSWill Deacon	ALT_UP(W(nop))
361f630c1bdSWill Deacon#endif
362bbe88886SCatalin Marinas	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
363bbe88886SCatalin Marinas
364bbe88886SCatalin Marinas	tst	r1, r3
365bbe88886SCatalin Marinas	bic	r1, r1, r3
366bbe88886SCatalin Marinas	mcrne	p15, 0, r1, c7, c14, 1		@ clean & invalidate D / U line
367bbe88886SCatalin Marinas1:
368bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D / U line
369bbe88886SCatalin Marinas	add	r0, r0, r2
370bbe88886SCatalin Marinas	cmp	r0, r1
371bbe88886SCatalin Marinas	blo	1b
3729581960aSWill Deacon	dsb	st
3736ebbf2ceSRussell King	ret	lr
37493ed3970SCatalin MarinasENDPROC(v7_dma_inv_range)
375bbe88886SCatalin Marinas
376bbe88886SCatalin Marinas/*
377bbe88886SCatalin Marinas *	v7_dma_clean_range(start,end)
378bbe88886SCatalin Marinas *	- start   - virtual start address of region
379bbe88886SCatalin Marinas *	- end     - virtual end address of region
380bbe88886SCatalin Marinas */
381702b94bfSRussell Kingv7_dma_clean_range:
382bbe88886SCatalin Marinas	dcache_line_size r2, r3
383bbe88886SCatalin Marinas	sub	r3, r2, #1
384bbe88886SCatalin Marinas	bic	r0, r0, r3
385f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
386f630c1bdSWill Deacon	ALT_SMP(W(dsb))
387f630c1bdSWill Deacon	ALT_UP(W(nop))
388f630c1bdSWill Deacon#endif
389bbe88886SCatalin Marinas1:
390bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c10, 1		@ clean D / U line
391bbe88886SCatalin Marinas	add	r0, r0, r2
392bbe88886SCatalin Marinas	cmp	r0, r1
393bbe88886SCatalin Marinas	blo	1b
3949581960aSWill Deacon	dsb	st
3956ebbf2ceSRussell King	ret	lr
39693ed3970SCatalin MarinasENDPROC(v7_dma_clean_range)
397bbe88886SCatalin Marinas
398bbe88886SCatalin Marinas/*
399bbe88886SCatalin Marinas *	v7_dma_flush_range(start,end)
400bbe88886SCatalin Marinas *	- start   - virtual start address of region
401bbe88886SCatalin Marinas *	- end     - virtual end address of region
402bbe88886SCatalin Marinas */
403bbe88886SCatalin MarinasENTRY(v7_dma_flush_range)
404bbe88886SCatalin Marinas	dcache_line_size r2, r3
405bbe88886SCatalin Marinas	sub	r3, r2, #1
406bbe88886SCatalin Marinas	bic	r0, r0, r3
407f630c1bdSWill Deacon#ifdef CONFIG_ARM_ERRATA_764369
408f630c1bdSWill Deacon	ALT_SMP(W(dsb))
409f630c1bdSWill Deacon	ALT_UP(W(nop))
410f630c1bdSWill Deacon#endif
411bbe88886SCatalin Marinas1:
412bbe88886SCatalin Marinas	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
413bbe88886SCatalin Marinas	add	r0, r0, r2
414bbe88886SCatalin Marinas	cmp	r0, r1
415bbe88886SCatalin Marinas	blo	1b
4169581960aSWill Deacon	dsb	st
4176ebbf2ceSRussell King	ret	lr
41893ed3970SCatalin MarinasENDPROC(v7_dma_flush_range)
419bbe88886SCatalin Marinas
420a9c9147eSRussell King/*
421a9c9147eSRussell King *	dma_map_area(start, size, dir)
422a9c9147eSRussell King *	- start	- kernel virtual start address
423a9c9147eSRussell King *	- size	- size of region
424a9c9147eSRussell King *	- dir	- DMA direction
425a9c9147eSRussell King */
426a9c9147eSRussell KingENTRY(v7_dma_map_area)
427a9c9147eSRussell King	add	r1, r1, r0
4282ffe2da3SRussell King	teq	r2, #DMA_FROM_DEVICE
4292ffe2da3SRussell King	beq	v7_dma_inv_range
4302ffe2da3SRussell King	b	v7_dma_clean_range
431a9c9147eSRussell KingENDPROC(v7_dma_map_area)
432a9c9147eSRussell King
433a9c9147eSRussell King/*
434a9c9147eSRussell King *	dma_unmap_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_unmap_area)
4402ffe2da3SRussell King	add	r1, r1, r0
4412ffe2da3SRussell King	teq	r2, #DMA_TO_DEVICE
4422ffe2da3SRussell King	bne	v7_dma_inv_range
4436ebbf2ceSRussell King	ret	lr
444a9c9147eSRussell KingENDPROC(v7_dma_unmap_area)
445a9c9147eSRussell King
446bbe88886SCatalin Marinas	__INITDATA
447bbe88886SCatalin Marinas
448455a01ecSDave Martin	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
449455a01ecSDave Martin	define_cache_functions v7
450