Home | History | Annotate | Line # | Download | only in vr
bcu_vrip.c revision 1.5
      1 /*	$NetBSD: bcu_vrip.c,v 1.5 2000/01/27 06:25:54 sato 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("vrbcu: cpu %d.%03dMHz, bus %d.%03dMHz, ram %d.%03dMHz\n",
    180 		cpuclock/1000000, (cpuclock%1000000)/1000,
    181 		tclock/1000000, (tclock%1000000)/1000,
    182 		vtclock/1000000, (vtclock%1000000)/1000);
    183 #ifdef VRBCUDEBUG
    184 	if (cpuid >= BCUREVID_RID_4111) {
    185 		reg = vrbcu_read(sc, BCUCNT3_REG_W);
    186 		printf("vrbcu: CNT3 %x: ",  reg);
    187 		bitdisp16(reg);
    188 	}
    189 #endif /* VRBCUDEBUG */
    190 
    191 }
    192 
    193 static char *cpuname[] = {
    194 	"VR4101",
    195 	"VR4102",
    196 	"VR4111",
    197 	"VR4121",
    198 	"UNKNOWN",
    199 	"UNKNOWN",
    200 	"UNKNOWN",
    201 	"UNKNOWN" };
    202 
    203 int
    204 vrbcu_vrip_getcpuid(void)
    205 {
    206 	volatile u_int16_t *revreg;
    207 
    208 	if (vr_cpuid != -1)
    209 		return vr_cpuid;
    210 
    211 	if (vr_cpuid == -1) {
    212 		revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    213 
    214 		vr_cpuid = *revreg;
    215 		vr_cpuid = (vr_cpuid&BCUREVID_RIDMASK)>>BCUREVID_RIDSHFT;
    216 	}
    217 	return vr_cpuid;
    218 }
    219 
    220 char *
    221 vrbcu_vrip_getcpuname(void)
    222 {
    223 	int cpuid;
    224 
    225 	if (vr_cpuname != NULL)
    226 		return vr_cpuname;
    227 
    228 	cpuid = vrbcu_vrip_getcpuid();
    229 	vr_cpuname = cpuname[cpuid];
    230 	return vr_cpuname;
    231 }
    232 
    233 
    234 int
    235 vrbcu_vrip_getcpumajor(void)
    236 {
    237 	volatile u_int16_t *revreg;
    238 
    239 	if (vr_major != -1)
    240 		return vr_major;
    241 
    242 	revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    243 
    244 	vr_major = *revreg;
    245 	vr_major = (vr_major&BCUREVID_MJREVMASK)>>BCUREVID_MJREVSHFT;
    246 	return vr_major;
    247 }
    248 
    249 int
    250 vrbcu_vrip_getcpuminor(void)
    251 {
    252 	volatile u_int16_t *revreg;
    253 
    254 	if (vr_minor != -1)
    255 		return vr_minor;
    256 
    257 	revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
    258 
    259 	vr_minor = *revreg;
    260 	vr_minor = (vr_minor&BCUREVID_MNREVMASK)>>BCUREVID_MNREVSHFT;
    261 	return vr_minor;
    262 }
    263 
    264 #define CLKX	18432000	/* CLKX1,CLKX2: 18.432MHz */
    265 #define MHZ	1000000
    266 
    267 int
    268 vrbcu_vrip_getcpuclock(void)
    269 {
    270 	u_int16_t clksp;
    271 	int cpuid, cpuclock;
    272 
    273 	clksp = *(u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUCLKSPEED_REG_W)) & BCUCLKSPEED_CLKSPMASK;
    274 	cpuid = vrbcu_vrip_getcpuid();
    275 
    276 	switch (cpuid) {
    277 	case BCUREVID_RID_4101:
    278 		/* assume 33MHz */
    279 		cpuclock = 33000000;
    280 		/* branch delay is 1 clock; 2 clock/loop */
    281 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    282 		break;
    283 	case BCUREVID_RID_4102:
    284 		cpuclock = CLKX / clksp * 32;
    285 		/* branch delay is 1 clock; 2 clock/loop */
    286 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    287 		break;
    288 	case BCUREVID_RID_4111:
    289 		cpuclock = CLKX / clksp * 64;
    290 		/* branch delay is 1 clock; 2 clock/loop */
    291 		cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
    292 		break;
    293 	case BCUREVID_RID_4121:
    294 		cpuclock = CLKX / clksp * 64;
    295 		/* branch delay is 2 clock; 3 clock/loop */
    296 		cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ;
    297 		break;
    298 	default:
    299 		panic("unknown CPU type %d\n", cpuid);
    300 		break;
    301 	}
    302 	return cpuclock;
    303 }
    304