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); 112344fbab9SJordan Niethe mtspr(SPRN_MMCR0, 0); 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*91668ab7SAthira Rajeev mtspr(SPRN_MMCR0, 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); 140344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 141344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH); 142344fbab9SJordan Niethe } 143344fbab9SJordan Niethe 144344fbab9SJordan Niethe void __restore_cpu_power7(void) 145344fbab9SJordan Niethe { 146344fbab9SJordan Niethe u64 msr; 147344fbab9SJordan Niethe 148344fbab9SJordan Niethe msr = mfmsr(); 149344fbab9SJordan Niethe if (!(msr & MSR_HV)) 150344fbab9SJordan Niethe return; 151344fbab9SJordan Niethe 152344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 153344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 154344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH); 155344fbab9SJordan Niethe } 156344fbab9SJordan Niethe 157344fbab9SJordan Niethe void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t) 158344fbab9SJordan Niethe { 159344fbab9SJordan Niethe init_FSCR(); 160344fbab9SJordan Niethe init_PMU(); 161344fbab9SJordan Niethe init_PMU_ISA207(); 162344fbab9SJordan Niethe 163344fbab9SJordan Niethe if (!init_hvmode_206(t)) 164344fbab9SJordan Niethe return; 165344fbab9SJordan Niethe 166344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 167344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 168344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */ 169344fbab9SJordan Niethe init_HFSCR(); 170344fbab9SJordan Niethe init_PMU_HV(); 171344fbab9SJordan Niethe init_PMU_HV_ISA207(); 172344fbab9SJordan Niethe } 173344fbab9SJordan Niethe 174344fbab9SJordan Niethe void __restore_cpu_power8(void) 175344fbab9SJordan Niethe { 176344fbab9SJordan Niethe u64 msr; 177344fbab9SJordan Niethe 178344fbab9SJordan Niethe init_FSCR(); 179344fbab9SJordan Niethe init_PMU(); 180344fbab9SJordan Niethe init_PMU_ISA207(); 181344fbab9SJordan Niethe 182344fbab9SJordan Niethe msr = mfmsr(); 183344fbab9SJordan Niethe if (!(msr & MSR_HV)) 184344fbab9SJordan Niethe return; 185344fbab9SJordan Niethe 186344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 187344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 188344fbab9SJordan Niethe init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */ 189344fbab9SJordan Niethe init_HFSCR(); 190344fbab9SJordan Niethe init_PMU_HV(); 191344fbab9SJordan Niethe init_PMU_HV_ISA207(); 192344fbab9SJordan Niethe } 193344fbab9SJordan Niethe 194344fbab9SJordan Niethe void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t) 195344fbab9SJordan Niethe { 196344fbab9SJordan Niethe init_FSCR_power9(); 197344fbab9SJordan Niethe init_PMU(); 198344fbab9SJordan Niethe 199344fbab9SJordan Niethe if (!init_hvmode_206(t)) 200344fbab9SJordan Niethe return; 201344fbab9SJordan Niethe 202344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0); 203344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 204344fbab9SJordan Niethe mtspr(SPRN_PID, 0); 205344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 206344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ 207344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); 208344fbab9SJordan Niethe init_HFSCR(); 209344fbab9SJordan Niethe init_PMU_HV(); 210344fbab9SJordan Niethe } 211344fbab9SJordan Niethe 212344fbab9SJordan Niethe void __restore_cpu_power9(void) 213344fbab9SJordan Niethe { 214344fbab9SJordan Niethe u64 msr; 215344fbab9SJordan Niethe 216344fbab9SJordan Niethe init_FSCR_power9(); 217344fbab9SJordan Niethe init_PMU(); 218344fbab9SJordan Niethe 219344fbab9SJordan Niethe msr = mfmsr(); 220344fbab9SJordan Niethe if (!(msr & MSR_HV)) 221344fbab9SJordan Niethe return; 222344fbab9SJordan Niethe 223344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0); 224344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 225344fbab9SJordan Niethe mtspr(SPRN_PID, 0); 226344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 227344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ 228344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); 229344fbab9SJordan Niethe init_HFSCR(); 230344fbab9SJordan Niethe init_PMU_HV(); 231344fbab9SJordan Niethe } 232344fbab9SJordan Niethe 233344fbab9SJordan Niethe void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t) 234344fbab9SJordan Niethe { 235344fbab9SJordan Niethe init_FSCR_power10(); 236344fbab9SJordan Niethe init_PMU(); 237344fbab9SJordan Niethe init_PMU_ISA31(); 238344fbab9SJordan Niethe 239344fbab9SJordan Niethe if (!init_hvmode_206(t)) 240344fbab9SJordan Niethe return; 241344fbab9SJordan Niethe 242344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0); 243344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 244344fbab9SJordan Niethe mtspr(SPRN_PID, 0); 245344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 246344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ 247344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); 248344fbab9SJordan Niethe init_HFSCR(); 249344fbab9SJordan Niethe init_PMU_HV(); 250344fbab9SJordan Niethe } 251344fbab9SJordan Niethe 252344fbab9SJordan Niethe void __restore_cpu_power10(void) 253344fbab9SJordan Niethe { 254344fbab9SJordan Niethe u64 msr; 255344fbab9SJordan Niethe 256344fbab9SJordan Niethe init_FSCR_power10(); 257344fbab9SJordan Niethe init_PMU(); 258344fbab9SJordan Niethe init_PMU_ISA31(); 259344fbab9SJordan Niethe 260344fbab9SJordan Niethe msr = mfmsr(); 261344fbab9SJordan Niethe if (!(msr & MSR_HV)) 262344fbab9SJordan Niethe return; 263344fbab9SJordan Niethe 264344fbab9SJordan Niethe mtspr(SPRN_PSSCR, 0); 265344fbab9SJordan Niethe mtspr(SPRN_LPID, 0); 266344fbab9SJordan Niethe mtspr(SPRN_PID, 0); 267344fbab9SJordan Niethe mtspr(SPRN_PCR, PCR_MASK); 268344fbab9SJordan Niethe init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ 269344fbab9SJordan Niethe LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); 270344fbab9SJordan Niethe init_HFSCR(); 271344fbab9SJordan Niethe init_PMU_HV(); 272344fbab9SJordan Niethe } 273