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: stable/11/sys/powerpc/powerpc/cpu.c 310441 2016-12-23 03:14:05Z jhibbits $ 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 77258722Sandreast#include <dev/ofw/openfirm.h> 78258722Sandreast 79199886Snwhitehornstatic void cpu_6xx_setup(int cpuid, uint16_t vers); 80199886Snwhitehornstatic void cpu_970_setup(int cpuid, uint16_t vers); 81236097Srajstatic void cpu_booke_setup(int cpuid, uint16_t vers); 82199886Snwhitehorn 83215157Snwhitehornint powerpc_pow_enabled; 84247454Sdavidevoid (*cpu_idle_hook)(sbintime_t) = NULL; 85247454Sdavidestatic void cpu_idle_60x(sbintime_t); 86247454Sdavidestatic void cpu_idle_booke(sbintime_t); 87215157Snwhitehorn 88110386Sbennostruct cputab { 89110386Sbenno const char *name; 90110386Sbenno uint16_t version; 91110386Sbenno uint16_t revfmt; 92199886Snwhitehorn int features; /* Do not include PPC_FEATURE_32 or 93199886Snwhitehorn * PPC_FEATURE_HAS_MMU */ 94293052Snwhitehorn int features2; 95199886Snwhitehorn void (*cpu_setup)(int cpuid, uint16_t vers); 96110386Sbenno}; 97110386Sbenno#define REVFMT_MAJMIN 1 /* %u.%u */ 98110386Sbenno#define REVFMT_HEX 2 /* 0x%04x */ 99110386Sbenno#define REVFMT_DEC 3 /* %u */ 100110386Sbennostatic const struct cputab models[] = { 101199886Snwhitehorn { "Motorola PowerPC 601", MPC601, REVFMT_DEC, 102293052Snwhitehorn PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, 0, cpu_6xx_setup }, 103199886Snwhitehorn { "Motorola PowerPC 602", MPC602, REVFMT_DEC, 104293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 105199886Snwhitehorn { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN, 106293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 107199886Snwhitehorn { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN, 108293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 109199886Snwhitehorn { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN, 110293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 111199886Snwhitehorn { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN, 112293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 113199886Snwhitehorn { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN, 114293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 115199886Snwhitehorn { "Motorola PowerPC 620", MPC620, REVFMT_HEX, 116293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 117199886Snwhitehorn { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN, 118293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 119199886Snwhitehorn { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN, 120293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 121199886Snwhitehorn { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN, 122199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 123293052Snwhitehorn 0, cpu_970_setup }, 124199886Snwhitehorn { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN, 125199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 126293052Snwhitehorn 0, cpu_970_setup }, 127199886Snwhitehorn { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN, 128199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 129293052Snwhitehorn 0, cpu_970_setup }, 130199886Snwhitehorn { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN, 131199886Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 132293052Snwhitehorn 0, cpu_970_setup }, 133255418Snwhitehorn { "IBM POWER4", IBMPOWER4, REVFMT_MAJMIN, 134293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 135255418Snwhitehorn { "IBM POWER4+", IBMPOWER4PLUS, REVFMT_MAJMIN, 136293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, NULL }, 137255418Snwhitehorn { "IBM POWER5", IBMPOWER5, REVFMT_MAJMIN, 138293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU | PPC_FEATURE_SMT, 0, NULL }, 139255418Snwhitehorn { "IBM POWER5+", IBMPOWER5PLUS, REVFMT_MAJMIN, 140293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU | PPC_FEATURE_SMT, 0, NULL }, 141255418Snwhitehorn { "IBM POWER6", IBMPOWER6, REVFMT_MAJMIN, 142293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 143293052Snwhitehorn PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05, 0, NULL }, 144255418Snwhitehorn { "IBM POWER7", IBMPOWER7, REVFMT_MAJMIN, 145279189Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 146293052Snwhitehorn PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 147293052Snwhitehorn PPC_FEATURE_HAS_VSX, 0, NULL }, 148255640Snwhitehorn { "IBM POWER7+", IBMPOWER7PLUS, REVFMT_MAJMIN, 149279189Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 150293052Snwhitehorn PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 151293052Snwhitehorn PPC_FEATURE_HAS_VSX, 0, NULL }, 152268320Snwhitehorn { "IBM POWER8E", IBMPOWER8E, REVFMT_MAJMIN, 153279189Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 154293052Snwhitehorn PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 155293052Snwhitehorn PPC_FEATURE_HAS_VSX, 156293052Snwhitehorn PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_HAS_HTM | 157293052Snwhitehorn PPC_FEATURE2_HAS_VCRYPTO, NULL }, 158255640Snwhitehorn { "IBM POWER8", IBMPOWER8, REVFMT_MAJMIN, 159279189Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 160293052Snwhitehorn PPC_FEATURE_SMT | PPC_FEATURE_ARCH_2_05 | PPC_FEATURE_ARCH_2_06 | 161293052Snwhitehorn PPC_FEATURE_HAS_VSX, 162293052Snwhitehorn PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_HAS_HTM | 163293052Snwhitehorn PPC_FEATURE2_HAS_VCRYPTO, NULL }, 164199886Snwhitehorn { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN, 165293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 166199886Snwhitehorn { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN, 167293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 168199886Snwhitehorn { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN, 169293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 170199886Snwhitehorn { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN, 171293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 172199886Snwhitehorn { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN, 173293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 174199886Snwhitehorn { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN, 175293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 176199886Snwhitehorn { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN, 177293052Snwhitehorn PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 178199886Snwhitehorn { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN, 179293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 180199886Snwhitehorn { "Motorola PowerPC 8245", MPC8245, REVFMT_MAJMIN, 181293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_6xx_setup }, 182199886Snwhitehorn { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN, 183293052Snwhitehorn PPC_FEATURE_BOOKE, 0, cpu_booke_setup }, 184199886Snwhitehorn { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN, 185293052Snwhitehorn PPC_FEATURE_BOOKE, 0, cpu_booke_setup }, 186236097Sraj { "Freescale e500mc core", FSL_E500mc, REVFMT_MAJMIN, 187293052Snwhitehorn PPC_FEATURE_BOOKE | PPC_FEATURE_HAS_FPU, 0, cpu_booke_setup }, 188236097Sraj { "Freescale e5500 core", FSL_E5500, REVFMT_MAJMIN, 189293052Snwhitehorn PPC_FEATURE_BOOKE | PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, 0, 190293052Snwhitehorn cpu_booke_setup }, 191292858Sjhibbits { "Freescale e6500 core", FSL_E6500, REVFMT_MAJMIN, 192293052Snwhitehorn PPC_FEATURE_BOOKE | PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | 193293052Snwhitehorn PPC_FEATURE_HAS_FPU, 0, cpu_booke_setup }, 194215182Snwhitehorn { "IBM Cell Broadband Engine", IBMCELLBE, REVFMT_MAJMIN, 195293052Snwhitehorn PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU | 196293052Snwhitehorn PPC_FEATURE_SMT, 0, NULL}, 197293052Snwhitehorn { "Unknown PowerPC CPU", 0, REVFMT_HEX, 0, 0, NULL }, 198110386Sbenno}; 199110386Sbenno 200199886Snwhitehornstatic void cpu_6xx_print_cacheinfo(u_int, uint16_t); 201199886Snwhitehornstatic int cpu_feature_bit(SYSCTL_HANDLER_ARGS); 202199886Snwhitehorn 203166011Smarcelstatic char model[64]; 204166011SmarcelSYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 205166011Smarcel 206199886Snwhitehornint cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU; 207293052Snwhitehornint cpu_features2 = 0; 208273377ShselaskySYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLFLAG_RD, 209199886Snwhitehorn &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features"); 210293052SnwhitehornSYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features2, CTLFLAG_RD, 211293052Snwhitehorn &cpu_features2, sizeof(cpu_features2), "IX", "PowerPC CPU features 2"); 212110386Sbenno 213199886Snwhitehorn/* Provide some user-friendly aliases for bits in cpu_features */ 214199886SnwhitehornSYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD, 215199886Snwhitehorn 0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I", 216199886Snwhitehorn "Floating point instructions executed in hardware"); 217199886SnwhitehornSYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD, 218199886Snwhitehorn 0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec"); 219198445Snwhitehorn 220110386Sbennovoid 221110386Sbennocpu_setup(u_int cpuid) 222110386Sbenno{ 223198445Snwhitehorn u_int pvr, maj, min; 224110386Sbenno uint16_t vers, rev, revfmt; 225199886Snwhitehorn uint64_t cps; 226110386Sbenno const struct cputab *cp; 227110386Sbenno const char *name; 228110386Sbenno 229110386Sbenno pvr = mfpvr(); 230110386Sbenno vers = pvr >> 16; 231110386Sbenno rev = pvr; 232110386Sbenno switch (vers) { 233176534Sraj case MPC7410: 234176534Sraj min = (pvr >> 0) & 0xff; 235176534Sraj maj = min <= 4 ? 1 : 2; 236176534Sraj break; 237176534Sraj case FSL_E500v1: 238176534Sraj case FSL_E500v2: 239236097Sraj case FSL_E500mc: 240236097Sraj case FSL_E5500: 241176534Sraj maj = (pvr >> 4) & 0xf; 242176534Sraj min = (pvr >> 0) & 0xf; 243176534Sraj break; 244176534Sraj default: 245176534Sraj maj = (pvr >> 8) & 0xf; 246176534Sraj min = (pvr >> 0) & 0xf; 247110386Sbenno } 248110386Sbenno 249166812Smarcel for (cp = models; cp->version != 0; cp++) { 250110386Sbenno if (cp->version == vers) 251110386Sbenno break; 252110386Sbenno } 253110386Sbenno 254110386Sbenno revfmt = cp->revfmt; 255110386Sbenno name = cp->name; 256110386Sbenno if (rev == MPC750 && pvr == 15) { 257110386Sbenno name = "Motorola MPC755"; 258110386Sbenno revfmt = REVFMT_HEX; 259110386Sbenno } 260166011Smarcel strncpy(model, name, sizeof(model) - 1); 261110386Sbenno 262110386Sbenno printf("cpu%d: %s revision ", cpuid, name); 263110386Sbenno 264110386Sbenno switch (revfmt) { 265176534Sraj case REVFMT_MAJMIN: 266176534Sraj printf("%u.%u", maj, min); 267176534Sraj break; 268176534Sraj case REVFMT_HEX: 269176534Sraj printf("0x%04x", rev); 270176534Sraj break; 271176534Sraj case REVFMT_DEC: 272176534Sraj printf("%u", rev); 273176534Sraj break; 274110386Sbenno } 275110386Sbenno 276199886Snwhitehorn if (cpu_est_clockrate(0, &cps) == 0) 277209975Snwhitehorn printf(", %jd.%02jd MHz", cps / 1000000, (cps / 10000) % 100); 278199886Snwhitehorn printf("\n"); 279199886Snwhitehorn 280199886Snwhitehorn cpu_features |= cp->features; 281293052Snwhitehorn cpu_features2 |= cp->features2; 282199886Snwhitehorn printf("cpu%d: Features %b\n", cpuid, cpu_features, 283199886Snwhitehorn PPC_FEATURE_BITMASK); 284293052Snwhitehorn if (cpu_features2 != 0) 285293052Snwhitehorn printf("cpu%d: Features2 %b\n", cpuid, cpu_features2, 286293052Snwhitehorn PPC_FEATURE2_BITMASK); 287199886Snwhitehorn 288110386Sbenno /* 289198445Snwhitehorn * Configure CPU 290110386Sbenno */ 291199886Snwhitehorn if (cp->cpu_setup != NULL) 292199886Snwhitehorn cp->cpu_setup(cpuid, vers); 293110386Sbenno} 294110386Sbenno 295193156Snwhitehorn/* Get current clock frequency for the given cpu id. */ 296193156Snwhitehornint 297193156Snwhitehorncpu_est_clockrate(int cpu_id, uint64_t *cps) 298193156Snwhitehorn{ 299193156Snwhitehorn uint16_t vers; 300194374Snwhitehorn register_t msr; 301258722Sandreast phandle_t cpu, dev, root; 302258722Sandreast int res = 0; 303258722Sandreast char buf[8]; 304193156Snwhitehorn 305193156Snwhitehorn vers = mfpvr() >> 16; 306194374Snwhitehorn msr = mfmsr(); 307194374Snwhitehorn mtmsr(msr & ~PSL_EE); 308193156Snwhitehorn 309193156Snwhitehorn switch (vers) { 310193156Snwhitehorn case MPC7450: 311193156Snwhitehorn case MPC7455: 312193156Snwhitehorn case MPC7457: 313193156Snwhitehorn case MPC750: 314193156Snwhitehorn case IBM750FX: 315193156Snwhitehorn case MPC7400: 316193156Snwhitehorn case MPC7410: 317193156Snwhitehorn case MPC7447A: 318193156Snwhitehorn case MPC7448: 319193156Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_FC); 320193156Snwhitehorn mtspr(SPR_PMC1, 0); 321193156Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); 322194374Snwhitehorn DELAY(1000); 323194374Snwhitehorn *cps = (mfspr(SPR_PMC1) * 1000) + 4999; 324194374Snwhitehorn mtspr(SPR_MMCR0, SPR_MMCR0_FC); 325194374Snwhitehorn 326194374Snwhitehorn mtmsr(msr); 327193156Snwhitehorn return (0); 328194374Snwhitehorn case IBM970: 329194374Snwhitehorn case IBM970FX: 330194374Snwhitehorn case IBM970MP: 331194374Snwhitehorn isync(); 332194374Snwhitehorn mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 333194374Snwhitehorn isync(); 334194374Snwhitehorn mtspr(SPR_970MMCR1, 0); 335194374Snwhitehorn mtspr(SPR_970MMCRA, 0); 336194374Snwhitehorn mtspr(SPR_970PMC1, 0); 337194374Snwhitehorn mtspr(SPR_970MMCR0, 338194374Snwhitehorn SPR_970MMCR0_PMC1SEL(PMC970N_CYCLES)); 339194374Snwhitehorn isync(); 340194374Snwhitehorn DELAY(1000); 341194374Snwhitehorn powerpc_sync(); 342194374Snwhitehorn mtspr(SPR_970MMCR0, SPR_MMCR0_FC); 343194374Snwhitehorn *cps = (mfspr(SPR_970PMC1) * 1000) + 4999; 344194374Snwhitehorn 345194374Snwhitehorn mtmsr(msr); 346194374Snwhitehorn return (0); 347258722Sandreast 348258757Snwhitehorn default: 349258722Sandreast root = OF_peer(0); 350258757Snwhitehorn if (root == 0) 351258757Snwhitehorn return (ENXIO); 352258757Snwhitehorn 353258722Sandreast dev = OF_child(root); 354258722Sandreast while (dev != 0) { 355258722Sandreast res = OF_getprop(dev, "name", buf, sizeof(buf)); 356258722Sandreast if (res > 0 && strcmp(buf, "cpus") == 0) 357258722Sandreast break; 358258722Sandreast dev = OF_peer(dev); 359258722Sandreast } 360258722Sandreast cpu = OF_child(dev); 361258722Sandreast while (cpu != 0) { 362258722Sandreast res = OF_getprop(cpu, "device_type", buf, 363258722Sandreast sizeof(buf)); 364258722Sandreast if (res > 0 && strcmp(buf, "cpu") == 0) 365258722Sandreast break; 366258722Sandreast cpu = OF_peer(cpu); 367258722Sandreast } 368258722Sandreast if (cpu == 0) 369258722Sandreast return (ENOENT); 370258757Snwhitehorn if (OF_getprop(cpu, "ibm,extended-clock-frequency", 371258757Snwhitehorn cps, sizeof(*cps)) >= 0) { 372258757Snwhitehorn return (0); 373258757Snwhitehorn } else if (OF_getprop(cpu, "clock-frequency", cps, 374258757Snwhitehorn sizeof(cell_t)) >= 0) { 375258757Snwhitehorn *cps >>= 32; 376258757Snwhitehorn return (0); 377258757Snwhitehorn } else { 378258757Snwhitehorn return (ENOENT); 379258757Snwhitehorn } 380193156Snwhitehorn } 381110386Sbenno} 382110386Sbenno 383110386Sbennovoid 384198445Snwhitehorncpu_6xx_setup(int cpuid, uint16_t vers) 385110386Sbenno{ 386198445Snwhitehorn register_t hid0, pvr; 387198445Snwhitehorn const char *bitmask; 388110386Sbenno 389198445Snwhitehorn hid0 = mfspr(SPR_HID0); 390198445Snwhitehorn pvr = mfpvr(); 391110386Sbenno 392198445Snwhitehorn /* 393198445Snwhitehorn * Configure power-saving mode. 394198445Snwhitehorn */ 395198445Snwhitehorn switch (vers) { 396198445Snwhitehorn case MPC603: 397198445Snwhitehorn case MPC603e: 398198445Snwhitehorn case MPC603ev: 399198445Snwhitehorn case MPC604ev: 400198445Snwhitehorn case MPC750: 401198445Snwhitehorn case IBM750FX: 402198445Snwhitehorn case MPC7400: 403198445Snwhitehorn case MPC7410: 404198445Snwhitehorn case MPC8240: 405198445Snwhitehorn case MPC8245: 406198445Snwhitehorn /* Select DOZE mode. */ 407198445Snwhitehorn hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 408198445Snwhitehorn hid0 |= HID0_DOZE | HID0_DPM; 409198445Snwhitehorn powerpc_pow_enabled = 1; 410198445Snwhitehorn break; 411198445Snwhitehorn 412198445Snwhitehorn case MPC7448: 413198445Snwhitehorn case MPC7447A: 414198445Snwhitehorn case MPC7457: 415198445Snwhitehorn case MPC7455: 416198445Snwhitehorn case MPC7450: 417198445Snwhitehorn /* Enable the 7450 branch caches */ 418198445Snwhitehorn hid0 |= HID0_SGE | HID0_BTIC; 419198445Snwhitehorn hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 420198445Snwhitehorn /* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */ 421198445Snwhitehorn if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 422198445Snwhitehorn || (pvr >> 16) == MPC7457) 423198445Snwhitehorn hid0 &= ~HID0_BTIC; 424198445Snwhitehorn /* Select NAP mode. */ 425198445Snwhitehorn hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 426198445Snwhitehorn hid0 |= HID0_NAP | HID0_DPM; 427198445Snwhitehorn powerpc_pow_enabled = 1; 428198445Snwhitehorn break; 429198445Snwhitehorn 430198445Snwhitehorn default: 431198445Snwhitehorn /* No power-saving mode is available. */ ; 432198445Snwhitehorn } 433198445Snwhitehorn 434198445Snwhitehorn switch (vers) { 435198445Snwhitehorn case IBM750FX: 436198445Snwhitehorn case MPC750: 437198445Snwhitehorn hid0 &= ~HID0_DBP; /* XXX correct? */ 438198445Snwhitehorn hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 439198445Snwhitehorn break; 440198445Snwhitehorn 441198445Snwhitehorn case MPC7400: 442198445Snwhitehorn case MPC7410: 443198445Snwhitehorn hid0 &= ~HID0_SPD; 444198445Snwhitehorn hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 445198445Snwhitehorn hid0 |= HID0_EIEC; 446198445Snwhitehorn break; 447198445Snwhitehorn 448198445Snwhitehorn } 449198445Snwhitehorn 450198445Snwhitehorn mtspr(SPR_HID0, hid0); 451198445Snwhitehorn 452198445Snwhitehorn if (bootverbose) 453198445Snwhitehorn cpu_6xx_print_cacheinfo(cpuid, vers); 454198445Snwhitehorn 455198445Snwhitehorn switch (vers) { 456198445Snwhitehorn case MPC7447A: 457198445Snwhitehorn case MPC7448: 458198445Snwhitehorn case MPC7450: 459198445Snwhitehorn case MPC7455: 460198445Snwhitehorn case MPC7457: 461198445Snwhitehorn bitmask = HID0_7450_BITMASK; 462198445Snwhitehorn break; 463198445Snwhitehorn default: 464198445Snwhitehorn bitmask = HID0_BITMASK; 465198445Snwhitehorn break; 466198445Snwhitehorn } 467198445Snwhitehorn 468199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); 469215157Snwhitehorn 470215157Snwhitehorn if (cpu_idle_hook == NULL) 471215157Snwhitehorn cpu_idle_hook = cpu_idle_60x; 472198445Snwhitehorn} 473198445Snwhitehorn 474198445Snwhitehorn 475198445Snwhitehornstatic void 476198445Snwhitehorncpu_6xx_print_cacheinfo(u_int cpuid, uint16_t vers) 477198445Snwhitehorn{ 478198445Snwhitehorn register_t hid; 479198445Snwhitehorn 480183029Smarcel hid = mfspr(SPR_HID0); 481183029Smarcel printf("cpu%u: ", cpuid); 482183029Smarcel printf("L1 I-cache %sabled, ", (hid & HID0_ICE) ? "en" : "dis"); 483183029Smarcel printf("L1 D-cache %sabled\n", (hid & HID0_DCE) ? "en" : "dis"); 484110386Sbenno 485183029Smarcel printf("cpu%u: ", cpuid); 486198378Snwhitehorn if (mfspr(SPR_L2CR) & L2CR_L2E) { 487183029Smarcel switch (vers) { 488183029Smarcel case MPC7450: 489183029Smarcel case MPC7455: 490183029Smarcel case MPC7457: 491183029Smarcel printf("256KB L2 cache, "); 492198378Snwhitehorn if (mfspr(SPR_L3CR) & L3CR_L3E) 493183029Smarcel printf("%cMB L3 backside cache", 494198378Snwhitehorn mfspr(SPR_L3CR) & L3CR_L3SIZ ? '2' : '1'); 495183029Smarcel else 496183029Smarcel printf("L3 cache disabled"); 497110386Sbenno printf("\n"); 498183029Smarcel break; 499183029Smarcel case IBM750FX: 500110386Sbenno printf("512KB L2 cache\n"); 501183029Smarcel break; 502110386Sbenno default: 503198378Snwhitehorn switch (mfspr(SPR_L2CR) & L2CR_L2SIZ) { 504183029Smarcel case L2SIZ_256K: 505183029Smarcel printf("256KB "); 506183029Smarcel break; 507183029Smarcel case L2SIZ_512K: 508183029Smarcel printf("512KB "); 509183029Smarcel break; 510183029Smarcel case L2SIZ_1M: 511183029Smarcel printf("1MB "); 512183029Smarcel break; 513183029Smarcel } 514198378Snwhitehorn printf("write-%s", (mfspr(SPR_L2CR) & L2CR_L2WT) 515183029Smarcel ? "through" : "back"); 516198378Snwhitehorn if (mfspr(SPR_L2CR) & L2CR_L2PE) 517183029Smarcel printf(", with parity"); 518183029Smarcel printf(" backside cache\n"); 519110386Sbenno break; 520110386Sbenno } 521110386Sbenno } else 522183029Smarcel printf("L2 cache disabled\n"); 523110386Sbenno} 524198445Snwhitehorn 525198445Snwhitehornstatic void 526236097Srajcpu_booke_setup(int cpuid, uint16_t vers) 527198445Snwhitehorn{ 528236141Sraj#ifdef BOOKE_E500 529198445Snwhitehorn register_t hid0; 530198445Snwhitehorn 531198445Snwhitehorn hid0 = mfspr(SPR_HID0); 532205527Smarcel 533205527Smarcel /* Programe power-management mode. */ 534205527Smarcel hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 535205527Smarcel hid0 |= HID0_DOZE; 536205527Smarcel 537205527Smarcel mtspr(SPR_HID0, hid0); 538205527Smarcel 539199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); 540236141Sraj#endif 541215157Snwhitehorn 542215157Snwhitehorn if (cpu_idle_hook == NULL) 543236097Sraj cpu_idle_hook = cpu_idle_booke; 544198445Snwhitehorn} 545198445Snwhitehorn 546198445Snwhitehornstatic void 547198445Snwhitehorncpu_970_setup(int cpuid, uint16_t vers) 548198445Snwhitehorn{ 549199886Snwhitehorn#ifdef AIM 550198445Snwhitehorn uint32_t hid0_hi, hid0_lo; 551198445Snwhitehorn 552198445Snwhitehorn __asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;" 553198445Snwhitehorn : "=r" (hid0_hi), "=r" (hid0_lo) : "K" (SPR_HID0)); 554198445Snwhitehorn 555198445Snwhitehorn /* Configure power-saving mode */ 556204127Snwhitehorn switch (vers) { 557204127Snwhitehorn case IBM970MP: 558215101Snwhitehorn hid0_hi |= (HID0_DEEPNAP | HID0_NAP | HID0_DPM); 559215101Snwhitehorn hid0_hi &= ~HID0_DOZE; 560204127Snwhitehorn break; 561204127Snwhitehorn default: 562204127Snwhitehorn hid0_hi |= (HID0_NAP | HID0_DPM); 563204127Snwhitehorn hid0_hi &= ~(HID0_DOZE | HID0_DEEPNAP); 564204127Snwhitehorn break; 565204127Snwhitehorn } 566198445Snwhitehorn powerpc_pow_enabled = 1; 567198445Snwhitehorn 568198445Snwhitehorn __asm __volatile (" \ 569198445Snwhitehorn sync; isync; \ 570198445Snwhitehorn sldi %0,%0,32; or %0,%0,%1; \ 571198445Snwhitehorn mtspr %2, %0; \ 572198445Snwhitehorn mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 573198445Snwhitehorn mfspr %0, %2; mfspr %0, %2; mfspr %0, %2; \ 574198445Snwhitehorn sync; isync" 575198445Snwhitehorn :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0)); 576198445Snwhitehorn 577198445Snwhitehorn __asm __volatile ("mfspr %0,%1; srdi %0,%0,32;" 578198445Snwhitehorn : "=r" (hid0_hi) : "K" (SPR_HID0)); 579199886Snwhitehorn printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); 580199886Snwhitehorn#endif 581215157Snwhitehorn 582215157Snwhitehorn cpu_idle_hook = cpu_idle_60x; 583198445Snwhitehorn} 584199886Snwhitehorn 585199886Snwhitehornstatic int 586199886Snwhitehorncpu_feature_bit(SYSCTL_HANDLER_ARGS) 587199886Snwhitehorn{ 588199886Snwhitehorn int result; 589199886Snwhitehorn 590199886Snwhitehorn result = (cpu_features & arg2) ? 1 : 0; 591199886Snwhitehorn 592199886Snwhitehorn return (sysctl_handle_int(oidp, &result, 0, req)); 593199886Snwhitehorn} 594199886Snwhitehorn 595215157Snwhitehornvoid 596215157Snwhitehorncpu_idle(int busy) 597215157Snwhitehorn{ 598247454Sdavide sbintime_t sbt = -1; 599215157Snwhitehorn 600215157Snwhitehorn#ifdef INVARIANTS 601215157Snwhitehorn if ((mfmsr() & PSL_EE) != PSL_EE) { 602215157Snwhitehorn struct thread *td = curthread; 603215157Snwhitehorn printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); 604215157Snwhitehorn panic("ints disabled in idleproc!"); 605215157Snwhitehorn } 606215157Snwhitehorn#endif 607215157Snwhitehorn 608215157Snwhitehorn CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", 609215157Snwhitehorn busy, curcpu); 610236097Sraj 611215157Snwhitehorn if (cpu_idle_hook != NULL) { 612215157Snwhitehorn if (!busy) { 613215157Snwhitehorn critical_enter(); 614247454Sdavide sbt = cpu_idleclock(); 615215157Snwhitehorn } 616247454Sdavide cpu_idle_hook(sbt); 617215157Snwhitehorn if (!busy) { 618215157Snwhitehorn cpu_activeclock(); 619215157Snwhitehorn critical_exit(); 620215157Snwhitehorn } 621215157Snwhitehorn } 622236097Sraj 623215157Snwhitehorn CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", 624215157Snwhitehorn busy, curcpu); 625215157Snwhitehorn} 626215157Snwhitehorn 627215157Snwhitehornstatic void 628247454Sdavidecpu_idle_60x(sbintime_t sbt) 629215157Snwhitehorn{ 630215157Snwhitehorn register_t msr; 631215157Snwhitehorn uint16_t vers; 632215157Snwhitehorn 633215157Snwhitehorn if (!powerpc_pow_enabled) 634215157Snwhitehorn return; 635215157Snwhitehorn 636215157Snwhitehorn msr = mfmsr(); 637215157Snwhitehorn vers = mfpvr() >> 16; 638215157Snwhitehorn 639215157Snwhitehorn#ifdef AIM 640215157Snwhitehorn switch (vers) { 641215157Snwhitehorn case IBM970: 642215157Snwhitehorn case IBM970FX: 643215157Snwhitehorn case IBM970MP: 644215157Snwhitehorn case MPC7447A: 645215157Snwhitehorn case MPC7448: 646215157Snwhitehorn case MPC7450: 647215157Snwhitehorn case MPC7455: 648215157Snwhitehorn case MPC7457: 649215157Snwhitehorn __asm __volatile("\ 650215157Snwhitehorn dssall; sync; mtmsr %0; isync" 651215157Snwhitehorn :: "r"(msr | PSL_POW)); 652215157Snwhitehorn break; 653215157Snwhitehorn default: 654215157Snwhitehorn powerpc_sync(); 655215157Snwhitehorn mtmsr(msr | PSL_POW); 656215157Snwhitehorn isync(); 657215157Snwhitehorn break; 658215157Snwhitehorn } 659215157Snwhitehorn#endif 660215157Snwhitehorn} 661215157Snwhitehorn 662215157Snwhitehornstatic void 663247454Sdavidecpu_idle_booke(sbintime_t sbt) 664215157Snwhitehorn{ 665215157Snwhitehorn 666310441Sjhibbits#ifdef BOOKE_E500 667293030Sjhibbits platform_cpu_idle(PCPU_GET(cpuid)); 668215157Snwhitehorn#endif 669215157Snwhitehorn} 670215157Snwhitehorn 671