xref: /openbmc/linux/arch/powerpc/kernel/cpu_setup_power.c (revision 245ebf8e7380b3d84c0aac37fbfd9306b45a3a7a)
1344fbab9SJordan Niethe // SPDX-License-Identifier: GPL-2.0-or-later
2344fbab9SJordan Niethe /*
3344fbab9SJordan Niethe  * Copyright 2020, Jordan Niethe, IBM Corporation.
4344fbab9SJordan Niethe  *
5344fbab9SJordan Niethe  * This file contains low level CPU setup functions.
6344fbab9SJordan Niethe  * Originally written in assembly by Benjamin Herrenschmidt & various other
7344fbab9SJordan Niethe  * authors.
8344fbab9SJordan Niethe  */
9344fbab9SJordan Niethe 
10344fbab9SJordan Niethe #include <asm/reg.h>
11344fbab9SJordan Niethe #include <asm/synch.h>
12344fbab9SJordan Niethe #include <linux/bitops.h>
13344fbab9SJordan Niethe #include <asm/cputable.h>
14344fbab9SJordan Niethe #include <asm/cpu_setup_power.h>
15344fbab9SJordan Niethe 
16344fbab9SJordan Niethe /* Disable CPU_FTR_HVMODE and return false if MSR:HV is not set */
17344fbab9SJordan Niethe static bool init_hvmode_206(struct cpu_spec *t)
18344fbab9SJordan Niethe {
19344fbab9SJordan Niethe 	u64 msr;
20344fbab9SJordan Niethe 
21344fbab9SJordan Niethe 	msr = mfmsr();
22344fbab9SJordan Niethe 	if (msr & MSR_HV)
23344fbab9SJordan Niethe 		return true;
24344fbab9SJordan Niethe 
25344fbab9SJordan Niethe 	t->cpu_features &= ~(CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST);
26344fbab9SJordan Niethe 	return false;
27344fbab9SJordan Niethe }
28344fbab9SJordan Niethe 
29344fbab9SJordan Niethe static void init_LPCR_ISA300(u64 lpcr, u64 lpes)
30344fbab9SJordan Niethe {
31344fbab9SJordan Niethe 	/* POWER9 has no VRMASD */
32344fbab9SJordan Niethe 	lpcr |= (lpes << LPCR_LPES_SH) & LPCR_LPES;
33344fbab9SJordan Niethe 	lpcr |= LPCR_PECE0|LPCR_PECE1|LPCR_PECE2;
34344fbab9SJordan Niethe 	lpcr |= (4ull << LPCR_DPFD_SH) & LPCR_DPFD;
35344fbab9SJordan Niethe 	lpcr &= ~LPCR_HDICE;	/* clear HDICE */
36344fbab9SJordan Niethe 	lpcr |= (4ull << LPCR_VC_SH);
37344fbab9SJordan Niethe 	mtspr(SPRN_LPCR, lpcr);
38344fbab9SJordan Niethe 	isync();
39344fbab9SJordan Niethe }
40344fbab9SJordan Niethe 
41344fbab9SJordan Niethe /*
42344fbab9SJordan Niethe  * Setup a sane LPCR:
43344fbab9SJordan Niethe  *   Called with initial LPCR and desired LPES 2-bit value
44344fbab9SJordan Niethe  *
45344fbab9SJordan Niethe  *   LPES = 0b01 (HSRR0/1 used for 0x500)
46344fbab9SJordan Niethe  *   PECE = 0b111
47344fbab9SJordan Niethe  *   DPFD = 4
48344fbab9SJordan Niethe  *   HDICE = 0
49344fbab9SJordan Niethe  *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
50344fbab9SJordan Niethe  *   VRMASD = 0b10000 (L=1, LP=00)
51344fbab9SJordan Niethe  *
52344fbab9SJordan Niethe  * Other bits untouched for now
53344fbab9SJordan Niethe  */
54344fbab9SJordan Niethe static void init_LPCR_ISA206(u64 lpcr, u64 lpes)
55344fbab9SJordan Niethe {
56344fbab9SJordan Niethe 	lpcr |= (0x10ull << LPCR_VRMASD_SH) & LPCR_VRMASD;
57344fbab9SJordan Niethe 	init_LPCR_ISA300(lpcr, lpes);
58344fbab9SJordan Niethe }
59344fbab9SJordan Niethe 
60344fbab9SJordan Niethe static void init_FSCR(void)
61344fbab9SJordan Niethe {
62344fbab9SJordan Niethe 	u64 fscr;
63344fbab9SJordan Niethe 
64344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
65344fbab9SJordan Niethe 	fscr |= FSCR_TAR|FSCR_EBB;
66344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
67344fbab9SJordan Niethe }
68344fbab9SJordan Niethe 
69344fbab9SJordan Niethe static void init_FSCR_power9(void)
70344fbab9SJordan Niethe {
71344fbab9SJordan Niethe 	u64 fscr;
72344fbab9SJordan Niethe 
73344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
74344fbab9SJordan Niethe 	fscr |= FSCR_SCV;
75344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
76344fbab9SJordan Niethe 	init_FSCR();
77344fbab9SJordan Niethe }
78344fbab9SJordan Niethe 
79344fbab9SJordan Niethe static void init_FSCR_power10(void)
80344fbab9SJordan Niethe {
81344fbab9SJordan Niethe 	u64 fscr;
82344fbab9SJordan Niethe 
83344fbab9SJordan Niethe 	fscr = mfspr(SPRN_FSCR);
84344fbab9SJordan Niethe 	fscr |= FSCR_PREFIX;
85344fbab9SJordan Niethe 	mtspr(SPRN_FSCR, fscr);
86344fbab9SJordan Niethe 	init_FSCR_power9();
87344fbab9SJordan Niethe }
88344fbab9SJordan Niethe 
89344fbab9SJordan Niethe static void init_HFSCR(void)
90344fbab9SJordan Niethe {
91344fbab9SJordan Niethe 	u64 hfscr;
92344fbab9SJordan Niethe 
93344fbab9SJordan Niethe 	hfscr = mfspr(SPRN_HFSCR);
94344fbab9SJordan Niethe 	hfscr |= HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|HFSCR_DSCR|\
95344fbab9SJordan Niethe 		 HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP;
96344fbab9SJordan Niethe 	mtspr(SPRN_HFSCR, hfscr);
97344fbab9SJordan Niethe }
98344fbab9SJordan Niethe 
99344fbab9SJordan Niethe static void init_PMU_HV(void)
100344fbab9SJordan Niethe {
101344fbab9SJordan Niethe 	mtspr(SPRN_MMCRC, 0);
102344fbab9SJordan Niethe }
103344fbab9SJordan Niethe 
104344fbab9SJordan Niethe static void init_PMU_HV_ISA207(void)
105344fbab9SJordan Niethe {
106344fbab9SJordan Niethe 	mtspr(SPRN_MMCRH, 0);
107344fbab9SJordan Niethe }
108344fbab9SJordan Niethe 
109344fbab9SJordan Niethe static void init_PMU(void)
110344fbab9SJordan Niethe {
111344fbab9SJordan Niethe 	mtspr(SPRN_MMCRA, 0);
112*245ebf8eSNicholas Piggin 	mtspr(SPRN_MMCR0, MMCR0_FC);
113344fbab9SJordan Niethe 	mtspr(SPRN_MMCR1, 0);
114344fbab9SJordan Niethe 	mtspr(SPRN_MMCR2, 0);
115344fbab9SJordan Niethe }
116344fbab9SJordan Niethe 
117344fbab9SJordan Niethe static void init_PMU_ISA207(void)
118344fbab9SJordan Niethe {
119344fbab9SJordan Niethe 	mtspr(SPRN_MMCRS, 0);
120344fbab9SJordan Niethe }
121344fbab9SJordan Niethe 
122344fbab9SJordan Niethe static void init_PMU_ISA31(void)
123344fbab9SJordan Niethe {
124344fbab9SJordan Niethe 	mtspr(SPRN_MMCR3, 0);
125344fbab9SJordan Niethe 	mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
126*245ebf8eSNicholas Piggin 	mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT);
127344fbab9SJordan Niethe }
128344fbab9SJordan Niethe 
129344fbab9SJordan Niethe /*
130344fbab9SJordan Niethe  * Note that we can be called twice of pseudo-PVRs.
131344fbab9SJordan Niethe  * The parameter offset is not used.
132344fbab9SJordan Niethe  */
133344fbab9SJordan Niethe 
134344fbab9SJordan Niethe void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
135344fbab9SJordan Niethe {
136344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
137344fbab9SJordan Niethe 		return;
138344fbab9SJordan Niethe 
139344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
14046f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
141344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
142344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
143344fbab9SJordan Niethe }
144344fbab9SJordan Niethe 
145344fbab9SJordan Niethe void __restore_cpu_power7(void)
146344fbab9SJordan Niethe {
147344fbab9SJordan Niethe 	u64 msr;
148344fbab9SJordan Niethe 
149344fbab9SJordan Niethe 	msr = mfmsr();
150344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
151344fbab9SJordan Niethe 		return;
152344fbab9SJordan Niethe 
153344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
15446f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
155344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
156344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
157344fbab9SJordan Niethe }
158344fbab9SJordan Niethe 
159344fbab9SJordan Niethe void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
160344fbab9SJordan Niethe {
161344fbab9SJordan Niethe 	init_FSCR();
162344fbab9SJordan Niethe 	init_PMU();
163344fbab9SJordan Niethe 	init_PMU_ISA207();
164344fbab9SJordan Niethe 
165344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
166344fbab9SJordan Niethe 		return;
167344fbab9SJordan Niethe 
168344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
16946f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
170344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
171344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
172344fbab9SJordan Niethe 	init_HFSCR();
173344fbab9SJordan Niethe 	init_PMU_HV();
174344fbab9SJordan Niethe 	init_PMU_HV_ISA207();
175344fbab9SJordan Niethe }
176344fbab9SJordan Niethe 
177344fbab9SJordan Niethe void __restore_cpu_power8(void)
178344fbab9SJordan Niethe {
179344fbab9SJordan Niethe 	u64 msr;
180344fbab9SJordan Niethe 
181344fbab9SJordan Niethe 	init_FSCR();
182344fbab9SJordan Niethe 	init_PMU();
183344fbab9SJordan Niethe 	init_PMU_ISA207();
184344fbab9SJordan Niethe 
185344fbab9SJordan Niethe 	msr = mfmsr();
186344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
187344fbab9SJordan Niethe 		return;
188344fbab9SJordan Niethe 
189344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
19046f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
191344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
192344fbab9SJordan Niethe 	init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
193344fbab9SJordan Niethe 	init_HFSCR();
194344fbab9SJordan Niethe 	init_PMU_HV();
195344fbab9SJordan Niethe 	init_PMU_HV_ISA207();
196344fbab9SJordan Niethe }
197344fbab9SJordan Niethe 
198344fbab9SJordan Niethe void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
199344fbab9SJordan Niethe {
200344fbab9SJordan Niethe 	init_FSCR_power9();
201344fbab9SJordan Niethe 	init_PMU();
202344fbab9SJordan Niethe 
203344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
204344fbab9SJordan Niethe 		return;
205344fbab9SJordan Niethe 
206344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
207344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
208344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
20946f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
210344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
211344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
212344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
213344fbab9SJordan Niethe 	init_HFSCR();
214344fbab9SJordan Niethe 	init_PMU_HV();
215344fbab9SJordan Niethe }
216344fbab9SJordan Niethe 
217344fbab9SJordan Niethe void __restore_cpu_power9(void)
218344fbab9SJordan Niethe {
219344fbab9SJordan Niethe 	u64 msr;
220344fbab9SJordan Niethe 
221344fbab9SJordan Niethe 	init_FSCR_power9();
222344fbab9SJordan Niethe 	init_PMU();
223344fbab9SJordan Niethe 
224344fbab9SJordan Niethe 	msr = mfmsr();
225344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
226344fbab9SJordan Niethe 		return;
227344fbab9SJordan Niethe 
228344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
229344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
230344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
23146f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
232344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
233344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
234344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
235344fbab9SJordan Niethe 	init_HFSCR();
236344fbab9SJordan Niethe 	init_PMU_HV();
237344fbab9SJordan Niethe }
238344fbab9SJordan Niethe 
239344fbab9SJordan Niethe void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
240344fbab9SJordan Niethe {
241344fbab9SJordan Niethe 	init_FSCR_power10();
242344fbab9SJordan Niethe 	init_PMU();
243344fbab9SJordan Niethe 	init_PMU_ISA31();
244344fbab9SJordan Niethe 
245344fbab9SJordan Niethe 	if (!init_hvmode_206(t))
246344fbab9SJordan Niethe 		return;
247344fbab9SJordan Niethe 
248344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
249344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
250344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
25146f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
252344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
253344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
254344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
255344fbab9SJordan Niethe 	init_HFSCR();
256344fbab9SJordan Niethe 	init_PMU_HV();
257344fbab9SJordan Niethe }
258344fbab9SJordan Niethe 
259344fbab9SJordan Niethe void __restore_cpu_power10(void)
260344fbab9SJordan Niethe {
261344fbab9SJordan Niethe 	u64 msr;
262344fbab9SJordan Niethe 
263344fbab9SJordan Niethe 	init_FSCR_power10();
264344fbab9SJordan Niethe 	init_PMU();
265344fbab9SJordan Niethe 	init_PMU_ISA31();
266344fbab9SJordan Niethe 
267344fbab9SJordan Niethe 	msr = mfmsr();
268344fbab9SJordan Niethe 	if (!(msr & MSR_HV))
269344fbab9SJordan Niethe 		return;
270344fbab9SJordan Niethe 
271344fbab9SJordan Niethe 	mtspr(SPRN_PSSCR, 0);
272344fbab9SJordan Niethe 	mtspr(SPRN_LPID, 0);
273344fbab9SJordan Niethe 	mtspr(SPRN_PID, 0);
27446f9caf1SNicholas Piggin 	mtspr(SPRN_AMOR, ~0);
275344fbab9SJordan Niethe 	mtspr(SPRN_PCR, PCR_MASK);
276344fbab9SJordan Niethe 	init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
277344fbab9SJordan Niethe 			 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
278344fbab9SJordan Niethe 	init_HFSCR();
279344fbab9SJordan Niethe 	init_PMU_HV();
280344fbab9SJordan Niethe }
281