1/*- 2 * Copyright (c) 2001 Matt Thomas. 3 * Copyright (c) 2001 Tsubai Masanari. 4 * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by 18 * Internet Research Institute, Inc. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33/*- 34 * Copyright (C) 2003 Benno Rice. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 * 57 * from $NetBSD: cpu_subr.c,v 1.1 2003/02/03 17:10:09 matt Exp $ 58 * $FreeBSD: stable/11/sys/powerpc/powerpc/cpu.c 310441 2016-12-23 03:14:05Z jhibbits $ 59 */ 60 61#include <sys/param.h> 62#include <sys/systm.h> 63#include <sys/bus.h> 64#include <sys/conf.h> 65#include <sys/cpu.h> 66#include <sys/kernel.h> 67#include <sys/proc.h> 68#include <sys/sysctl.h> 69 70#include <machine/bus.h> 71#include <machine/cpu.h> 72#include <machine/hid.h> 73#include <machine/md_var.h> 74#include <machine/smp.h> 75#include <machine/spr.h> 76 77#include <dev/ofw/openfirm.h> 78 79static void cpu_6xx_setup(int cpuid, uint16_t vers); 80static void cpu_970_setup(int cpuid, uint16_t vers); 81static void cpu_booke_setup(int cpuid, uint16_t vers); 82 83int powerpc_pow_enabled; 84void (*cpu_idle_hook)(sbintime_t) = NULL; 85static void cpu_idle_60x(sbintime_t); 86static void cpu_idle_booke(sbintime_t); 87 88struct cputab { 89 const char *name; 90 uint16_t version; 91 uint16_t revfmt; 92 int features; /* Do not include PPC_FEATURE_32 or 93 * PPC_FEATURE_HAS_MMU */ 94 int features2; 95 void (*cpu_setup)(int cpuid, uint16_t vers); 96}; 97#define REVFMT_MAJMIN 1 /* %u.%u */ 98#define REVFMT_HEX 2 /* 0x%04x */ 99#define REVFMT_DEC 3 /* %u */ 100static const struct cputab models[] = { 101 { "Motorola PowerPC 601", MPC601, REVFMT_DEC, 102 PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, 0, cpu_6xx_setup }, 103 { "Motorola PowerPC 602", MPC602, REVFMT_DEC, 104 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 105 { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN, 106 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 107 { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN, 108 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 109 { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN, 110 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 111 { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN, 112 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 113 { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN, 114 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 115 { "Motorola PowerPC 620", MPC620, REVFMT_HEX, 116 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 117 { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN, 118 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 119 { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN, 120 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 121 { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN, 122 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 123 0, cpu_970_setup }, 124 { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN, 125 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 126 0, cpu_970_setup }, 127 { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN, 128 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 129 0, cpu_970_setup }, 130 { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN, 131 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 132 0, cpu_970_setup }, 133 { "IBM POWER4", IBMPOWER4, REVFMT_MAJMIN, 134 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 135 { "IBM POWER4+", IBMPOWER4PLUS, REVFMT_MAJMIN, 136 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 137 { "IBM POWER5", IBMPOWER5, REVFMT_MAJMIN, 138 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU | PPC_FEATURE_SMT, 0, NULL }, 139 { "IBM POWER5+", IBMPOWER5PLUS, REVFMT_MAJMIN, 140 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU | PPC_FEATURE_SMT, 0, NULL }, 141 { "IBM POWER6", IBMPOWER6, REVFMT_MAJMIN, 142 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 143 PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05, 0, NULL }, 144 { "IBM POWER7", IBMPOWER7, REVFMT_MAJMIN, 145 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 146 PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 147 PPC_FEATURE_HAS_VSX, 0, NULL }, 148 { "IBM POWER7+", IBMPOWER7PLUS, REVFMT_MAJMIN, 149 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 150 PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 151 PPC_FEATURE_HAS_VSX, 0, NULL }, 152 { "IBM POWER8E", IBMPOWER8E, REVFMT_MAJMIN, 153 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 154 PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 155 PPC_FEATURE_HAS_VSX, 156 PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_HAS_HTM | 157 PPC_FEATURE2_HAS_VCRYPTO, NULL }, 158 { "IBM POWER8", IBMPOWER8, REVFMT_MAJMIN, 159 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 160 PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 161 PPC_FEATURE_HAS_VSX, 162 PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_HAS_HTM | 163 PPC_FEATURE2_HAS_VCRYPTO, NULL }, 164 { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN, 165 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 166 { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN, 167 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 168 { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN, 169 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 170 { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN, 171 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 172 { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN, 173 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 174 { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN, 175 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 176 { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN, 177 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 178 { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN, 179 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 180 { "Motorola PowerPC 8245", MPC8245, REVFMT_MAJMIN, 181 PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 182 { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN, 183 PPC_FEATURE_BOOKE, 0, cpu_booke_setup }, 184 { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN, 185 PPC_FEATURE_BOOKE, 0, cpu_booke_setup }, 186 { "Freescale e500mc core", FSL_E500mc, REVFMT_MAJMIN, 187 PPC_FEATURE_BOOKE | PPC_FEATURE_HAS_FPU, 0, cpu_booke_setup }, 188 { "Freescale e5500 core", FSL_E5500, REVFMT_MAJMIN, 189 PPC_FEATURE_BOOKE | PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, 190 cpu_booke_setup }, 191 { "Freescale e6500 core", FSL_E6500, REVFMT_MAJMIN, 192 PPC_FEATURE_BOOKE | PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | 193 PPC_FEATURE_HAS_FPU, 0, cpu_booke_setup }, 194 { "IBM Cell Broadband Engine", IBMCELLBE, REVFMT_MAJMIN, 195 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 196 PPC_FEATURE_SMT, 0, NULL}, 197 { "Unknown PowerPC CPU", 0, REVFMT_HEX, 0, 0, NULL }, 198}; 199 200static void cpu_6xx_print_cacheinfo(u_int, uint16_t); 201static int cpu_feature_bit(SYSCTL_HANDLER_ARGS); 202 203static char model[64]; 204SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 205 206int cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU; 207int cpu_features2 = 0; 208SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLFLAG_RD, 209 &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features"); 210SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features2, CTLFLAG_RD, 211 &cpu_features2, sizeof(cpu_features2), "IX", "PowerPC CPU features 2"); 212 213/* Provide some user-friendly aliases for bits in cpu_features */ 214SYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD, 215 0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I", 216 "Floating point instructions executed in hardware"); 217SYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD, 218 0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec"); 219 220void 221cpu_setup(u_int cpuid) 222{ 223 u_int pvr, maj, min; 224 uint16_t vers, rev, revfmt; 225 uint64_t cps; 226 const struct cputab *cp; 227 const char *name; 228 229 pvr = mfpvr(); 230 vers = pvr >> 16; 231 rev = pvr; 232 switch (vers) { 233 case MPC7410: 234 min = (pvr >> 0) & 0xff; 235 maj = min <= 4 ? 1 : 2; 236 break; 237 case FSL_E500v1: 238 case FSL_E500v2: 239 case FSL_E500mc: 240 case FSL_E5500: 241 maj = (pvr >> 4) & 0xf; 242 min = (pvr >> 0) & 0xf; 243 break; 244 default: 245 maj = (pvr >> 8) & 0xf; 246 min = (pvr >> 0) & 0xf; 247 } 248 249 for (cp = models; cp->version != 0; cp++) { 250 if (cp->version == vers) 251 break; 252 } 253 254 revfmt = cp->revfmt; 255 name = cp->name; 256 if (rev == MPC750 && pvr == 15) { 257 name = "Motorola MPC755"; 258 revfmt = REVFMT_HEX; 259 } 260 strncpy(model, name, sizeof(model) - 1); 261 262 printf("cpu%d: %s revision ", cpuid, name); 263 264 switch (revfmt) { 265 case REVFMT_MAJMIN: 266 printf("%u.%u", maj, min); 267 break; 268 case REVFMT_HEX: 269 printf("0x%04x", rev); 270 break; 271 case REVFMT_DEC: 272 printf("%u", rev); 273 break; 274 } 275 276 if (cpu_est_clockrate(0, &cps) == 0) 277 printf(", %jd.%02jd MHz", cps / 1000000, (cps / 10000) % 100); 278 printf("\n"); 279 280 cpu_features |= cp->features; 281 cpu_features2 |= cp->features2; 282 printf("cpu%d: Features %b\n", cpuid, cpu_features, 283 PPC_FEATURE_BITMASK); 284 if (cpu_features2 != 0) 285 printf("cpu%d: Features2 %b\n", cpuid, cpu_features2, 286 PPC_FEATURE2_BITMASK); 287 288 /* 289 * Configure CPU 290 */ 291 if (cp->cpu_setup != NULL) 292 cp->cpu_setup(cpuid, vers); 293} 294 295/* Get current clock frequency for the given cpu id. */ 296int 297cpu_est_clockrate(int cpu_id, uint64_t *cps) 298{ 299 uint16_t vers; 300 register_t msr; 301 phandle_t cpu, dev, root; 302 int res = 0; 303 char buf[8]; 304 305 vers = mfpvr() >> 16; 306 msr = mfmsr(); 307 mtmsr(msr & ~PSL_EE); 308 309 switch (vers) { 310 case MPC7450: 311 case MPC7455: 312 case MPC7457: 313 case MPC750: 314 case IBM750FX: 315 case MPC7400: 316 case MPC7410: 317 case MPC7447A: 318 case MPC7448: 319 mtspr(SPR_MMCR0, SPR_MMCR0_FC); 320 mtspr(SPR_PMC1, 0); 321 mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); 322 DELAY(1000); 323 *cps = (mfspr(SPR_PMC1) * 1000) + 4999; 324 mtspr(SPR_MMCR0, SPR_MMCR0_FC); 325 326 mtmsr(msr); 327 return (0); 328 case IBM970: 329 case IBM970FX: 330 case IBM970MP: 331 isync(); 332 mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 333 isync(); 334 mtspr(SPR_970MMCR1, 0); 335 mtspr(SPR_970MMCRA, 0); 336 mtspr(SPR_970PMC1, 0); 337 mtspr(SPR_970MMCR0, 338 SPR_970MMCR0_PMC1SEL(PMC970N_CYCLES)); 339 isync(); 340 DELAY(1000); 341 powerpc_sync(); 342 mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 343 *cps = (mfspr(SPR_970PMC1) * 1000) + 4999; 344 345 mtmsr(msr); 346 return (0); 347 348 default: 349 root = OF_peer(0); 350 if (root == 0) 351 return (ENXIO); 352 353 dev = OF_child(root); 354 while (dev != 0) { 355 res = OF_getprop(dev, "name", buf, sizeof(buf)); 356 if (res > 0 && strcmp(buf, "cpus") == 0) 357 break; 358 dev = OF_peer(dev); 359 } 360 cpu = OF_child(dev); 361 while (cpu != 0) { 362 res = OF_getprop(cpu, "device_type", buf, 363 sizeof(buf)); 364 if (res > 0 && strcmp(buf, "cpu") == 0) 365 break; 366 cpu = OF_peer(cpu); 367 } 368 if (cpu == 0) 369 return (ENOENT); 370 if (OF_getprop(cpu, "ibm,extended-clock-frequency", 371 cps, sizeof(*cps)) >= 0) { 372 return (0); 373 } else if (OF_getprop(cpu, "clock-frequency", cps, 374 sizeof(cell_t)) >= 0) { 375 *cps >>= 32; 376 return (0); 377 } else { 378 return (ENOENT); 379 } 380 } 381} 382 383void 384cpu_6xx_setup(int cpuid, uint16_t vers) 385{ 386 register_t hid0, pvr; 387 const char *bitmask; 388 389 hid0 = mfspr(SPR_HID0); 390 pvr = mfpvr(); 391 392 /* 393 * Configure power-saving mode. 394 */ 395 switch (vers) { 396 case MPC603: 397 case MPC603e: 398 case MPC603ev: 399 case MPC604ev: 400 case MPC750: 401 case IBM750FX: 402 case MPC7400: 403 case MPC7410: 404 case MPC8240: 405 case MPC8245: 406 /* Select DOZE mode. */ 407 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 408 hid0 |= HID0_DOZE | HID0_DPM; 409 powerpc_pow_enabled = 1; 410 break; 411 412 case MPC7448: 413 case MPC7447A: 414 case MPC7457: 415 case MPC7455: 416 case MPC7450: 417 /* Enable the 7450 branch caches */ 418 hid0 |= HID0_SGE | HID0_BTIC; 419 hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 420 /* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */ 421 if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 422 || (pvr >> 16) == MPC7457) 423 hid0 &= ~HID0_BTIC; 424 /* Select NAP mode. */ 425 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 426 hid0 |= HID0_NAP | HID0_DPM; 427 powerpc_pow_enabled = 1; 428 break; 429 430 default: 431 /* No power-saving mode is available. */ ; 432 } 433 434 switch (vers) { 435 case IBM750FX: 436 case MPC750: 437 hid0 &= ~HID0_DBP; /* XXX correct? */ 438 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 439 break; 440 441 case MPC7400: 442 case MPC7410: 443 hid0 &= ~HID0_SPD; 444 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 445 hid0 |= HID0_EIEC; 446 break; 447 448 } 449 450 mtspr(SPR_HID0, hid0); 451 452 if (bootverbose) 453 cpu_6xx_print_cacheinfo(cpuid, vers); 454 455 switch (vers) { 456 case MPC7447A: 457 case MPC7448: 458 case MPC7450: 459 case MPC7455: 460 case MPC7457: 461 bitmask = HID0_7450_BITMASK; 462 break; 463 default: 464 bitmask = HID0_BITMASK; 465 break; 466 } 467 468 printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); 469 470 if (cpu_idle_hook == NULL) 471 cpu_idle_hook = cpu_idle_60x; 472} 473 474 475static void 476cpu_6xx_print_cacheinfo(u_int cpuid, uint16_t vers) 477{ 478 register_t hid; 479 480 hid = mfspr(SPR_HID0); 481 printf("cpu%u: ", cpuid); 482 printf("L1 I-cache %sabled, ", (hid & HID0_ICE) ? "en" : "dis"); 483 printf("L1 D-cache %sabled\n", (hid & HID0_DCE) ? "en" : "dis"); 484 485 printf("cpu%u: ", cpuid); 486 if (mfspr(SPR_L2CR) & L2CR_L2E) { 487 switch (vers) { 488 case MPC7450: 489 case MPC7455: 490 case MPC7457: 491 printf("256KB L2 cache, "); 492 if (mfspr(SPR_L3CR) & L3CR_L3E) 493 printf("%cMB L3 backside cache", 494 mfspr(SPR_L3CR) & L3CR_L3SIZ ? '2' : '1'); 495 else 496 printf("L3 cache disabled"); 497 printf("\n"); 498 break; 499 case IBM750FX: 500 printf("512KB L2 cache\n"); 501 break; 502 default: 503 switch (mfspr(SPR_L2CR) & L2CR_L2SIZ) { 504 case L2SIZ_256K: 505 printf("256KB "); 506 break; 507 case L2SIZ_512K: 508 printf("512KB "); 509 break; 510 case L2SIZ_1M: 511 printf("1MB "); 512 break; 513 } 514 printf("write-%s", (mfspr(SPR_L2CR) & L2CR_L2WT) 515 ? "through" : "back"); 516 if (mfspr(SPR_L2CR) & L2CR_L2PE) 517 printf(", with parity"); 518 printf(" backside cache\n"); 519 break; 520 } 521 } else 522 printf("L2 cache disabled\n"); 523} 524 525static void 526cpu_booke_setup(int cpuid, uint16_t vers) 527{ 528#ifdef BOOKE_E500 529 register_t hid0; 530 531 hid0 = mfspr(SPR_HID0); 532 533 /* Programe power-management mode. */ 534 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 535 hid0 |= HID0_DOZE; 536 537 mtspr(SPR_HID0, hid0); 538 539 printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); 540#endif 541 542 if (cpu_idle_hook == NULL) 543 cpu_idle_hook = cpu_idle_booke; 544} 545 546static void 547cpu_970_setup(int cpuid, uint16_t vers) 548{ 549#ifdef AIM 550 uint32_t hid0_hi, hid0_lo; 551 552 __asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;" 553 : "=r" (hid0_hi), "=r" (hid0_lo) : "K" (SPR_HID0)); 554 555 /* Configure power-saving mode */ 556 switch (vers) { 557 case IBM970MP: 558 hid0_hi |= (HID0_DEEPNAP | HID0_NAP | HID0_DPM); 559 hid0_hi &= ~HID0_DOZE; 560 break; 561 default: 562 hid0_hi |= (HID0_NAP | HID0_DPM); 563 hid0_hi &= ~(HID0_DOZE | HID0_DEEPNAP); 564 break; 565 } 566 powerpc_pow_enabled = 1; 567 568 __asm __volatile (" \ 569 sync; isync; \ 570 sldi %0,%0,32; or %0,%0,%1; \ 571 mtspr %2, %0; \ 572 mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 573 mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 574 sync; isync" 575 :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0)); 576 577 __asm __volatile ("mfspr %0,%1; srdi %0,%0,32;" 578 : "=r" (hid0_hi) : "K" (SPR_HID0)); 579 printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); 580#endif 581 582 cpu_idle_hook = cpu_idle_60x; 583} 584 585static int 586cpu_feature_bit(SYSCTL_HANDLER_ARGS) 587{ 588 int result; 589 590 result = (cpu_features & arg2) ? 1 : 0; 591 592 return (sysctl_handle_int(oidp, &result, 0, req)); 593} 594 595void 596cpu_idle(int busy) 597{ 598 sbintime_t sbt = -1; 599 600#ifdef INVARIANTS 601 if ((mfmsr() & PSL_EE) != PSL_EE) { 602 struct thread *td = curthread; 603 printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); 604 panic("ints disabled in idleproc!"); 605 } 606#endif 607 608 CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", 609 busy, curcpu); 610 611 if (cpu_idle_hook != NULL) { 612 if (!busy) { 613 critical_enter(); 614 sbt = cpu_idleclock(); 615 } 616 cpu_idle_hook(sbt); 617 if (!busy) { 618 cpu_activeclock(); 619 critical_exit(); 620 } 621 } 622 623 CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", 624 busy, curcpu); 625} 626 627static void 628cpu_idle_60x(sbintime_t sbt) 629{ 630 register_t msr; 631 uint16_t vers; 632 633 if (!powerpc_pow_enabled) 634 return; 635 636 msr = mfmsr(); 637 vers = mfpvr() >> 16; 638 639#ifdef AIM 640 switch (vers) { 641 case IBM970: 642 case IBM970FX: 643 case IBM970MP: 644 case MPC7447A: 645 case MPC7448: 646 case MPC7450: 647 case MPC7455: 648 case MPC7457: 649 __asm __volatile("\ 650 dssall; sync; mtmsr %0; isync" 651 :: "r"(msr | PSL_POW)); 652 break; 653 default: 654 powerpc_sync(); 655 mtmsr(msr | PSL_POW); 656 isync(); 657 break; 658 } 659#endif 660} 661 662static void 663cpu_idle_booke(sbintime_t sbt) 664{ 665 666#ifdef BOOKE_E500 667 platform_cpu_idle(PCPU_GET(cpuid)); 668#endif 669} 670 671