cpu.c revision 110388
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: head/sys/powerpc/powerpc/cpu.c 110388 2003-02-05 12:33:49Z benno $ 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/kernel.h> 66 67#include <machine/bus.h> 68#include <machine/hid.h> 69#include <machine/md_var.h> 70#include <machine/spr.h> 71 72struct cputab { 73 const char *name; 74 uint16_t version; 75 uint16_t revfmt; 76}; 77#define REVFMT_MAJMIN 1 /* %u.%u */ 78#define REVFMT_HEX 2 /* 0x%04x */ 79#define REVFMT_DEC 3 /* %u */ 80static const struct cputab models[] = { 81 { "Motorola PowerPC 601", MPC601, REVFMT_DEC }, 82 { "Motorola PowerPC 602", MPC602, REVFMT_DEC }, 83 { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN }, 84 { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN }, 85 { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN }, 86 { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN }, 87 { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN }, 88 { "Motorola PowerPC 620", MPC620, REVFMT_HEX }, 89 { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN }, 90 { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN }, 91 { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN }, 92 { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN }, 93 { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN }, 94 { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN }, 95 { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN }, 96 { "Unknown PowerPC CPU", 0, REVFMT_HEX } 97}; 98 99static register_t l2cr_config = 0; 100 101static void cpu_print_speed(void); 102static void cpu_config_l2cr(u_int, uint16_t); 103 104void 105cpu_setup(u_int cpuid) 106{ 107 u_int pvr, maj, min, hid0; 108 uint16_t vers, rev, revfmt; 109 const struct cputab *cp; 110 const char *name; 111 char *bitmask; 112 113 pvr = mfpvr(); 114 vers = pvr >> 16; 115 rev = pvr; 116 switch (vers) { 117 case MPC7410: 118 min = (pvr >> 0) & 0xff; 119 maj = min <= 4 ? 1 : 2; 120 break; 121 default: 122 maj = (pvr >> 8) & 0xf; 123 min = (pvr >> 0) & 0xf; 124 } 125 126 for (cp = models; cp->name[0] != '\0'; cp++) { 127 if (cp->version == vers) 128 break; 129 } 130 131 revfmt = cp->revfmt; 132 name = cp->name; 133 if (rev == MPC750 && pvr == 15) { 134 name = "Motorola MPC755"; 135 revfmt = REVFMT_HEX; 136 } 137 138 printf("cpu%d: %s revision ", cpuid, name); 139 140 switch (revfmt) { 141 case REVFMT_MAJMIN: 142 printf("%u.%u", maj, min); 143 break; 144 case REVFMT_HEX: 145 printf("0x%04x", rev); 146 break; 147 case REVFMT_DEC: 148 printf("%u", rev); 149 break; 150 } 151 152 hid0 = mfspr(SPR_HID0); 153 154 /* 155 * Configure power-saving mode. 156 */ 157 switch (vers) { 158 case MPC603: 159 case MPC603e: 160 case MPC603ev: 161 case MPC604ev: 162 case MPC750: 163 case IBM750FX: 164 case MPC7400: 165 case MPC7410: 166 case MPC8240: 167 case MPC8245: 168 /* Select DOZE mode. */ 169 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 170 hid0 |= HID0_DOZE | HID0_DPM; 171#ifdef notyet 172 powersave = 1; 173#endif 174 break; 175 176 case MPC7455: 177 case MPC7450: 178 /* Disable BTIC on 7450 Rev 2.0 or earlier */ 179 if ((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 180 hid0 &= ~HID0_BTIC; 181 /* Select NAP mode. */ 182 hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 183 hid0 |= HID0_NAP | HID0_DPM; 184#ifdef notyet 185 powersave = 0; /* but don't use it */ 186#endif 187 break; 188 189 default: 190 /* No power-saving mode is available. */ ; 191 } 192 193 switch (vers) { 194 case IBM750FX: 195 case MPC750: 196 hid0 &= ~HID0_DBP; /* XXX correct? */ 197 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 198 break; 199 200 case MPC7400: 201 case MPC7410: 202 hid0 &= ~HID0_SPD; 203 hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 204 hid0 |= HID0_EIEC; 205 break; 206 } 207 208 mtspr(SPR_HID0, hid0); 209 210 switch (vers) { 211 case MPC7450: 212 case MPC7455: 213 bitmask = HID0_7450_BITMASK; 214 break; 215 default: 216 bitmask = HID0_BITMASK; 217 break; 218 } 219 220 switch (vers) { 221 case MPC750: 222 case IBM750FX: 223 case MPC7400: 224 case MPC7410: 225 case MPC7450: 226 case MPC7455: 227 cpu_print_speed(); 228 printf("\n"); 229 cpu_config_l2cr(cpuid, vers); 230 break; 231 232 default: 233 printf("\n"); 234 break; 235 } 236 237 printf("cpu%d: HID0 %b\n", cpuid, hid0, bitmask); 238} 239 240void 241cpu_print_speed(void) 242{ 243 uint64_t cps; 244 245 mtspr(SPR_MMCR0, SPR_MMCR0_FC); 246 mtspr(SPR_PMC1, 0); 247 mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); 248 delay(100000); 249 cps = (mfspr(SPR_PMC1) * 10) + 4999; 250 printf(", %lld.%02lld MHz", cps / 1000000, (cps / 10000) % 100); 251} 252 253void 254cpu_config_l2cr(u_int cpuid, uint16_t vers) 255{ 256 u_int l2cr, x, msr; 257 258 l2cr = mfspr(SPR_L2CR); 259 260 /* 261 * For MP systems, the firmware may only configure the L2 cache 262 * on the first CPU. In this case, assume that the other CPUs 263 * should use the same value for L2CR. 264 */ 265 if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { 266 l2cr_config = l2cr; 267 } 268 269 /* 270 * Configure L2 cache if not enabled. 271 */ 272 if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { 273 l2cr = l2cr_config; 274 275 /* Disable interrupts and set the cache config bits. */ 276 msr = mfmsr(); 277 mtmsr(msr & ~PSL_EE); 278#ifdef ALTIVEC 279 if (cpu_altivec) 280 __asm __volatile("dssall"); 281#endif 282 __asm __volatile("sync"); 283 mtspr(SPR_L2CR, l2cr & ~L2CR_L2E); 284 __asm __volatile("sync"); 285 286 /* Wait for L2 clock to be stable (640 L2 clocks). */ 287 delay(100); 288 289 /* Invalidate all L2 contents. */ 290 mtspr(SPR_L2CR, l2cr | L2CR_L2I); 291 do { 292 x = mfspr(SPR_L2CR); 293 } while (x & L2CR_L2IP); 294 295 /* Enable L2 cache. */ 296 l2cr |= L2CR_L2E; 297 mtspr(SPR_L2CR, l2cr); 298 mtmsr(msr); 299 } 300 301 if (!bootverbose) 302 return; 303 304 printf("cpu%d: ", cpuid); 305 306 if (l2cr & L2CR_L2E) { 307 if (vers == MPC7450 || vers == MPC7455) { 308 u_int l3cr; 309 310 printf("256KB L2 cache"); 311 312 l3cr = mfspr(SPR_L3CR); 313 if (l3cr & L3CR_L3E) 314 printf(", %cMB L3 backside cache", 315 l3cr & L3CR_L3SIZ ? '2' : '1'); 316 printf("\n"); 317 return; 318 } 319 if (vers == IBM750FX) { 320 printf("512KB L2 cache\n"); 321 return; 322 } 323 switch (l2cr & L2CR_L2SIZ) { 324 case L2SIZ_256K: 325 printf("256KB"); 326 break; 327 case L2SIZ_512K: 328 printf("512KB"); 329 break; 330 case L2SIZ_1M: 331 printf("1MB"); 332 break; 333 default: 334 printf("unknown size"); 335 } 336 if (l2cr & L2CR_L2WT) { 337 printf(" write-through"); 338 } else { 339 printf(" write-back"); 340 } 341 switch (l2cr & L2CR_L2RAM) { 342 case L2RAM_FLOWTHRU_BURST: 343 printf(" flow-through synchronous burst SRAM"); 344 break; 345 case L2RAM_PIPELINE_BURST: 346 printf(" pipelined synchronous burst SRAM"); 347 break; 348 case L2RAM_PIPELINE_LATE: 349 printf(" pipelined synchronous late-write SRAM"); 350 break; 351 default: 352 printf(" unknown type"); 353 } 354 355 if (l2cr & L2CR_L2PE) 356 printf(" with parity"); 357 printf(" backside cache"); 358 } else 359 printf("L2 cache not enabled"); 360 361 printf("\n"); 362} 363