version 1.17.6.4, 2005/11/10 14:04:15 |
version 1.18, 2004/04/22 00:17:11 |
Line 65 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 65 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <machine/bus.h> |
#include <machine/bus.h> |
|
|
#if defined(LMDEBUG) |
#if defined(LMDEBUG) |
#define DPRINTF(x) printf x |
#define DPRINTF(x) do { printf x; } while (0) |
#else |
#else |
#define DPRINTF(x) |
#define DPRINTF(x) |
#endif |
#endif |
Line 82 const struct envsys_range lm_ranges[] = |
|
Line 82 const struct envsys_range lm_ranges[] = |
|
}; |
}; |
|
|
|
|
static void setup_fan(struct lm_softc *, int, int); |
static void setup_fan __P((struct lm_softc *, int, int)); |
static void setup_temp(struct lm_softc *, int, int); |
static void setup_temp __P((struct lm_softc *, int, int)); |
static void wb_setup_volt(struct lm_softc *); |
static void wb_setup_volt __P((struct lm_softc *)); |
|
|
int lm_match(struct lm_softc *); |
int lm_match __P((struct lm_softc *)); |
int wb_match(struct lm_softc *); |
int wb_match __P((struct lm_softc *)); |
int itec_match(struct lm_softc *); |
int def_match __P((struct lm_softc *)); |
int def_match(struct lm_softc *); |
void lm_common_match __P((struct lm_softc *)); |
void lm_common_match(struct lm_softc *); |
static int lm_generic_banksel __P((struct lm_softc *, int)); |
static int lm_generic_banksel(struct lm_softc *, int); |
|
|
static void generic_stemp __P((struct lm_softc *, struct envsys_tre_data *)); |
static void generic_stemp(struct lm_softc *, struct envsys_tre_data *); |
static void generic_svolt __P((struct lm_softc *, struct envsys_tre_data *, |
static void generic_svolt(struct lm_softc *, struct envsys_tre_data *, |
struct envsys_basic_info *)); |
struct envsys_basic_info *); |
static void generic_fanrpm __P((struct lm_softc *, struct envsys_tre_data *)); |
static void generic_fanrpm(struct lm_softc *, struct envsys_tre_data *); |
|
|
void lm_refresh_sensor_data __P((struct lm_softc *)); |
void lm_refresh_sensor_data(struct lm_softc *); |
|
|
static void wb_svolt __P((struct lm_softc *)); |
static void wb_svolt(struct lm_softc *); |
static void wb_stemp __P((struct lm_softc *, struct envsys_tre_data *, int)); |
static void wb_stemp(struct lm_softc *, struct envsys_tre_data *, int); |
static void wb781_fanrpm __P((struct lm_softc *, struct envsys_tre_data *)); |
static void wb781_fanrpm(struct lm_softc *, struct envsys_tre_data *); |
static void wb_fanrpm __P((struct lm_softc *, struct envsys_tre_data *)); |
static void wb_fanrpm(struct lm_softc *, struct envsys_tre_data *); |
|
|
void wb781_refresh_sensor_data __P((struct lm_softc *)); |
void wb781_refresh_sensor_data(struct lm_softc *); |
void wb782_refresh_sensor_data __P((struct lm_softc *)); |
void wb782_refresh_sensor_data(struct lm_softc *); |
void wb697_refresh_sensor_data __P((struct lm_softc *)); |
void wb697_refresh_sensor_data(struct lm_softc *); |
|
|
int lm_gtredata __P((struct sysmon_envsys *, struct envsys_tre_data *)); |
static void itec_svolt(struct lm_softc *, struct envsys_tre_data *, |
|
struct envsys_basic_info *); |
int generic_streinfo_fan __P((struct lm_softc *, struct envsys_basic_info *, |
static void itec_stemp(struct lm_softc *, struct envsys_tre_data *); |
int, struct envsys_basic_info *)); |
static void itec_fanrpm(struct lm_softc *, struct envsys_tre_data *); |
int lm_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *)); |
void itec_refresh_sensor_data(struct lm_softc *); |
int wb781_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *)); |
|
int wb782_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *)); |
int lm_gtredata(struct sysmon_envsys *, struct envsys_tre_data *); |
|
|
|
int generic_streinfo_fan(struct lm_softc *, struct envsys_basic_info *, |
|
int, struct envsys_basic_info *); |
|
int lm_streinfo(struct sysmon_envsys *, struct envsys_basic_info *); |
|
int wb781_streinfo(struct sysmon_envsys *, struct envsys_basic_info *); |
|
int wb782_streinfo(struct sysmon_envsys *, struct envsys_basic_info *); |
|
int itec_streinfo(struct sysmon_envsys *, struct envsys_basic_info *); |
|
|
|
struct lm_chip { |
struct lm_chip { |
int (*chip_match)(struct lm_softc *); |
int (*chip_match) __P((struct lm_softc *)); |
}; |
}; |
|
|
struct lm_chip lm_chips[] = { |
struct lm_chip lm_chips[] = { |
{ itec_match }, |
|
{ wb_match }, |
{ wb_match }, |
{ lm_match }, |
{ lm_match }, |
{ def_match } /* Must be last */ |
{ def_match } /* Must be last */ |
Line 143 lm_generic_banksel(lmsc, bank) |
|
Line 134 lm_generic_banksel(lmsc, bank) |
|
{ |
{ |
|
|
(*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank); |
(*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank); |
return 0; |
return (0); |
} |
} |
|
|
|
|
Line 158 lm_probe(iot, ioh) |
|
Line 149 lm_probe(iot, ioh) |
|
u_int8_t cr; |
u_int8_t cr; |
int rv; |
int rv; |
|
|
/* |
|
* Check for it8705f, before we do the chip reset. |
|
* In case of an it8705f this might reset all the fan control |
|
* parameters to defaults which would void all settings done by |
|
* the BOOTROM/BIOS. |
|
*/ |
|
bus_space_write_1(iot, ioh, LMC_ADDR, ITEC_RES48); |
|
cr = bus_space_read_1(iot, ioh, LMC_DATA); |
|
|
|
if (cr == ITEC_RES48_DEFAULT) { |
|
bus_space_write_1(iot, ioh, LMC_ADDR, ITEC_RES52); |
|
cr = bus_space_read_1(iot, ioh, LMC_DATA); |
|
if (cr == ITEC_RES52_DEFAULT) |
|
return 1; |
|
} |
|
|
|
/* Check for some power-on defaults */ |
/* Check for some power-on defaults */ |
bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG); |
bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG); |
|
|
Line 185 lm_probe(iot, ioh) |
|
Line 160 lm_probe(iot, ioh) |
|
cr = bus_space_read_1(iot, ioh, LMC_DATA); |
cr = bus_space_read_1(iot, ioh, LMC_DATA); |
|
|
/* XXX - spec says *only* 0x08! */ |
/* XXX - spec says *only* 0x08! */ |
if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03)) |
if ((cr == 0x08) || (cr == 0x01)) |
rv = 1; |
rv = 1; |
else |
else |
rv = 0; |
rv = 0; |
|
|
case WB_CHIPID_83627: |
case WB_CHIPID_83627: |
printf(": W83627HF\n"); |
printf(": W83627HF\n"); |
break; |
break; |
case WB_CHIPID_83627THF: |
|
printf(": W83627THF\n"); |
|
break; |
|
default: |
default: |
printf(": unknow winbond chip ID 0x%x\n", j); |
printf(": unknow winbond chip ID 0x%x\n", j); |
/* handle as a standart lm7x */ |
/* handle as a standart lm7x */ |
Line 426 wb_setup_volt(sc) |
|
Line 398 wb_setup_volt(sc) |
|
sc->info[8].rfact = 10000; |
sc->info[8].rfact = 10000; |
} |
} |
|
|
int |
|
itec_match(sc) |
|
struct lm_softc *sc; |
|
{ |
|
int vendor, coreid; |
|
|
|
/* do the same thing as in lm_probe() */ |
|
if ((*sc->lm_readreg)(sc, ITEC_RES48) != ITEC_RES48_DEFAULT) |
|
return 0; |
|
|
|
if ((*sc->lm_readreg)(sc, ITEC_RES52) != ITEC_RES52_DEFAULT) |
|
return 0; |
|
|
|
/* We check for the core ID register (0x5B), which is available |
|
* only in the 8712F, if that fails, we check the vendor ID |
|
* register, available on 8705F and 8712F */ |
|
|
|
coreid = (*sc->lm_readreg)(sc, ITEC_COREID); |
|
|
|
if (coreid == ITEC_COREID_ITE) |
|
printf(": ITE8712F\n"); |
|
else { |
|
vendor = (*sc->lm_readreg)(sc, ITEC_VENDID); |
|
if (vendor == ITEC_VENDID_ITE) |
|
printf(": ITE8705F\n"); |
|
else |
|
printf(": unknown ITE87%02x compatible\n", vendor); |
|
} |
|
|
|
/* |
|
* XXX this is a litle bit lame... |
|
* All VIN inputs work exactly the same way, it depends of the |
|
* external wiring what voltages they monitor and which correction |
|
* factors are needed. We assume a pretty standard setup here |
|
*/ |
|
wb_setup_volt(sc); |
|
strlcpy(sc->info[0].desc, "CPU", sizeof(sc->info[0].desc)); |
|
strlcpy(sc->info[1].desc, "AGP", sizeof(sc->info[1].desc)); |
|
strlcpy(sc->info[6].desc, "+2.5V", sizeof(sc->info[6].desc)); |
|
sc->info[5].rfact = 51100; |
|
sc->info[7].rfact = 16778; |
|
|
|
setup_temp(sc, 9, 3); |
|
setup_fan(sc, 12, 3); |
|
sc->numsensors = ITEC_NUM_SENSORS; |
|
sc->refresh_sensor_data = itec_refresh_sensor_data; |
|
sc->sc_sysmon.sme_streinfo = itec_streinfo; |
|
|
|
return 1; |
|
} |
|
|
|
|
|
static void |
static void |
setup_temp(sc, start, n) |
setup_temp(sc, start, n) |
struct lm_softc *sc; |
struct lm_softc *sc; |
Line 532 lm_gtredata(sme, tred) |
|
Line 452 lm_gtredata(sme, tred) |
|
|
|
*tred = sc->sensors[tred->sensor]; |
*tred = sc->sensors[tred->sensor]; |
|
|
return 0; |
return (0); |
} |
} |
|
|
int |
int |
Line 550 generic_streinfo_fan(sc, info, n, binfo) |
|
Line 470 generic_streinfo_fan(sc, info, n, binfo) |
|
&& (n < 2)) { |
&& (n < 2)) { |
if (binfo->rpms == 0) { |
if (binfo->rpms == 0) { |
binfo->validflags = 0; |
binfo->validflags = 0; |
return 0; |
return (0); |
} |
} |
|
|
/* write back the nominal FAN speed */ |
/* write back the nominal FAN speed */ |
Line 584 generic_streinfo_fan(sc, info, n, binfo) |
|
Line 504 generic_streinfo_fan(sc, info, n, binfo) |
|
|
|
(*sc->lm_writereg)(sc, LMD_VIDFAN, sdata); |
(*sc->lm_writereg)(sc, LMD_VIDFAN, sdata); |
} |
} |
return 0; |
return (0); |
|
|
} |
} |
|
|
Line 602 lm_streinfo(sme, binfo) |
|
Line 522 lm_streinfo(sme, binfo) |
|
generic_streinfo_fan(sc, &sc->info[binfo->sensor], |
generic_streinfo_fan(sc, &sc->info[binfo->sensor], |
binfo->sensor - 8, binfo); |
binfo->sensor - 8, binfo); |
} |
} |
strlcpy(sc->info[binfo->sensor].desc, binfo->desc, |
memcpy(sc->info[binfo->sensor].desc, binfo->desc, |
sizeof(sc->info[binfo->sensor].desc)); |
sizeof(sc->info[binfo->sensor].desc)); |
|
sc->info[binfo->sensor].desc[ |
|
sizeof(sc->info[binfo->sensor].desc) - 1] = '\0'; |
|
|
binfo->validflags = ENVSYS_FVALID; |
binfo->validflags = ENVSYS_FVALID; |
} |
} |
return 0; |
return (0); |
} |
} |
|
|
int |
int |
Line 625 wb781_streinfo(sme, binfo) |
|
Line 548 wb781_streinfo(sme, binfo) |
|
if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) { |
if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) { |
if (binfo->rpms == 0) { |
if (binfo->rpms == 0) { |
binfo->validflags = 0; |
binfo->validflags = 0; |
return 0; |
return (0); |
} |
} |
|
|
/* write back the nominal FAN speed */ |
/* write back the nominal FAN speed */ |
Line 663 wb781_streinfo(sme, binfo) |
|
Line 586 wb781_streinfo(sme, binfo) |
|
(*sc->lm_writereg)(sc, WB_PIN, sdata); |
(*sc->lm_writereg)(sc, WB_PIN, sdata); |
} |
} |
} |
} |
strlcpy(sc->info[binfo->sensor].desc, binfo->desc, |
memcpy(sc->info[binfo->sensor].desc, binfo->desc, |
sizeof(sc->info[binfo->sensor].desc)); |
sizeof(sc->info[binfo->sensor].desc)); |
|
sc->info[binfo->sensor].desc[ |
|
sizeof(sc->info[binfo->sensor].desc) - 1] = '\0'; |
|
|
binfo->validflags = ENVSYS_FVALID; |
binfo->validflags = ENVSYS_FVALID; |
} |
} |
return 0; |
return (0); |
} |
} |
|
|
int |
int |
Line 686 wb782_streinfo(sme, binfo) |
|
Line 612 wb782_streinfo(sme, binfo) |
|
if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) { |
if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) { |
if (binfo->rpms == 0) { |
if (binfo->rpms == 0) { |
binfo->validflags = 0; |
binfo->validflags = 0; |
return 0; |
return (0); |
} |
} |
|
|
/* write back the nominal FAN speed */ |
/* write back the nominal FAN speed */ |
Line 731 wb782_streinfo(sme, binfo) |
|
Line 657 wb782_streinfo(sme, binfo) |
|
(*sc->lm_writereg)(sc, WB_BANK0_FANBAT, sdata); |
(*sc->lm_writereg)(sc, WB_BANK0_FANBAT, sdata); |
} |
} |
|
|
strlcpy(sc->info[binfo->sensor].desc, binfo->desc, |
memcpy(sc->info[binfo->sensor].desc, binfo->desc, |
sizeof(sc->info[binfo->sensor].desc)); |
sizeof(sc->info[binfo->sensor].desc)); |
binfo->validflags = ENVSYS_FVALID; |
sc->info[binfo->sensor].desc[ |
} |
sizeof(sc->info[binfo->sensor].desc) - 1] = '\0'; |
return 0; |
|
} |
|
|
|
int |
|
itec_streinfo(sme, binfo) |
|
struct sysmon_envsys *sme; |
|
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) { |
|
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; |
|
|
|
sdata = (*sc->lm_readreg)(sc, ITEC_FANDIV); |
|
/* |
|
* FAN1 div is in bits <0:2>, FAN2 is in <3:5> |
|
* FAN3 is in <6>, if set divisor is 8, else 2 |
|
*/ |
|
if ( binfo->sensor == 10 ) { /* FAN1 */ |
|
sdata = (sdata & 0xf8) | divisor; |
|
} else if ( binfo->sensor == 11 ) { /* FAN2 */ |
|
sdata = (sdata & 0xc7) | divisor << 3; |
|
} else { /* FAN3 */ |
|
if (divisor>2) |
|
sdata = sdata & 0xbf; |
|
else |
|
sdata = sdata | 0x40; |
|
} |
|
(*sc->lm_writereg)(sc, ITEC_FANDIV, sdata); |
|
} |
|
strlcpy(sc->info[binfo->sensor].desc, binfo->desc, |
|
sizeof(sc->info[binfo->sensor].desc)); |
|
binfo->validflags = ENVSYS_FVALID; |
binfo->validflags = ENVSYS_FVALID; |
} |
} |
return 0; |
return (0); |
} |
} |
|
|
static void |
static void |
Line 1026 wb697_refresh_sensor_data(sc) |
|
Line 899 wb697_refresh_sensor_data(sc) |
|
wb_stemp(sc, &sc->sensors[9], 2); |
wb_stemp(sc, &sc->sensors[9], 2); |
wb_fanrpm(sc, &sc->sensors[11]); |
wb_fanrpm(sc, &sc->sensors[11]); |
} |
} |
|
|
static void |
|
itec_svolt(sc, sensors, infos) |
|
struct lm_softc *sc; |
|
struct envsys_tre_data *sensors; |
|
struct envsys_basic_info *infos; |
|
{ |
|
int i, sdata; |
|
|
|
for (i = 0; i < 9; i++) { |
|
sdata = (*sc->lm_readreg)(sc, ITEC_VIN0 + i); |
|
DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata)); |
|
/* voltage returned as (mV >> 4), we convert to uVDC */ |
|
sensors[i].cur.data_s = ( sdata << 4 ); |
|
/* rfact is (factor * 10^4) */ |
|
|
|
sensors[i].cur.data_s *= infos[i].rfact; |
|
/* |
|
* XXX We assume input 5 is wired the way iTE suggests to |
|
* monitor a negative voltage. I'd prefer using negative rfacts |
|
* for detecting those cases but since rfact is an u_int this |
|
* isn't possible. |
|
*/ |
|
if (i == 5) |
|
sensors[i].cur.data_s -= |
|
(infos[i].rfact - 10000) * ITEC_VREF; |
|
/* division by 10 gets us back to uVDC */ |
|
sensors[i].cur.data_s /= 10; |
|
} |
|
} |
|
|
|
static void |
|
itec_stemp(sc, sensors) |
|
struct lm_softc *sc; |
|
struct envsys_tre_data *sensors; |
|
{ |
|
int i, sdata; |
|
|
|
/* temperatures. Given in dC, we convert to uK */ |
|
for (i = 0; i < 3; i++) { |
|
sdata = (*sc->lm_readreg)(sc, ITEC_TEMP1 + i); |
|
DPRINTF(("sdata[temp%d] 0x%x\n",i, sdata)); |
|
sensors[i].cur.data_us = sdata * 1000000 + 273150000; |
|
} |
|
} |
|
|
|
static void |
|
itec_fanrpm(sc, sensors) |
|
struct lm_softc *sc; |
|
struct envsys_tre_data *sensors; |
|
{ |
|
int i, fandiv, divisor, sdata; |
|
(*sc->lm_banksel)(sc, 0); |
|
fandiv = ((*sc->lm_readreg)(sc, ITEC_FANDIV)); |
|
|
|
for (i = 0; i < 3; i++) { |
|
sdata = (*sc->lm_readreg)(sc, ITEC_FAN1 + i); |
|
DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata)); |
|
switch (i) { |
|
case 0: |
|
divisor = fandiv & 0x7; |
|
break; |
|
case 1: |
|
divisor = (fandiv >> 3) & 0x7; |
|
break; |
|
case 2: |
|
default: /* XXX */ |
|
divisor = (fandiv & 0x40) ? 3 : 1; |
|
break; |
|
} |
|
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); |
|
} |
|
} |
|
|
|
} |
|
|
|
void |
|
itec_refresh_sensor_data(sc) |
|
struct lm_softc *sc; |
|
{ |
|
itec_svolt(sc, &sc->sensors[0], &sc->info[0]); |
|
itec_stemp(sc, &sc->sensors[9]); |
|
itec_fanrpm(sc, &sc->sensors[12]); |
|
} |
|