1 /* $NetBSD: bcu_vrip.c,v 1.30 2012/10/27 17:17:54 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999-2001 SATO Kazumi. All rights reserved. 5 * Copyright (c) 1999, 2002 PocketBSD Project. 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 the PocketBSD project 18 * and its contributors. 19 * 4. Neither the name of the project nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: bcu_vrip.c,v 1.30 2012/10/27 17:17:54 chs Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/reboot.h> 44 45 #include <machine/bus.h> 46 #include <machine/debug.h> 47 #include <machine/platid.h> 48 #include <machine/platid_mask.h> 49 50 #include <mips/cpuregs.h> 51 52 #include "opt_vr41xx.h" 53 #include <hpcmips/vr/vr.h> 54 #include <hpcmips/vr/vrcpudef.h> 55 #include <hpcmips/vr/vripif.h> 56 #include <hpcmips/vr/vripvar.h> 57 #include <hpcmips/vr/vripreg.h> 58 #include <hpcmips/vr/bcureg.h> 59 #include <hpcmips/vr/bcuvar.h> 60 61 static int vrbcu_match(device_t, cfdata_t, void *); 62 static void vrbcu_attach(device_t, device_t, void *); 63 64 static void vrbcu_write(struct vrbcu_softc *, int, unsigned short); 65 static unsigned short vrbcu_read(struct vrbcu_softc *, int); 66 67 static void vrbcu_dump_regs(void); 68 69 const char *vr_cpuname=NULL; 70 int vr_major=-1; 71 int vr_minor=-1; 72 int vr_cpuid=-1; 73 74 CFATTACH_DECL_NEW(vrbcu, sizeof(struct vrbcu_softc), 75 vrbcu_match, vrbcu_attach, NULL, NULL); 76 77 struct vrbcu_softc *the_bcu_sc = NULL; 78 79 #ifdef SINGLE_VRIP_BASE 80 #define vrbcu_addr() VRIP_BCU_ADDR 81 #else 82 static bus_addr_t vrbcu_addr(void); 83 static bus_addr_t 84 vrbcu_addr(void) 85 { 86 static bus_addr_t addr = 0; 87 static struct platid_data addrs[] = { 88 { &platid_mask_CPU_MIPS_VR_4102, (void *)VR4102_BCU_ADDR }, 89 { &platid_mask_CPU_MIPS_VR_4111, (void *)VR4102_BCU_ADDR }, 90 { &platid_mask_CPU_MIPS_VR_4121, (void *)VR4102_BCU_ADDR }, 91 { &platid_mask_CPU_MIPS_VR_4122, (void *)VR4122_BCU_ADDR }, 92 { &platid_mask_CPU_MIPS_VR_4131, (void *)VR4122_BCU_ADDR }, 93 { &platid_mask_CPU_MIPS_VR_4181, (void *)VR4181_BCU_ADDR }, 94 { NULL, NULL } /* terminator, don't delete */ 95 }; 96 struct platid_data *p; 97 98 if (addr == 0) { 99 if ((p = platid_search_data(&platid, addrs)) == NULL) 100 panic("%s: can't find VR BCU address", __func__); 101 addr = (bus_addr_t)p->data; 102 } 103 104 return (addr); 105 } 106 #endif /* SINGLE_VRIP_BASE */ 107 108 static inline void 109 vrbcu_write(struct vrbcu_softc *sc, int port, unsigned short val) 110 { 111 112 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 113 } 114 115 static inline unsigned short 116 vrbcu_read(struct vrbcu_softc *sc, int port) 117 { 118 119 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 120 } 121 122 static int 123 vrbcu_match(device_t parent, cfdata_t cf, void *aux) 124 { 125 126 return (2); 127 } 128 129 static void 130 vrbcu_attach(device_t parent, device_t self, void *aux) 131 { 132 struct vrip_attach_args *va = aux; 133 struct vrbcu_softc *sc = device_private(self); 134 135 sc->sc_dev = self; 136 sc->sc_iot = va->va_iot; 137 bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 138 0, /* no flags */ 139 &sc->sc_ioh); 140 141 printf("\n"); 142 the_bcu_sc = sc; 143 vrbcu_dump_regs(); 144 } 145 146 static void 147 vrbcu_dump_regs(void) 148 { 149 struct vrbcu_softc *sc = the_bcu_sc; 150 int cpuclock = 0, tclock = 0, vtclock = 0, cpuid; 151 #if !defined(ONLY_VR4102) 152 int spdreg = 0; /* XXX gcc doesn't stand a chance of tracking this! */ 153 #endif 154 #ifdef VRBCUDEBUG 155 int reg; 156 #endif /* VRBCUDEBUG */ 157 158 cpuid = vrbcu_vrip_getcpuid(); 159 #if !defined(ONLY_VR4181) && !defined(ONLY_VR4102) 160 if (cpuid != BCUREVID_FIXRID_4181 161 && cpuid <= BCUREVID_RID_4131 162 && cpuid >= BCUREVID_RID_4111) { 163 spdreg = vrbcu_read(sc, BCUCLKSPEED_REG_W); 164 #ifdef VRBCUDEBUG 165 printf("vrbcu: CLKSPEED %x: \n", spdreg); 166 #endif /* VRBCUDEBUG */ 167 } 168 #endif 169 #if defined VR4181 170 if (cpuid == BCUREVID_FIXRID_4181){ 171 spdreg = vrbcu_read(sc, BCU81CLKSPEED_REG_W); 172 #ifdef VRBCUDEBUG 173 printf("vrbcu: CLKSPEED %x: \n", spdreg); 174 #endif /* VRBCUDEBUG */ 175 } 176 #endif 177 178 cpuclock = vrbcu_vrip_getcpuclock(); 179 180 switch (cpuid) { 181 #if defined VR4181 182 case BCUREVID_FIXRID_4181: 183 switch ((spdreg & BCU81CLKSPEED_DIVTMASK) >> 184 BCU81CLKSPEED_DIVTSHFT){ 185 case BCU81CLKSPEED_DIVT1: 186 vtclock = tclock = cpuclock; 187 break; 188 case BCU81CLKSPEED_DIVT2: 189 vtclock = tclock = cpuclock/2; 190 break; 191 case BCU81CLKSPEED_DIVT3: 192 vtclock = tclock = cpuclock/3; 193 break; 194 case BCU81CLKSPEED_DIVT4: 195 vtclock = tclock = cpuclock/4; 196 break; 197 default: 198 vtclock = tclock = 0; 199 } 200 break; 201 #endif /* VR4181 */ 202 case BCUREVID_RID_4101: 203 case BCUREVID_RID_4102: 204 vtclock = tclock = cpuclock/2; 205 break; 206 #if defined VR4111 207 case BCUREVID_RID_4111: 208 if ((spdreg&BCUCLKSPEED_DIVT2B) == 0) 209 vtclock = tclock = cpuclock/2; 210 else if ((spdreg&BCUCLKSPEED_DIVT3B) == 0) 211 vtclock = tclock = cpuclock/3; 212 else if ((spdreg&BCUCLKSPEED_DIVT4B) == 0) 213 vtclock = tclock = cpuclock/4; 214 else 215 vtclock = tclock = 0; /* XXX */ 216 break; 217 #endif /* VR4111 */ 218 #if defined VR4121 219 case BCUREVID_RID_4121: 220 { 221 int vt; 222 tclock = cpuclock / ((spdreg & BCUCLKSPEED_DIVTMASK) >> 223 BCUCLKSPEED_DIVTSHFT); 224 vt = ((spdreg & BCUCLKSPEED_DIVVTMASK) >> 225 BCUCLKSPEED_DIVVTSHFT); 226 if (vt == 0) 227 vtclock = 0; /* XXX */ 228 else if (vt < 0x9) 229 vtclock = cpuclock / vt; 230 else 231 vtclock = cpuclock / ((vt - 8)*2+1) * 2; 232 } 233 break; 234 #endif /* VR4121 */ 235 #if defined VR4122 || defined VR4131 236 case BCUREVID_RID_4122: 237 case BCUREVID_RID_4131: 238 { 239 int vtdiv; 240 241 vtdiv = ((spdreg & BCUCLKSPEED_VTDIVMODE) >> 242 BCUCLKSPEED_VTDIVSHFT); 243 if (vtdiv == 0 || vtdiv > BCUCLKSPEED_VTDIV6) 244 vtclock = 0; /* XXX */ 245 else 246 vtclock = cpuclock / vtdiv; 247 tclock = vtclock / 248 (((spdreg & BCUCLKSPEED_TDIVMODE) >> 249 BCUCLKSPEED_TDIVSHFT) ? 4 : 2); 250 } 251 break; 252 #endif /* VR4122 || VR4131 */ 253 default: 254 break; 255 } 256 if (tclock) 257 printf("%s: CPU %d.%03dMHz, bus %d.%03dMHz, ram %d.%03dMHz\n", 258 device_xname(sc->sc_dev), 259 cpuclock/1000000, (cpuclock%1000000)/1000, 260 tclock/1000000, (tclock%1000000)/1000, 261 vtclock/1000000, (vtclock%1000000)/1000); 262 else { 263 printf("%s: CPU %d.%03dMHz\n", 264 device_xname(sc->sc_dev), 265 cpuclock/1000000, (cpuclock%1000000)/1000); 266 printf("%s: UNKNOWN BUS CLOCK SPEED:" 267 " CPU is UNKNOWN or NOT CONFIGURED\n", 268 device_xname(sc->sc_dev)); 269 } 270 #ifdef VRBCUDEBUG 271 reg = vrbcu_read(sc, BCUCNT1_REG_W); 272 printf("vrbcu: CNT1 %x: ", reg); 273 dbg_bit_print(reg); 274 #if !defined(ONLY_VR4181) 275 if (cpuid != BCUREVID_FIXRID_4181 276 && cpuid <= BCUREVID_RID_4121 277 && cpuid >= BCUREVID_RID_4102) { 278 reg = vrbcu_read(sc, BCUCNT2_REG_W); 279 printf("vrbcu: CNT2 %x: ", reg); 280 dbg_bit_print(reg); 281 } 282 #endif /* !defined ONLY_VR4181 */ 283 #if !defined(ONLY_VR4181) || !defined(ONLY_VR4122_4131) 284 if (cpuid != BCUREVID_FIXRID_4181 285 && cpuid <= BCUREVID_RID_4121 286 && cpuid >= BCUREVID_RID_4102) { 287 reg = vrbcu_read(sc, BCUSPEED_REG_W); 288 printf("vrbcu: SPEED %x: ", reg); 289 dbg_bit_print(reg); 290 reg = vrbcu_read(sc, BCUERRST_REG_W); 291 printf("vrbcu: ERRST %x: ", reg); 292 dbg_bit_print(reg); 293 reg = vrbcu_read(sc, BCURFCNT_REG_W); 294 printf("vrbcu: RFCNT %x\n", reg); 295 reg = vrbcu_read(sc, BCUREFCOUNT_REG_W); 296 printf("vrbcu: RFCOUNT %x\n", reg); 297 } 298 #endif /* !defined(ONLY_VR4181) || !defined(ONLY_VR4122_4131) */ 299 #if !defined(ONLY_VR4181) 300 if (cpuid != BCUREVID_FIXRID_4181 301 && cpuid <= BCUREVID_RID_4131 302 && cpuid >= BCUREVID_RID_4111) 303 { 304 reg = vrbcu_read(sc, BCUCNT3_REG_W); 305 printf("vrbcu: CNT3 %x: ", reg); 306 dbg_bit_print(reg); 307 } 308 #endif /* !defined ONLY_VR4181 */ 309 #endif /* VRBCUDEBUG */ 310 311 } 312 313 static const char *cpuname[] = { 314 "VR4101", /* 0 */ 315 "VR4102", /* 1 */ 316 "VR4111", /* 2 */ 317 "VR4121", /* 3 */ 318 "VR4122", /* 4 */ 319 "VR4131", /* 5 */ 320 "UNKNOWN", 321 "UNKNOWN", 322 "UNKNOWN", 323 "UNKNOWN", 324 "UNKNOWN", 325 "UNKNOWN", 326 "UNKNOWN", 327 "UNKNOWN", 328 "UNKNOWN", 329 "UNKNOWN", 330 "VR4181", /* 0x10 + 0 */ 331 }; 332 333 int 334 vrbcu_vrip_getcpuid(void) 335 { 336 volatile u_int16_t *revreg; 337 338 if (vr_cpuid != -1) 339 return (vr_cpuid); 340 341 if (vr_cpuid == -1) { 342 if (vrbcu_addr() == VR4181_BCU_ADDR) 343 revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1 344 ((vrbcu_addr() + BCU81REVID_REG_W)); 345 else 346 revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1 347 ((vrbcu_addr() + BCUREVID_REG_W)); 348 349 vr_cpuid = *revreg; 350 vr_cpuid = (vr_cpuid&BCUREVID_RIDMASK)>>BCUREVID_RIDSHFT; 351 if (vrbcu_addr() == VR4181_BCU_ADDR 352 && vr_cpuid == BCUREVID_RID_4181) /* conflict vr4101 */ 353 vr_cpuid = BCUREVID_FIXRID_4181; 354 } 355 return (vr_cpuid); 356 } 357 358 const char * 359 vrbcu_vrip_getcpuname(void) 360 { 361 int cpuid; 362 363 if (vr_cpuname != NULL) 364 return (vr_cpuname); 365 366 cpuid = vrbcu_vrip_getcpuid(); 367 vr_cpuname = cpuname[cpuid]; 368 369 return (vr_cpuname); 370 } 371 372 373 int 374 vrbcu_vrip_getcpumajor(void) 375 { 376 volatile u_int16_t *revreg; 377 378 if (vr_major != -1) 379 return (vr_major); 380 381 revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1 382 ((vrbcu_addr() + BCUREVID_REG_W)); 383 384 vr_major = *revreg; 385 vr_major = (vr_major&BCUREVID_MJREVMASK)>>BCUREVID_MJREVSHFT; 386 387 return (vr_major); 388 } 389 390 int 391 vrbcu_vrip_getcpuminor(void) 392 { 393 volatile u_int16_t *revreg; 394 395 if (vr_minor != -1) 396 return (vr_minor); 397 398 revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1 399 ((vrbcu_addr() + BCUREVID_REG_W)); 400 401 vr_minor = *revreg; 402 vr_minor = (vr_minor&BCUREVID_MNREVMASK)>>BCUREVID_MNREVSHFT; 403 404 return (vr_minor); 405 } 406 407 #define CLKX 18432000 /* CLKX1,CLKX2: 18.432MHz */ 408 #define MHZ 1000000 409 410 int 411 vrbcu_vrip_getcpuclock(void) 412 { 413 u_int16_t clksp = 0; 414 int cpuid, cpuclock; 415 416 cpuid = vrbcu_vrip_getcpuid(); 417 if (cpuid != BCUREVID_FIXRID_4181 && cpuid >= BCUREVID_RID_4111) { 418 clksp = *(u_int16_t *)MIPS_PHYS_TO_KSEG1 419 ((vrbcu_addr() + BCUCLKSPEED_REG_W)) & 420 BCUCLKSPEED_CLKSPMASK; 421 } else if (cpuid == BCUREVID_FIXRID_4181) { 422 clksp = *(u_int16_t *)MIPS_PHYS_TO_KSEG1 423 ((vrbcu_addr() + BCU81CLKSPEED_REG_W)) & 424 BCUCLKSPEED_CLKSPMASK; 425 } 426 427 switch (cpuid) { 428 case BCUREVID_FIXRID_4181: 429 cpuclock = CLKX / clksp * 64; 430 /* branch delay is 1 clock; 2 clock/loop */ 431 cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ; 432 break; 433 case BCUREVID_RID_4101: 434 /* assume 33MHz */ 435 cpuclock = 33000000; 436 /* branch delay is 1 clock; 2 clock/loop */ 437 cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ; 438 break; 439 case BCUREVID_RID_4102: 440 cpuclock = CLKX / clksp * 32; 441 /* branch delay is 1 clock; 2 clock/loop */ 442 cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ; 443 break; 444 case BCUREVID_RID_4111: 445 cpuclock = CLKX / clksp * 64; 446 /* branch delay is 1 clock; 2 clock/loop */ 447 cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ; 448 break; 449 case BCUREVID_RID_4121: 450 cpuclock = CLKX / clksp * 64; 451 /* branch delay is 2 clock; 3 clock/loop */ 452 cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ; 453 break; 454 case BCUREVID_RID_4122: 455 cpuclock = CLKX / clksp * 98; 456 /* branch delay is 2 clock; 3 clock/loop */ 457 cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ; 458 break; 459 case BCUREVID_RID_4131: 460 cpuclock = CLKX / clksp * 98; 461 /* branch delay is 2 clock; 3 clock/loop */ 462 cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ; 463 break; 464 default: 465 panic("unknown CPU type %d", cpuid); 466 break; 467 } 468 469 return (cpuclock); 470 } 471