Subject: kern/16118: Some bugfixes/enhancements for the lm7x driver
To: None <gnats-bugs@gnats.netbsd.org>
From: None <Thilo.Manske@HEH.Uni-Oldenburg.DE>
List: netbsd-bugs
Date: 03/29/2002 22:35:17
>Number: 16118
>Category: kern
>Synopsis: Some bufixes/enhancements for the lm8x driver
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Mar 29 13:36:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Thilo Manske
>Release: NetBSD 1.5ZC
>Organization:
Dies ist Thilos Unix Signature! Viel Spass damit.
>Environment:
System: NetBSD WintelKiller 1.5ZC NetBSD 1.5ZC (WintelKiller) #341: Fri Mar 29 17:38:25 MET 2002 thilo@WintelKiller:/usr/src/sys/arch/i386/compile/WintelKiller i386
Architecture: i386
Machine: i386
>Description:
There are several bugs with our current lm7x driver treating fan sensors:
1. for hardware monitors which use the generic_streinfo routines setting
any of the nominal fan speeds (with ENVSYS_STREINFO) will result in setting
FAN2's divisor (mixing fan number with sensor number in the code)
2. the Winbond 83781D does have a programmable divisor for FAN3 unlike generic lm
sensors (and thus needs special treatment)
3. the nominal RPMs will never be set anywhere?!?
4. a bug/typo in the code for setting FAN3's divisor for W83782 type
hardware monitors
>How-To-Repeat:
>Fix:
Index: nslm7x.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/nslm7x.c,v
retrieving revision 1.13
diff -c -u -r1.13 nslm7x.c
--- nslm7x.c 2001/11/13 13:14:42 1.13
+++ nslm7x.c 2002/03/29 21:17:24
@@ -103,6 +103,7 @@
static void wb_svolt __P((struct lm_softc *));
static void wb_stemp __P((struct lm_softc *, struct envsys_tre_data *, int));
+static void wb781_fanrpm __P((struct lm_softc *, struct envsys_tre_data *));
static void wb_fanrpm __P((struct lm_softc *, struct envsys_tre_data *));
void wb781_refresh_sensor_data __P((struct lm_softc *));
@@ -467,12 +468,15 @@
/* FAN1 and FAN2 can have divisors set, but not FAN3 */
if ((sc->info[binfo->sensor].units == ENVSYS_SFANRPM)
- && (binfo->sensor != 2)) {
+ && (n < 2)) {
if (binfo->rpms == 0) {
binfo->validflags = 0;
return (0);
}
+ /* write back the nominal FAN speed */
+ info->rpms =binfo->rpms;
+
/* 153 is the nominal FAN speed value */
divisor = 1350000 / (binfo->rpms * 153);
@@ -491,7 +495,7 @@
* in <7:6>
*/
sdata = lm_readreg(sc, LMD_VIDFAN);
- if ( binfo->sensor == 0 ) { /* FAN1 */
+ if ( n == 0 ) { /* FAN1 */
divisor <<= 4;
sdata = (sdata & 0xCF) | divisor;
} else { /* FAN2 */
@@ -535,13 +539,53 @@
struct envsys_basic_info *binfo;
{
struct lm_softc *sc = sme->sme_cookie;
+ int divisor;
+ u_int8_t sdata;
+ int i;
if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
sc->info[binfo->sensor].rfact = binfo->rfact;
else {
if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
- generic_streinfo_fan(sc, &sc->info[binfo->sensor],
- binfo->sensor - 10, binfo);
+ if (binfo->rpms == 0) {
+ binfo->validflags = 0;
+ return (0);
+ }
+
+ /* write back the nominal FAN speed */
+ sc->info[binfo->sensor].rpms=binfo->rpms;
+
+ /* 153 is the nominal FAN speed value */
+ divisor = 1350000 / (binfo->rpms * 153);
+
+ /* ...but we need lg(divisor) */
+ for (i = 0; i < 7; i++) {
+ if (divisor <= (1 << i))
+ break;
+ }
+ divisor = i;
+
+ if (binfo->sensor == 10 || binfo->sensor == 11) {
+ /*
+ * FAN1 div is in bits <5:4>, FAN2 div
+ * is in <7:6>
+ */
+ sdata = lm_readreg(sc, LMD_VIDFAN);
+ if ( binfo->sensor == 10 ) { /* FAN1 */
+ sdata = (sdata & 0xCF) |
+ ((divisor & 0x3) << 4);
+ } else { /* FAN2 */
+ sdata = (sdata & 0x3F) |
+ ((divisor & 0x3) << 6);
+ }
+ lm_writereg(sc, LMD_VIDFAN, sdata);
+ } else {
+ /* FAN3 is in WB_PIN <7:6> */
+ sdata = lm_readreg(sc, WB_PIN);
+ sdata = (sdata & 0x3F) |
+ ((divisor & 0x3) << 6);
+ lm_writereg(sc, WB_PIN, sdata);
+ }
}
memcpy(sc->info[binfo->sensor].desc, binfo->desc,
sizeof(sc->info[binfo->sensor].desc));
@@ -572,6 +616,9 @@
return (0);
}
+ /* write back the nominal FAN speed */
+ sc->info[binfo->sensor].rpms=binfo->rpms;
+
/* 153 is the nominal FAN speed value */
divisor = 1350000 / (binfo->rpms * 153);
@@ -601,7 +648,7 @@
sdata = lm_readreg(sc, WB_PIN);
sdata = (sdata & 0x3F) |
((divisor & 0x3) << 6);
- lm_writereg(sc, LMD_VIDFAN, sdata);
+ lm_writereg(sc, WB_PIN, sdata);
}
/* Bit 2 of divisor is in WB_BANK0_FANBAT */
lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
@@ -760,6 +807,33 @@
}
static void
+wb781_fanrpm(sc, sensors)
+ struct lm_softc *sc;
+ struct envsys_tre_data *sensors;
+{
+ int i, divisor, sdata;
+ lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
+ for (i = 0; i < 3; i++) {
+ sdata = lm_readreg(sc, LMD_SENSORBASE + i + 8);
+ DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
+ if (i == 0)
+ divisor = (lm_readreg(sc, LMD_VIDFAN) >> 4) & 0x3;
+ else if (i == 1)
+ divisor = (lm_readreg(sc, LMD_VIDFAN) >> 6) & 0x3;
+ else
+ divisor = (lm_readreg(sc, WB_PIN) >> 6) & 0x3;
+
+ DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
+ if (sdata == 0xff || sdata == 0x00) {
+ sensors[i].cur.data_us = 0;
+ } else {
+ sensors[i].cur.data_us = 1350000 /
+ (sdata << divisor);
+ }
+ }
+}
+
+static void
wb_fanrpm(sc, sensors)
struct lm_softc *sc;
struct envsys_tre_data *sensors;
@@ -798,7 +872,7 @@
lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
wb_stemp(sc, &sc->sensors[7], 3);
lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
- generic_fanrpm(sc, &sc->sensors[10]);
+ wb781_fanrpm(sc, &sc->sensors[10]);
}
void
>Release-Note:
>Audit-Trail:
>Unformatted: