1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3	L2CR functions
4	Copyright �� 1997-1998 by PowerLogix R & D, Inc.
5
6*/
7/*
8	Thur, Dec. 12, 1998.
9	- First public release, contributed by PowerLogix.
10	***********
11	Sat, Aug. 7, 1999.
12	- Terry: Made sure code disabled interrupts before running. (Previously
13			it was assumed interrupts were already disabled).
14	- Terry: Updated for tentative G4 support.  4MB of memory is now flushed
15			instead of 2MB.  (Prob. only 3 is necessary).
16	- Terry: Updated for workaround to HID0[DPM] processor bug
17			during global invalidates.
18	***********
19	Thu, July 13, 2000.
20	- Terry: Added isync to correct for an errata.
21
22	22 August 2001.
23	- DanM: Finally added the 7450 patch I've had for the past
24		several months.  The L2CR is similar, but I'm going
25		to assume the user of this functions knows what they
26		are doing.
27
28	Author:	Terry Greeniaus (tgree@phys.ualberta.ca)
29	Please e-mail updates to this file to me, thanks!
30*/
31#include <asm/processor.h>
32#include <asm/cputable.h>
33#include <asm/ppc_asm.h>
34#include <asm/cache.h>
35#include <asm/page.h>
36#include <asm/feature-fixups.h>
37
38/* Usage:
39
40	When setting the L2CR register, you must do a few special
41	things.  If you are enabling the cache, you must perform a
42	global invalidate.  If you are disabling the cache, you must
43	flush the cache contents first.  This routine takes care of
44	doing these things.  When first enabling the cache, make sure
45	you pass in the L2CR you want, as well as passing in the
46	global invalidate bit set.  A global invalidate will only be
47	performed if the L2I bit is set in applyThis.  When enabling
48	the cache, you should also set the L2E bit in applyThis.  If
49	you want to modify the L2CR contents after the cache has been
50	enabled, the recommended procedure is to first call
51	__setL2CR(0) to disable the cache and then call it again with
52	the new values for L2CR.  Examples:
53
54	_setL2CR(0)		- disables the cache
55	_setL2CR(0xB3A04000)	- enables my G3 upgrade card:
56				- L2E set to turn on the cache
57				- L2SIZ set to 1MB
58				- L2CLK set to 1:1
59				- L2RAM set to pipelined synchronous late-write
60				- L2I set to perform a global invalidation
61				- L2OH set to 0.5 nS
62				- L2DF set because this upgrade card
63				  requires it
64
65	A similar call should work for your card.  You need to know
66	the correct setting for your card and then place them in the
67	fields I have outlined above.  Other fields support optional
68	features, such as L2DO which caches only data, or L2TS which
69	causes cache pushes from the L1 cache to go to the L2 cache
70	instead of to main memory.
71
72IMPORTANT:
73	Starting with the 7450, the bits in this register have moved
74	or behave differently.  The Enable, Parity Enable, Size,
75	and L2 Invalidate are the only bits that have not moved.
76	The size is read-only for these processors with internal L2
77	cache, and the invalidate is a control as well as status.
78		-- Dan
79
80*/
81/*
82 * Summary: this procedure ignores the L2I bit in the value passed in,
83 * flushes the cache if it was already enabled, always invalidates the
84 * cache, then enables the cache if the L2E bit is set in the value
85 * passed in.
86 *   -- paulus.
87 */
88_GLOBAL(_set_L2CR)
89	/* Make sure this is a 750 or 7400 chip */
90BEGIN_FTR_SECTION
91	li	r3,-1
92	blr
93END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
94
95	mflr	r9
96
97	/* Stop DST streams */
98BEGIN_FTR_SECTION
99	PPC_DSSALL
100	sync
101END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
102
103	/* Turn off interrupts and data relocation. */
104	mfmsr	r7		/* Save MSR in r7 */
105	rlwinm	r4,r7,0,17,15
106	rlwinm	r4,r4,0,28,26	/* Turn off DR bit */
107	sync
108	mtmsr	r4
109	isync
110
111	/* Before we perform the global invalidation, we must disable dynamic
112	 * power management via HID0[DPM] to work around a processor bug where
113	 * DPM can possibly interfere with the state machine in the processor
114	 * that invalidates the L2 cache tags.
115	 */
116	mfspr	r8,SPRN_HID0		/* Save HID0 in r8 */
117	rlwinm	r4,r8,0,12,10		/* Turn off HID0[DPM] */
118	sync
119	mtspr	SPRN_HID0,r4		/* Disable DPM */
120	sync
121
122	/* Get the current enable bit of the L2CR into r4 */
123	mfspr	r4,SPRN_L2CR
124
125	/* Tweak some bits */
126	rlwinm	r5,r3,0,0,0		/* r5 contains the new enable bit */
127	rlwinm	r3,r3,0,11,9		/* Turn off the invalidate bit */
128	rlwinm	r3,r3,0,1,31		/* Turn off the enable bit */
129
130	/* Check to see if we need to flush */
131	rlwinm.	r4,r4,0,0,0
132	beq	2f
133
134	/* Flush the cache. First, read the first 4MB of memory (physical) to
135	 * put new data in the cache.  (Actually we only need
136	 * the size of the L2 cache plus the size of the L1 cache, but 4MB will
137	 * cover everything just to be safe).
138	 */
139
140	 /**** Might be a good idea to set L2DO here - to prevent instructions
141	       from getting into the cache.  But since we invalidate
142	       the next time we enable the cache it doesn't really matter.
143	       Don't do this unless you accommodate all processor variations.
144	       The bit moved on the 7450.....
145	  ****/
146
147BEGIN_FTR_SECTION
148	/* Disable L2 prefetch on some 745x and try to ensure
149	 * L2 prefetch engines are idle. As explained by errata
150	 * text, we can't be sure they are, we just hope very hard
151	 * that well be enough (sic !). At least I noticed Apple
152	 * doesn't even bother doing the dcbf's here...
153	 */
154	mfspr	r4,SPRN_MSSCR0
155	rlwinm	r4,r4,0,0,29
156	sync
157	mtspr	SPRN_MSSCR0,r4
158	sync
159	isync
160	lis	r4,KERNELBASE@h
161	dcbf	0,r4
162	dcbf	0,r4
163	dcbf	0,r4
164	dcbf	0,r4
165END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
166
167	/* TODO: use HW flush assist when available */
168
169	lis	r4,0x0002
170	mtctr	r4
171	li	r4,0
1721:
173	lwzx	r0,0,r4
174	addi	r4,r4,32		/* Go to start of next cache line */
175	bdnz	1b
176	isync
177
178	/* Now, flush the first 4MB of memory */
179	lis	r4,0x0002
180	mtctr	r4
181	li	r4,0
182	sync
1831:
184	dcbf	0,r4
185	addi	r4,r4,32		/* Go to start of next cache line */
186	bdnz	1b
187
1882:
189	/* Set up the L2CR configuration bits (and switch L2 off) */
190	/* CPU errata: Make sure the mtspr below is already in the
191	 * L1 icache
192	 */
193	b	20f
194	.balign	L1_CACHE_BYTES
19522:
196	sync
197	mtspr	SPRN_L2CR,r3
198	sync
199	b	23f
20020:
201	b	21f
20221:	sync
203	isync
204	b	22b
205
20623:
207	/* Perform a global invalidation */
208	oris	r3,r3,0x0020
209	sync
210	mtspr	SPRN_L2CR,r3
211	sync
212	isync				/* For errata */
213
214BEGIN_FTR_SECTION
215	/* On the 7450, we wait for the L2I bit to clear......
216	*/
21710:	mfspr	r3,SPRN_L2CR
218	andis.	r4,r3,0x0020
219	bne	10b
220	b	11f
221END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
222
223	/* Wait for the invalidation to complete */
2243:	mfspr	r3,SPRN_L2CR
225	rlwinm.	r4,r3,0,31,31
226	bne	3b
227
22811:	rlwinm	r3,r3,0,11,9		/* Turn off the L2I bit */
229	sync
230	mtspr	SPRN_L2CR,r3
231	sync
232
233	/* See if we need to enable the cache */
234	cmplwi	r5,0
235	beq	4f
236
237	/* Enable the cache */
238	oris	r3,r3,0x8000
239	mtspr	SPRN_L2CR,r3
240	sync
241
242	/* Enable L2 HW prefetch on 744x/745x */
243BEGIN_FTR_SECTION
244	mfspr	r3,SPRN_MSSCR0
245	ori	r3,r3,3
246	sync
247	mtspr	SPRN_MSSCR0,r3
248	sync
249	isync
250END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
2514:
252
253	/* Restore HID0[DPM] to whatever it was before */
254	sync
255	mtspr	1008,r8
256	sync
257
258	/* Restore MSR (restores EE and DR bits to original state) */
259	mtmsr	r7
260	isync
261
262	mtlr	r9
263	blr
264
265_GLOBAL(_get_L2CR)
266	/* Return the L2CR contents */
267	li	r3,0
268BEGIN_FTR_SECTION
269	mfspr	r3,SPRN_L2CR
270END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
271	blr
272
273
274/*
275 * Here is a similar routine for dealing with the L3 cache
276 * on the 745x family of chips
277 */
278
279_GLOBAL(_set_L3CR)
280	/* Make sure this is a 745x chip */
281BEGIN_FTR_SECTION
282	li	r3,-1
283	blr
284END_FTR_SECTION_IFCLR(CPU_FTR_L3CR)
285
286	/* Turn off interrupts and data relocation. */
287	mfmsr	r7		/* Save MSR in r7 */
288	rlwinm	r4,r7,0,17,15
289	rlwinm	r4,r4,0,28,26	/* Turn off DR bit */
290	sync
291	mtmsr	r4
292	isync
293
294	/* Stop DST streams */
295	PPC_DSSALL
296	sync
297
298	/* Get the current enable bit of the L3CR into r4 */
299	mfspr	r4,SPRN_L3CR
300
301	/* Tweak some bits */
302	rlwinm	r5,r3,0,0,0		/* r5 contains the new enable bit */
303	rlwinm	r3,r3,0,22,20		/* Turn off the invalidate bit */
304	rlwinm	r3,r3,0,2,31		/* Turn off the enable & PE bits */
305	rlwinm	r3,r3,0,5,3		/* Turn off the clken bit */
306	/* Check to see if we need to flush */
307	rlwinm.	r4,r4,0,0,0
308	beq	2f
309
310	/* Flush the cache.
311	 */
312
313	/* TODO: use HW flush assist */
314
315	lis	r4,0x0008
316	mtctr	r4
317	li	r4,0
3181:
319	lwzx	r0,0,r4
320	dcbf	0,r4
321	addi	r4,r4,32		/* Go to start of next cache line */
322	bdnz	1b
323
3242:
325	/* Set up the L3CR configuration bits (and switch L3 off) */
326	sync
327	mtspr	SPRN_L3CR,r3
328	sync
329
330	oris	r3,r3,L3CR_L3RES@h		/* Set reserved bit 5 */
331	mtspr	SPRN_L3CR,r3
332	sync
333	oris	r3,r3,L3CR_L3CLKEN@h		/* Set clken */
334	mtspr	SPRN_L3CR,r3
335	sync
336
337	/* Wait for stabilize */
338	li	r0,256
339	mtctr	r0
3401:	bdnz	1b
341
342	/* Perform a global invalidation */
343	ori	r3,r3,0x0400
344	sync
345	mtspr	SPRN_L3CR,r3
346	sync
347	isync
348
349	/* We wait for the L3I bit to clear...... */
35010:	mfspr	r3,SPRN_L3CR
351	andi.	r4,r3,0x0400
352	bne	10b
353
354	/* Clear CLKEN */
355	rlwinm	r3,r3,0,5,3		/* Turn off the clken bit */
356	mtspr	SPRN_L3CR,r3
357	sync
358
359	/* Wait for stabilize */
360	li	r0,256
361	mtctr	r0
3621:	bdnz	1b
363
364	/* See if we need to enable the cache */
365	cmplwi	r5,0
366	beq	4f
367
368	/* Enable the cache */
369	oris	r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h
370	mtspr	SPRN_L3CR,r3
371	sync
372
373	/* Wait for stabilize */
374	li	r0,256
375	mtctr	r0
3761:	bdnz	1b
377
378	/* Restore MSR (restores EE and DR bits to original state) */
3794:
380	mtmsr	r7
381	isync
382	blr
383
384_GLOBAL(_get_L3CR)
385	/* Return the L3CR contents */
386	li	r3,0
387BEGIN_FTR_SECTION
388	mfspr	r3,SPRN_L3CR
389END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
390	blr
391
392/* --- End of PowerLogix code ---
393 */
394
395
396/* flush_disable_L1()	- Flush and disable L1 cache
397 *
398 * clobbers r0, r3, ctr, cr0
399 * Must be called with interrupts disabled and MMU enabled.
400 */
401_GLOBAL(__flush_disable_L1)
402	/* Stop pending alitvec streams and memory accesses */
403BEGIN_FTR_SECTION
404	PPC_DSSALL
405END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
406 	sync
407
408	/* Load counter to 0x4000 cache lines (512k) and
409	 * load cache with datas
410	 */
411	li	r3,0x4000	/* 512kB / 32B */
412	mtctr	r3
413	lis	r3,KERNELBASE@h
4141:
415	lwz	r0,0(r3)
416	addi	r3,r3,0x0020	/* Go to start of next cache line */
417	bdnz	1b
418	isync
419	sync
420
421	/* Now flush those cache lines */
422	li	r3,0x4000	/* 512kB / 32B */
423	mtctr	r3
424	lis	r3,KERNELBASE@h
4251:
426	dcbf	0,r3
427	addi	r3,r3,0x0020	/* Go to start of next cache line */
428	bdnz	1b
429	sync
430
431	/* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */
432	mfspr	r3,SPRN_HID0
433	rlwinm	r3,r3,0,18,15
434	mtspr	SPRN_HID0,r3
435	sync
436	isync
437 	blr
438
439/* inval_enable_L1	- Invalidate and enable L1 cache
440 *
441 * Assumes L1 is already disabled and MSR:EE is off
442 *
443 * clobbers r3
444 */
445_GLOBAL(__inval_enable_L1)
446	/* Enable and then Flash inval the instruction & data cache */
447	mfspr	r3,SPRN_HID0
448	ori	r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
449	sync
450	isync
451	mtspr	SPRN_HID0,r3
452	xori	r3,r3, HID0_ICFI|HID0_DCI
453	mtspr	SPRN_HID0,r3
454	sync
455
456 	blr
457_ASM_NOKPROBE_SYMBOL(__inval_enable_L1)
458
459
460