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