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