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