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