1/* 2 * This file contains low level CPU setup functions. 3 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 8 * 2 of the License, or (at your option) any later version. 9 * 10 */ 11 12#include <asm/processor.h> 13#include <asm/page.h> 14#include <asm/cputable.h> 15#include <asm/ppc_asm.h> 16#include <asm/asm-offsets.h> 17#include <asm/cache.h> 18#include <asm/book3s/64/mmu-hash.h> 19 20/* Entry: r3 = crap, r4 = ptr to cputable entry 21 * 22 * Note that we can be called twice for pseudo-PVRs 23 */ 24_GLOBAL(__setup_cpu_power7) 25 mflr r11 26 bl __init_hvmode_206 27 mtlr r11 28 beqlr 29 li r0,0 30 mtspr SPRN_LPID,r0 31 mtspr SPRN_PCR,r0 32 mfspr r3,SPRN_LPCR 33 li r4,(LPCR_LPES1 >> LPCR_LPES_SH) 34 bl __init_LPCR_ISA206 35 bl __init_tlb_power7 36 mtlr r11 37 blr 38 39_GLOBAL(__restore_cpu_power7) 40 mflr r11 41 mfmsr r3 42 rldicl. r0,r3,4,63 43 beqlr 44 li r0,0 45 mtspr SPRN_LPID,r0 46 mtspr SPRN_PCR,r0 47 mfspr r3,SPRN_LPCR 48 li r4,(LPCR_LPES1 >> LPCR_LPES_SH) 49 bl __init_LPCR_ISA206 50 bl __init_tlb_power7 51 mtlr r11 52 blr 53 54_GLOBAL(__setup_cpu_power8) 55 mflr r11 56 bl __init_FSCR 57 bl __init_PMU 58 bl __init_PMU_ISA207 59 bl __init_hvmode_206 60 mtlr r11 61 beqlr 62 li r0,0 63 mtspr SPRN_LPID,r0 64 mtspr SPRN_PCR,r0 65 mfspr r3,SPRN_LPCR 66 ori r3, r3, LPCR_PECEDH 67 li r4,0 /* LPES = 0 */ 68 bl __init_LPCR_ISA206 69 bl __init_HFSCR 70 bl __init_tlb_power8 71 bl __init_PMU_HV 72 bl __init_PMU_HV_ISA207 73 mtlr r11 74 blr 75 76_GLOBAL(__restore_cpu_power8) 77 mflr r11 78 bl __init_FSCR 79 bl __init_PMU 80 bl __init_PMU_ISA207 81 mfmsr r3 82 rldicl. r0,r3,4,63 83 mtlr r11 84 beqlr 85 li r0,0 86 mtspr SPRN_LPID,r0 87 mtspr SPRN_PCR,r0 88 mfspr r3,SPRN_LPCR 89 ori r3, r3, LPCR_PECEDH 90 li r4,0 /* LPES = 0 */ 91 bl __init_LPCR_ISA206 92 bl __init_HFSCR 93 bl __init_tlb_power8 94 bl __init_PMU_HV 95 bl __init_PMU_HV_ISA207 96 mtlr r11 97 blr 98 99_GLOBAL(__setup_cpu_power9) 100 mflr r11 101 bl __init_FSCR 102 bl __init_PMU 103 bl __init_hvmode_206 104 mtlr r11 105 beqlr 106 li r0,0 107 mtspr SPRN_PSSCR,r0 108 mtspr SPRN_LPID,r0 109 mtspr SPRN_PID,r0 110 mtspr SPRN_PCR,r0 111 mfspr r3,SPRN_LPCR 112 LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) 113 or r3, r3, r4 114 LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR) 115 andc r3, r3, r4 116 li r4,0 /* LPES = 0 */ 117 bl __init_LPCR_ISA300 118 bl __init_HFSCR 119 bl __init_tlb_power9 120 bl __init_PMU_HV 121 mtlr r11 122 blr 123 124_GLOBAL(__restore_cpu_power9) 125 mflr r11 126 bl __init_FSCR 127 bl __init_PMU 128 mfmsr r3 129 rldicl. r0,r3,4,63 130 mtlr r11 131 beqlr 132 li r0,0 133 mtspr SPRN_PSSCR,r0 134 mtspr SPRN_LPID,r0 135 mtspr SPRN_PID,r0 136 mtspr SPRN_PCR,r0 137 mfspr r3,SPRN_LPCR 138 LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) 139 or r3, r3, r4 140 LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR) 141 andc r3, r3, r4 142 li r4,0 /* LPES = 0 */ 143 bl __init_LPCR_ISA300 144 bl __init_HFSCR 145 bl __init_tlb_power9 146 bl __init_PMU_HV 147 mtlr r11 148 blr 149 150__init_hvmode_206: 151 /* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */ 152 mfmsr r3 153 rldicl. r0,r3,4,63 154 bnelr 155 ld r5,CPU_SPEC_FEATURES(r4) 156 LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE) 157 xor r5,r5,r6 158 std r5,CPU_SPEC_FEATURES(r4) 159 blr 160 161__init_LPCR_ISA206: 162 /* Setup a sane LPCR: 163 * Called with initial LPCR in R3 and desired LPES 2-bit value in R4 164 * 165 * LPES = 0b01 (HSRR0/1 used for 0x500) 166 * PECE = 0b111 167 * DPFD = 4 168 * HDICE = 0 169 * VC = 0b100 (VPM0=1, VPM1=0, ISL=0) 170 * VRMASD = 0b10000 (L=1, LP=00) 171 * 172 * Other bits untouched for now 173 */ 174 li r5,0x10 175 rldimi r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5 176 177 /* POWER9 has no VRMASD */ 178__init_LPCR_ISA300: 179 rldimi r3,r4, LPCR_LPES_SH, 64-LPCR_LPES_SH-2 180 ori r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2) 181 li r5,4 182 rldimi r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3 183 clrrdi r3,r3,1 /* clear HDICE */ 184 li r5,4 185 rldimi r3,r5, LPCR_VC_SH, 0 186 mtspr SPRN_LPCR,r3 187 isync 188 blr 189 190__init_FSCR: 191 mfspr r3,SPRN_FSCR 192 ori r3,r3,FSCR_TAR|FSCR_DSCR|FSCR_EBB 193 mtspr SPRN_FSCR,r3 194 blr 195 196__init_HFSCR: 197 mfspr r3,SPRN_HFSCR 198 ori r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|\ 199 HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP 200 mtspr SPRN_HFSCR,r3 201 blr 202 203/* 204 * Clear the TLB using the specified IS form of tlbiel instruction 205 * (invalidate by congruence class). P7 has 128 CCs., P8 has 512. 206 */ 207__init_tlb_power7: 208 li r6,POWER7_TLB_SETS 209 mtctr r6 210 li r7,0xc00 /* IS field = 0b11 */ 211 ptesync 2122: tlbiel r7 213 addi r7,r7,0x1000 214 bdnz 2b 215 ptesync 2161: blr 217 218__init_tlb_power8: 219 li r6,POWER8_TLB_SETS 220 mtctr r6 221 li r7,0xc00 /* IS field = 0b11 */ 222 ptesync 2232: tlbiel r7 224 addi r7,r7,0x1000 225 bdnz 2b 226 ptesync 2271: blr 228 229/* 230 * Flush the TLB in hash mode. Hash must flush with RIC=2 once for process 231 * and one for partition scope to clear process and partition table entries. 232 */ 233__init_tlb_power9: 234 li r6,POWER9_TLB_SETS_HASH - 1 235 mtctr r6 236 li r7,0xc00 /* IS field = 0b11 */ 237 li r8,0 238 ptesync 239 PPC_TLBIEL(7, 8, 2, 1, 0) 240 PPC_TLBIEL(7, 8, 2, 0, 0) 2412: addi r7,r7,0x1000 242 PPC_TLBIEL(7, 8, 0, 0, 0) 243 bdnz 2b 244 ptesync 2451: blr 246 247__init_PMU_HV: 248 li r5,0 249 mtspr SPRN_MMCRC,r5 250 blr 251 252__init_PMU_HV_ISA207: 253 li r5,0 254 mtspr SPRN_MMCRH,r5 255 blr 256 257__init_PMU: 258 li r5,0 259 mtspr SPRN_MMCRA,r5 260 mtspr SPRN_MMCR0,r5 261 mtspr SPRN_MMCR1,r5 262 mtspr SPRN_MMCR2,r5 263 blr 264 265__init_PMU_ISA207: 266 li r5,0 267 mtspr SPRN_MMCRS,r5 268 blr 269