xref: /openbsd/sys/arch/powerpc/powerpc/cpu_subr.c (revision 462c954b)
1*462c954bSmpi /*	$OpenBSD: cpu_subr.c,v 1.8 2015/04/27 07:20:57 mpi Exp $	*/
23019af2aSkettenis 
33019af2aSkettenis /*
4b87faa37Smpi  * Copyright (c) 2013 Martin Pieuchot
53019af2aSkettenis  * Copyright (c) 2005 Mark Kettenis
63019af2aSkettenis  *
73019af2aSkettenis  * Permission to use, copy, modify, and distribute this software for any
83019af2aSkettenis  * purpose with or without fee is hereby granted, provided that the above
93019af2aSkettenis  * copyright notice and this permission notice appear in all copies.
103019af2aSkettenis  *
113019af2aSkettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
123019af2aSkettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
133019af2aSkettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
143019af2aSkettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
153019af2aSkettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
163019af2aSkettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
173019af2aSkettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
183019af2aSkettenis  */
193019af2aSkettenis 
203019af2aSkettenis #include <sys/param.h>
213019af2aSkettenis 
225c8048c1Smpi #include <powerpc/cpu.h>
235c8048c1Smpi 
245c8048c1Smpi int		ppc_cpuidle;		/* Support DOZE, NAP or DEEP NAP? */
255c8048c1Smpi int		ppc_altivec;		/* CPU has altivec support. */
265c8048c1Smpi int		ppc_proc_is_64b;	/* CPU is 64bit */
275c8048c1Smpi int		ppc_nobat;		/* Do not use BAT registers. */
283019af2aSkettenis 
295d280ceeSmpi struct patch {
305d280ceeSmpi 	uint32_t *s;
315d280ceeSmpi 	uint32_t *e;
325d280ceeSmpi };
335c8048c1Smpi extern struct patch	rfi_start, nop32_start, nopbat_start;
345c8048c1Smpi extern uint32_t		rfid_inst, nop_inst;
355d280ceeSmpi 
365d280ceeSmpi void
cpu_bootstrap(void)375c8048c1Smpi cpu_bootstrap(void)
385d280ceeSmpi {
395d280ceeSmpi 	uint32_t cpu;
405d280ceeSmpi 	uint32_t *inst;
415d280ceeSmpi 	struct patch *p;
425d280ceeSmpi 
435d280ceeSmpi 	cpu = ppc_mfpvr() >> 16;
445d280ceeSmpi 
455d280ceeSmpi 	switch (cpu) {
465d280ceeSmpi 	case PPC_CPU_IBM970:
475d280ceeSmpi 	case PPC_CPU_IBM970FX:
485d280ceeSmpi 	case PPC_CPU_IBM970MP:
495c8048c1Smpi 		ppc_nobat = 1;
505d280ceeSmpi 		ppc_proc_is_64b = 1;
515c8048c1Smpi 
525d280ceeSmpi 		for (p = &rfi_start; p->s; p++) {
535d280ceeSmpi 			for (inst = p->s; inst < p->e; inst++)
545d280ceeSmpi 				*inst = rfid_inst;
555d280ceeSmpi 			syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
565d280ceeSmpi 		}
575c8048c1Smpi 		break;
585c8048c1Smpi 	case PPC_CPU_MPC83xx:
595c8048c1Smpi 		ppc_mtibat4u(0);
605c8048c1Smpi 		ppc_mtibat5u(0);
615c8048c1Smpi 		ppc_mtibat6u(0);
625c8048c1Smpi 		ppc_mtibat7u(0);
635c8048c1Smpi 		ppc_mtdbat4u(0);
645c8048c1Smpi 		ppc_mtdbat5u(0);
655c8048c1Smpi 		ppc_mtdbat6u(0);
665c8048c1Smpi 		ppc_mtdbat7u(0);
675c8048c1Smpi 		/* FALLTHROUGH */
685c8048c1Smpi 	default:
695c8048c1Smpi 		ppc_mtibat0u(0);
705c8048c1Smpi 		ppc_mtibat1u(0);
715c8048c1Smpi 		ppc_mtibat2u(0);
725c8048c1Smpi 		ppc_mtibat3u(0);
735c8048c1Smpi 		ppc_mtdbat0u(0);
745c8048c1Smpi 		ppc_mtdbat1u(0);
755c8048c1Smpi 		ppc_mtdbat2u(0);
765c8048c1Smpi 		ppc_mtdbat3u(0);
775c8048c1Smpi 
785c8048c1Smpi 		for (p = &nop32_start; p->s; p++) {
795d280ceeSmpi 			for (inst = p->s; inst < p->e; inst++)
805d280ceeSmpi 				*inst = nop_inst;
815d280ceeSmpi 			syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
825d280ceeSmpi 		}
835c8048c1Smpi 	}
845d280ceeSmpi 
855c8048c1Smpi 	if (ppc_nobat) {
865c8048c1Smpi 		for (p = &nopbat_start; p->s; p++) {
875d280ceeSmpi 			for (inst = p->s; inst < p->e; inst++)
885d280ceeSmpi 				*inst = nop_inst;
895d280ceeSmpi 			syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
905d280ceeSmpi 		}
915d280ceeSmpi 	}
925d280ceeSmpi }
939bb45dbeSmpi 
9437ba4aa9Skettenis void
ppc_mtscomc(u_int32_t val)9537ba4aa9Skettenis ppc_mtscomc(u_int32_t val)
9637ba4aa9Skettenis {
9737ba4aa9Skettenis 	int s;
9837ba4aa9Skettenis 
9937ba4aa9Skettenis 	s = ppc_intr_disable();
1002df76cc2Sguenther 	__asm volatile ("mtspr 276,%0; isync" :: "r" (val));
10137ba4aa9Skettenis 	ppc_intr_enable(s);
10237ba4aa9Skettenis }
10337ba4aa9Skettenis 
10437ba4aa9Skettenis void
ppc_mtscomd(u_int32_t val)10537ba4aa9Skettenis ppc_mtscomd(u_int32_t val)
10637ba4aa9Skettenis {
10737ba4aa9Skettenis 	int s;
10837ba4aa9Skettenis 
10937ba4aa9Skettenis 	s = ppc_intr_disable();
1102df76cc2Sguenther 	__asm volatile ("mtspr 277,%0; isync" :: "r" (val));
11137ba4aa9Skettenis 	ppc_intr_enable(s);
11237ba4aa9Skettenis }
11337ba4aa9Skettenis 
1143019af2aSkettenis u_int64_t
ppc64_mfscomc(void)1153019af2aSkettenis ppc64_mfscomc(void)
1163019af2aSkettenis {
1173019af2aSkettenis 	u_int64_t ret;
1183019af2aSkettenis 	int s;
1193019af2aSkettenis 
1203019af2aSkettenis 	s = ppc_intr_disable();
1212df76cc2Sguenther 	__asm volatile ("mfspr %0,276;"
1223019af2aSkettenis 	    " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret));
1233019af2aSkettenis 	ppc_intr_enable(s);
1243019af2aSkettenis 	return ret;
1253019af2aSkettenis }
1263019af2aSkettenis 
1273019af2aSkettenis void
ppc64_mtscomc(u_int64_t val)1283019af2aSkettenis ppc64_mtscomc(u_int64_t val)
1293019af2aSkettenis {
1303019af2aSkettenis 	int s;
1313019af2aSkettenis 
1323019af2aSkettenis 	s = ppc_intr_disable();
1332df76cc2Sguenther 	__asm volatile ("sldi %0,%0,32; or %0,%0,%0+1;"
1343019af2aSkettenis 	    " mtspr 276,%0; isync" :: "r" (val));
1353019af2aSkettenis 	ppc_intr_enable(s);
1363019af2aSkettenis }
1373019af2aSkettenis 
1383019af2aSkettenis u_int64_t
ppc64_mfscomd(void)1393019af2aSkettenis ppc64_mfscomd(void)
1403019af2aSkettenis {
1413019af2aSkettenis 	u_int64_t ret;
1423019af2aSkettenis 	int s;
1433019af2aSkettenis 
1443019af2aSkettenis 	s = ppc_intr_disable();
1452df76cc2Sguenther 	__asm volatile ("mfspr %0,277;"
1463019af2aSkettenis             " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret));
1473019af2aSkettenis 	ppc_intr_enable(s);
1483019af2aSkettenis 	return ret;
1493019af2aSkettenis }
150b87faa37Smpi 
151b87faa37Smpi static __inline u_int32_t
ppc64_mfhid0(u_int32_t * lo)152b87faa37Smpi ppc64_mfhid0(u_int32_t *lo)
153b87faa37Smpi {
154b87faa37Smpi 	u_int32_t hid0_hi, hid0_lo;
155b87faa37Smpi 
156b87faa37Smpi 	__asm volatile ("mfspr %0,1008;"
157b87faa37Smpi 	    " mr %1, %0; srdi %0,%0,32;" : "=r" (hid0_hi), "=r" (hid0_lo));
158b87faa37Smpi 	if (lo != NULL)
159b87faa37Smpi 		*lo = hid0_lo;
160b87faa37Smpi 	return hid0_hi;
161b87faa37Smpi }
162b87faa37Smpi 
163b87faa37Smpi static __inline void
ppc64_mthid0(u_int32_t hid0_hi,u_int32_t hid0_lo)164b87faa37Smpi ppc64_mthid0(u_int32_t hid0_hi, u_int32_t hid0_lo)
165b87faa37Smpi {
166b87faa37Smpi 	/*
167b87faa37Smpi 	 * No! It's not a joke (:
168b87faa37Smpi 	 *
169b87faa37Smpi 	 * Note 1 of the Table 2-3 from the 970MP User manual.
170b87faa37Smpi 	 */
171b87faa37Smpi 	__asm volatile ("sldi %0,%0,32; or %0,%0,%1;"
172b87faa37Smpi 	    "sync; mtspr 1008,%0;"
173b87faa37Smpi 	    "mfspr %0,1008; mfspr %0,1008; mfspr %0,1008;"
174b87faa37Smpi 	    "mfspr %0,1008; mfspr %0,1008; mfspr %0,1008;"
175b87faa37Smpi 	    "isync" :: "r" (hid0_hi), "r"(hid0_lo));
176b87faa37Smpi }
177b87faa37Smpi 
178b87faa37Smpi u_int32_t
ppc_mfhid0(void)179b87faa37Smpi ppc_mfhid0(void)
180b87faa37Smpi {
181b87faa37Smpi 	u_int32_t ret;
182b87faa37Smpi 
183b87faa37Smpi 	/* Since the lower 32 bits are reserved, do not expose them. */
184b87faa37Smpi 	if (ppc_proc_is_64b)
185b87faa37Smpi 		return ppc64_mfhid0(NULL);
186b87faa37Smpi 
187b87faa37Smpi 	__asm volatile ("mfspr %0,1008" : "=r" (ret));
188b87faa37Smpi 	return ret;
189b87faa37Smpi }
190b87faa37Smpi 
191b87faa37Smpi void
ppc_mthid0(u_int32_t val)192b87faa37Smpi ppc_mthid0(u_int32_t val)
193b87faa37Smpi {
194b87faa37Smpi 	if (ppc_proc_is_64b) {
195b87faa37Smpi 		u_int32_t lo;
196b87faa37Smpi 
197b87faa37Smpi 		/* Don't write any garbage in the lower 32 bits. */
198b87faa37Smpi 		(void)ppc64_mfhid0(&lo);
199b87faa37Smpi 		return ppc64_mthid0(val, lo);
200b87faa37Smpi 	}
201b87faa37Smpi 
202b87faa37Smpi 	__asm volatile ("mtspr 1008,%0; isync" :: "r" (val));
203b87faa37Smpi }
204b87faa37Smpi 
205b87faa37Smpi u_int64_t
ppc64_mfhid1(void)206b87faa37Smpi ppc64_mfhid1(void)
207b87faa37Smpi {
208b87faa37Smpi 	u_int64_t ret;
209b87faa37Smpi 
210b87faa37Smpi 	__asm volatile ("mfspr %0,1009;"
211b87faa37Smpi             " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret));
212b87faa37Smpi 	return ret;
213b87faa37Smpi }
214b87faa37Smpi 
215b87faa37Smpi void
ppc64_mthid1(u_int64_t val)216b87faa37Smpi ppc64_mthid1(u_int64_t val)
217b87faa37Smpi {
218*462c954bSmpi 	__asm volatile ("sldi %0,%0,32; or %0,%0,%0+1;"
219*462c954bSmpi 	    "mtspr 1009,%0; mtspr 1009,%0; isync;" :: "r" (val));
220b87faa37Smpi }
221b87faa37Smpi 
222b87faa37Smpi u_int64_t
ppc64_mfhid4(void)223b87faa37Smpi ppc64_mfhid4(void)
224b87faa37Smpi {
225b87faa37Smpi 	u_int64_t ret;
226b87faa37Smpi 
227b87faa37Smpi 	__asm volatile ("mfspr %0,1012;"
228b87faa37Smpi             " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret));
229b87faa37Smpi 	return ret;
230b87faa37Smpi }
231b87faa37Smpi 
232b87faa37Smpi void
ppc64_mthid4(u_int64_t val)233b87faa37Smpi ppc64_mthid4(u_int64_t val)
234b87faa37Smpi {
235*462c954bSmpi 	__asm volatile ("sldi %0,%0,32; or %0,%0,%0+1;"
236*462c954bSmpi 	    "sync; mtspr 1012,%0; isync;" :: "r" (val));
237b87faa37Smpi }
238b87faa37Smpi 
239b87faa37Smpi u_int64_t
ppc64_mfhid5(void)240b87faa37Smpi ppc64_mfhid5(void)
241b87faa37Smpi {
242b87faa37Smpi 	u_int64_t ret;
243b87faa37Smpi 
244b87faa37Smpi 	__asm volatile ("mfspr %0,1014;"
245b87faa37Smpi             " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret));
246b87faa37Smpi 	return ret;
247b87faa37Smpi }
248b87faa37Smpi 
249b87faa37Smpi void
ppc64_mthid5(u_int64_t val)250b87faa37Smpi ppc64_mthid5(u_int64_t val)
251b87faa37Smpi {
252*462c954bSmpi 	__asm volatile ("sldi %0,%0,32; or %0,%0,%0+1;"
253*462c954bSmpi 	    "sync; mtspr 1014,%0; isync;" :: "r" (val));
254b87faa37Smpi }
255