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