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$ 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 77static void cpu_6xx_setup(int cpuid, uint16_t vers); 78static void cpu_970_setup(int cpuid, uint16_t vers); 79static void cpu_booke_setup(int cpuid, uint16_t vers); 80 81int powerpc_pow_enabled; 82void (*cpu_idle_hook)(sbintime_t) = NULL; 83static void cpu_idle_60x(sbintime_t); 84static void cpu_idle_booke(sbintime_t); 85 86struct cputab { 87 const char *name; 88 uint16_t version; 89 uint16_t revfmt; 90 int features; /* Do not include PPC_FEATURE_32 or 91 * PPC_FEATURE_HAS_MMU */ 92 void (*cpu_setup)(int cpuid, uint16_t vers); 93}; 94#define REVFMT_MAJMIN 1 /* %u.%u */ 95#define REVFMT_HEX 2 /* 0x%04x */ 96#define REVFMT_DEC 3 /* %u */ 97static const struct cputab models[] = { 98 { "Motorola PowerPC 601", MPC601, REVFMT_DEC, 99 PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, cpu_6xx_setup }, 100 { "Motorola PowerPC 602", MPC602, REVFMT_DEC, 101 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 102 { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN, 103 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 104 { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN, 105 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 106 { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN, 107 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 108 { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN, 109 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 110 { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN, 111 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 112 { "Motorola PowerPC 620", MPC620, REVFMT_HEX, 113 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 114 { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN, 115 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 116 { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN, 117 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 118 { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN, 119 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 120 cpu_970_setup }, 121 { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN, 122 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 123 cpu_970_setup }, 124 { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN, 125 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 126 cpu_970_setup }, 127 { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN, 128 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 129 cpu_970_setup }, 130 { "IBM POWER4", IBMPOWER4, REVFMT_MAJMIN, 131 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 132 { "IBM POWER4+", IBMPOWER4PLUS, REVFMT_MAJMIN, 133 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 134 { "IBM POWER5", IBMPOWER5, REVFMT_MAJMIN, 135 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 136 { "IBM POWER5+", IBMPOWER5PLUS, REVFMT_MAJMIN, 137 PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 138 { "IBM POWER6", IBMPOWER6, REVFMT_MAJMIN, 139 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 140 NULL }, 141 { "IBM POWER7", IBMPOWER7, REVFMT_MAJMIN, 142 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 143 NULL }, 144 { "IBM POWER7+", IBMPOWER7PLUS, REVFMT_MAJMIN, 145 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 146 NULL }, 147 { "IBM POWER8", IBMPOWER8, REVFMT_MAJMIN, 148 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 149 NULL }, 150 { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN, 151 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 152 { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN, 153 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 154 { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN, 155 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 156 { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN, 157 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 158 { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN, 159 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 160 { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN, 161 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 162 { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN, 163 PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 164 { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN, 165 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 166 { "Motorola PowerPC 8245", MPC8245, REVFMT_MAJMIN, 167 PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 168 { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN, 169 0, cpu_booke_setup }, 170 { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN, 171 0, cpu_booke_setup }, 172 { "Freescale e500mc core", FSL_E500mc, REVFMT_MAJMIN, 173 0, cpu_booke_setup }, 174 { "Freescale e5500 core", FSL_E5500, REVFMT_MAJMIN, 175 0, cpu_booke_setup }, 176 { "IBM Cell Broadband Engine", IBMCELLBE, REVFMT_MAJMIN, 177 PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 178 NULL}, 179 { "Unknown PowerPC CPU", 0, REVFMT_HEX, 0, NULL }, 180}; 181 182static void cpu_6xx_print_cacheinfo(u_int, uint16_t); 183static int cpu_feature_bit(SYSCTL_HANDLER_ARGS); 184 185static char model[64]; 186SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 187 188int cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU; 189SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLTYPE_INT | CTLFLAG_RD, 190 &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features"); 191 192/* Provide some user-friendly aliases for bits in cpu_features */ 193SYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD, 194 0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I", 195 "Floating point instructions executed in hardware"); 196SYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD, 197 0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec"); 198 199void 200cpu_setup(u_int cpuid) 201{ 202 u_int pvr, maj, min; 203 uint16_t vers, rev, revfmt; 204 uint64_t cps; 205 const struct cputab *cp; 206 const char *name; 207 208 pvr = mfpvr(); 209 vers = pvr >> 16; 210 rev = pvr; 211 switch (vers) { 212 case MPC7410: 213 min = (pvr >> 0) & 0xff; 214 maj = min <= 4 ? 1 : 2; 215 break; 216 case FSL_E500v1: 217 case FSL_E500v2: 218 case FSL_E500mc: 219 case FSL_E5500: 220 maj = (pvr >> 4) & 0xf; 221 min = (pvr >> 0) & 0xf; 222 break; 223 default: 224 maj = (pvr >> 8) & 0xf; 225 min = (pvr >> 0) & 0xf; 226 } 227 228 for (cp = models; cp->version != 0; cp++) { 229 if (cp->version == vers) 230 break; 231 } 232 233 revfmt = cp->revfmt; 234 name = cp->name; 235 if (rev == MPC750 && pvr == 15) { 236 name = "Motorola MPC755"; 237 revfmt = REVFMT_HEX; 238 } 239 strncpy(model, name, sizeof(model) - 1); 240 241 printf("cpu%d: %s revision ", cpuid, name); 242 243 switch (revfmt) { 244 case REVFMT_MAJMIN: 245 printf("%u.%u", maj, min); 246 break; 247 case REVFMT_HEX: 248 printf("0x%04x", rev); 249 break; 250 case REVFMT_DEC: 251 printf("%u", rev); 252 break; 253 } 254 255 if (cpu_est_clockrate(0, &cps) == 0) 256 printf(", %jd.%02jd MHz", cps / 1000000, (cps / 10000) % 100); 257 printf("\n"); 258 259 cpu_features |= cp->features; 260 printf("cpu%d: Features %b\n", cpuid, cpu_features, 261 PPC_FEATURE_BITMASK); 262 263 /* 264 * Configure CPU 265 */ 266 if (cp->cpu_setup != NULL) 267 cp->cpu_setup(cpuid, vers); 268} 269 270/* Get current clock frequency for the given cpu id. */ 271int 272cpu_est_clockrate(int cpu_id, uint64_t *cps) 273{ 274 uint16_t vers; 275 register_t msr; 276 277 vers = mfpvr() >> 16; 278 msr = mfmsr(); 279 mtmsr(msr & ~PSL_EE); 280 281 switch (vers) { 282 case MPC7450: 283 case MPC7455: 284 case MPC7457: 285 case MPC750: 286 case IBM750FX: 287 case MPC7400: 288 case MPC7410: 289 case MPC7447A: 290 case MPC7448: 291 mtspr(SPR_MMCR0, SPR_MMCR0_FC); 292 mtspr(SPR_PMC1, 0); 293 mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); 294 DELAY(1000); 295 *cps = (mfspr(SPR_PMC1) * 1000) + 4999; 296 mtspr(SPR_MMCR0, SPR_MMCR0_FC); 297 298 mtmsr(msr); 299 return (0); 300 case IBM970: 301 case IBM970FX: 302 case IBM970MP: 303 isync(); 304 mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 305 isync(); 306 mtspr(SPR_970MMCR1, 0); 307 mtspr(SPR_970MMCRA, 0); 308 mtspr(SPR_970PMC1, 0); 309 mtspr(SPR_970MMCR0, 310 SPR_970MMCR0_PMC1SEL(PMC970N_CYCLES)); 311 isync(); 312 DELAY(1000); 313 powerpc_sync(); 314 mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 315 *cps = (mfspr(SPR_970PMC1) * 1000) + 4999; 316 317 mtmsr(msr); 318 return (0); 319 } 320 321 return (ENXIO); 322} 323 324void 325cpu_6xx_setup(int cpuid, uint16_t vers) 326{ 327 register_t hid0, pvr; 328 const char *bitmask; 329 330 hid0 = mfspr(SPR_HID0); 331 pvr = mfpvr(); 332 333 /* 334 * Configure power-saving mode. 335 */ 336 switch (vers) { 337 case MPC603: 338 case MPC603e: 339 case MPC603ev: 340 case MPC604ev: 341 case MPC750: 342 case IBM750FX: 343 case MPC7400: 344 case MPC7410: 345 case MPC8240: 346 case MPC8245: 347 /* Select DOZE mode. */ 348 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 349 hid0 |= HID0_DOZE | HID0_DPM; 350 powerpc_pow_enabled = 1; 351 break; 352 353 case MPC7448: 354 case MPC7447A: 355 case MPC7457: 356 case MPC7455: 357 case MPC7450: 358 /* Enable the 7450 branch caches */ 359 hid0 |= HID0_SGE | HID0_BTIC; 360 hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 361 /* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */ 362 if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 363 || (pvr >> 16) == MPC7457) 364 hid0 &= ~HID0_BTIC; 365 /* Select NAP mode. */ 366 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 367 hid0 |= HID0_NAP | HID0_DPM; 368 powerpc_pow_enabled = 1; 369 break; 370 371 default: 372 /* No power-saving mode is available. */ ; 373 } 374 375 switch (vers) { 376 case IBM750FX: 377 case MPC750: 378 hid0 &= ~HID0_DBP; /* XXX correct? */ 379 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 380 break; 381 382 case MPC7400: 383 case MPC7410: 384 hid0 &= ~HID0_SPD; 385 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 386 hid0 |= HID0_EIEC; 387 break; 388 389 } 390 391 mtspr(SPR_HID0, hid0); 392 393 if (bootverbose) 394 cpu_6xx_print_cacheinfo(cpuid, vers); 395 396 switch (vers) { 397 case MPC7447A: 398 case MPC7448: 399 case MPC7450: 400 case MPC7455: 401 case MPC7457: 402 bitmask = HID0_7450_BITMASK; 403 break; 404 default: 405 bitmask = HID0_BITMASK; 406 break; 407 } 408 409 printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); 410 411 if (cpu_idle_hook == NULL) 412 cpu_idle_hook = cpu_idle_60x; 413} 414 415 416static void 417cpu_6xx_print_cacheinfo(u_int cpuid, uint16_t vers) 418{ 419 register_t hid; 420 421 hid = mfspr(SPR_HID0); 422 printf("cpu%u: ", cpuid); 423 printf("L1 I-cache %sabled, ", (hid & HID0_ICE) ? "en" : "dis"); 424 printf("L1 D-cache %sabled\n", (hid & HID0_DCE) ? "en" : "dis"); 425 426 printf("cpu%u: ", cpuid); 427 if (mfspr(SPR_L2CR) & L2CR_L2E) { 428 switch (vers) { 429 case MPC7450: 430 case MPC7455: 431 case MPC7457: 432 printf("256KB L2 cache, "); 433 if (mfspr(SPR_L3CR) & L3CR_L3E) 434 printf("%cMB L3 backside cache", 435 mfspr(SPR_L3CR) & L3CR_L3SIZ ? '2' : '1'); 436 else 437 printf("L3 cache disabled"); 438 printf("\n"); 439 break; 440 case IBM750FX: 441 printf("512KB L2 cache\n"); 442 break; 443 default: 444 switch (mfspr(SPR_L2CR) & L2CR_L2SIZ) { 445 case L2SIZ_256K: 446 printf("256KB "); 447 break; 448 case L2SIZ_512K: 449 printf("512KB "); 450 break; 451 case L2SIZ_1M: 452 printf("1MB "); 453 break; 454 } 455 printf("write-%s", (mfspr(SPR_L2CR) & L2CR_L2WT) 456 ? "through" : "back"); 457 if (mfspr(SPR_L2CR) & L2CR_L2PE) 458 printf(", with parity"); 459 printf(" backside cache\n"); 460 break; 461 } 462 } else 463 printf("L2 cache disabled\n"); 464} 465 466static void 467cpu_booke_setup(int cpuid, uint16_t vers) 468{ 469#ifdef BOOKE_E500 470 register_t hid0; 471 472 hid0 = mfspr(SPR_HID0); 473 474 /* Programe power-management mode. */ 475 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 476 hid0 |= HID0_DOZE; 477 478 mtspr(SPR_HID0, hid0); 479 480 printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); 481#endif 482 483 if (cpu_idle_hook == NULL) 484 cpu_idle_hook = cpu_idle_booke; 485} 486 487static void 488cpu_970_setup(int cpuid, uint16_t vers) 489{ 490#ifdef AIM 491 uint32_t hid0_hi, hid0_lo; 492 493 __asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;" 494 : "=r" (hid0_hi), "=r" (hid0_lo) : "K" (SPR_HID0)); 495 496 /* Configure power-saving mode */ 497 switch (vers) { 498 case IBM970MP: 499 hid0_hi |= (HID0_DEEPNAP | HID0_NAP | HID0_DPM); 500 hid0_hi &= ~HID0_DOZE; 501 break; 502 default: 503 hid0_hi |= (HID0_NAP | HID0_DPM); 504 hid0_hi &= ~(HID0_DOZE | HID0_DEEPNAP); 505 break; 506 } 507 powerpc_pow_enabled = 1; 508 509 __asm __volatile (" \ 510 sync; isync; \ 511 sldi %0,%0,32; or %0,%0,%1; \ 512 mtspr %2, %0; \ 513 mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 514 mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 515 sync; isync" 516 :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0)); 517 518 __asm __volatile ("mfspr %0,%1; srdi %0,%0,32;" 519 : "=r" (hid0_hi) : "K" (SPR_HID0)); 520 printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); 521#endif 522 523 cpu_idle_hook = cpu_idle_60x; 524} 525 526static int 527cpu_feature_bit(SYSCTL_HANDLER_ARGS) 528{ 529 int result; 530 531 result = (cpu_features & arg2) ? 1 : 0; 532 533 return (sysctl_handle_int(oidp, &result, 0, req)); 534} 535 536void 537cpu_idle(int busy) 538{ 539 sbintime_t sbt = -1; 540 541#ifdef INVARIANTS 542 if ((mfmsr() & PSL_EE) != PSL_EE) { 543 struct thread *td = curthread; 544 printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); 545 panic("ints disabled in idleproc!"); 546 } 547#endif 548 549 CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", 550 busy, curcpu); 551 552 if (cpu_idle_hook != NULL) { 553 if (!busy) { 554 critical_enter(); 555 sbt = cpu_idleclock(); 556 } 557 cpu_idle_hook(sbt); 558 if (!busy) { 559 cpu_activeclock(); 560 critical_exit(); 561 } 562 } 563 564 CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", 565 busy, curcpu); 566} 567 568int 569cpu_idle_wakeup(int cpu) 570{ 571 return (0); 572} 573 574static void 575cpu_idle_60x(sbintime_t sbt) 576{ 577 register_t msr; 578 uint16_t vers; 579 580 if (!powerpc_pow_enabled) 581 return; 582 583 msr = mfmsr(); 584 vers = mfpvr() >> 16; 585 586#ifdef AIM 587 switch (vers) { 588 case IBM970: 589 case IBM970FX: 590 case IBM970MP: 591 case MPC7447A: 592 case MPC7448: 593 case MPC7450: 594 case MPC7455: 595 case MPC7457: 596 __asm __volatile("\ 597 dssall; sync; mtmsr %0; isync" 598 :: "r"(msr | PSL_POW)); 599 break; 600 default: 601 powerpc_sync(); 602 mtmsr(msr | PSL_POW); 603 isync(); 604 break; 605 } 606#endif 607} 608 609static void 610cpu_idle_booke(sbintime_t sbt) 611{ 612 register_t msr; 613 614 msr = mfmsr(); 615 616#ifdef E500 617 /* Freescale E500 core RM section 6.4.1. */ 618 __asm __volatile("msync; mtmsr %0; isync" :: 619 "r" (msr | PSL_WE)); 620#endif 621} 622 623