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