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