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