xref: /rk3399_rockchip-uboot/arch/powerpc/cpu/mpc86xx/cache.S (revision a47a12becf66f02a56da91c161e2edb625e9f20c)
1*a47a12beSStefan Roese#include <config.h>
2*a47a12beSStefan Roese#include <mpc86xx.h>
3*a47a12beSStefan Roese#include <version.h>
4*a47a12beSStefan Roese
5*a47a12beSStefan Roese#include <ppc_asm.tmpl>
6*a47a12beSStefan Roese#include <ppc_defs.h>
7*a47a12beSStefan Roese
8*a47a12beSStefan Roese#include <asm/cache.h>
9*a47a12beSStefan Roese#include <asm/mmu.h>
10*a47a12beSStefan Roese
11*a47a12beSStefan Roese#ifndef CACHE_LINE_SIZE
12*a47a12beSStefan Roese# define CACHE_LINE_SIZE L1_CACHE_BYTES
13*a47a12beSStefan Roese#endif
14*a47a12beSStefan Roese
15*a47a12beSStefan Roese#if CACHE_LINE_SIZE == 128
16*a47a12beSStefan Roese#define LG_CACHE_LINE_SIZE 7
17*a47a12beSStefan Roese#elif CACHE_LINE_SIZE == 32
18*a47a12beSStefan Roese#define LG_CACHE_LINE_SIZE 5
19*a47a12beSStefan Roese#elif CACHE_LINE_SIZE == 16
20*a47a12beSStefan Roese#define LG_CACHE_LINE_SIZE 4
21*a47a12beSStefan Roese#elif CACHE_LINE_SIZE == 8
22*a47a12beSStefan Roese#define LG_CACHE_LINE_SIZE 3
23*a47a12beSStefan Roese#else
24*a47a12beSStefan Roese# error "Invalid cache line size!"
25*a47a12beSStefan Roese#endif
26*a47a12beSStefan Roese
27*a47a12beSStefan Roese/*
28*a47a12beSStefan Roese * Most of this code is taken from 74xx_7xx/cache.S
29*a47a12beSStefan Roese * and then cleaned up a bit
30*a47a12beSStefan Roese */
31*a47a12beSStefan Roese
32*a47a12beSStefan Roese/*
33*a47a12beSStefan Roese * Invalidate L1 instruction cache.
34*a47a12beSStefan Roese */
35*a47a12beSStefan Roese_GLOBAL(invalidate_l1_instruction_cache)
36*a47a12beSStefan Roese	/* use invalidate-all bit in HID0 */
37*a47a12beSStefan Roese	mfspr	r3,HID0
38*a47a12beSStefan Roese	ori	r3,r3,HID0_ICFI
39*a47a12beSStefan Roese	mtspr	HID0,r3
40*a47a12beSStefan Roese	isync
41*a47a12beSStefan Roese	blr
42*a47a12beSStefan Roese
43*a47a12beSStefan Roese/*
44*a47a12beSStefan Roese * Invalidate L1 data cache.
45*a47a12beSStefan Roese */
46*a47a12beSStefan Roese_GLOBAL(invalidate_l1_data_cache)
47*a47a12beSStefan Roese	mfspr	r3,HID0
48*a47a12beSStefan Roese	ori	r3,r3,HID0_DCFI
49*a47a12beSStefan Roese	mtspr	HID0,r3
50*a47a12beSStefan Roese	isync
51*a47a12beSStefan Roese	blr
52*a47a12beSStefan Roese
53*a47a12beSStefan Roese/*
54*a47a12beSStefan Roese * Flush data cache.
55*a47a12beSStefan Roese */
56*a47a12beSStefan Roese_GLOBAL(flush_dcache)
57*a47a12beSStefan Roese	lis	r3,0
58*a47a12beSStefan Roese	lis	r5,CACHE_LINE_SIZE
59*a47a12beSStefan Roeseflush:
60*a47a12beSStefan Roese	cmp	0,1,r3,r5
61*a47a12beSStefan Roese	bge	done
62*a47a12beSStefan Roese	lwz	r5,0(r3)
63*a47a12beSStefan Roese	lis	r5,CACHE_LINE_SIZE
64*a47a12beSStefan Roese	addi	r3,r3,0x4
65*a47a12beSStefan Roese	b	flush
66*a47a12beSStefan Roesedone:
67*a47a12beSStefan Roese	blr
68*a47a12beSStefan Roese/*
69*a47a12beSStefan Roese * Write any modified data cache blocks out to memory
70*a47a12beSStefan Roese * and invalidate the corresponding instruction cache blocks.
71*a47a12beSStefan Roese * This is a no-op on the 601.
72*a47a12beSStefan Roese *
73*a47a12beSStefan Roese * flush_icache_range(unsigned long start, unsigned long stop)
74*a47a12beSStefan Roese */
75*a47a12beSStefan Roese_GLOBAL(flush_icache_range)
76*a47a12beSStefan Roese	li	r5,CACHE_LINE_SIZE-1
77*a47a12beSStefan Roese	andc	r3,r3,r5
78*a47a12beSStefan Roese	subf	r4,r3,r4
79*a47a12beSStefan Roese	add	r4,r4,r5
80*a47a12beSStefan Roese	srwi.	r4,r4,LG_CACHE_LINE_SIZE
81*a47a12beSStefan Roese	beqlr
82*a47a12beSStefan Roese	mtctr	r4
83*a47a12beSStefan Roese	mr	r6,r3
84*a47a12beSStefan Roese1:	dcbst	0,r3
85*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
86*a47a12beSStefan Roese	bdnz	1b
87*a47a12beSStefan Roese	sync				/* wait for dcbst's to get to ram */
88*a47a12beSStefan Roese	mtctr	r4
89*a47a12beSStefan Roese2:	icbi	0,r6
90*a47a12beSStefan Roese	addi	r6,r6,CACHE_LINE_SIZE
91*a47a12beSStefan Roese	bdnz	2b
92*a47a12beSStefan Roese	sync				/* additional sync needed on g4 */
93*a47a12beSStefan Roese	isync
94*a47a12beSStefan Roese	blr
95*a47a12beSStefan Roese/*
96*a47a12beSStefan Roese * Write any modified data cache blocks out to memory.
97*a47a12beSStefan Roese * Does not invalidate the corresponding cache lines (especially for
98*a47a12beSStefan Roese * any corresponding instruction cache).
99*a47a12beSStefan Roese *
100*a47a12beSStefan Roese * clean_dcache_range(unsigned long start, unsigned long stop)
101*a47a12beSStefan Roese */
102*a47a12beSStefan Roese_GLOBAL(clean_dcache_range)
103*a47a12beSStefan Roese	li	r5,CACHE_LINE_SIZE-1
104*a47a12beSStefan Roese	andc	r3,r3,r5	/* align r3 down to cache line */
105*a47a12beSStefan Roese	subf	r4,r3,r4	/* r4 = offset of stop from start of cache line */
106*a47a12beSStefan Roese	add	r4,r4,r5	/* r4 += cache_line_size-1 */
107*a47a12beSStefan Roese	srwi.	r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */
108*a47a12beSStefan Roese	beqlr				  /* if r4 == 0 return */
109*a47a12beSStefan Roese	mtctr	r4			  /* ctr = r4 */
110*a47a12beSStefan Roese
111*a47a12beSStefan Roese	sync
112*a47a12beSStefan Roese1:	dcbst	0,r3
113*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
114*a47a12beSStefan Roese	bdnz	1b
115*a47a12beSStefan Roese	sync				/* wait for dcbst's to get to ram */
116*a47a12beSStefan Roese	blr
117*a47a12beSStefan Roese
118*a47a12beSStefan Roese/*
119*a47a12beSStefan Roese * Write any modified data cache blocks out to memory
120*a47a12beSStefan Roese * and invalidate the corresponding instruction cache blocks.
121*a47a12beSStefan Roese *
122*a47a12beSStefan Roese * flush_dcache_range(unsigned long start, unsigned long stop)
123*a47a12beSStefan Roese */
124*a47a12beSStefan Roese_GLOBAL(flush_dcache_range)
125*a47a12beSStefan Roese	li	r5,CACHE_LINE_SIZE-1
126*a47a12beSStefan Roese	andc	r3,r3,r5
127*a47a12beSStefan Roese	subf	r4,r3,r4
128*a47a12beSStefan Roese	add	r4,r4,r5
129*a47a12beSStefan Roese	srwi.	r4,r4,LG_CACHE_LINE_SIZE
130*a47a12beSStefan Roese	beqlr
131*a47a12beSStefan Roese	mtctr	r4
132*a47a12beSStefan Roese
133*a47a12beSStefan Roese	sync
134*a47a12beSStefan Roese1:	dcbf	0,r3
135*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
136*a47a12beSStefan Roese	bdnz	1b
137*a47a12beSStefan Roese	sync				/* wait for dcbf's to get to ram */
138*a47a12beSStefan Roese	blr
139*a47a12beSStefan Roese
140*a47a12beSStefan Roese/*
141*a47a12beSStefan Roese * Like above, but invalidate the D-cache.  This is used by the 8xx
142*a47a12beSStefan Roese * to invalidate the cache so the PPC core doesn't get stale data
143*a47a12beSStefan Roese * from the CPM (no cache snooping here :-).
144*a47a12beSStefan Roese *
145*a47a12beSStefan Roese * invalidate_dcache_range(unsigned long start, unsigned long stop)
146*a47a12beSStefan Roese */
147*a47a12beSStefan Roese_GLOBAL(invalidate_dcache_range)
148*a47a12beSStefan Roese	li	r5,CACHE_LINE_SIZE-1
149*a47a12beSStefan Roese	andc	r3,r3,r5
150*a47a12beSStefan Roese	subf	r4,r3,r4
151*a47a12beSStefan Roese	add	r4,r4,r5
152*a47a12beSStefan Roese	srwi.	r4,r4,LG_CACHE_LINE_SIZE
153*a47a12beSStefan Roese	beqlr
154*a47a12beSStefan Roese	mtctr	r4
155*a47a12beSStefan Roese
156*a47a12beSStefan Roese	sync
157*a47a12beSStefan Roese1:	dcbi	0,r3
158*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
159*a47a12beSStefan Roese	bdnz	1b
160*a47a12beSStefan Roese	sync				/* wait for dcbi's to get to ram */
161*a47a12beSStefan Roese	blr
162*a47a12beSStefan Roese
163*a47a12beSStefan Roese/*
164*a47a12beSStefan Roese * Flush a particular page from the data cache to RAM.
165*a47a12beSStefan Roese * Note: this is necessary because the instruction cache does *not*
166*a47a12beSStefan Roese * snoop from the data cache.
167*a47a12beSStefan Roese *
168*a47a12beSStefan Roese *	void __flush_page_to_ram(void *page)
169*a47a12beSStefan Roese */
170*a47a12beSStefan Roese_GLOBAL(__flush_page_to_ram)
171*a47a12beSStefan Roese	rlwinm	r3,r3,0,0,19		/* Get page base address */
172*a47a12beSStefan Roese	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
173*a47a12beSStefan Roese	mtctr	r4
174*a47a12beSStefan Roese	mr	r6,r3
175*a47a12beSStefan Roese0:	dcbst	0,r3			/* Write line to ram */
176*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
177*a47a12beSStefan Roese	bdnz	0b
178*a47a12beSStefan Roese	sync
179*a47a12beSStefan Roese	mtctr	r4
180*a47a12beSStefan Roese1:	icbi	0,r6
181*a47a12beSStefan Roese	addi	r6,r6,CACHE_LINE_SIZE
182*a47a12beSStefan Roese	bdnz	1b
183*a47a12beSStefan Roese	sync
184*a47a12beSStefan Roese	isync
185*a47a12beSStefan Roese	blr
186*a47a12beSStefan Roese
187*a47a12beSStefan Roese/*
188*a47a12beSStefan Roese * Flush a particular page from the instruction cache.
189*a47a12beSStefan Roese * Note: this is necessary because the instruction cache does *not*
190*a47a12beSStefan Roese * snoop from the data cache.
191*a47a12beSStefan Roese *
192*a47a12beSStefan Roese *	void __flush_icache_page(void *page)
193*a47a12beSStefan Roese */
194*a47a12beSStefan Roese_GLOBAL(__flush_icache_page)
195*a47a12beSStefan Roese	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
196*a47a12beSStefan Roese	mtctr	r4
197*a47a12beSStefan Roese1:	icbi	0,r3
198*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
199*a47a12beSStefan Roese	bdnz	1b
200*a47a12beSStefan Roese	sync
201*a47a12beSStefan Roese	isync
202*a47a12beSStefan Roese	blr
203*a47a12beSStefan Roese
204*a47a12beSStefan Roese/*
205*a47a12beSStefan Roese * Clear a page using the dcbz instruction, which doesn't cause any
206*a47a12beSStefan Roese * memory traffic (except to write out any cache lines which get
207*a47a12beSStefan Roese * displaced).  This only works on cacheable memory.
208*a47a12beSStefan Roese */
209*a47a12beSStefan Roese_GLOBAL(clear_page)
210*a47a12beSStefan Roese	li	r0,4096/CACHE_LINE_SIZE
211*a47a12beSStefan Roese	mtctr	r0
212*a47a12beSStefan Roese1:	dcbz	0,r3
213*a47a12beSStefan Roese	addi	r3,r3,CACHE_LINE_SIZE
214*a47a12beSStefan Roese	bdnz	1b
215*a47a12beSStefan Roese	blr
216*a47a12beSStefan Roese
217*a47a12beSStefan Roese/*
218*a47a12beSStefan Roese * Enable L1 Instruction cache
219*a47a12beSStefan Roese */
220*a47a12beSStefan Roese_GLOBAL(icache_enable)
221*a47a12beSStefan Roese	mfspr	r3, HID0
222*a47a12beSStefan Roese	li	r5, HID0_ICFI|HID0_ILOCK
223*a47a12beSStefan Roese	andc	r3, r3, r5
224*a47a12beSStefan Roese	ori	r3, r3, HID0_ICE
225*a47a12beSStefan Roese	ori	r5, r3, HID0_ICFI
226*a47a12beSStefan Roese	mtspr	HID0, r5
227*a47a12beSStefan Roese	mtspr	HID0, r3
228*a47a12beSStefan Roese	isync
229*a47a12beSStefan Roese	blr
230*a47a12beSStefan Roese
231*a47a12beSStefan Roese/*
232*a47a12beSStefan Roese * Disable L1 Instruction cache
233*a47a12beSStefan Roese */
234*a47a12beSStefan Roese_GLOBAL(icache_disable)
235*a47a12beSStefan Roese	mflr	r4
236*a47a12beSStefan Roese	bl	invalidate_l1_instruction_cache		/* uses r3 */
237*a47a12beSStefan Roese	sync
238*a47a12beSStefan Roese	mtlr	r4
239*a47a12beSStefan Roese	mfspr	r3, HID0
240*a47a12beSStefan Roese	li	r5, 0
241*a47a12beSStefan Roese	ori	r5, r5, HID0_ICE
242*a47a12beSStefan Roese	andc	r3, r3, r5
243*a47a12beSStefan Roese	mtspr	HID0, r3
244*a47a12beSStefan Roese	isync
245*a47a12beSStefan Roese	blr
246*a47a12beSStefan Roese
247*a47a12beSStefan Roese/*
248*a47a12beSStefan Roese * Is instruction cache enabled?
249*a47a12beSStefan Roese */
250*a47a12beSStefan Roese_GLOBAL(icache_status)
251*a47a12beSStefan Roese	mfspr	r3, HID0
252*a47a12beSStefan Roese	andi.	r3, r3, HID0_ICE
253*a47a12beSStefan Roese	blr
254*a47a12beSStefan Roese
255*a47a12beSStefan Roese
256*a47a12beSStefan Roese_GLOBAL(l1dcache_enable)
257*a47a12beSStefan Roese	mfspr	r3, HID0
258*a47a12beSStefan Roese	li	r5, HID0_DCFI|HID0_DLOCK
259*a47a12beSStefan Roese	andc	r3, r3, r5
260*a47a12beSStefan Roese	mtspr	HID0, r3		/* no invalidate, unlock */
261*a47a12beSStefan Roese	ori	r3, r3, HID0_DCE
262*a47a12beSStefan Roese	ori	r5, r3, HID0_DCFI
263*a47a12beSStefan Roese	mtspr	HID0, r5		/* enable + invalidate */
264*a47a12beSStefan Roese	mtspr	HID0, r3		/* enable */
265*a47a12beSStefan Roese	sync
266*a47a12beSStefan Roese	blr
267*a47a12beSStefan Roese
268*a47a12beSStefan Roese/*
269*a47a12beSStefan Roese * Enable data cache(s) - L1 and optionally L2
270*a47a12beSStefan Roese * Calls l2cache_enable. LR saved in r5
271*a47a12beSStefan Roese */
272*a47a12beSStefan Roese_GLOBAL(dcache_enable)
273*a47a12beSStefan Roese	mfspr	r3, HID0
274*a47a12beSStefan Roese	li	r5, HID0_DCFI|HID0_DLOCK
275*a47a12beSStefan Roese	andc	r3, r3, r5
276*a47a12beSStefan Roese	mtspr	HID0, r3		/* no invalidate, unlock */
277*a47a12beSStefan Roese	ori	r3, r3, HID0_DCE
278*a47a12beSStefan Roese	ori	r5, r3, HID0_DCFI
279*a47a12beSStefan Roese	mtspr	HID0, r5		/* enable + invalidate */
280*a47a12beSStefan Roese	mtspr	HID0, r3		/* enable */
281*a47a12beSStefan Roese	sync
282*a47a12beSStefan Roese#ifdef CONFIG_SYS_L2
283*a47a12beSStefan Roese	mflr	r5
284*a47a12beSStefan Roese	bl	l2cache_enable		/* uses r3 and r4 */
285*a47a12beSStefan Roese	sync
286*a47a12beSStefan Roese	mtlr	r5
287*a47a12beSStefan Roese#endif
288*a47a12beSStefan Roese	blr
289*a47a12beSStefan Roese
290*a47a12beSStefan Roese
291*a47a12beSStefan Roese/*
292*a47a12beSStefan Roese * Disable data cache(s) - L1 and optionally L2
293*a47a12beSStefan Roese * Calls flush_dcache and l2cache_disable_no_flush.
294*a47a12beSStefan Roese * LR saved in r4
295*a47a12beSStefan Roese */
296*a47a12beSStefan Roese_GLOBAL(dcache_disable)
297*a47a12beSStefan Roese	mflr	r4			/* save link register */
298*a47a12beSStefan Roese	bl	flush_dcache	/* uses r3 and r5 */
299*a47a12beSStefan Roese	sync
300*a47a12beSStefan Roese	mfspr	r3, HID0
301*a47a12beSStefan Roese	li	r5, HID0_DCFI|HID0_DLOCK
302*a47a12beSStefan Roese	andc	r3, r3, r5
303*a47a12beSStefan Roese	mtspr	HID0, r3		/* no invalidate, unlock */
304*a47a12beSStefan Roese	li	r5, HID0_DCE|HID0_DCFI
305*a47a12beSStefan Roese	andc	r3, r3, r5		/* no enable, no invalidate */
306*a47a12beSStefan Roese	mtspr	HID0, r3
307*a47a12beSStefan Roese	sync
308*a47a12beSStefan Roese#ifdef CONFIG_SYS_L2
309*a47a12beSStefan Roese	bl	l2cache_disable_no_flush /* uses r3 */
310*a47a12beSStefan Roese#endif
311*a47a12beSStefan Roese	mtlr	r4			/* restore link register */
312*a47a12beSStefan Roese	blr
313*a47a12beSStefan Roese
314*a47a12beSStefan Roese/*
315*a47a12beSStefan Roese * Is data cache enabled?
316*a47a12beSStefan Roese */
317*a47a12beSStefan Roese_GLOBAL(dcache_status)
318*a47a12beSStefan Roese	mfspr	r3, HID0
319*a47a12beSStefan Roese	andi.	r3, r3, HID0_DCE
320*a47a12beSStefan Roese	blr
321*a47a12beSStefan Roese
322*a47a12beSStefan Roese/*
323*a47a12beSStefan Roese * Invalidate L2 cache using L2I, assume L2 is enabled
324*a47a12beSStefan Roese */
325*a47a12beSStefan Roese_GLOBAL(l2cache_invalidate)
326*a47a12beSStefan Roese	mfspr	r3, l2cr
327*a47a12beSStefan Roese	rlwinm.	r3, r3, 0, 0, 0
328*a47a12beSStefan Roese	beq	1f
329*a47a12beSStefan Roese
330*a47a12beSStefan Roese	mfspr	r3, l2cr
331*a47a12beSStefan Roese	rlwinm	r3, r3, 0, 1, 31
332*a47a12beSStefan Roese
333*a47a12beSStefan Roese#ifdef	CONFIG_ALTIVEC
334*a47a12beSStefan Roese	dssall
335*a47a12beSStefan Roese#endif
336*a47a12beSStefan Roese	sync
337*a47a12beSStefan Roese	mtspr	l2cr, r3
338*a47a12beSStefan Roese	sync
339*a47a12beSStefan Roese1:	mfspr	r3, l2cr
340*a47a12beSStefan Roese	oris	r3, r3, L2CR_L2I@h
341*a47a12beSStefan Roese	mtspr	l2cr, r3
342*a47a12beSStefan Roese
343*a47a12beSStefan Roeseinvl2:
344*a47a12beSStefan Roese	mfspr	r3, l2cr
345*a47a12beSStefan Roese	andis.	r3, r3, L2CR_L2I@h
346*a47a12beSStefan Roese	bne	invl2
347*a47a12beSStefan Roese	blr
348*a47a12beSStefan Roese
349*a47a12beSStefan Roese/*
350*a47a12beSStefan Roese * Enable L2 cache
351*a47a12beSStefan Roese * Calls l2cache_invalidate. LR is saved in r4
352*a47a12beSStefan Roese */
353*a47a12beSStefan Roese_GLOBAL(l2cache_enable)
354*a47a12beSStefan Roese	mflr	r4			/* save link register */
355*a47a12beSStefan Roese	bl	l2cache_invalidate	/* uses r3 */
356*a47a12beSStefan Roese	sync
357*a47a12beSStefan Roese	lis	r3, L2_ENABLE@h
358*a47a12beSStefan Roese	ori	r3, r3, L2_ENABLE@l
359*a47a12beSStefan Roese	mtspr	l2cr, r3
360*a47a12beSStefan Roese	isync
361*a47a12beSStefan Roese	mtlr	r4			/* restore link register */
362*a47a12beSStefan Roese	blr
363*a47a12beSStefan Roese
364*a47a12beSStefan Roese/*
365*a47a12beSStefan Roese * Disable L2 cache
366*a47a12beSStefan Roese * Calls flush_dcache. LR is saved in r4
367*a47a12beSStefan Roese */
368*a47a12beSStefan Roese_GLOBAL(l2cache_disable)
369*a47a12beSStefan Roese	mflr	r4			/* save link register */
370*a47a12beSStefan Roese	bl	flush_dcache		/* uses r3 and r5 */
371*a47a12beSStefan Roese	sync
372*a47a12beSStefan Roese	mtlr	r4			/* restore link register */
373*a47a12beSStefan Roesel2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */
374*a47a12beSStefan Roese	lis	r3, L2_INIT@h
375*a47a12beSStefan Roese	ori	r3, r3, L2_INIT@l
376*a47a12beSStefan Roese	mtspr	l2cr, r3
377*a47a12beSStefan Roese	isync
378*a47a12beSStefan Roese	blr
379