Home | History | Annotate | Line # | Download | only in vr
bcu_vrip.c revision 1.1.1.1.2.2
      1 /*	$NetBSD: bcu_vrip.c,v 1.1.1.1.2.2 2000/11/22 16:00:13 bouyer Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 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 
     44 #include <mips/cpuregs.h>
     45 
     46 #include <hpcmips/vr/vr.h>
     47 #include <hpcmips/vr/vripvar.h>
     48 #include <hpcmips/vr/vripreg.h>
     49 #include <hpcmips/vr/bcureg.h>
     50 #include <hpcmips/vr/bcuvar.h>
     51 
     52 static int vrbcu_match __P((struct device *, struct cfdata *, void *));
     53 static void vrbcu_attach __P((struct device *, struct device *, void *));
     54 
     55 static void vrbcu_write __P((struct vrbcu_softc *, int, unsigned short));
     56 static unsigned short vrbcu_read __P((struct vrbcu_softc *, int));
     57 
     58 static void vrbcu_dump_regs __P((void));
     59 
     60 char	*vr_cpuname=NULL;
     61 int	vr_major=-1;
     62 int	vr_minor=-1;
     63 int	vr_cpuid=-1;
     64 
     65 struct cfattach vrbcu_ca = {
     66 	sizeof(struct vrbcu_softc), vrbcu_match, vrbcu_attach
     67 };
     68 
     69 struct vrbcu_softc *the_bcu_sc = NULL;
     70 
     71 static inline void
     72 vrbcu_write(sc, port, val)
     73 	struct vrbcu_softc *sc;
     74 	int port;
     75 	unsigned short val;
     76 {
     77 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
     78 }
     79 
     80 static inline unsigned short
     81 vrbcu_read(sc, port)
     82 	struct vrbcu_softc *sc;
     83 	int port;
     84 {
     85 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
     86 }
     87 
     88 static int
     89 vrbcu_match(parent, cf, aux)
     90      struct device *parent;
     91      struct cfdata *cf;
     92      void *aux;
     93 {
     94 	return 2;
     95 }
     96 
     97 static void
     98 vrbcu_attach(parent, self, aux)
     99      struct device *parent;
    100      struct device *self;
    101      void *aux;
    102 {
    103 	struct vrip_attach_args *va = aux;
    104 	struct vrbcu_softc *sc = (struct vrbcu_softc *)self;
    105 
    106 	sc->sc_iot = va->va_iot;
    107 	bus_space_map(sc->sc_iot, va->va_addr, va->va_size,
    108 		0, /* no flags */
    109 		&sc->sc_ioh);
    110 
    111 	printf("\n");
    112 	the_bcu_sc = sc;
    113 	vrbcu_dump_regs();
    114 }
    115 
    116 static void
    117 vrbcu_dump_regs()
    118 {
    119 	struct vrbcu_softc *sc = the_bcu_sc;
    120 	int reg;
    121 	int cpuclock, tclock, vtclock, cpuid, vt;
    122 
    123 #ifdef VRBCUDEBUG
    124 	reg = vrbcu_read(sc, BCUCNT1_REG_W);
    125 	printf("vrbcu: CNT1 %x: ",  reg);
    126 	bitdisp16(reg);
    127 	reg = vrbcu_read(sc, BCUCNT2_REG_W);
    128 	printf("vrbcu: CNT2 %x: ",  reg);
    129 	bitdisp16(reg);
    130 	reg = vrbcu_read(sc, BCUSPEED_REG_W);
    131 	printf("vrbcu: SPEED %x: ",  reg);
    132 	bitdisp16(reg);
    133 	reg = vrbcu_read(sc, BCUERRST_REG_W);
    134 	printf("vrbcu: ERRST %x: ",  reg);
    135 	bitdisp16(reg);
    136 	reg = vrbcu_read(sc, BCURFCNT_REG_W);
    137 	printf("vrbcu: RFCNT %x\n",  reg);
    138 	reg = vrbcu_read(sc, BCUREFCOUNT_REG_W);
    139 	printf("vrbcu: RFCOUNT %x\n",  reg);
    140 #endif /* VRBCUDEBUG */
    141 	reg = vrbcu_read(sc, BCUCLKSPEED_REG_W);
    142 #ifdef VRBCUDEBUG
    143 	printf("vrbcu: CLKSPEED %x: \n",  reg);
    144 #endif /* VRBCUDEBUG */
    145 	cpuclock = vrbcu_vrip_getcpuclock();
    146 	cpuid = vrbcu_vrip_getcpuid();
    147 
    148 	switch (cpuid) {
    149 	case BCUREVID_RID_4101:
    150 		/* assume 33MHz */
    151 		vtclock = tclock = cpuclock/2;	/* XXX */
    152 		break;
    153 	case BCUREVID_RID_4102:
    154 		vtclock = tclock = cpuclock/2;
    155 		break;
    156 	case BCUREVID_RID_4111:
    157 		if ((reg&BCUCLKSPEED_DIVT2B) == 0)
    158 			vtclock = tclock = cpuclock/2;
    159 		else if ((reg&BCUCLKSPEED_DIVT3B) == 0)
    160 			vtclock = tclock = cpuclock/3;
    161 		else if ((reg&BCUCLKSPEED_DIVT4B) == 0)
    162 			vtclock = tclock = cpuclock/4;
    163 		else
    164 			vtclock = tclock = 0; /* XXX */
    165 		break;
    166 	case BCUREVID_RID_4121:
    167 			tclock = cpuclock / ((reg&BCUCLKSPEED_DIVTMASK)>>BCUCLKSPEED_DIVTSHFT);
    168 			vt = ((reg&BCUCLKSPEED_DIVVTMASK)>>BCUCLKSPEED_DIVVTSHFT);
    169 			if (vt == 0)
    170 				vtclock = 0; /* XXX */
    171 			else if (vt < 0x9)
    172 				vtclock = cpuclock / vt;
    173 			else
    174 				vtclock = cpuclock / ((vt - 8)*2+1) * 2;
    175 		break;
    176 	default:
    177 		break;
    178 	}
    179 	printf("%s: cpu %d.%03dMHz, bus %d.%03dMHz, ram %d.%03dMHz\n",
    180 		sc->sc_dev.dv_xname,
    181 		cpuclock/1000000, (cpuclock%1000000)/1000,
    182 		tclock/1000000, (tclock%1000000)/1000,
    183 		vtclock/1000000, (vtclock%1000000)/1000);
    184 #ifdef VRBCUDEBUG
    185 	if (cpuid >= BCUREVID_RID_4111) {
    186 		reg = vrbcu_read(sc, BCUCNT3_REG_W);
    187 		printf("vrbcu: CNT3 %x: ",  reg);
    188 		bitdisp16(reg);
    189 	}
    190 #endif /* VRBCUDEBUG */
    191 
    192 }
    193 
    194 static char *cpuname[] = {
    195 	"VR4101",
    196 	"VR4102",
    197 	"VR4111",
    198 	"VR4121",
    199 	"UNKNOWN",
    200 	"UNKNOWN",
    201 	"UNKNOWN",
    202 	"UNKNOWN" };
    203 
    204 int
    205 vrbcu_vrip_getcpuid(void)
    206 {
    207 	volatile u_int16_t *revreg;
    208 
    209 	if (vr_cpuid != -1)
    210 		return vr_cpuid;
    211 
    212 	if (vr_cpuid == -1) {
    213 		revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    214 
    215 		vr_cpuid = *revreg;
    216 		vr_cpuid = (vr_cpuid&BCUREVID_RIDMASK)>>BCUREVID_RIDSHFT;
    217 	}
    218 	return vr_cpuid;
    219 }
    220 
    221 char *
    222 vrbcu_vrip_getcpuname(void)
    223 {
    224 	int cpuid;
    225 
    226 	if (vr_cpuname != NULL)
    227 		return vr_cpuname;
    228 
    229 	cpuid = vrbcu_vrip_getcpuid();
    230 	vr_cpuname = cpuname[cpuid];
    231 	return vr_cpuname;
    232 }
    233 
    234 
    235 int
    236 vrbcu_vrip_getcpumajor(void)
    237 {
    238 	volatile u_int16_t *revreg;
    239 
    240 	if (vr_major != -1)
    241 		return vr_major;
    242 
    243 	revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    244 
    245 	vr_major = *revreg;
    246 	vr_major = (vr_major&BCUREVID_MJREVMASK)>>BCUREVID_MJREVSHFT;
    247 	return vr_major;
    248 }
    249 
    250 int
    251 vrbcu_vrip_getcpuminor(void)
    252 {
    253 	volatile u_int16_t *revreg;
    254 
    255 	if (vr_minor != -1)
    256 		return vr_minor;
    257 
    258 	revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    259 
    260 	vr_minor = *revreg;
    261 	vr_minor = (vr_minor&BCUREVID_MNREVMASK)>>BCUREVID_MNREVSHFT;
    262 	return vr_minor;
    263 }
    264 
    265 #define CLKX	18432000	/* CLKX1,CLKX2: 18.432MHz */
    266 #define MHZ	1000000
    267 
    268 int
    269 vrbcu_vrip_getcpuclock(void)
    270 {
    271 	u_int16_t clksp;
    272 	int cpuid, cpuclock;
    273 
    274 	clksp = *(u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUCLKSPEED_REG_W)) & BCUCLKSPEED_CLKSPMASK;
    275 	cpuid = vrbcu_vrip_getcpuid();
    276 
    277 	switch (cpuid) {
    278 	case BCUREVID_RID_4101:
    279 		/* assume 33MHz */
    280 		cpuclock = 33000000;
    281 		/* branch delay is 1 clock; 2 clock/loop */
    282 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    283 		break;
    284 	case BCUREVID_RID_4102:
    285 		cpuclock = CLKX / clksp * 32;
    286 		/* branch delay is 1 clock; 2 clock/loop */
    287 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    288 		break;
    289 	case BCUREVID_RID_4111:
    290 		cpuclock = CLKX / clksp * 64;
    291 		/* branch delay is 1 clock; 2 clock/loop */
    292 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    293 		break;
    294 	case BCUREVID_RID_4121:
    295 		cpuclock = CLKX / clksp * 64;
    296 		/* branch delay is 2 clock; 3 clock/loop */
    297 		cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ;
    298 		break;
    299 	default:
    300 		panic("unknown CPU type %d\n", cpuid);
    301 		break;
    302 	}
    303 	return cpuclock;
    304 }
    305