1110386Sbenno/*- 2110386Sbenno * Copyright (c) 2001 Matt Thomas. 3110386Sbenno * Copyright (c) 2001 Tsubai Masanari. 4110386Sbenno * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. 5110386Sbenno * All rights reserved. 6110386Sbenno * 7110386Sbenno * Redistribution and use in source and binary forms, with or without 8110386Sbenno * modification, are permitted provided that the following conditions 9110386Sbenno * are met: 10110386Sbenno * 1. Redistributions of source code must retain the above copyright 11110386Sbenno * notice, this list of conditions and the following disclaimer. 12110386Sbenno * 2. Redistributions in binary form must reproduce the above copyright 13110386Sbenno * notice, this list of conditions and the following disclaimer in the 14110386Sbenno * documentation and/or other materials provided with the distribution. 15110386Sbenno * 3. All advertising materials mentioning features or use of this software 16110386Sbenno * must display the following acknowledgement: 17110386Sbenno * This product includes software developed by 18110386Sbenno * Internet Research Institute, Inc. 19110386Sbenno * 4. The name of the author may not be used to endorse or promote products 20110386Sbenno * derived from this software without specific prior written permission. 21110386Sbenno * 22110386Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23110386Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24110386Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25110386Sbenno * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26110386Sbenno * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27110386Sbenno * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28110386Sbenno * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29110386Sbenno * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30110386Sbenno * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31110386Sbenno * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32110386Sbenno */ 33139825Simp/*- 34110386Sbenno * Copyright (C) 2003 Benno Rice. 35110386Sbenno * All rights reserved. 36110386Sbenno * 37110386Sbenno * Redistribution and use in source and binary forms, with or without 38110386Sbenno * modification, are permitted provided that the following conditions 39110386Sbenno * are met: 40110386Sbenno * 1. Redistributions of source code must retain the above copyright 41110386Sbenno * notice, this list of conditions and the following disclaimer. 42110386Sbenno * 2. Redistributions in binary form must reproduce the above copyright 43110386Sbenno * notice, this list of conditions and the following disclaimer in the 44110386Sbenno * documentation and/or other materials provided with the distribution. 45110386Sbenno * 46110386Sbenno * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47110386Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48110386Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49110386Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50110386Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51110386Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52110386Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53110386Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54110386Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55110386Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56110386Sbenno * 57110386Sbenno * from $NetBSD: cpu_subr.c,v 1.1 2003/02/03 17:10:09 matt Exp $ 58110386Sbenno * $FreeBSD$ 59110386Sbenno */ 60110386Sbenno 61110386Sbenno#include <sys/param.h> 62110386Sbenno#include <sys/systm.h> 63110386Sbenno#include <sys/bus.h> 64110386Sbenno#include <sys/conf.h> 65193156Snwhitehorn#include <sys/cpu.h> 66110386Sbenno#include <sys/kernel.h> 67215157Snwhitehorn#include <sys/proc.h> 68166011Smarcel#include <sys/sysctl.h> 69110386Sbenno 70110386Sbenno#include <machine/bus.h> 71199886Snwhitehorn#include <machine/cpu.h> 72110386Sbenno#include <machine/hid.h> 73110386Sbenno#include <machine/md_var.h> 74198378Snwhitehorn#include <machine/smp.h> 75110386Sbenno#include <machine/spr.h> 76110386Sbenno 77199886Snwhitehornstatic void cpu_6xx_setup(int cpuid, uint16_t vers); 78199886Snwhitehornstatic void cpu_970_setup(int cpuid, uint16_t vers); 79236097Srajstatic void cpu_booke_setup(int cpuid, uint16_t vers); 80199886Snwhitehorn 81215157Snwhitehornint powerpc_pow_enabled; 82247454Sdavidevoid (*cpu_idle_hook)(sbintime_t) = NULL; 83247454Sdavidestatic void cpu_idle_60x(sbintime_t); 84247454Sdavidestatic void cpu_idle_booke(sbintime_t); 85215157Snwhitehorn 86110386Sbennostruct cputab { 87110386Sbenno const char *name; 88110386Sbenno uint16_t version; 89110386Sbenno uint16_t revfmt; 90199886Snwhitehorn int features; /* Do not include PPC_FEATURE_32 or 91199886Snwhitehorn * PPC_FEATURE_HAS_MMU */ 92199886Snwhitehorn void (*cpu_setup)(int cpuid, uint16_t vers); 93110386Sbenno}; 94110386Sbenno#define REVFMT_MAJMIN 1 /* %u.%u */ 95110386Sbenno#define REVFMT_HEX 2 /* 0x%04x */ 96110386Sbenno#define REVFMT_DEC 3 /* %u */ 97110386Sbennostatic const struct cputab models[] = { 98199886Snwhitehorn { "Motorola PowerPC 601", MPC601, REVFMT_DEC, 99199886Snwhitehorn PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, cpu_6xx_setup }, 100199886Snwhitehorn { "Motorola PowerPC 602", MPC602, REVFMT_DEC, 101199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 102199886Snwhitehorn { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN, 103199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 104199886Snwhitehorn { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN, 105199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 106199886Snwhitehorn { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN, 107199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 108199886Snwhitehorn { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN, 109199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 110199886Snwhitehorn { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN, 111199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 112199886Snwhitehorn { "Motorola PowerPC 620", MPC620, REVFMT_HEX, 113199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 114199886Snwhitehorn { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN, 115199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 116199886Snwhitehorn { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN, 117199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 118199886Snwhitehorn { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN, 119199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 120199886Snwhitehorn cpu_970_setup }, 121199886Snwhitehorn { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN, 122199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 123199886Snwhitehorn cpu_970_setup }, 124199886Snwhitehorn { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN, 125199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 126199886Snwhitehorn cpu_970_setup }, 127199886Snwhitehorn { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN, 128199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 129199886Snwhitehorn cpu_970_setup }, 130255418Snwhitehorn { "IBM POWER4", IBMPOWER4, REVFMT_MAJMIN, 131255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 132255418Snwhitehorn { "IBM POWER4+", IBMPOWER4PLUS, REVFMT_MAJMIN, 133255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 134255418Snwhitehorn { "IBM POWER5", IBMPOWER5, REVFMT_MAJMIN, 135255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 136255418Snwhitehorn { "IBM POWER5+", IBMPOWER5PLUS, REVFMT_MAJMIN, 137255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, 138255418Snwhitehorn { "IBM POWER6", IBMPOWER6, REVFMT_MAJMIN, 139255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 140255418Snwhitehorn NULL }, 141255418Snwhitehorn { "IBM POWER7", IBMPOWER7, REVFMT_MAJMIN, 142255418Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 143255418Snwhitehorn NULL }, 144255640Snwhitehorn { "IBM POWER7+", IBMPOWER7PLUS, REVFMT_MAJMIN, 145255640Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 146255640Snwhitehorn NULL }, 147255640Snwhitehorn { "IBM POWER8", IBMPOWER8, REVFMT_MAJMIN, 148255640Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 149255640Snwhitehorn NULL }, 150199886Snwhitehorn { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN, 151199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 152199886Snwhitehorn { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN, 153199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 154199886Snwhitehorn { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN, 155199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 156199886Snwhitehorn { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN, 157199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 158199886Snwhitehorn { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN, 159199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 160199886Snwhitehorn { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN, 161199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 162199886Snwhitehorn { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN, 163199886Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 164199886Snwhitehorn { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN, 165199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 166199886Snwhitehorn { "Motorola PowerPC 8245", MPC8245, REVFMT_MAJMIN, 167199886Snwhitehorn PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, 168199886Snwhitehorn { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN, 169236097Sraj 0, cpu_booke_setup }, 170199886Snwhitehorn { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN, 171236097Sraj 0, cpu_booke_setup }, 172236097Sraj { "Freescale e500mc core", FSL_E500mc, REVFMT_MAJMIN, 173236097Sraj 0, cpu_booke_setup }, 174236097Sraj { "Freescale e5500 core", FSL_E5500, REVFMT_MAJMIN, 175236097Sraj 0, cpu_booke_setup }, 176215182Snwhitehorn { "IBM Cell Broadband Engine", IBMCELLBE, REVFMT_MAJMIN, 177215182Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 178215182Snwhitehorn NULL}, 179199886Snwhitehorn { "Unknown PowerPC CPU", 0, REVFMT_HEX, 0, NULL }, 180110386Sbenno}; 181110386Sbenno 182199886Snwhitehornstatic void cpu_6xx_print_cacheinfo(u_int, uint16_t); 183199886Snwhitehornstatic int cpu_feature_bit(SYSCTL_HANDLER_ARGS); 184199886Snwhitehorn 185166011Smarcelstatic char model[64]; 186166011SmarcelSYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 187166011Smarcel 188199886Snwhitehornint cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU; 189199886SnwhitehornSYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLTYPE_INT | CTLFLAG_RD, 190199886Snwhitehorn &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features"); 191110386Sbenno 192199886Snwhitehorn/* Provide some user-friendly aliases for bits in cpu_features */ 193199886SnwhitehornSYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD, 194199886Snwhitehorn 0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I", 195199886Snwhitehorn "Floating point instructions executed in hardware"); 196199886SnwhitehornSYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD, 197199886Snwhitehorn 0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec"); 198198445Snwhitehorn 199110386Sbennovoid 200110386Sbennocpu_setup(u_int cpuid) 201110386Sbenno{ 202198445Snwhitehorn u_int pvr, maj, min; 203110386Sbenno uint16_t vers, rev, revfmt; 204199886Snwhitehorn uint64_t cps; 205110386Sbenno const struct cputab *cp; 206110386Sbenno const char *name; 207110386Sbenno 208110386Sbenno pvr = mfpvr(); 209110386Sbenno vers = pvr >> 16; 210110386Sbenno rev = pvr; 211110386Sbenno switch (vers) { 212176534Sraj case MPC7410: 213176534Sraj min = (pvr >> 0) & 0xff; 214176534Sraj maj = min <= 4 ? 1 : 2; 215176534Sraj break; 216176534Sraj case FSL_E500v1: 217176534Sraj case FSL_E500v2: 218236097Sraj case FSL_E500mc: 219236097Sraj case FSL_E5500: 220176534Sraj maj = (pvr >> 4) & 0xf; 221176534Sraj min = (pvr >> 0) & 0xf; 222176534Sraj break; 223176534Sraj default: 224176534Sraj maj = (pvr >> 8) & 0xf; 225176534Sraj min = (pvr >> 0) & 0xf; 226110386Sbenno } 227110386Sbenno 228166812Smarcel for (cp = models; cp->version != 0; cp++) { 229110386Sbenno if (cp->version == vers) 230110386Sbenno break; 231110386Sbenno } 232110386Sbenno 233110386Sbenno revfmt = cp->revfmt; 234110386Sbenno name = cp->name; 235110386Sbenno if (rev == MPC750 && pvr == 15) { 236110386Sbenno name = "Motorola MPC755"; 237110386Sbenno revfmt = REVFMT_HEX; 238110386Sbenno } 239166011Smarcel strncpy(model, name, sizeof(model) - 1); 240110386Sbenno 241110386Sbenno printf("cpu%d: %s revision ", cpuid, name); 242110386Sbenno 243110386Sbenno switch (revfmt) { 244176534Sraj case REVFMT_MAJMIN: 245176534Sraj printf("%u.%u", maj, min); 246176534Sraj break; 247176534Sraj case REVFMT_HEX: 248176534Sraj printf("0x%04x", rev); 249176534Sraj break; 250176534Sraj case REVFMT_DEC: 251176534Sraj printf("%u", rev); 252176534Sraj break; 253110386Sbenno } 254110386Sbenno 255199886Snwhitehorn if (cpu_est_clockrate(0, &cps) == 0) 256209975Snwhitehorn printf(", %jd.%02jd MHz", cps / 1000000, (cps / 10000) % 100); 257199886Snwhitehorn printf("\n"); 258199886Snwhitehorn 259199886Snwhitehorn cpu_features |= cp->features; 260199886Snwhitehorn printf("cpu%d: Features %b\n", cpuid, cpu_features, 261199886Snwhitehorn PPC_FEATURE_BITMASK); 262199886Snwhitehorn 263110386Sbenno /* 264198445Snwhitehorn * Configure CPU 265110386Sbenno */ 266199886Snwhitehorn if (cp->cpu_setup != NULL) 267199886Snwhitehorn cp->cpu_setup(cpuid, vers); 268110386Sbenno} 269110386Sbenno 270193156Snwhitehorn/* Get current clock frequency for the given cpu id. */ 271193156Snwhitehornint 272193156Snwhitehorncpu_est_clockrate(int cpu_id, uint64_t *cps) 273193156Snwhitehorn{ 274193156Snwhitehorn uint16_t vers; 275194374Snwhitehorn register_t msr; 276193156Snwhitehorn 277193156Snwhitehorn vers = mfpvr() >> 16; 278194374Snwhitehorn msr = mfmsr(); 279194374Snwhitehorn mtmsr(msr & ~PSL_EE); 280193156Snwhitehorn 281193156Snwhitehorn switch (vers) { 282193156Snwhitehorn case MPC7450: 283193156Snwhitehorn case MPC7455: 284193156Snwhitehorn case MPC7457: 285193156Snwhitehorn case MPC750: 286193156Snwhitehorn case IBM750FX: 287193156Snwhitehorn case MPC7400: 288193156Snwhitehorn case MPC7410: 289193156Snwhitehorn case MPC7447A: 290193156Snwhitehorn case MPC7448: 291193156Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_FC); 292193156Snwhitehorn mtspr(SPR_PMC1, 0); 293193156Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); 294194374Snwhitehorn DELAY(1000); 295194374Snwhitehorn *cps = (mfspr(SPR_PMC1) * 1000) + 4999; 296194374Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_FC); 297194374Snwhitehorn 298194374Snwhitehorn mtmsr(msr); 299193156Snwhitehorn return (0); 300194374Snwhitehorn case IBM970: 301194374Snwhitehorn case IBM970FX: 302194374Snwhitehorn case IBM970MP: 303194374Snwhitehorn isync(); 304194374Snwhitehorn mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 305194374Snwhitehorn isync(); 306194374Snwhitehorn mtspr(SPR_970MMCR1, 0); 307194374Snwhitehorn mtspr(SPR_970MMCRA, 0); 308194374Snwhitehorn mtspr(SPR_970PMC1, 0); 309194374Snwhitehorn mtspr(SPR_970MMCR0, 310194374Snwhitehorn SPR_970MMCR0_PMC1SEL(PMC970N_CYCLES)); 311194374Snwhitehorn isync(); 312194374Snwhitehorn DELAY(1000); 313194374Snwhitehorn powerpc_sync(); 314194374Snwhitehorn mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 315194374Snwhitehorn *cps = (mfspr(SPR_970PMC1) * 1000) + 4999; 316194374Snwhitehorn 317194374Snwhitehorn mtmsr(msr); 318194374Snwhitehorn return (0); 319193156Snwhitehorn } 320194374Snwhitehorn 321193156Snwhitehorn return (ENXIO); 322110386Sbenno} 323110386Sbenno 324110386Sbennovoid 325198445Snwhitehorncpu_6xx_setup(int cpuid, uint16_t vers) 326110386Sbenno{ 327198445Snwhitehorn register_t hid0, pvr; 328198445Snwhitehorn const char *bitmask; 329110386Sbenno 330198445Snwhitehorn hid0 = mfspr(SPR_HID0); 331198445Snwhitehorn pvr = mfpvr(); 332110386Sbenno 333198445Snwhitehorn /* 334198445Snwhitehorn * Configure power-saving mode. 335198445Snwhitehorn */ 336198445Snwhitehorn switch (vers) { 337198445Snwhitehorn case MPC603: 338198445Snwhitehorn case MPC603e: 339198445Snwhitehorn case MPC603ev: 340198445Snwhitehorn case MPC604ev: 341198445Snwhitehorn case MPC750: 342198445Snwhitehorn case IBM750FX: 343198445Snwhitehorn case MPC7400: 344198445Snwhitehorn case MPC7410: 345198445Snwhitehorn case MPC8240: 346198445Snwhitehorn case MPC8245: 347198445Snwhitehorn /* Select DOZE mode. */ 348198445Snwhitehorn hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 349198445Snwhitehorn hid0 |= HID0_DOZE | HID0_DPM; 350198445Snwhitehorn powerpc_pow_enabled = 1; 351198445Snwhitehorn break; 352198445Snwhitehorn 353198445Snwhitehorn case MPC7448: 354198445Snwhitehorn case MPC7447A: 355198445Snwhitehorn case MPC7457: 356198445Snwhitehorn case MPC7455: 357198445Snwhitehorn case MPC7450: 358198445Snwhitehorn /* Enable the 7450 branch caches */ 359198445Snwhitehorn hid0 |= HID0_SGE | HID0_BTIC; 360198445Snwhitehorn hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 361198445Snwhitehorn /* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */ 362198445Snwhitehorn if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 363198445Snwhitehorn || (pvr >> 16) == MPC7457) 364198445Snwhitehorn hid0 &= ~HID0_BTIC; 365198445Snwhitehorn /* Select NAP mode. */ 366198445Snwhitehorn hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 367198445Snwhitehorn hid0 |= HID0_NAP | HID0_DPM; 368198445Snwhitehorn powerpc_pow_enabled = 1; 369198445Snwhitehorn break; 370198445Snwhitehorn 371198445Snwhitehorn default: 372198445Snwhitehorn /* No power-saving mode is available. */ ; 373198445Snwhitehorn } 374198445Snwhitehorn 375198445Snwhitehorn switch (vers) { 376198445Snwhitehorn case IBM750FX: 377198445Snwhitehorn case MPC750: 378198445Snwhitehorn hid0 &= ~HID0_DBP; /* XXX correct? */ 379198445Snwhitehorn hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 380198445Snwhitehorn break; 381198445Snwhitehorn 382198445Snwhitehorn case MPC7400: 383198445Snwhitehorn case MPC7410: 384198445Snwhitehorn hid0 &= ~HID0_SPD; 385198445Snwhitehorn hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 386198445Snwhitehorn hid0 |= HID0_EIEC; 387198445Snwhitehorn break; 388198445Snwhitehorn 389198445Snwhitehorn } 390198445Snwhitehorn 391198445Snwhitehorn mtspr(SPR_HID0, hid0); 392198445Snwhitehorn 393198445Snwhitehorn if (bootverbose) 394198445Snwhitehorn cpu_6xx_print_cacheinfo(cpuid, vers); 395198445Snwhitehorn 396198445Snwhitehorn switch (vers) { 397198445Snwhitehorn case MPC7447A: 398198445Snwhitehorn case MPC7448: 399198445Snwhitehorn case MPC7450: 400198445Snwhitehorn case MPC7455: 401198445Snwhitehorn case MPC7457: 402198445Snwhitehorn bitmask = HID0_7450_BITMASK; 403198445Snwhitehorn break; 404198445Snwhitehorn default: 405198445Snwhitehorn bitmask = HID0_BITMASK; 406198445Snwhitehorn break; 407198445Snwhitehorn } 408198445Snwhitehorn 409199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); 410215157Snwhitehorn 411215157Snwhitehorn if (cpu_idle_hook == NULL) 412215157Snwhitehorn cpu_idle_hook = cpu_idle_60x; 413198445Snwhitehorn} 414198445Snwhitehorn 415198445Snwhitehorn 416198445Snwhitehornstatic void 417198445Snwhitehorncpu_6xx_print_cacheinfo(u_int cpuid, uint16_t vers) 418198445Snwhitehorn{ 419198445Snwhitehorn register_t hid; 420198445Snwhitehorn 421183029Smarcel hid = mfspr(SPR_HID0); 422183029Smarcel printf("cpu%u: ", cpuid); 423183029Smarcel printf("L1 I-cache %sabled, ", (hid & HID0_ICE) ? "en" : "dis"); 424183029Smarcel printf("L1 D-cache %sabled\n", (hid & HID0_DCE) ? "en" : "dis"); 425110386Sbenno 426183029Smarcel printf("cpu%u: ", cpuid); 427198378Snwhitehorn if (mfspr(SPR_L2CR) & L2CR_L2E) { 428183029Smarcel switch (vers) { 429183029Smarcel case MPC7450: 430183029Smarcel case MPC7455: 431183029Smarcel case MPC7457: 432183029Smarcel printf("256KB L2 cache, "); 433198378Snwhitehorn if (mfspr(SPR_L3CR) & L3CR_L3E) 434183029Smarcel printf("%cMB L3 backside cache", 435198378Snwhitehorn mfspr(SPR_L3CR) & L3CR_L3SIZ ? '2' : '1'); 436183029Smarcel else 437183029Smarcel printf("L3 cache disabled"); 438110386Sbenno printf("\n"); 439183029Smarcel break; 440183029Smarcel case IBM750FX: 441110386Sbenno printf("512KB L2 cache\n"); 442183029Smarcel break; 443110386Sbenno default: 444198378Snwhitehorn switch (mfspr(SPR_L2CR) & L2CR_L2SIZ) { 445183029Smarcel case L2SIZ_256K: 446183029Smarcel printf("256KB "); 447183029Smarcel break; 448183029Smarcel case L2SIZ_512K: 449183029Smarcel printf("512KB "); 450183029Smarcel break; 451183029Smarcel case L2SIZ_1M: 452183029Smarcel printf("1MB "); 453183029Smarcel break; 454183029Smarcel } 455198378Snwhitehorn printf("write-%s", (mfspr(SPR_L2CR) & L2CR_L2WT) 456183029Smarcel ? "through" : "back"); 457198378Snwhitehorn if (mfspr(SPR_L2CR) & L2CR_L2PE) 458183029Smarcel printf(", with parity"); 459183029Smarcel printf(" backside cache\n"); 460110386Sbenno break; 461110386Sbenno } 462110386Sbenno } else 463183029Smarcel printf("L2 cache disabled\n"); 464110386Sbenno} 465198445Snwhitehorn 466198445Snwhitehornstatic void 467236097Srajcpu_booke_setup(int cpuid, uint16_t vers) 468198445Snwhitehorn{ 469236141Sraj#ifdef BOOKE_E500 470198445Snwhitehorn register_t hid0; 471198445Snwhitehorn 472198445Snwhitehorn hid0 = mfspr(SPR_HID0); 473205527Smarcel 474205527Smarcel /* Programe power-management mode. */ 475205527Smarcel hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 476205527Smarcel hid0 |= HID0_DOZE; 477205527Smarcel 478205527Smarcel mtspr(SPR_HID0, hid0); 479205527Smarcel 480199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); 481236141Sraj#endif 482215157Snwhitehorn 483215157Snwhitehorn if (cpu_idle_hook == NULL) 484236097Sraj cpu_idle_hook = cpu_idle_booke; 485198445Snwhitehorn} 486198445Snwhitehorn 487198445Snwhitehornstatic void 488198445Snwhitehorncpu_970_setup(int cpuid, uint16_t vers) 489198445Snwhitehorn{ 490199886Snwhitehorn#ifdef AIM 491198445Snwhitehorn uint32_t hid0_hi, hid0_lo; 492198445Snwhitehorn 493198445Snwhitehorn __asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;" 494198445Snwhitehorn : "=r" (hid0_hi), "=r" (hid0_lo) : "K" (SPR_HID0)); 495198445Snwhitehorn 496198445Snwhitehorn /* Configure power-saving mode */ 497204127Snwhitehorn switch (vers) { 498204127Snwhitehorn case IBM970MP: 499215101Snwhitehorn hid0_hi |= (HID0_DEEPNAP | HID0_NAP | HID0_DPM); 500215101Snwhitehorn hid0_hi &= ~HID0_DOZE; 501204127Snwhitehorn break; 502204127Snwhitehorn default: 503204127Snwhitehorn hid0_hi |= (HID0_NAP | HID0_DPM); 504204127Snwhitehorn hid0_hi &= ~(HID0_DOZE | HID0_DEEPNAP); 505204127Snwhitehorn break; 506204127Snwhitehorn } 507198445Snwhitehorn powerpc_pow_enabled = 1; 508198445Snwhitehorn 509198445Snwhitehorn __asm __volatile (" \ 510198445Snwhitehorn sync; isync; \ 511198445Snwhitehorn sldi %0,%0,32; or %0,%0,%1; \ 512198445Snwhitehorn mtspr %2, %0; \ 513198445Snwhitehorn mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 514198445Snwhitehorn mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 515198445Snwhitehorn sync; isync" 516198445Snwhitehorn :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0)); 517198445Snwhitehorn 518198445Snwhitehorn __asm __volatile ("mfspr %0,%1; srdi %0,%0,32;" 519198445Snwhitehorn : "=r" (hid0_hi) : "K" (SPR_HID0)); 520199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); 521199886Snwhitehorn#endif 522215157Snwhitehorn 523215157Snwhitehorn cpu_idle_hook = cpu_idle_60x; 524198445Snwhitehorn} 525199886Snwhitehorn 526199886Snwhitehornstatic int 527199886Snwhitehorncpu_feature_bit(SYSCTL_HANDLER_ARGS) 528199886Snwhitehorn{ 529199886Snwhitehorn int result; 530199886Snwhitehorn 531199886Snwhitehorn result = (cpu_features & arg2) ? 1 : 0; 532199886Snwhitehorn 533199886Snwhitehorn return (sysctl_handle_int(oidp, &result, 0, req)); 534199886Snwhitehorn} 535199886Snwhitehorn 536215157Snwhitehornvoid 537215157Snwhitehorncpu_idle(int busy) 538215157Snwhitehorn{ 539247454Sdavide sbintime_t sbt = -1; 540215157Snwhitehorn 541215157Snwhitehorn#ifdef INVARIANTS 542215157Snwhitehorn if ((mfmsr() & PSL_EE) != PSL_EE) { 543215157Snwhitehorn struct thread *td = curthread; 544215157Snwhitehorn printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); 545215157Snwhitehorn panic("ints disabled in idleproc!"); 546215157Snwhitehorn } 547215157Snwhitehorn#endif 548215157Snwhitehorn 549215157Snwhitehorn CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", 550215157Snwhitehorn busy, curcpu); 551236097Sraj 552215157Snwhitehorn if (cpu_idle_hook != NULL) { 553215157Snwhitehorn if (!busy) { 554215157Snwhitehorn critical_enter(); 555247454Sdavide sbt = cpu_idleclock(); 556215157Snwhitehorn } 557247454Sdavide cpu_idle_hook(sbt); 558215157Snwhitehorn if (!busy) { 559215157Snwhitehorn cpu_activeclock(); 560215157Snwhitehorn critical_exit(); 561215157Snwhitehorn } 562215157Snwhitehorn } 563236097Sraj 564215157Snwhitehorn CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", 565215157Snwhitehorn busy, curcpu); 566215157Snwhitehorn} 567215157Snwhitehorn 568215157Snwhitehornint 569215157Snwhitehorncpu_idle_wakeup(int cpu) 570215157Snwhitehorn{ 571215157Snwhitehorn return (0); 572215157Snwhitehorn} 573215157Snwhitehorn 574215157Snwhitehornstatic void 575247454Sdavidecpu_idle_60x(sbintime_t sbt) 576215157Snwhitehorn{ 577215157Snwhitehorn register_t msr; 578215157Snwhitehorn uint16_t vers; 579215157Snwhitehorn 580215157Snwhitehorn if (!powerpc_pow_enabled) 581215157Snwhitehorn return; 582215157Snwhitehorn 583215157Snwhitehorn msr = mfmsr(); 584215157Snwhitehorn vers = mfpvr() >> 16; 585215157Snwhitehorn 586215157Snwhitehorn#ifdef AIM 587215157Snwhitehorn switch (vers) { 588215157Snwhitehorn case IBM970: 589215157Snwhitehorn case IBM970FX: 590215157Snwhitehorn case IBM970MP: 591215157Snwhitehorn case MPC7447A: 592215157Snwhitehorn case MPC7448: 593215157Snwhitehorn case MPC7450: 594215157Snwhitehorn case MPC7455: 595215157Snwhitehorn case MPC7457: 596215157Snwhitehorn __asm __volatile("\ 597215157Snwhitehorn dssall; sync; mtmsr %0; isync" 598215157Snwhitehorn :: "r"(msr | PSL_POW)); 599215157Snwhitehorn break; 600215157Snwhitehorn default: 601215157Snwhitehorn powerpc_sync(); 602215157Snwhitehorn mtmsr(msr | PSL_POW); 603215157Snwhitehorn isync(); 604215157Snwhitehorn break; 605215157Snwhitehorn } 606215157Snwhitehorn#endif 607215157Snwhitehorn} 608215157Snwhitehorn 609215157Snwhitehornstatic void 610247454Sdavidecpu_idle_booke(sbintime_t sbt) 611215157Snwhitehorn{ 612215157Snwhitehorn register_t msr; 613215157Snwhitehorn 614215157Snwhitehorn msr = mfmsr(); 615215157Snwhitehorn 616215157Snwhitehorn#ifdef E500 617215157Snwhitehorn /* Freescale E500 core RM section 6.4.1. */ 618215157Snwhitehorn __asm __volatile("msync; mtmsr %0; isync" :: 619215157Snwhitehorn "r" (msr | PSL_WE)); 620215157Snwhitehorn#endif 621215157Snwhitehorn} 622215157Snwhitehorn 623