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