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 * Flush a particular page from the data cache to RAM.
119 * Note: this is necessary because the instruction cache does *not*
120 * snoop from the data cache.
121 *
122 *	void __flush_page_to_ram(void *page)
123 */
124_GLOBAL(__flush_page_to_ram)
125	rlwinm	r3,r3,0,0,19		/* Get page base address */
126	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
127	mtctr	r4
128	mr	r6,r3
1290:	dcbst	0,r3			/* Write line to ram */
130	addi	r3,r3,CACHE_LINE_SIZE
131	bdnz	0b
132	sync
133	mtctr	r4
1341:	icbi	0,r6
135	addi	r6,r6,CACHE_LINE_SIZE
136	bdnz	1b
137	sync
138	isync
139	blr
140
141/*
142 * Flush a particular page from the instruction cache.
143 * Note: this is necessary because the instruction cache does *not*
144 * snoop from the data cache.
145 *
146 *	void __flush_icache_page(void *page)
147 */
148_GLOBAL(__flush_icache_page)
149	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
150	mtctr	r4
1511:	icbi	0,r3
152	addi	r3,r3,CACHE_LINE_SIZE
153	bdnz	1b
154	sync
155	isync
156	blr
157
158/*
159 * Clear a page using the dcbz instruction, which doesn't cause any
160 * memory traffic (except to write out any cache lines which get
161 * displaced).  This only works on cacheable memory.
162 */
163_GLOBAL(clear_page)
164	li	r0,4096/CACHE_LINE_SIZE
165	mtctr	r0
1661:	dcbz	0,r3
167	addi	r3,r3,CACHE_LINE_SIZE
168	bdnz	1b
169	blr
170
171/*
172 * Enable L1 Instruction cache
173 */
174_GLOBAL(icache_enable)
175	mfspr	r3, HID0
176	li	r5, HID0_ICFI|HID0_ILOCK
177	andc	r3, r3, r5
178	ori	r3, r3, HID0_ICE
179	ori	r5, r3, HID0_ICFI
180	mtspr	HID0, r5
181	mtspr	HID0, r3
182	isync
183	blr
184
185/*
186 * Disable L1 Instruction cache
187 */
188_GLOBAL(icache_disable)
189	mflr	r4
190	bl	invalidate_l1_instruction_cache		/* uses r3 */
191	sync
192	mtlr	r4
193	mfspr	r3, HID0
194	li	r5, 0
195	ori	r5, r5, HID0_ICE
196	andc	r3, r3, r5
197	mtspr	HID0, r3
198	isync
199	blr
200
201/*
202 * Is instruction cache enabled?
203 */
204_GLOBAL(icache_status)
205	mfspr	r3, HID0
206	andi.	r3, r3, HID0_ICE
207	blr
208
209
210_GLOBAL(l1dcache_enable)
211	mfspr	r3, HID0
212	li	r5, HID0_DCFI|HID0_DLOCK
213	andc	r3, r3, r5
214	mtspr	HID0, r3		/* no invalidate, unlock */
215	ori	r3, r3, HID0_DCE
216	ori	r5, r3, HID0_DCFI
217	mtspr	HID0, r5		/* enable + invalidate */
218	mtspr	HID0, r3		/* enable */
219	sync
220	blr
221
222/*
223 * Enable data cache(s) - L1 and optionally L2
224 * Calls l2cache_enable. LR saved in r5
225 */
226_GLOBAL(dcache_enable)
227	mfspr	r3, HID0
228	li	r5, HID0_DCFI|HID0_DLOCK
229	andc	r3, r3, r5
230	mtspr	HID0, r3		/* no invalidate, unlock */
231	ori	r3, r3, HID0_DCE
232	ori	r5, r3, HID0_DCFI
233	mtspr	HID0, r5		/* enable + invalidate */
234	mtspr	HID0, r3		/* enable */
235	sync
236#ifdef CONFIG_SYS_L2
237	mflr	r5
238	bl	l2cache_enable		/* uses r3 and r4 */
239	sync
240	mtlr	r5
241#endif
242	blr
243
244
245/*
246 * Disable data cache(s) - L1 and optionally L2
247 * Calls flush_dcache and l2cache_disable_no_flush.
248 * LR saved in r4
249 */
250_GLOBAL(dcache_disable)
251	mflr	r4			/* save link register */
252	bl	flush_dcache	/* uses r3 and r5 */
253	sync
254	mfspr	r3, HID0
255	li	r5, HID0_DCFI|HID0_DLOCK
256	andc	r3, r3, r5
257	mtspr	HID0, r3		/* no invalidate, unlock */
258	li	r5, HID0_DCE|HID0_DCFI
259	andc	r3, r3, r5		/* no enable, no invalidate */
260	mtspr	HID0, r3
261	sync
262#ifdef CONFIG_SYS_L2
263	bl	l2cache_disable_no_flush /* uses r3 */
264#endif
265	mtlr	r4			/* restore link register */
266	blr
267
268/*
269 * Is data cache enabled?
270 */
271_GLOBAL(dcache_status)
272	mfspr	r3, HID0
273	andi.	r3, r3, HID0_DCE
274	blr
275
276/*
277 * Invalidate L2 cache using L2I, assume L2 is enabled
278 */
279_GLOBAL(l2cache_invalidate)
280	mfspr	r3, l2cr
281	rlwinm.	r3, r3, 0, 0, 0
282	beq	1f
283
284	mfspr	r3, l2cr
285	rlwinm	r3, r3, 0, 1, 31
286
287#ifdef	CONFIG_ALTIVEC
288	dssall
289#endif
290	sync
291	mtspr	l2cr, r3
292	sync
2931:	mfspr	r3, l2cr
294	oris	r3, r3, L2CR_L2I@h
295	mtspr	l2cr, r3
296
297invl2:
298	mfspr	r3, l2cr
299	andis.	r3, r3, L2CR_L2I@h
300	bne	invl2
301	blr
302
303/*
304 * Enable L2 cache
305 * Calls l2cache_invalidate. LR is saved in r4
306 */
307_GLOBAL(l2cache_enable)
308	mflr	r4			/* save link register */
309	bl	l2cache_invalidate	/* uses r3 */
310	sync
311	lis	r3, L2_ENABLE@h
312	ori	r3, r3, L2_ENABLE@l
313	mtspr	l2cr, r3
314	isync
315	mtlr	r4			/* restore link register */
316	blr
317
318/*
319 * Disable L2 cache
320 * Calls flush_dcache. LR is saved in r4
321 */
322_GLOBAL(l2cache_disable)
323	mflr	r4			/* save link register */
324	bl	flush_dcache		/* uses r3 and r5 */
325	sync
326	mtlr	r4			/* restore link register */
327l2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */
328	lis	r3, L2_INIT@h
329	ori	r3, r3, L2_INIT@l
330	mtspr	l2cr, r3
331	isync
332	blr
333