bcu_vrip.c revision 1.7 1 1.7 sato /* $NetBSD: bcu_vrip.c,v 1.7 2001/04/18 11:07:26 sato Exp $ */
2 1.1 takemura
3 1.1 takemura /*-
4 1.7 sato * Copyright (c) 1999-2001 SATO Kazumi. All rights reserved.
5 1.1 takemura * Copyright (c) 1999 PocketBSD Project. All rights reserved.
6 1.1 takemura *
7 1.1 takemura * Redistribution and use in source and binary forms, with or without
8 1.1 takemura * modification, are permitted provided that the following conditions
9 1.1 takemura * are met:
10 1.1 takemura * 1. Redistributions of source code must retain the above copyright
11 1.1 takemura * notice, this list of conditions and the following disclaimer.
12 1.1 takemura * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 takemura * notice, this list of conditions and the following disclaimer in the
14 1.1 takemura * documentation and/or other materials provided with the distribution.
15 1.1 takemura * 3. All advertising materials mentioning features or use of this software
16 1.1 takemura * must display the following acknowledgement:
17 1.1 takemura * This product includes software developed by the PocketBSD project
18 1.1 takemura * and its contributors.
19 1.1 takemura * 4. Neither the name of the project nor the names of its contributors
20 1.1 takemura * may be used to endorse or promote products derived from this software
21 1.1 takemura * without specific prior written permission.
22 1.1 takemura *
23 1.1 takemura * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 takemura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 takemura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 takemura * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 takemura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 takemura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 takemura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 takemura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 takemura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 takemura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 takemura * SUCH DAMAGE.
34 1.1 takemura *
35 1.1 takemura */
36 1.1 takemura
37 1.1 takemura #include <sys/param.h>
38 1.1 takemura #include <sys/systm.h>
39 1.1 takemura #include <sys/device.h>
40 1.1 takemura #include <sys/reboot.h>
41 1.1 takemura
42 1.1 takemura #include <machine/bus.h>
43 1.1 takemura
44 1.1 takemura #include <mips/cpuregs.h>
45 1.1 takemura
46 1.7 sato #include "opt_vr41xx.h"
47 1.1 takemura #include <hpcmips/vr/vr.h>
48 1.7 sato #include <hpcmips/vr/vrcpudef.h>
49 1.1 takemura #include <hpcmips/vr/vripvar.h>
50 1.1 takemura #include <hpcmips/vr/vripreg.h>
51 1.1 takemura #include <hpcmips/vr/bcureg.h>
52 1.1 takemura #include <hpcmips/vr/bcuvar.h>
53 1.1 takemura
54 1.3 sato static int vrbcu_match __P((struct device *, struct cfdata *, void *));
55 1.3 sato static void vrbcu_attach __P((struct device *, struct device *, void *));
56 1.1 takemura
57 1.3 sato static void vrbcu_write __P((struct vrbcu_softc *, int, unsigned short));
58 1.3 sato static unsigned short vrbcu_read __P((struct vrbcu_softc *, int));
59 1.2 sato
60 1.5 sato static void vrbcu_dump_regs __P((void));
61 1.5 sato
62 1.2 sato char *vr_cpuname=NULL;
63 1.2 sato int vr_major=-1;
64 1.2 sato int vr_minor=-1;
65 1.2 sato int vr_cpuid=-1;
66 1.1 takemura
67 1.1 takemura struct cfattach vrbcu_ca = {
68 1.3 sato sizeof(struct vrbcu_softc), vrbcu_match, vrbcu_attach
69 1.1 takemura };
70 1.1 takemura
71 1.3 sato struct vrbcu_softc *the_bcu_sc = NULL;
72 1.3 sato
73 1.3 sato static inline void
74 1.3 sato vrbcu_write(sc, port, val)
75 1.3 sato struct vrbcu_softc *sc;
76 1.3 sato int port;
77 1.3 sato unsigned short val;
78 1.3 sato {
79 1.3 sato bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
80 1.3 sato }
81 1.3 sato
82 1.3 sato static inline unsigned short
83 1.3 sato vrbcu_read(sc, port)
84 1.3 sato struct vrbcu_softc *sc;
85 1.3 sato int port;
86 1.3 sato {
87 1.3 sato return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
88 1.3 sato }
89 1.3 sato
90 1.1 takemura static int
91 1.3 sato vrbcu_match(parent, cf, aux)
92 1.1 takemura struct device *parent;
93 1.1 takemura struct cfdata *cf;
94 1.1 takemura void *aux;
95 1.1 takemura {
96 1.2 sato return 2;
97 1.1 takemura }
98 1.1 takemura
99 1.1 takemura static void
100 1.3 sato vrbcu_attach(parent, self, aux)
101 1.1 takemura struct device *parent;
102 1.1 takemura struct device *self;
103 1.1 takemura void *aux;
104 1.1 takemura {
105 1.1 takemura struct vrip_attach_args *va = aux;
106 1.3 sato struct vrbcu_softc *sc = (struct vrbcu_softc *)self;
107 1.1 takemura
108 1.3 sato sc->sc_iot = va->va_iot;
109 1.3 sato bus_space_map(sc->sc_iot, va->va_addr, va->va_size,
110 1.1 takemura 0, /* no flags */
111 1.3 sato &sc->sc_ioh);
112 1.1 takemura
113 1.1 takemura printf("\n");
114 1.3 sato the_bcu_sc = sc;
115 1.5 sato vrbcu_dump_regs();
116 1.5 sato }
117 1.5 sato
118 1.5 sato static void
119 1.5 sato vrbcu_dump_regs()
120 1.5 sato {
121 1.5 sato struct vrbcu_softc *sc = the_bcu_sc;
122 1.7 sato int cpuclock = 0, tclock = 0, vtclock = 0, cpuid;
123 1.7 sato #if !defined(ONLY_VR4181) && !defined(ONLY_VR4102) && defined VRGROUP_4111_4122
124 1.7 sato int spdreg;
125 1.7 sato #endif
126 1.7 sato #ifdef VRBCUDEBUG
127 1.5 sato int reg;
128 1.7 sato #endif /* VRBCUDEBUG */
129 1.5 sato
130 1.7 sato cpuid = vrbcu_vrip_getcpuid();
131 1.7 sato #if !defined(ONLY_VR4181) && !defined(ONLY_VR4102) && defined VRGROUP_4111_4122
132 1.7 sato if (cpuid != BCUREVID_FIXRID_4181
133 1.7 sato && cpuid <= BCUREVID_RID_4122
134 1.7 sato && cpuid >= BCUREVID_RID_4111) {
135 1.7 sato spdreg = vrbcu_read(sc, BCUCLKSPEED_REG_W);
136 1.5 sato #ifdef VRBCUDEBUG
137 1.7 sato printf("vrbcu: CLKSPEED %x: \n", spdreg);
138 1.7 sato #endif /* VRBCUDEBUG */
139 1.7 sato }
140 1.7 sato #endif
141 1.7 sato
142 1.5 sato cpuclock = vrbcu_vrip_getcpuclock();
143 1.5 sato
144 1.5 sato switch (cpuid) {
145 1.7 sato case BCUREVID_FIXRID_4181:
146 1.5 sato case BCUREVID_RID_4101:
147 1.5 sato case BCUREVID_RID_4102:
148 1.5 sato vtclock = tclock = cpuclock/2;
149 1.5 sato break;
150 1.7 sato #if defined VR4111
151 1.5 sato case BCUREVID_RID_4111:
152 1.7 sato if ((spdreg&BCUCLKSPEED_DIVT2B) == 0)
153 1.5 sato vtclock = tclock = cpuclock/2;
154 1.7 sato else if ((spdreg&BCUCLKSPEED_DIVT3B) == 0)
155 1.5 sato vtclock = tclock = cpuclock/3;
156 1.7 sato else if ((spdreg&BCUCLKSPEED_DIVT4B) == 0)
157 1.5 sato vtclock = tclock = cpuclock/4;
158 1.5 sato else
159 1.5 sato vtclock = tclock = 0; /* XXX */
160 1.5 sato break;
161 1.7 sato #endif /* VR4111 */
162 1.7 sato #if defined VR4121
163 1.5 sato case BCUREVID_RID_4121:
164 1.7 sato {
165 1.7 sato int vt;
166 1.7 sato tclock = cpuclock / ((spdreg&BCUCLKSPEED_DIVTMASK)>>BCUCLKSPEED_DIVTSHFT);
167 1.7 sato vt = ((spdreg&BCUCLKSPEED_DIVVTMASK)>>BCUCLKSPEED_DIVVTSHFT);
168 1.5 sato if (vt == 0)
169 1.5 sato vtclock = 0; /* XXX */
170 1.5 sato else if (vt < 0x9)
171 1.5 sato vtclock = cpuclock / vt;
172 1.5 sato else
173 1.5 sato vtclock = cpuclock / ((vt - 8)*2+1) * 2;
174 1.7 sato }
175 1.5 sato break;
176 1.7 sato #endif /* VR4121 */
177 1.5 sato default:
178 1.5 sato break;
179 1.5 sato }
180 1.7 sato if (tclock)
181 1.7 sato printf("%s: cpu %d.%03dMHz, bus %d.%03dMHz, ram %d.%03dMHz\n",
182 1.7 sato sc->sc_dev.dv_xname,
183 1.7 sato cpuclock/1000000, (cpuclock%1000000)/1000,
184 1.7 sato tclock/1000000, (tclock%1000000)/1000,
185 1.7 sato vtclock/1000000, (vtclock%1000000)/1000);
186 1.7 sato else {
187 1.7 sato printf("%s: cpu %d.%03dMHz\n",
188 1.7 sato sc->sc_dev.dv_xname,
189 1.7 sato cpuclock/1000000, (cpuclock%1000000)/1000);
190 1.7 sato printf("%s: UNKNOWN BUS CLOCK SPEED: CPU is UNKNOWN or NOT CONFIGURED\n",
191 1.7 sato sc->sc_dev.dv_xname);
192 1.7 sato }
193 1.5 sato #ifdef VRBCUDEBUG
194 1.7 sato reg = vrbcu_read(sc, BCUCNT1_REG_W);
195 1.7 sato printf("vrbcu: CNT1 %x: ", reg);
196 1.7 sato bitdisp16(reg);
197 1.7 sato #if !defined(ONLY_VR4181)
198 1.7 sato if (cpuid != BCUREVID_FIXRID_4181
199 1.7 sato && cpuid <= BCUREVID_RID_4121
200 1.7 sato && cpuid >= BCUREVID_RID_4102) {
201 1.7 sato reg = vrbcu_read(sc, BCUCNT2_REG_W);
202 1.7 sato printf("vrbcu: CNT2 %x: ", reg);
203 1.7 sato bitdisp16(reg);
204 1.7 sato }
205 1.7 sato #endif /* !defined ONLY_VR4181 */
206 1.7 sato #if !defined(ONLY_VR4181) || !defined(ONLY_VR4122)
207 1.7 sato if (cpuid != BCUREVID_FIXRID_4181
208 1.7 sato && cpuid <= BCUREVID_RID_4121
209 1.7 sato && cpuid >= BCUREVID_RID_4102) {
210 1.7 sato reg = vrbcu_read(sc, BCUSPEED_REG_W);
211 1.7 sato printf("vrbcu: SPEED %x: ", reg);
212 1.7 sato bitdisp16(reg);
213 1.7 sato reg = vrbcu_read(sc, BCUERRST_REG_W);
214 1.7 sato printf("vrbcu: ERRST %x: ", reg);
215 1.7 sato bitdisp16(reg);
216 1.7 sato reg = vrbcu_read(sc, BCURFCNT_REG_W);
217 1.7 sato printf("vrbcu: RFCNT %x\n", reg);
218 1.7 sato reg = vrbcu_read(sc, BCUREFCOUNT_REG_W);
219 1.7 sato printf("vrbcu: RFCOUNT %x\n", reg);
220 1.7 sato }
221 1.7 sato #endif /* !defined(ONLY_VR4181) || !defined(ONLY_VR4122) */
222 1.7 sato #if !defined(ONLY_VR4181)
223 1.7 sato if (cpuid != BCUREVID_FIXRID_4181
224 1.7 sato && cpuid <= BCUREVID_RID_4122
225 1.7 sato && cpuid >= BCUREVID_RID_4111)
226 1.7 sato {
227 1.5 sato reg = vrbcu_read(sc, BCUCNT3_REG_W);
228 1.5 sato printf("vrbcu: CNT3 %x: ", reg);
229 1.5 sato bitdisp16(reg);
230 1.5 sato }
231 1.7 sato #endif /* !defined ONLY_VR4181 */
232 1.5 sato #endif /* VRBCUDEBUG */
233 1.5 sato
234 1.1 takemura }
235 1.1 takemura
236 1.1 takemura static char *cpuname[] = {
237 1.7 sato "VR4101", /* 0 */
238 1.7 sato "VR4102", /* 1 */
239 1.7 sato "VR4111", /* 2 */
240 1.7 sato "VR4121", /* 3 */
241 1.7 sato "VR4122", /* 4 */
242 1.7 sato "UNKNOWN",
243 1.7 sato "UNKNOWN",
244 1.7 sato "UNKNOWN",
245 1.1 takemura "UNKNOWN",
246 1.1 takemura "UNKNOWN",
247 1.1 takemura "UNKNOWN",
248 1.7 sato "UNKNOWN",
249 1.7 sato "UNKNOWN",
250 1.7 sato "UNKNOWN",
251 1.7 sato "UNKNOWN",
252 1.7 sato "UNKNOWN",
253 1.7 sato "VR4181", /* 0x10 + 0 */
254 1.7 sato };
255 1.1 takemura
256 1.2 sato int
257 1.2 sato vrbcu_vrip_getcpuid(void)
258 1.2 sato {
259 1.2 sato volatile u_int16_t *revreg;
260 1.2 sato
261 1.2 sato if (vr_cpuid != -1)
262 1.2 sato return vr_cpuid;
263 1.2 sato
264 1.2 sato if (vr_cpuid == -1) {
265 1.2 sato revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
266 1.2 sato
267 1.2 sato vr_cpuid = *revreg;
268 1.2 sato vr_cpuid = (vr_cpuid&BCUREVID_RIDMASK)>>BCUREVID_RIDSHFT;
269 1.7 sato #if !defined(VR4101) && defined(VR4181)
270 1.7 sato if (vr_cpuid == BCUREVID_RID_4181) /* conflict vr4101 */
271 1.7 sato vr_cpuid = BCUREVID_FIXRID_4181;
272 1.7 sato #endif /* !defined(VR4101) && defined(VR4181) */
273 1.2 sato }
274 1.2 sato return vr_cpuid;
275 1.2 sato }
276 1.2 sato
277 1.1 takemura char *
278 1.1 takemura vrbcu_vrip_getcpuname(void)
279 1.1 takemura {
280 1.2 sato int cpuid;
281 1.1 takemura
282 1.2 sato if (vr_cpuname != NULL)
283 1.2 sato return vr_cpuname;
284 1.1 takemura
285 1.2 sato cpuid = vrbcu_vrip_getcpuid();
286 1.2 sato vr_cpuname = cpuname[cpuid];
287 1.2 sato return vr_cpuname;
288 1.1 takemura }
289 1.1 takemura
290 1.2 sato
291 1.1 takemura int
292 1.1 takemura vrbcu_vrip_getcpumajor(void)
293 1.1 takemura {
294 1.1 takemura volatile u_int16_t *revreg;
295 1.2 sato
296 1.2 sato if (vr_major != -1)
297 1.2 sato return vr_major;
298 1.1 takemura
299 1.1 takemura revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
300 1.1 takemura
301 1.2 sato vr_major = *revreg;
302 1.2 sato vr_major = (vr_major&BCUREVID_MJREVMASK)>>BCUREVID_MJREVSHFT;
303 1.2 sato return vr_major;
304 1.1 takemura }
305 1.1 takemura
306 1.1 takemura int
307 1.1 takemura vrbcu_vrip_getcpuminor(void)
308 1.1 takemura {
309 1.1 takemura volatile u_int16_t *revreg;
310 1.2 sato
311 1.2 sato if (vr_minor != -1)
312 1.2 sato return vr_minor;
313 1.1 takemura
314 1.1 takemura revreg = (u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUREVID_REG_W));
315 1.1 takemura
316 1.2 sato vr_minor = *revreg;
317 1.2 sato vr_minor = (vr_minor&BCUREVID_MNREVMASK)>>BCUREVID_MNREVSHFT;
318 1.2 sato return vr_minor;
319 1.1 takemura }
320 1.4 shin
321 1.4 shin #define CLKX 18432000 /* CLKX1,CLKX2: 18.432MHz */
322 1.4 shin #define MHZ 1000000
323 1.4 shin
324 1.4 shin int
325 1.4 shin vrbcu_vrip_getcpuclock(void)
326 1.4 shin {
327 1.4 shin u_int16_t clksp;
328 1.4 shin int cpuid, cpuclock;
329 1.4 shin
330 1.4 shin cpuid = vrbcu_vrip_getcpuid();
331 1.7 sato if (cpuid != BCUREVID_FIXRID_4181 && cpuid >= BCUREVID_RID_4111) {
332 1.7 sato clksp = *(u_int16_t *)MIPS_PHYS_TO_KSEG1((VRIP_BCU_ADDR+BCUCLKSPEED_REG_W)) & BCUCLKSPEED_CLKSPMASK;
333 1.7 sato }
334 1.4 shin
335 1.4 shin switch (cpuid) {
336 1.7 sato case BCUREVID_FIXRID_4181:
337 1.7 sato /* assume 66MHz */
338 1.7 sato cpuclock = 66000000;
339 1.7 sato /* branch delay is 1 clock; 2 clock/loop */
340 1.7 sato cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
341 1.7 sato break;
342 1.4 shin case BCUREVID_RID_4101:
343 1.4 shin /* assume 33MHz */
344 1.4 shin cpuclock = 33000000;
345 1.4 shin /* branch delay is 1 clock; 2 clock/loop */
346 1.4 shin cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
347 1.4 shin break;
348 1.4 shin case BCUREVID_RID_4102:
349 1.4 shin cpuclock = CLKX / clksp * 32;
350 1.4 shin /* branch delay is 1 clock; 2 clock/loop */
351 1.4 shin cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
352 1.4 shin break;
353 1.4 shin case BCUREVID_RID_4111:
354 1.4 shin cpuclock = CLKX / clksp * 64;
355 1.4 shin /* branch delay is 1 clock; 2 clock/loop */
356 1.4 shin cpuspeed = (cpuclock / 2 + MHZ / 2) / MHZ;
357 1.4 shin break;
358 1.4 shin case BCUREVID_RID_4121:
359 1.4 shin cpuclock = CLKX / clksp * 64;
360 1.4 shin /* branch delay is 2 clock; 3 clock/loop */
361 1.4 shin cpuspeed = (cpuclock / 3 + MHZ / 2) / MHZ;
362 1.4 shin break;
363 1.4 shin default:
364 1.4 shin panic("unknown CPU type %d\n", cpuid);
365 1.4 shin break;
366 1.4 shin }
367 1.4 shin return cpuclock;
368 1.4 shin }
369