1 /* $NetBSD: bcu_vrip.c,v 1.28 2007/12/15 00:39:18 perry Exp $ */
4 * Copyright (c) 1999-2001 SATO Kazumi. All rights reserved.
5 * Copyright (c) 1999, 2002 PocketBSD Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: bcu_vrip.c,v 1.28 2007/12/15 00:39:18 perry Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/reboot.h>
45 #include <machine/bus.h>
46 #include <machine/debug.h>
47 #include <machine/platid.h>
48 #include <machine/platid_mask.h>
50 #include <mips/cpuregs.h>
52 #include "opt_vr41xx.h"
53 #include <hpcmips/vr/vr.h>
54 #include <hpcmips/vr/vrcpudef.h>
55 #include <hpcmips/vr/vripif.h>
56 #include <hpcmips/vr/vripvar.h>
57 #include <hpcmips/vr/vripreg.h>
58 #include <hpcmips/vr/bcureg.h>
59 #include <hpcmips/vr/bcuvar.h>
61 static int vrbcu_match(struct device
*, struct cfdata
*, void *);
62 static void vrbcu_attach(struct device
*, struct device
*, void *);
64 static void vrbcu_write(struct vrbcu_softc
*, int, unsigned short);
65 static unsigned short vrbcu_read(struct vrbcu_softc
*, int);
67 static void vrbcu_dump_regs(void);
69 const char *vr_cpuname
=NULL
;
74 CFATTACH_DECL(vrbcu
, sizeof(struct vrbcu_softc
),
75 vrbcu_match
, vrbcu_attach
, NULL
, NULL
);
77 struct vrbcu_softc
*the_bcu_sc
= NULL
;
79 #ifdef SINGLE_VRIP_BASE
80 #define vrbcu_addr() VRIP_BCU_ADDR
82 static bus_addr_t
vrbcu_addr(void);
86 static bus_addr_t addr
= 0;
87 static struct platid_data addrs
[] = {
88 { &platid_mask_CPU_MIPS_VR_4102
, (void *)VR4102_BCU_ADDR
},
89 { &platid_mask_CPU_MIPS_VR_4111
, (void *)VR4102_BCU_ADDR
},
90 { &platid_mask_CPU_MIPS_VR_4121
, (void *)VR4102_BCU_ADDR
},
91 { &platid_mask_CPU_MIPS_VR_4122
, (void *)VR4122_BCU_ADDR
},
92 { &platid_mask_CPU_MIPS_VR_4131
, (void *)VR4122_BCU_ADDR
},
93 { &platid_mask_CPU_MIPS_VR_4181
, (void *)VR4181_BCU_ADDR
},
94 { NULL
, NULL
} /* terminator, don't delete */
96 struct platid_data
*p
;
99 if ((p
= platid_search_data(&platid
, addrs
)) == NULL
)
100 panic("%s: can't find VR BCU address", __func__
);
101 addr
= (bus_addr_t
)p
->data
;
106 #endif /* SINGLE_VRIP_BASE */
109 vrbcu_write(struct vrbcu_softc
*sc
, int port
, unsigned short val
)
112 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, port
, val
);
115 static inline unsigned short
116 vrbcu_read(struct vrbcu_softc
*sc
, int port
)
119 return (bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, port
));
123 vrbcu_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
130 vrbcu_attach(struct device
*parent
, struct device
*self
, void *aux
)
132 struct vrip_attach_args
*va
= aux
;
133 struct vrbcu_softc
*sc
= (struct vrbcu_softc
*)self
;
135 sc
->sc_iot
= va
->va_iot
;
136 bus_space_map(sc
->sc_iot
, va
->va_addr
, va
->va_size
,
146 vrbcu_dump_regs(void)
148 struct vrbcu_softc
*sc
= the_bcu_sc
;
149 int cpuclock
= 0, tclock
= 0, vtclock
= 0, cpuid
;
150 #if !defined(ONLY_VR4102)
151 int spdreg
= 0; /* XXX gcc doesn't stand a chance of tracking this! */
155 #endif /* VRBCUDEBUG */
157 cpuid
= vrbcu_vrip_getcpuid();
158 #if !defined(ONLY_VR4181) && !defined(ONLY_VR4102)
159 if (cpuid
!= BCUREVID_FIXRID_4181
160 && cpuid
<= BCUREVID_RID_4131
161 && cpuid
>= BCUREVID_RID_4111
) {
162 spdreg
= vrbcu_read(sc
, BCUCLKSPEED_REG_W
);
164 printf("vrbcu: CLKSPEED %x: \n", spdreg
);
165 #endif /* VRBCUDEBUG */
169 if (cpuid
== BCUREVID_FIXRID_4181
){
170 spdreg
= vrbcu_read(sc
, BCU81CLKSPEED_REG_W
);
172 printf("vrbcu: CLKSPEED %x: \n", spdreg
);
173 #endif /* VRBCUDEBUG */
177 cpuclock
= vrbcu_vrip_getcpuclock();
181 case BCUREVID_FIXRID_4181
:
182 switch ((spdreg
& BCU81CLKSPEED_DIVTMASK
) >>
183 BCU81CLKSPEED_DIVTSHFT
){
184 case BCU81CLKSPEED_DIVT1
:
185 vtclock
= tclock
= cpuclock
;
187 case BCU81CLKSPEED_DIVT2
:
188 vtclock
= tclock
= cpuclock
/2;
190 case BCU81CLKSPEED_DIVT3
:
191 vtclock
= tclock
= cpuclock
/3;
193 case BCU81CLKSPEED_DIVT4
:
194 vtclock
= tclock
= cpuclock
/4;
197 vtclock
= tclock
= 0;
201 case BCUREVID_RID_4101
:
202 case BCUREVID_RID_4102
:
203 vtclock
= tclock
= cpuclock
/2;
206 case BCUREVID_RID_4111
:
207 if ((spdreg
&BCUCLKSPEED_DIVT2B
) == 0)
208 vtclock
= tclock
= cpuclock
/2;
209 else if ((spdreg
&BCUCLKSPEED_DIVT3B
) == 0)
210 vtclock
= tclock
= cpuclock
/3;
211 else if ((spdreg
&BCUCLKSPEED_DIVT4B
) == 0)
212 vtclock
= tclock
= cpuclock
/4;
214 vtclock
= tclock
= 0; /* XXX */
218 case BCUREVID_RID_4121
:
221 tclock
= cpuclock
/ ((spdreg
& BCUCLKSPEED_DIVTMASK
) >>
222 BCUCLKSPEED_DIVTSHFT
);
223 vt
= ((spdreg
& BCUCLKSPEED_DIVVTMASK
) >>
224 BCUCLKSPEED_DIVVTSHFT
);
226 vtclock
= 0; /* XXX */
228 vtclock
= cpuclock
/ vt
;
230 vtclock
= cpuclock
/ ((vt
- 8)*2+1) * 2;
234 #if defined VR4122 || defined VR4131
235 case BCUREVID_RID_4122
:
236 case BCUREVID_RID_4131
:
240 vtdiv
= ((spdreg
& BCUCLKSPEED_VTDIVMODE
) >>
241 BCUCLKSPEED_VTDIVSHFT
);
242 if (vtdiv
== 0 || vtdiv
> BCUCLKSPEED_VTDIV6
)
243 vtclock
= 0; /* XXX */
245 vtclock
= cpuclock
/ vtdiv
;
247 (((spdreg
& BCUCLKSPEED_TDIVMODE
) >>
248 BCUCLKSPEED_TDIVSHFT
) ? 4 : 2);
251 #endif /* VR4122 || VR4131 */
256 printf("%s: CPU %d.%03dMHz, bus %d.%03dMHz, ram %d.%03dMHz\n",
258 cpuclock
/1000000, (cpuclock
%1000000)/1000,
259 tclock
/1000000, (tclock
%1000000)/1000,
260 vtclock
/1000000, (vtclock
%1000000)/1000);
262 printf("%s: CPU %d.%03dMHz\n",
264 cpuclock
/1000000, (cpuclock
%1000000)/1000);
265 printf("%s: UNKNOWN BUS CLOCK SPEED:"
266 " CPU is UNKNOWN or NOT CONFIGURED\n",
267 sc
->sc_dev
.dv_xname
);
270 reg
= vrbcu_read(sc
, BCUCNT1_REG_W
);
271 printf("vrbcu: CNT1 %x: ", reg
);
273 #if !defined(ONLY_VR4181)
274 if (cpuid
!= BCUREVID_FIXRID_4181
275 && cpuid
<= BCUREVID_RID_4121
276 && cpuid
>= BCUREVID_RID_4102
) {
277 reg
= vrbcu_read(sc
, BCUCNT2_REG_W
);
278 printf("vrbcu: CNT2 %x: ", reg
);
281 #endif /* !defined ONLY_VR4181 */
282 #if !defined(ONLY_VR4181) || !defined(ONLY_VR4122_4131)
283 if (cpuid
!= BCUREVID_FIXRID_4181
284 && cpuid
<= BCUREVID_RID_4121
285 && cpuid
>= BCUREVID_RID_4102
) {
286 reg
= vrbcu_read(sc
, BCUSPEED_REG_W
);
287 printf("vrbcu: SPEED %x: ", reg
);
289 reg
= vrbcu_read(sc
, BCUERRST_REG_W
);
290 printf("vrbcu: ERRST %x: ", reg
);
292 reg
= vrbcu_read(sc
, BCURFCNT_REG_W
);
293 printf("vrbcu: RFCNT %x\n", reg
);
294 reg
= vrbcu_read(sc
, BCUREFCOUNT_REG_W
);
295 printf("vrbcu: RFCOUNT %x\n", reg
);
297 #endif /* !defined(ONLY_VR4181) || !defined(ONLY_VR4122_4131) */
298 #if !defined(ONLY_VR4181)
299 if (cpuid
!= BCUREVID_FIXRID_4181
300 && cpuid
<= BCUREVID_RID_4131
301 && cpuid
>= BCUREVID_RID_4111
)
303 reg
= vrbcu_read(sc
, BCUCNT3_REG_W
);
304 printf("vrbcu: CNT3 %x: ", reg
);
307 #endif /* !defined ONLY_VR4181 */
308 #endif /* VRBCUDEBUG */
312 static const char *cpuname
[] = {
329 "VR4181", /* 0x10 + 0 */
333 vrbcu_vrip_getcpuid(void)
335 volatile u_int16_t
*revreg
;
340 if (vr_cpuid
== -1) {
341 if (vrbcu_addr() == VR4181_BCU_ADDR
)
342 revreg
= (u_int16_t
*)MIPS_PHYS_TO_KSEG1
343 ((vrbcu_addr() + BCU81REVID_REG_W
));
345 revreg
= (u_int16_t
*)MIPS_PHYS_TO_KSEG1
346 ((vrbcu_addr() + BCUREVID_REG_W
));
349 vr_cpuid
= (vr_cpuid
&BCUREVID_RIDMASK
)>>BCUREVID_RIDSHFT
;
350 if (vrbcu_addr() == VR4181_BCU_ADDR
351 && vr_cpuid
== BCUREVID_RID_4181
) /* conflict vr4101 */
352 vr_cpuid
= BCUREVID_FIXRID_4181
;
358 vrbcu_vrip_getcpuname(void)
362 if (vr_cpuname
!= NULL
)
365 cpuid
= vrbcu_vrip_getcpuid();
366 vr_cpuname
= cpuname
[cpuid
];
373 vrbcu_vrip_getcpumajor(void)
375 volatile u_int16_t
*revreg
;
380 revreg
= (u_int16_t
*)MIPS_PHYS_TO_KSEG1
381 ((vrbcu_addr() + BCUREVID_REG_W
));
384 vr_major
= (vr_major
&BCUREVID_MJREVMASK
)>>BCUREVID_MJREVSHFT
;
390 vrbcu_vrip_getcpuminor(void)
392 volatile u_int16_t
*revreg
;
397 revreg
= (u_int16_t
*)MIPS_PHYS_TO_KSEG1
398 ((vrbcu_addr() + BCUREVID_REG_W
));
401 vr_minor
= (vr_minor
&BCUREVID_MNREVMASK
)>>BCUREVID_MNREVSHFT
;
406 #define CLKX 18432000 /* CLKX1,CLKX2: 18.432MHz */
410 vrbcu_vrip_getcpuclock(void)
415 cpuid
= vrbcu_vrip_getcpuid();
416 if (cpuid
!= BCUREVID_FIXRID_4181
&& cpuid
>= BCUREVID_RID_4111
) {
417 clksp
= *(u_int16_t
*)MIPS_PHYS_TO_KSEG1
418 ((vrbcu_addr() + BCUCLKSPEED_REG_W
)) &
419 BCUCLKSPEED_CLKSPMASK
;
420 } else if (cpuid
== BCUREVID_FIXRID_4181
) {
421 clksp
= *(u_int16_t
*)MIPS_PHYS_TO_KSEG1
422 ((vrbcu_addr() + BCU81CLKSPEED_REG_W
)) &
423 BCUCLKSPEED_CLKSPMASK
;
427 case BCUREVID_FIXRID_4181
:
428 cpuclock
= CLKX
/ clksp
* 64;
429 /* branch delay is 1 clock; 2 clock/loop */
430 cpuspeed
= (cpuclock
/ 2 + MHZ
/ 2) / MHZ
;
432 case BCUREVID_RID_4101
:
435 /* branch delay is 1 clock; 2 clock/loop */
436 cpuspeed
= (cpuclock
/ 2 + MHZ
/ 2) / MHZ
;
438 case BCUREVID_RID_4102
:
439 cpuclock
= CLKX
/ clksp
* 32;
440 /* branch delay is 1 clock; 2 clock/loop */
441 cpuspeed
= (cpuclock
/ 2 + MHZ
/ 2) / MHZ
;
443 case BCUREVID_RID_4111
:
444 cpuclock
= CLKX
/ clksp
* 64;
445 /* branch delay is 1 clock; 2 clock/loop */
446 cpuspeed
= (cpuclock
/ 2 + MHZ
/ 2) / MHZ
;
448 case BCUREVID_RID_4121
:
449 cpuclock
= CLKX
/ clksp
* 64;
450 /* branch delay is 2 clock; 3 clock/loop */
451 cpuspeed
= (cpuclock
/ 3 + MHZ
/ 2) / MHZ
;
453 case BCUREVID_RID_4122
:
454 cpuclock
= CLKX
/ clksp
* 98;
455 /* branch delay is 2 clock; 3 clock/loop */
456 cpuspeed
= (cpuclock
/ 3 + MHZ
/ 2) / MHZ
;
458 case BCUREVID_RID_4131
:
459 cpuclock
= CLKX
/ clksp
* 98;
460 /* branch delay is 2 clock; 3 clock/loop */
461 cpuspeed
= (cpuclock
/ 3 + MHZ
/ 2) / MHZ
;
464 panic("unknown CPU type %d", cpuid
);