bcu_vrip.c revision 1.6 1 /* $NetBSD: bcu_vrip.c,v 1.6 2000/10/27 08:10:32 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("%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