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>
1476b71988SChristophe Leroy #include <asm/cpu_setup.h>
15344fbab9SJordan Niethe
16344fbab9SJordan Niethe /* Disable CPU_FTR_HVMODE and return false if MSR:HV is not set */
init_hvmode_206(struct cpu_spec * t)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
init_LPCR_ISA300(u64 lpcr,u64 lpes)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 */
init_LPCR_ISA206(u64 lpcr,u64 lpes)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
init_FSCR(void)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
init_FSCR_power9(void)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
init_FSCR_power10(void)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
init_HFSCR(void)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
init_PMU_HV(void)99344fbab9SJordan Niethe static void init_PMU_HV(void)
100344fbab9SJordan Niethe {
101344fbab9SJordan Niethe mtspr(SPRN_MMCRC, 0);
102344fbab9SJordan Niethe }
103344fbab9SJordan Niethe
init_PMU_HV_ISA207(void)104344fbab9SJordan Niethe static void init_PMU_HV_ISA207(void)
105344fbab9SJordan Niethe {
106344fbab9SJordan Niethe mtspr(SPRN_MMCRH, 0);
107344fbab9SJordan Niethe }
108344fbab9SJordan Niethe
init_PMU(void)109344fbab9SJordan Niethe static void init_PMU(void)
110344fbab9SJordan Niethe {
111344fbab9SJordan Niethe mtspr(SPRN_MMCRA, 0);
112245ebf8eSNicholas Piggin mtspr(SPRN_MMCR0, MMCR0_FC);
113344fbab9SJordan Niethe mtspr(SPRN_MMCR1, 0);
114344fbab9SJordan Niethe mtspr(SPRN_MMCR2, 0);
115344fbab9SJordan Niethe }
116344fbab9SJordan Niethe
init_PMU_ISA207(void)117344fbab9SJordan Niethe static void init_PMU_ISA207(void)
118344fbab9SJordan Niethe {
119344fbab9SJordan Niethe mtspr(SPRN_MMCRS, 0);
120344fbab9SJordan Niethe }
121344fbab9SJordan Niethe
init_PMU_ISA31(void)122344fbab9SJordan Niethe static void init_PMU_ISA31(void)
123344fbab9SJordan Niethe {
124344fbab9SJordan Niethe mtspr(SPRN_MMCR3, 0);
125344fbab9SJordan Niethe mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
126245ebf8eSNicholas Piggin mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT);
127344fbab9SJordan Niethe }
128344fbab9SJordan Niethe
init_DEXCR(void)129*0ffd60b7SBenjamin Gray static void init_DEXCR(void)
130*0ffd60b7SBenjamin Gray {
131*0ffd60b7SBenjamin Gray mtspr(SPRN_DEXCR, DEXCR_INIT);
132*0ffd60b7SBenjamin Gray mtspr(SPRN_HASHKEYR, 0);
133*0ffd60b7SBenjamin Gray }
134*0ffd60b7SBenjamin Gray
135344fbab9SJordan Niethe /*
136344fbab9SJordan Niethe * Note that we can be called twice of pseudo-PVRs.
137344fbab9SJordan Niethe * The parameter offset is not used.
138344fbab9SJordan Niethe */
139344fbab9SJordan Niethe
__setup_cpu_power7(unsigned long offset,struct cpu_spec * t)140344fbab9SJordan Niethe void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
141344fbab9SJordan Niethe {
142344fbab9SJordan Niethe if (!init_hvmode_206(t))
143344fbab9SJordan Niethe return;
144344fbab9SJordan Niethe
145344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
14646f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
147344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
148344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
149344fbab9SJordan Niethe }
150344fbab9SJordan Niethe
__restore_cpu_power7(void)151344fbab9SJordan Niethe void __restore_cpu_power7(void)
152344fbab9SJordan Niethe {
153344fbab9SJordan Niethe u64 msr;
154344fbab9SJordan Niethe
155344fbab9SJordan Niethe msr = mfmsr();
156344fbab9SJordan Niethe if (!(msr & MSR_HV))
157344fbab9SJordan Niethe return;
158344fbab9SJordan Niethe
159344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
16046f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
161344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
162344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
163344fbab9SJordan Niethe }
164344fbab9SJordan Niethe
__setup_cpu_power8(unsigned long offset,struct cpu_spec * t)165344fbab9SJordan Niethe void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
166344fbab9SJordan Niethe {
167344fbab9SJordan Niethe init_FSCR();
168344fbab9SJordan Niethe init_PMU();
169344fbab9SJordan Niethe init_PMU_ISA207();
170344fbab9SJordan Niethe
171344fbab9SJordan Niethe if (!init_hvmode_206(t))
172344fbab9SJordan Niethe return;
173344fbab9SJordan Niethe
174344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
17546f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
176344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
177344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
178344fbab9SJordan Niethe init_HFSCR();
179344fbab9SJordan Niethe init_PMU_HV();
180344fbab9SJordan Niethe init_PMU_HV_ISA207();
181344fbab9SJordan Niethe }
182344fbab9SJordan Niethe
__restore_cpu_power8(void)183344fbab9SJordan Niethe void __restore_cpu_power8(void)
184344fbab9SJordan Niethe {
185344fbab9SJordan Niethe u64 msr;
186344fbab9SJordan Niethe
187344fbab9SJordan Niethe init_FSCR();
188344fbab9SJordan Niethe init_PMU();
189344fbab9SJordan Niethe init_PMU_ISA207();
190344fbab9SJordan Niethe
191344fbab9SJordan Niethe msr = mfmsr();
192344fbab9SJordan Niethe if (!(msr & MSR_HV))
193344fbab9SJordan Niethe return;
194344fbab9SJordan Niethe
195344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
19646f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
197344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
198344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
199344fbab9SJordan Niethe init_HFSCR();
200344fbab9SJordan Niethe init_PMU_HV();
201344fbab9SJordan Niethe init_PMU_HV_ISA207();
202344fbab9SJordan Niethe }
203344fbab9SJordan Niethe
__setup_cpu_power9(unsigned long offset,struct cpu_spec * t)204344fbab9SJordan Niethe void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
205344fbab9SJordan Niethe {
206344fbab9SJordan Niethe init_FSCR_power9();
207344fbab9SJordan Niethe init_PMU();
208344fbab9SJordan Niethe
209344fbab9SJordan Niethe if (!init_hvmode_206(t))
210344fbab9SJordan Niethe return;
211344fbab9SJordan Niethe
212344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0);
213344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
214344fbab9SJordan Niethe mtspr(SPRN_PID, 0);
21546f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
216344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
217344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
218344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
219344fbab9SJordan Niethe init_HFSCR();
220344fbab9SJordan Niethe init_PMU_HV();
221344fbab9SJordan Niethe }
222344fbab9SJordan Niethe
__restore_cpu_power9(void)223344fbab9SJordan Niethe void __restore_cpu_power9(void)
224344fbab9SJordan Niethe {
225344fbab9SJordan Niethe u64 msr;
226344fbab9SJordan Niethe
227344fbab9SJordan Niethe init_FSCR_power9();
228344fbab9SJordan Niethe init_PMU();
229344fbab9SJordan Niethe
230344fbab9SJordan Niethe msr = mfmsr();
231344fbab9SJordan Niethe if (!(msr & MSR_HV))
232344fbab9SJordan Niethe return;
233344fbab9SJordan Niethe
234344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0);
235344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
236344fbab9SJordan Niethe mtspr(SPRN_PID, 0);
23746f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
238344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
239344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
240344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
241344fbab9SJordan Niethe init_HFSCR();
242344fbab9SJordan Niethe init_PMU_HV();
243344fbab9SJordan Niethe }
244344fbab9SJordan Niethe
__setup_cpu_power10(unsigned long offset,struct cpu_spec * t)245344fbab9SJordan Niethe void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
246344fbab9SJordan Niethe {
247344fbab9SJordan Niethe init_FSCR_power10();
248344fbab9SJordan Niethe init_PMU();
249344fbab9SJordan Niethe init_PMU_ISA31();
250*0ffd60b7SBenjamin Gray init_DEXCR();
251344fbab9SJordan Niethe
252344fbab9SJordan Niethe if (!init_hvmode_206(t))
253344fbab9SJordan Niethe return;
254344fbab9SJordan Niethe
255344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0);
256344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
257344fbab9SJordan Niethe mtspr(SPRN_PID, 0);
25846f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
259344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
260344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
261344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
262344fbab9SJordan Niethe init_HFSCR();
263344fbab9SJordan Niethe init_PMU_HV();
264344fbab9SJordan Niethe }
265344fbab9SJordan Niethe
__restore_cpu_power10(void)266344fbab9SJordan Niethe void __restore_cpu_power10(void)
267344fbab9SJordan Niethe {
268344fbab9SJordan Niethe u64 msr;
269344fbab9SJordan Niethe
270344fbab9SJordan Niethe init_FSCR_power10();
271344fbab9SJordan Niethe init_PMU();
272344fbab9SJordan Niethe init_PMU_ISA31();
273*0ffd60b7SBenjamin Gray init_DEXCR();
274344fbab9SJordan Niethe
275344fbab9SJordan Niethe msr = mfmsr();
276344fbab9SJordan Niethe if (!(msr & MSR_HV))
277344fbab9SJordan Niethe return;
278344fbab9SJordan Niethe
279344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0);
280344fbab9SJordan Niethe mtspr(SPRN_LPID, 0);
281344fbab9SJordan Niethe mtspr(SPRN_PID, 0);
28246f9caf1SNicholas Piggin mtspr(SPRN_AMOR, ~0);
283344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK);
284344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
285344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
286344fbab9SJordan Niethe init_HFSCR();
287344fbab9SJordan Niethe init_PMU_HV();
288344fbab9SJordan Niethe }
289