1/*
2 * Useful bootup functions, which are more easily done in asm than C.
3 *
4 * NOTE:  Be very very careful about the registers you use here.
5 *	We don't follow any ABI calling convention among the
6 *	assembler functions that call each other, especially early
7 *	in the initialization.  Please preserve at least r3 and r4
8 *	for these early functions, as they often contain information
9 *	passed from boot roms into the C decompress function.
10 *
11 * Author: Tom Rini
12 *	   trini@mvista.com
13 * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
14 *
15 * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
16 * the terms of the GNU General Public License version 2.  This program
17 * is licensed "as is" without any warranty of any kind, whether express
18 * or implied.
19 */
20
21#include <asm/processor.h>
22#include <asm/cache.h>
23#include <asm/ppc_asm.h>
24
25
26	.text
27
28#ifdef CONFIG_6xx
29	.globl	disable_6xx_mmu
30disable_6xx_mmu:
31	/* Establish default MSR value, exception prefix 0xFFF.
32	 * If necessary, this function must fix up the LR if we
33	 * return to a different address space once the MMU is
34	 * disabled.
35	 */
36	li	r8,MSR_IP|MSR_FP
37	mtmsr	r8
38	isync
39
40	/* Test for a 601 */
41	mfpvr	r10
42	srwi	r10,r10,16
43	cmpwi	0,r10,1		/* 601 ? */
44	beq	.clearbats_601
45
46	/* Clear BATs */
47	li	r8,0
48	mtspr	SPRN_DBAT0U,r8
49	mtspr	SPRN_DBAT0L,r8
50	mtspr	SPRN_DBAT1U,r8
51	mtspr	SPRN_DBAT1L,r8
52	mtspr	SPRN_DBAT2U,r8
53	mtspr	SPRN_DBAT2L,r8
54	mtspr	SPRN_DBAT3U,r8
55	mtspr	SPRN_DBAT3L,r8
56.clearbats_601:
57	mtspr	SPRN_IBAT0U,r8
58	mtspr	SPRN_IBAT0L,r8
59	mtspr	SPRN_IBAT1U,r8
60	mtspr	SPRN_IBAT1L,r8
61	mtspr	SPRN_IBAT2U,r8
62	mtspr	SPRN_IBAT2L,r8
63	mtspr	SPRN_IBAT3U,r8
64	mtspr	SPRN_IBAT3L,r8
65	isync
66	sync
67	sync
68
69	/* Set segment registers */
70	li	r8,16		/* load up segment register values */
71	mtctr	r8		/* for context 0 */
72	lis	r8,0x2000	/* Ku = 1, VSID = 0 */
73	li	r10,0
743:	mtsrin	r8,r10
75	addi	r8,r8,0x111	/* increment VSID */
76	addis	r10,r10,0x1000	/* address of next segment */
77	bdnz	3b
78	blr
79
80	.globl	disable_6xx_l1cache
81disable_6xx_l1cache:
82	/* Enable, invalidate and then disable the L1 icache/dcache. */
83	li	r8,0
84	ori	r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
85	mfspr	r11,SPRN_HID0
86	or	r11,r11,r8
87	andc	r10,r11,r8
88	isync
89	mtspr	SPRN_HID0,r8
90	sync
91	isync
92	mtspr	SPRN_HID0,r10
93	sync
94	isync
95	blr
96#endif
97
98	.globl	_setup_L2CR
99_setup_L2CR:
100/*
101 * We should be skipping this section on CPUs where this results in an
102 * illegal instruction.  If not, please send trini@kernel.crashing.org
103 * the PVR of your CPU.
104 */
105	/* Invalidate/disable L2 cache */
106	sync
107	isync
108	mfspr	r8,SPRN_L2CR
109	rlwinm	r8,r8,0,1,31
110	oris	r8,r8,L2CR_L2I@h
111	sync
112	isync
113	mtspr	SPRN_L2CR,r8
114	sync
115	isync
116
117	/* Wait for the invalidation to complete */
118	mfspr   r8,SPRN_PVR
119	srwi    r8,r8,16
120	cmplwi	cr0,r8,0x8000			/* 7450 */
121	cmplwi	cr1,r8,0x8001			/* 7455 */
122	cmplwi	cr2,r8,0x8002			/* 7457 */
123	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq	/* Now test if any are true. */
124	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
125	bne     2f
126
1271:	mfspr	r8,SPRN_L2CR	/* On 745x, poll L2I bit (bit 10) */
128	rlwinm.	r9,r8,0,10,10
129	bne	1b
130	b	3f
131
1322:      mfspr   r8,SPRN_L2CR	/* On 75x & 74[01]0, poll L2IP bit (bit 31) */
133	rlwinm. r9,r8,0,31,31
134	bne     2b
135
1363:	rlwinm	r8,r8,0,11,9	/* Turn off L2I bit */
137	sync
138	isync
139	mtspr	SPRN_L2CR,r8
140	sync
141	isync
142	blr
143
144	.globl	_setup_L3CR
145_setup_L3CR:
146	/* Invalidate/disable L3 cache */
147	sync
148	isync
149	mfspr	r8,SPRN_L3CR
150	rlwinm	r8,r8,0,1,31
151	ori	r8,r8,L3CR_L3I@l
152	sync
153	isync
154	mtspr	SPRN_L3CR,r8
155	sync
156	isync
157
158	/* Wait for the invalidation to complete */
1591:	mfspr	r8,SPRN_L3CR
160	rlwinm.	r9,r8,0,21,21
161	bne	1b
162
163	rlwinm	r8,r8,0,22,20		/* Turn off L3I bit */
164	sync
165	isync
166	mtspr	SPRN_L3CR,r8
167	sync
168	isync
169	blr
170
171
172/* udelay (on non-601 processors) needs to know the period of the
173 * timebase in nanoseconds.  This used to be hardcoded to be 60ns
174 * (period of 66MHz/4).  Now a variable is used that is initialized to
175 * 60 for backward compatibility, but it can be overridden as necessary
176 * with code something like this:
177 *    extern unsigned long timebase_period_ns;
178 *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
179 */
180	.data
181	.globl timebase_period_ns
182timebase_period_ns:
183	.long	60
184
185	.text
186/*
187 * Delay for a number of microseconds
188 */
189	.globl	udelay
190udelay:
191	mfspr	r4,SPRN_PVR
192	srwi	r4,r4,16
193	cmpwi	0,r4,1		/* 601 ? */
194	bne	.udelay_not_601
19500:	li	r0,86	/* Instructions / microsecond? */
196	mtctr	r0
19710:	addi	r0,r0,0 /* NOP */
198	bdnz	10b
199	subic.	r3,r3,1
200	bne	00b
201	blr
202
203.udelay_not_601:
204	mulli	r4,r3,1000	/* nanoseconds */
205	/*  Change r4 to be the number of ticks using:
206	 *	(nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
207	 *  timebase_period_ns defaults to 60 (16.6MHz) */
208	lis	r5,timebase_period_ns@ha
209	lwz	r5,timebase_period_ns@l(r5)
210	add	r4,r4,r5
211	addi	r4,r4,-1
212	divw	r4,r4,r5	/* BUS ticks */
2131:	mftbu	r5
214	mftb	r6
215	mftbu	r7
216	cmpw	0,r5,r7
217	bne	1b		/* Get [synced] base time */
218	addc	r9,r6,r4	/* Compute end time */
219	addze	r8,r5
2202:	mftbu	r5
221	cmpw	0,r5,r8
222	blt	2b
223	bgt	3f
224	mftb	r6
225	cmpw	0,r6,r9
226	blt	2b
2273:	blr
228
229	.section ".relocate_code","xa"
230/*
231 * Flush and enable instruction cache
232 * First, flush the data cache in case it was enabled and may be
233 * holding instructions for copy back.
234 */
235        .globl flush_instruction_cache
236flush_instruction_cache:
237	mflr	r6
238	bl	flush_data_cache
239
240#ifdef CONFIG_8xx
241	lis	r3, IDC_INVALL@h
242	mtspr	SPRN_IC_CST, r3
243	lis	r3, IDC_ENABLE@h
244	mtspr	SPRN_IC_CST, r3
245	lis	r3, IDC_DISABLE@h
246	mtspr	SPRN_DC_CST, r3
247#elif CONFIG_4xx
248	lis	r3,start@h		# r9 = &_start
249	lis	r4,_etext@ha
250	addi	r4,r4,_etext@l		# r8 = &_etext
2511:	dcbf	r0,r3			# Flush the data cache
252	icbi	r0,r3			# Invalidate the instruction cache
253	addi	r3,r3,0x10		# Increment by one cache line
254	cmplw	cr0,r3,r4		# Are we at the end yet?
255	blt	1b			# No, keep flushing and invalidating
256#else
257	/* Enable, invalidate and then disable the L1 icache/dcache. */
258	li	r3,0
259	ori	r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
260	mfspr	r4,SPRN_HID0
261	or	r5,r4,r3
262	isync
263	mtspr	SPRN_HID0,r5
264	sync
265	isync
266	ori	r5,r4,HID0_ICE	/* Enable cache */
267	mtspr	SPRN_HID0,r5
268	sync
269	isync
270#endif
271	mtlr	r6
272	blr
273
274#define NUM_CACHE_LINES 128*8
275#define cache_flush_buffer 0x1000
276
277/*
278 * Flush data cache
279 * Do this by just reading lots of stuff into the cache.
280 */
281        .globl flush_data_cache
282flush_data_cache:
283	lis	r3,cache_flush_buffer@h
284	ori	r3,r3,cache_flush_buffer@l
285	li	r4,NUM_CACHE_LINES
286	mtctr	r4
28700:	lwz	r4,0(r3)
288	addi	r3,r3,L1_CACHE_BYTES	/* Next line, please */
289	bdnz	00b
29010:	blr
291
292	.previous
293