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