0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <asm/reg.h>
0011 #include <asm/synch.h>
0012 #include <linux/bitops.h>
0013 #include <asm/cputable.h>
0014 #include <asm/cpu_setup_power.h>
0015
0016
0017 static bool init_hvmode_206(struct cpu_spec *t)
0018 {
0019 u64 msr;
0020
0021 msr = mfmsr();
0022 if (msr & MSR_HV)
0023 return true;
0024
0025 t->cpu_features &= ~(CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST);
0026 return false;
0027 }
0028
0029 static void init_LPCR_ISA300(u64 lpcr, u64 lpes)
0030 {
0031
0032 lpcr |= (lpes << LPCR_LPES_SH) & LPCR_LPES;
0033 lpcr |= LPCR_PECE0|LPCR_PECE1|LPCR_PECE2;
0034 lpcr |= (4ull << LPCR_DPFD_SH) & LPCR_DPFD;
0035 lpcr &= ~LPCR_HDICE;
0036 lpcr |= (4ull << LPCR_VC_SH);
0037 mtspr(SPRN_LPCR, lpcr);
0038 isync();
0039 }
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 static void init_LPCR_ISA206(u64 lpcr, u64 lpes)
0055 {
0056 lpcr |= (0x10ull << LPCR_VRMASD_SH) & LPCR_VRMASD;
0057 init_LPCR_ISA300(lpcr, lpes);
0058 }
0059
0060 static void init_FSCR(void)
0061 {
0062 u64 fscr;
0063
0064 fscr = mfspr(SPRN_FSCR);
0065 fscr |= FSCR_TAR|FSCR_EBB;
0066 mtspr(SPRN_FSCR, fscr);
0067 }
0068
0069 static void init_FSCR_power9(void)
0070 {
0071 u64 fscr;
0072
0073 fscr = mfspr(SPRN_FSCR);
0074 fscr |= FSCR_SCV;
0075 mtspr(SPRN_FSCR, fscr);
0076 init_FSCR();
0077 }
0078
0079 static void init_FSCR_power10(void)
0080 {
0081 u64 fscr;
0082
0083 fscr = mfspr(SPRN_FSCR);
0084 fscr |= FSCR_PREFIX;
0085 mtspr(SPRN_FSCR, fscr);
0086 init_FSCR_power9();
0087 }
0088
0089 static void init_HFSCR(void)
0090 {
0091 u64 hfscr;
0092
0093 hfscr = mfspr(SPRN_HFSCR);
0094 hfscr |= HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|HFSCR_DSCR|\
0095 HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP;
0096 mtspr(SPRN_HFSCR, hfscr);
0097 }
0098
0099 static void init_PMU_HV(void)
0100 {
0101 mtspr(SPRN_MMCRC, 0);
0102 }
0103
0104 static void init_PMU_HV_ISA207(void)
0105 {
0106 mtspr(SPRN_MMCRH, 0);
0107 }
0108
0109 static void init_PMU(void)
0110 {
0111 mtspr(SPRN_MMCRA, 0);
0112 mtspr(SPRN_MMCR0, MMCR0_FC);
0113 mtspr(SPRN_MMCR1, 0);
0114 mtspr(SPRN_MMCR2, 0);
0115 }
0116
0117 static void init_PMU_ISA207(void)
0118 {
0119 mtspr(SPRN_MMCRS, 0);
0120 }
0121
0122 static void init_PMU_ISA31(void)
0123 {
0124 mtspr(SPRN_MMCR3, 0);
0125 mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
0126 mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT);
0127 }
0128
0129
0130
0131
0132
0133
0134 void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
0135 {
0136 if (!init_hvmode_206(t))
0137 return;
0138
0139 mtspr(SPRN_LPID, 0);
0140 mtspr(SPRN_AMOR, ~0);
0141 mtspr(SPRN_PCR, PCR_MASK);
0142 init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
0143 }
0144
0145 void __restore_cpu_power7(void)
0146 {
0147 u64 msr;
0148
0149 msr = mfmsr();
0150 if (!(msr & MSR_HV))
0151 return;
0152
0153 mtspr(SPRN_LPID, 0);
0154 mtspr(SPRN_AMOR, ~0);
0155 mtspr(SPRN_PCR, PCR_MASK);
0156 init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
0157 }
0158
0159 void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
0160 {
0161 init_FSCR();
0162 init_PMU();
0163 init_PMU_ISA207();
0164
0165 if (!init_hvmode_206(t))
0166 return;
0167
0168 mtspr(SPRN_LPID, 0);
0169 mtspr(SPRN_AMOR, ~0);
0170 mtspr(SPRN_PCR, PCR_MASK);
0171 init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0);
0172 init_HFSCR();
0173 init_PMU_HV();
0174 init_PMU_HV_ISA207();
0175 }
0176
0177 void __restore_cpu_power8(void)
0178 {
0179 u64 msr;
0180
0181 init_FSCR();
0182 init_PMU();
0183 init_PMU_ISA207();
0184
0185 msr = mfmsr();
0186 if (!(msr & MSR_HV))
0187 return;
0188
0189 mtspr(SPRN_LPID, 0);
0190 mtspr(SPRN_AMOR, ~0);
0191 mtspr(SPRN_PCR, PCR_MASK);
0192 init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0);
0193 init_HFSCR();
0194 init_PMU_HV();
0195 init_PMU_HV_ISA207();
0196 }
0197
0198 void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
0199 {
0200 init_FSCR_power9();
0201 init_PMU();
0202
0203 if (!init_hvmode_206(t))
0204 return;
0205
0206 mtspr(SPRN_PSSCR, 0);
0207 mtspr(SPRN_LPID, 0);
0208 mtspr(SPRN_PID, 0);
0209 mtspr(SPRN_AMOR, ~0);
0210 mtspr(SPRN_PCR, PCR_MASK);
0211 init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0212 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0213 init_HFSCR();
0214 init_PMU_HV();
0215 }
0216
0217 void __restore_cpu_power9(void)
0218 {
0219 u64 msr;
0220
0221 init_FSCR_power9();
0222 init_PMU();
0223
0224 msr = mfmsr();
0225 if (!(msr & MSR_HV))
0226 return;
0227
0228 mtspr(SPRN_PSSCR, 0);
0229 mtspr(SPRN_LPID, 0);
0230 mtspr(SPRN_PID, 0);
0231 mtspr(SPRN_AMOR, ~0);
0232 mtspr(SPRN_PCR, PCR_MASK);
0233 init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0234 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0235 init_HFSCR();
0236 init_PMU_HV();
0237 }
0238
0239 void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
0240 {
0241 init_FSCR_power10();
0242 init_PMU();
0243 init_PMU_ISA31();
0244
0245 if (!init_hvmode_206(t))
0246 return;
0247
0248 mtspr(SPRN_PSSCR, 0);
0249 mtspr(SPRN_LPID, 0);
0250 mtspr(SPRN_PID, 0);
0251 mtspr(SPRN_AMOR, ~0);
0252 mtspr(SPRN_PCR, PCR_MASK);
0253 init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0254 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0255 init_HFSCR();
0256 init_PMU_HV();
0257 }
0258
0259 void __restore_cpu_power10(void)
0260 {
0261 u64 msr;
0262
0263 init_FSCR_power10();
0264 init_PMU();
0265 init_PMU_ISA31();
0266
0267 msr = mfmsr();
0268 if (!(msr & MSR_HV))
0269 return;
0270
0271 mtspr(SPRN_PSSCR, 0);
0272 mtspr(SPRN_LPID, 0);
0273 mtspr(SPRN_PID, 0);
0274 mtspr(SPRN_AMOR, ~0);
0275 mtspr(SPRN_PCR, PCR_MASK);
0276 init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0277 LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0278 init_HFSCR();
0279 init_PMU_HV();
0280 }