xref: /openbmc/linux/arch/powerpc/kernel/cpu_setup_power.c (revision 344fbab991a568dc33ad90711b489d870e18d26d)
1*344fbab9SJordan Niethe // SPDX-License-Identifier: GPL-2.0-or-later
2*344fbab9SJordan Niethe /*
3*344fbab9SJordan Niethe  * Copyright 2020, Jordan Niethe, IBM Corporation.
4*344fbab9SJordan Niethe  *
5*344fbab9SJordan Niethe  * This file contains low level CPU setup functions.
6*344fbab9SJordan Niethe  * Originally written in assembly by Benjamin Herrenschmidt & various other
7*344fbab9SJordan Niethe  * authors.
8*344fbab9SJordan Niethe  */
9*344fbab9SJordan Niethe 
10*344fbab9SJordan Niethe #include <asm/reg.h>
11*344fbab9SJordan Niethe #include <asm/synch.h>
12*344fbab9SJordan Niethe #include <linux/bitops.h>
13*344fbab9SJordan Niethe #include <asm/cputable.h>
14*344fbab9SJordan Niethe #include <asm/cpu_setup_power.h>
15*344fbab9SJordan Niethe 
16*344fbab9SJordan Niethe /* Disable CPU_FTR_HVMODE and return false if MSR:HV is not set */
17*344fbab9SJordan Niethe static bool init_hvmode_206(struct cpu_spec *t)
18*344fbab9SJordan Niethe {
19*344fbab9SJordan Niethe 	u64 msr;
20*344fbab9SJordan Niethe 
21*344fbab9SJordan Niethe 	msr = mfmsr();
22*344fbab9SJordan Niethe 	if (msr & MSR_HV)
23*344fbab9SJordan Niethe 		return true;
24*344fbab9SJordan Niethe 
25*344fbab9SJordan Niethe 	t->cpu_features &= ~(CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST);
26*344fbab9SJordan Niethe 	return false;
27*344fbab9SJordan Niethe }
28*344fbab9SJordan Niethe 
29*344fbab9SJordan Niethe static void init_LPCR_ISA300(u64 lpcr, u64 lpes)
30*344fbab9SJordan Niethe {
31*344fbab9SJordan Niethe 	/* POWER9 has no VRMASD */
32*344fbab9SJordan Niethe 	lpcr |= (lpes << LPCR_LPES_SH) & LPCR_LPES;
33*344fbab9SJordan Niethe 	lpcr |= LPCR_PECE0|LPCR_PECE1|LPCR_PECE2;
34*344fbab9SJordan Niethe 	lpcr |= (4ull << LPCR_DPFD_SH) & LPCR_DPFD;
35*344fbab9SJordan Niethe 	lpcr &= ~LPCR_HDICE;	/* clear HDICE */
36*344fbab9SJordan Niethe 	lpcr |= (4ull << LPCR_VC_SH);
37*344fbab9SJordan Niethe 	mtspr(SPRN_LPCR, lpcr);
38*344fbab9SJordan Niethe 	isync();
39*344fbab9SJordan Niethe }
40*344fbab9SJordan Niethe 
41*344fbab9SJordan Niethe /*
42*344fbab9SJordan Niethe  * Setup a sane LPCR:
43*344fbab9SJordan Niethe  *   Called with initial LPCR and desired LPES 2-bit value
44*344fbab9SJordan Niethe  *
45*344fbab9SJordan Niethe  *   LPES = 0b01 (HSRR0/1 used for 0x500)
46*344fbab9SJordan Niethe  *   PECE = 0b111
47*344fbab9SJordan Niethe  *   DPFD = 4
48*344fbab9SJordan Niethe  *   HDICE = 0
49*344fbab9SJordan Niethe  *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
50*344fbab9SJordan Niethe  *   VRMASD = 0b10000 (L=1, LP=00)
51*344fbab9SJordan Niethe  *
52*344fbab9SJordan Niethe  * Other bits untouched for now
53*344fbab9SJordan Niethe  */
54*344fbab9SJordan Niethe static void init_LPCR_ISA206(u64 lpcr, u64 lpes)
55*344fbab9SJordan Niethe {
56*344fbab9SJordan Niethe 	lpcr |= (0x10ull << LPCR_VRMASD_SH) & LPCR_VRMASD;
57*344fbab9SJordan Niethe 	init_LPCR_ISA300(lpcr, lpes);
58*344fbab9SJordan Niethe }
59*344fbab9SJordan Niethe 
60*344fbab9SJordan Niethe static void init_FSCR(void)
61*344fbab9SJordan Niethe {
62*344fbab9SJordan Niethe 	u64 fscr;
63*344fbab9SJordan Niethe 
64*344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
65*344fbab9SJordan Niethe 	fscr |= FSCR_TAR|FSCR_EBB;
66*344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
67*344fbab9SJordan Niethe }
68*344fbab9SJordan Niethe 
69*344fbab9SJordan Niethe static void init_FSCR_power9(void)
70*344fbab9SJordan Niethe {
71*344fbab9SJordan Niethe 	u64 fscr;
72*344fbab9SJordan Niethe 
73*344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
74*344fbab9SJordan Niethe 	fscr |= FSCR_SCV;
75*344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
76*344fbab9SJordan Niethe 	init_FSCR();
77*344fbab9SJordan Niethe }
78*344fbab9SJordan Niethe 
79*344fbab9SJordan Niethe static void init_FSCR_power10(void)
80*344fbab9SJordan Niethe {
81*344fbab9SJordan Niethe 	u64 fscr;
82*344fbab9SJordan Niethe 
83*344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
84*344fbab9SJordan Niethe 	fscr |= FSCR_PREFIX;
85*344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
86*344fbab9SJordan Niethe 	init_FSCR_power9();
87*344fbab9SJordan Niethe }
88*344fbab9SJordan Niethe 
89*344fbab9SJordan Niethe static void init_HFSCR(void)
90*344fbab9SJordan Niethe {
91*344fbab9SJordan Niethe 	u64 hfscr;
92*344fbab9SJordan Niethe 
93*344fbab9SJordan Niethe 	hfscr = mfspr(SPRN_HFSCR);
94*344fbab9SJordan Niethe 	hfscr |= HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|HFSCR_DSCR|\
95*344fbab9SJordan Niethe 		 HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP;
96*344fbab9SJordan Niethe 	mtspr(SPRN_HFSCR, hfscr);
97*344fbab9SJordan Niethe }
98*344fbab9SJordan Niethe 
99*344fbab9SJordan Niethe static void init_PMU_HV(void)
100*344fbab9SJordan Niethe {
101*344fbab9SJordan Niethe 	mtspr(SPRN_MMCRC, 0);
102*344fbab9SJordan Niethe }
103*344fbab9SJordan Niethe 
104*344fbab9SJordan Niethe static void init_PMU_HV_ISA207(void)
105*344fbab9SJordan Niethe {
106*344fbab9SJordan Niethe 	mtspr(SPRN_MMCRH, 0);
107*344fbab9SJordan Niethe }
108*344fbab9SJordan Niethe 
109*344fbab9SJordan Niethe static void init_PMU(void)
110*344fbab9SJordan Niethe {
111*344fbab9SJordan Niethe 	mtspr(SPRN_MMCRA, 0);
112*344fbab9SJordan Niethe 	mtspr(SPRN_MMCR0, 0);
113*344fbab9SJordan Niethe 	mtspr(SPRN_MMCR1, 0);
114*344fbab9SJordan Niethe 	mtspr(SPRN_MMCR2, 0);
115*344fbab9SJordan Niethe }
116*344fbab9SJordan Niethe 
117*344fbab9SJordan Niethe static void init_PMU_ISA207(void)
118*344fbab9SJordan Niethe {
119*344fbab9SJordan Niethe 	mtspr(SPRN_MMCRS, 0);
120*344fbab9SJordan Niethe }
121*344fbab9SJordan Niethe 
122*344fbab9SJordan Niethe static void init_PMU_ISA31(void)
123*344fbab9SJordan Niethe {
124*344fbab9SJordan Niethe 	mtspr(SPRN_MMCR3, 0);
125*344fbab9SJordan Niethe 	mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
126*344fbab9SJordan Niethe }
127*344fbab9SJordan Niethe 
128*344fbab9SJordan Niethe /*
129*344fbab9SJordan Niethe  * Note that we can be called twice of pseudo-PVRs.
130*344fbab9SJordan Niethe  * The parameter offset is not used.
131*344fbab9SJordan Niethe  */
132*344fbab9SJordan Niethe 
133*344fbab9SJordan Niethe void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
134*344fbab9SJordan Niethe {
135*344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
136*344fbab9SJordan Niethe 		return;
137*344fbab9SJordan Niethe 
138*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
139*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
140*344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
141*344fbab9SJordan Niethe }
142*344fbab9SJordan Niethe 
143*344fbab9SJordan Niethe void __restore_cpu_power7(void)
144*344fbab9SJordan Niethe {
145*344fbab9SJordan Niethe 	u64 msr;
146*344fbab9SJordan Niethe 
147*344fbab9SJordan Niethe 	msr = mfmsr();
148*344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
149*344fbab9SJordan Niethe 		return;
150*344fbab9SJordan Niethe 
151*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
152*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
153*344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
154*344fbab9SJordan Niethe }
155*344fbab9SJordan Niethe 
156*344fbab9SJordan Niethe void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
157*344fbab9SJordan Niethe {
158*344fbab9SJordan Niethe 	init_FSCR();
159*344fbab9SJordan Niethe 	init_PMU();
160*344fbab9SJordan Niethe 	init_PMU_ISA207();
161*344fbab9SJordan Niethe 
162*344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
163*344fbab9SJordan Niethe 		return;
164*344fbab9SJordan Niethe 
165*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
166*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
167*344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
168*344fbab9SJordan Niethe 	init_HFSCR();
169*344fbab9SJordan Niethe 	init_PMU_HV();
170*344fbab9SJordan Niethe 	init_PMU_HV_ISA207();
171*344fbab9SJordan Niethe }
172*344fbab9SJordan Niethe 
173*344fbab9SJordan Niethe void __restore_cpu_power8(void)
174*344fbab9SJordan Niethe {
175*344fbab9SJordan Niethe 	u64 msr;
176*344fbab9SJordan Niethe 
177*344fbab9SJordan Niethe 	init_FSCR();
178*344fbab9SJordan Niethe 	init_PMU();
179*344fbab9SJordan Niethe 	init_PMU_ISA207();
180*344fbab9SJordan Niethe 
181*344fbab9SJordan Niethe 	msr = mfmsr();
182*344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
183*344fbab9SJordan Niethe 		return;
184*344fbab9SJordan Niethe 
185*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
186*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
187*344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
188*344fbab9SJordan Niethe 	init_HFSCR();
189*344fbab9SJordan Niethe 	init_PMU_HV();
190*344fbab9SJordan Niethe 	init_PMU_HV_ISA207();
191*344fbab9SJordan Niethe }
192*344fbab9SJordan Niethe 
193*344fbab9SJordan Niethe void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
194*344fbab9SJordan Niethe {
195*344fbab9SJordan Niethe 	init_FSCR_power9();
196*344fbab9SJordan Niethe 	init_PMU();
197*344fbab9SJordan Niethe 
198*344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
199*344fbab9SJordan Niethe 		return;
200*344fbab9SJordan Niethe 
201*344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
202*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
203*344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
204*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
205*344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
206*344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
207*344fbab9SJordan Niethe 	init_HFSCR();
208*344fbab9SJordan Niethe 	init_PMU_HV();
209*344fbab9SJordan Niethe }
210*344fbab9SJordan Niethe 
211*344fbab9SJordan Niethe void __restore_cpu_power9(void)
212*344fbab9SJordan Niethe {
213*344fbab9SJordan Niethe 	u64 msr;
214*344fbab9SJordan Niethe 
215*344fbab9SJordan Niethe 	init_FSCR_power9();
216*344fbab9SJordan Niethe 	init_PMU();
217*344fbab9SJordan Niethe 
218*344fbab9SJordan Niethe 	msr = mfmsr();
219*344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
220*344fbab9SJordan Niethe 		return;
221*344fbab9SJordan Niethe 
222*344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
223*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
224*344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
225*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
226*344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
227*344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
228*344fbab9SJordan Niethe 	init_HFSCR();
229*344fbab9SJordan Niethe 	init_PMU_HV();
230*344fbab9SJordan Niethe }
231*344fbab9SJordan Niethe 
232*344fbab9SJordan Niethe void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
233*344fbab9SJordan Niethe {
234*344fbab9SJordan Niethe 	init_FSCR_power10();
235*344fbab9SJordan Niethe 	init_PMU();
236*344fbab9SJordan Niethe 	init_PMU_ISA31();
237*344fbab9SJordan Niethe 
238*344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
239*344fbab9SJordan Niethe 		return;
240*344fbab9SJordan Niethe 
241*344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
242*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
243*344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
244*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
245*344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
246*344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
247*344fbab9SJordan Niethe 	init_HFSCR();
248*344fbab9SJordan Niethe 	init_PMU_HV();
249*344fbab9SJordan Niethe }
250*344fbab9SJordan Niethe 
251*344fbab9SJordan Niethe void __restore_cpu_power10(void)
252*344fbab9SJordan Niethe {
253*344fbab9SJordan Niethe 	u64 msr;
254*344fbab9SJordan Niethe 
255*344fbab9SJordan Niethe 	init_FSCR_power10();
256*344fbab9SJordan Niethe 	init_PMU();
257*344fbab9SJordan Niethe 	init_PMU_ISA31();
258*344fbab9SJordan Niethe 
259*344fbab9SJordan Niethe 	msr = mfmsr();
260*344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
261*344fbab9SJordan Niethe 		return;
262*344fbab9SJordan Niethe 
263*344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
264*344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
265*344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
266*344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
267*344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
268*344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
269*344fbab9SJordan Niethe 	init_HFSCR();
270*344fbab9SJordan Niethe 	init_PMU_HV();
271*344fbab9SJordan Niethe }
272