1e3ff9bd7SConstantine A. Murenin /* $OpenBSD: lm78.c,v 1.20 2007/06/25 22:50:18 cnst Exp $ */
2e3ff9bd7SConstantine A. Murenin
31d03db02SHasso Tepper /*
41d03db02SHasso Tepper * Copyright (c) 2005, 2006 Mark Kettenis
51d03db02SHasso Tepper * Copyright (c) 2006, 2007 Constantine A. Murenin
61d03db02SHasso Tepper *
71d03db02SHasso Tepper * Permission to use, copy, modify, and distribute this software for any
81d03db02SHasso Tepper * purpose with or without fee is hereby granted, provided that the above
91d03db02SHasso Tepper * copyright notice and this permission notice appear in all copies.
101d03db02SHasso Tepper *
111d03db02SHasso Tepper * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
121d03db02SHasso Tepper * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
131d03db02SHasso Tepper * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
141d03db02SHasso Tepper * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
151d03db02SHasso Tepper * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
161d03db02SHasso Tepper * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
171d03db02SHasso Tepper * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
181d03db02SHasso Tepper */
191d03db02SHasso Tepper
201d03db02SHasso Tepper #include <sys/param.h>
211d03db02SHasso Tepper #include <sys/systm.h>
221d03db02SHasso Tepper #include <sys/bus.h>
231d03db02SHasso Tepper #include <sys/sensors.h>
241d03db02SHasso Tepper
251d03db02SHasso Tepper #include "lm78var.h"
26*1d3c4164SMatthew Dillon #include "../wbsio/wbsioreg.h"
271d03db02SHasso Tepper
281d03db02SHasso Tepper #if defined(LMDEBUG)
296ab5c081SSascha Wildner #define DPRINTF(x) do { kprintf x; } while (0)
301d03db02SHasso Tepper #else
311d03db02SHasso Tepper #define DPRINTF(x)
321d03db02SHasso Tepper #endif
331d03db02SHasso Tepper
341d03db02SHasso Tepper /*
351d03db02SHasso Tepper * LM78-compatible chips can typically measure voltages up to 4.096 V.
361d03db02SHasso Tepper * To measure higher voltages the input is attenuated with (external)
371d03db02SHasso Tepper * resistors. Negative voltages are measured using inverting op amps
381d03db02SHasso Tepper * and resistors. So we have to convert the sensor values back to
391d03db02SHasso Tepper * real voltages by applying the appropriate resistor factor.
401d03db02SHasso Tepper */
411d03db02SHasso Tepper #define RFACT_NONE 10000
421d03db02SHasso Tepper #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
431d03db02SHasso Tepper #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
441d03db02SHasso Tepper
451d03db02SHasso Tepper int lm_match(struct lm_softc *);
461d03db02SHasso Tepper int wb_match(struct lm_softc *);
471d03db02SHasso Tepper int def_match(struct lm_softc *);
481d03db02SHasso Tepper
491d03db02SHasso Tepper void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
501d03db02SHasso Tepper void lm_refresh(void *);
511d03db02SHasso Tepper
521d03db02SHasso Tepper void lm_refresh_sensor_data(struct lm_softc *);
531d03db02SHasso Tepper void lm_refresh_volt(struct lm_softc *, int);
541d03db02SHasso Tepper void lm_refresh_temp(struct lm_softc *, int);
551d03db02SHasso Tepper void lm_refresh_fanrpm(struct lm_softc *, int);
561d03db02SHasso Tepper
571d03db02SHasso Tepper void wb_refresh_sensor_data(struct lm_softc *);
581d03db02SHasso Tepper void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
591d03db02SHasso Tepper void wb_refresh_nvolt(struct lm_softc *, int);
601d03db02SHasso Tepper void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
611d03db02SHasso Tepper void wb_refresh_temp(struct lm_softc *, int);
621d03db02SHasso Tepper void wb_refresh_fanrpm(struct lm_softc *, int);
63*1d3c4164SMatthew Dillon void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
641d03db02SHasso Tepper void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
651d03db02SHasso Tepper
661d03db02SHasso Tepper void as_refresh_temp(struct lm_softc *, int);
671d03db02SHasso Tepper
681d03db02SHasso Tepper struct lm_chip {
691d03db02SHasso Tepper int (*chip_match)(struct lm_softc *);
701d03db02SHasso Tepper };
711d03db02SHasso Tepper
721d03db02SHasso Tepper struct lm_chip lm_chips[] = {
731d03db02SHasso Tepper { wb_match },
741d03db02SHasso Tepper { lm_match },
751d03db02SHasso Tepper { def_match } /* Must be last */
761d03db02SHasso Tepper };
771d03db02SHasso Tepper
781d03db02SHasso Tepper struct lm_sensor lm78_sensors[] = {
791d03db02SHasso Tepper /* Voltage */
801d03db02SHasso Tepper { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
811d03db02SHasso Tepper { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
821d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
831d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
841d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
851d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
861d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
871d03db02SHasso Tepper
881d03db02SHasso Tepper /* Temperature */
891d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
901d03db02SHasso Tepper
911d03db02SHasso Tepper /* Fans */
921d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
931d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
941d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
951d03db02SHasso Tepper
961d03db02SHasso Tepper { NULL }
971d03db02SHasso Tepper };
981d03db02SHasso Tepper
991d03db02SHasso Tepper struct lm_sensor w83627hf_sensors[] = {
1001d03db02SHasso Tepper /* Voltage */
1011d03db02SHasso Tepper { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
1021d03db02SHasso Tepper { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
1031d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
1041d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
1051d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
1061d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
1071d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
1081d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
1091d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
1101d03db02SHasso Tepper
1111d03db02SHasso Tepper /* Temperature */
1121d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
1131d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
1141d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
1151d03db02SHasso Tepper
1161d03db02SHasso Tepper /* Fans */
1171d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
1181d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
1191d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
1201d03db02SHasso Tepper
1211d03db02SHasso Tepper { NULL }
1221d03db02SHasso Tepper };
1231d03db02SHasso Tepper
1241d03db02SHasso Tepper /*
1251d03db02SHasso Tepper * The W83627EHF can measure voltages up to 2.048 V instead of the
1261d03db02SHasso Tepper * traditional 4.096 V. For measuring positive voltages, this can be
1271d03db02SHasso Tepper * accounted for by halving the resistor factor. Negative voltages
1281d03db02SHasso Tepper * need special treatment, also because the reference voltage is 2.048 V
1291d03db02SHasso Tepper * instead of the traditional 3.6 V.
1301d03db02SHasso Tepper */
1311d03db02SHasso Tepper struct lm_sensor w83627ehf_sensors[] = {
1321d03db02SHasso Tepper /* Voltage */
1331d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
1341d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
1351d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
1361d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
1371d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
1381d03db02SHasso Tepper { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
1391d03db02SHasso Tepper { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
1401d03db02SHasso Tepper { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
1411d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
1421d03db02SHasso Tepper { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
1431d03db02SHasso Tepper
1441d03db02SHasso Tepper /* Temperature */
1451d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
1461d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
1471d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
1481d03db02SHasso Tepper
1491d03db02SHasso Tepper /* Fans */
1501d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
1511d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
1521d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
1531d03db02SHasso Tepper
1541d03db02SHasso Tepper { NULL }
1551d03db02SHasso Tepper };
1561d03db02SHasso Tepper
1571d03db02SHasso Tepper /*
1581d03db02SHasso Tepper * w83627dhg is almost identical to w83627ehf, except that
1591d03db02SHasso Tepper * it has 9 instead of 10 voltage sensors
1601d03db02SHasso Tepper */
1611d03db02SHasso Tepper struct lm_sensor w83627dhg_sensors[] = {
1621d03db02SHasso Tepper /* Voltage */
1631d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
1641d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
1651d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
1661d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
1671d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
1681d03db02SHasso Tepper { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
1691d03db02SHasso Tepper { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
1701d03db02SHasso Tepper { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
1711d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
1721d03db02SHasso Tepper
1731d03db02SHasso Tepper /* Temperature */
1741d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
1751d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
1761d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
1771d03db02SHasso Tepper
1781d03db02SHasso Tepper /* Fans */
1791d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
1801d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
1811d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
1821d03db02SHasso Tepper
1831d03db02SHasso Tepper { NULL }
1841d03db02SHasso Tepper };
1851d03db02SHasso Tepper
186*1d3c4164SMatthew Dillon struct lm_sensor nct6776f_sensors[] = {
187*1d3c4164SMatthew Dillon /* Voltage */
188*1d3c4164SMatthew Dillon { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
189*1d3c4164SMatthew Dillon { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
190*1d3c4164SMatthew Dillon { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
191*1d3c4164SMatthew Dillon { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
192*1d3c4164SMatthew Dillon { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
193*1d3c4164SMatthew Dillon { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
194*1d3c4164SMatthew Dillon { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
195*1d3c4164SMatthew Dillon { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
196*1d3c4164SMatthew Dillon { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
197*1d3c4164SMatthew Dillon
198*1d3c4164SMatthew Dillon /* Temperature */
199*1d3c4164SMatthew Dillon { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
200*1d3c4164SMatthew Dillon { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
201*1d3c4164SMatthew Dillon { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
202*1d3c4164SMatthew Dillon
203*1d3c4164SMatthew Dillon /* Fans */
204*1d3c4164SMatthew Dillon { "", SENSOR_FANRPM, 6, 0x56, wb_nct6776f_refresh_fanrpm },
205*1d3c4164SMatthew Dillon { "", SENSOR_FANRPM, 6, 0x58, wb_nct6776f_refresh_fanrpm },
206*1d3c4164SMatthew Dillon { "", SENSOR_FANRPM, 6, 0x5a, wb_nct6776f_refresh_fanrpm },
207*1d3c4164SMatthew Dillon { "", SENSOR_FANRPM, 6, 0x5c, wb_nct6776f_refresh_fanrpm },
208*1d3c4164SMatthew Dillon { "", SENSOR_FANRPM, 6, 0x5e, wb_nct6776f_refresh_fanrpm },
209*1d3c4164SMatthew Dillon
210*1d3c4164SMatthew Dillon { NULL }
211*1d3c4164SMatthew Dillon };
212*1d3c4164SMatthew Dillon
2131d03db02SHasso Tepper struct lm_sensor w83637hf_sensors[] = {
2141d03db02SHasso Tepper /* Voltage */
2151d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
2161d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
2171d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
2181d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
2191d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
2201d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
2211d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
2221d03db02SHasso Tepper
2231d03db02SHasso Tepper /* Temperature */
2241d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
2251d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
2261d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
2271d03db02SHasso Tepper
2281d03db02SHasso Tepper /* Fans */
2291d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
2301d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
2311d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
2321d03db02SHasso Tepper
2331d03db02SHasso Tepper { NULL }
2341d03db02SHasso Tepper };
2351d03db02SHasso Tepper
2361d03db02SHasso Tepper struct lm_sensor w83697hf_sensors[] = {
2371d03db02SHasso Tepper /* Voltage */
2381d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
2391d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
2401d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
2411d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
2421d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
2431d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
2441d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
2451d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
2461d03db02SHasso Tepper
2471d03db02SHasso Tepper /* Temperature */
2481d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
2491d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
2501d03db02SHasso Tepper
2511d03db02SHasso Tepper /* Fans */
2521d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
2531d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
2541d03db02SHasso Tepper
2551d03db02SHasso Tepper { NULL }
2561d03db02SHasso Tepper };
2571d03db02SHasso Tepper
2581d03db02SHasso Tepper /*
2591d03db02SHasso Tepper * The datasheet doesn't mention the (internal) resistors used for the
2601d03db02SHasso Tepper * +5V, but using the values from the W83782D datasheets seems to
2611d03db02SHasso Tepper * provide sensible results.
2621d03db02SHasso Tepper */
2631d03db02SHasso Tepper struct lm_sensor w83781d_sensors[] = {
2641d03db02SHasso Tepper /* Voltage */
2651d03db02SHasso Tepper { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
2661d03db02SHasso Tepper { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
2671d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
2681d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
2691d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
2701d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
2711d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
2721d03db02SHasso Tepper
2731d03db02SHasso Tepper /* Temperature */
2741d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
2751d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
2761d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
2771d03db02SHasso Tepper
2781d03db02SHasso Tepper /* Fans */
2791d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
2801d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
2811d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
2821d03db02SHasso Tepper
2831d03db02SHasso Tepper { NULL }
2841d03db02SHasso Tepper };
2851d03db02SHasso Tepper
2861d03db02SHasso Tepper struct lm_sensor w83782d_sensors[] = {
2871d03db02SHasso Tepper /* Voltage */
2881d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
2891d03db02SHasso Tepper { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
2901d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
2911d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
2921d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
2931d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
2941d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
2951d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
2961d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
2971d03db02SHasso Tepper
2981d03db02SHasso Tepper /* Temperature */
2991d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
3001d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
3011d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
3021d03db02SHasso Tepper
3031d03db02SHasso Tepper /* Fans */
3041d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
3051d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
3061d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
3071d03db02SHasso Tepper
3081d03db02SHasso Tepper { NULL }
3091d03db02SHasso Tepper };
3101d03db02SHasso Tepper
3111d03db02SHasso Tepper struct lm_sensor w83783s_sensors[] = {
3121d03db02SHasso Tepper /* Voltage */
3131d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
3141d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
3151d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
3161d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
3171d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
3181d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
3191d03db02SHasso Tepper
3201d03db02SHasso Tepper /* Temperature */
3211d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
3221d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
3231d03db02SHasso Tepper
3241d03db02SHasso Tepper /* Fans */
3251d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
3261d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
3271d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
3281d03db02SHasso Tepper
3291d03db02SHasso Tepper { NULL }
3301d03db02SHasso Tepper };
3311d03db02SHasso Tepper
3321d03db02SHasso Tepper struct lm_sensor w83791d_sensors[] = {
3331d03db02SHasso Tepper /* Voltage */
3341d03db02SHasso Tepper { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
3351d03db02SHasso Tepper { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
3361d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
3371d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
3381d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
3391d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
3401d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
3411d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
3421d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
3431d03db02SHasso Tepper { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
3441d03db02SHasso Tepper
3451d03db02SHasso Tepper /* Temperature */
3461d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
3471d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
3481d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
3491d03db02SHasso Tepper
3501d03db02SHasso Tepper /* Fans */
3511d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
3521d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
3531d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
3541d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
3551d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
3561d03db02SHasso Tepper
3571d03db02SHasso Tepper { NULL }
3581d03db02SHasso Tepper };
3591d03db02SHasso Tepper
3601d03db02SHasso Tepper struct lm_sensor w83792d_sensors[] = {
3611d03db02SHasso Tepper /* Voltage */
3621d03db02SHasso Tepper { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
3631d03db02SHasso Tepper { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
3641d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
3651d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
3661d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
3671d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
3681d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
3691d03db02SHasso Tepper { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
3701d03db02SHasso Tepper { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
3711d03db02SHasso Tepper
3721d03db02SHasso Tepper /* Temperature */
3731d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
3741d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
3751d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
3761d03db02SHasso Tepper
3771d03db02SHasso Tepper /* Fans */
3781d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
3791d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
3801d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
3811d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
3821d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
3831d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
3841d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
3851d03db02SHasso Tepper
3861d03db02SHasso Tepper { NULL }
3871d03db02SHasso Tepper };
3881d03db02SHasso Tepper
3891d03db02SHasso Tepper struct lm_sensor as99127f_sensors[] = {
3901d03db02SHasso Tepper /* Voltage */
3911d03db02SHasso Tepper { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
3921d03db02SHasso Tepper { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
3931d03db02SHasso Tepper { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
3941d03db02SHasso Tepper { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
3951d03db02SHasso Tepper { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
3961d03db02SHasso Tepper { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
3971d03db02SHasso Tepper { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
3981d03db02SHasso Tepper
3991d03db02SHasso Tepper /* Temperature */
4001d03db02SHasso Tepper { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
4011d03db02SHasso Tepper { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
4021d03db02SHasso Tepper { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
4031d03db02SHasso Tepper
4041d03db02SHasso Tepper /* Fans */
4051d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
4061d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
4071d03db02SHasso Tepper { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
4081d03db02SHasso Tepper
4091d03db02SHasso Tepper { NULL }
4101d03db02SHasso Tepper };
4111d03db02SHasso Tepper
4121d03db02SHasso Tepper void
lm_probe(struct lm_softc * sc)4131d03db02SHasso Tepper lm_probe(struct lm_softc *sc)
4141d03db02SHasso Tepper {
4151d03db02SHasso Tepper int i;
4161d03db02SHasso Tepper
417c157ff7aSSascha Wildner for (i = 0; i < NELEM(lm_chips); i++)
4181d03db02SHasso Tepper if (lm_chips[i].chip_match(sc))
4191d03db02SHasso Tepper break;
4201d03db02SHasso Tepper }
4211d03db02SHasso Tepper
4221d03db02SHasso Tepper void
lm_attach(struct lm_softc * sc)4231d03db02SHasso Tepper lm_attach(struct lm_softc *sc)
4241d03db02SHasso Tepper {
4251d03db02SHasso Tepper u_int i, config;
4261d03db02SHasso Tepper
4271d03db02SHasso Tepper /* No point in doing anything if we don't have any sensors. */
4281d03db02SHasso Tepper if (sc->numsensors == 0)
4291d03db02SHasso Tepper return;
4301d03db02SHasso Tepper
4311bedd63aSSepherosa Ziehau sensor_task_register(sc, lm_refresh, 5);
4321d03db02SHasso Tepper
4331d03db02SHasso Tepper /* Start the monitoring loop */
4341d03db02SHasso Tepper config = sc->lm_readreg(sc, LM_CONFIG);
4351d03db02SHasso Tepper sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
4361d03db02SHasso Tepper
4371d03db02SHasso Tepper /* Add sensors */
4381d03db02SHasso Tepper strlcpy(sc->sensordev.xname, device_get_nameunit(sc->sc_dev),
4391d03db02SHasso Tepper sizeof(sc->sensordev.xname));
4401d03db02SHasso Tepper for (i = 0; i < sc->numsensors; ++i)
4411d03db02SHasso Tepper sensor_attach(&sc->sensordev, &sc->sensors[i]);
4421d03db02SHasso Tepper sensordev_install(&sc->sensordev);
4431d03db02SHasso Tepper }
4441d03db02SHasso Tepper
4451d03db02SHasso Tepper int
lm_detach(struct lm_softc * sc)4461d03db02SHasso Tepper lm_detach(struct lm_softc *sc)
4471d03db02SHasso Tepper {
4481d03db02SHasso Tepper int i;
4491d03db02SHasso Tepper
4501d03db02SHasso Tepper /* Remove sensors */
4511d03db02SHasso Tepper sensordev_deinstall(&sc->sensordev);
4521d03db02SHasso Tepper for (i = 0; i < sc->numsensors; i++)
4531d03db02SHasso Tepper sensor_detach(&sc->sensordev, &sc->sensors[i]);
4541d03db02SHasso Tepper
4551d03db02SHasso Tepper sensor_task_unregister(sc);
4561d03db02SHasso Tepper
4571d03db02SHasso Tepper return 0;
4581d03db02SHasso Tepper }
4591d03db02SHasso Tepper
4601d03db02SHasso Tepper int
lm_match(struct lm_softc * sc)4611d03db02SHasso Tepper lm_match(struct lm_softc *sc)
4621d03db02SHasso Tepper {
4631d03db02SHasso Tepper int chipid;
4641d03db02SHasso Tepper const char *cdesc;
4651d03db02SHasso Tepper char fulldesc[64];
4661d03db02SHasso Tepper
4671d03db02SHasso Tepper /* See if we have an LM78 or LM79. */
4681d03db02SHasso Tepper chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
4691d03db02SHasso Tepper switch(chipid) {
4701d03db02SHasso Tepper case LM_CHIPID_LM78:
4711d03db02SHasso Tepper cdesc = "LM78";
4721d03db02SHasso Tepper break;
4731d03db02SHasso Tepper case LM_CHIPID_LM78J:
4741d03db02SHasso Tepper cdesc = "LM78J";
4751d03db02SHasso Tepper break;
4761d03db02SHasso Tepper case LM_CHIPID_LM79:
4771d03db02SHasso Tepper cdesc = "LM79";
4781d03db02SHasso Tepper break;
4791d03db02SHasso Tepper case LM_CHIPID_LM81:
4801d03db02SHasso Tepper cdesc = "LM81";
4811d03db02SHasso Tepper break;
4821d03db02SHasso Tepper default:
4831d03db02SHasso Tepper return 0;
4841d03db02SHasso Tepper }
4851d03db02SHasso Tepper ksnprintf(fulldesc, sizeof(fulldesc),
4861d03db02SHasso Tepper "National Semiconductor %s Hardware Monitor", cdesc);
4871d03db02SHasso Tepper device_set_desc_copy(sc->sc_dev, fulldesc);
4881d03db02SHasso Tepper
4891d03db02SHasso Tepper lm_setup_sensors(sc, lm78_sensors);
4901d03db02SHasso Tepper sc->refresh_sensor_data = lm_refresh_sensor_data;
4911d03db02SHasso Tepper return 1;
4921d03db02SHasso Tepper }
4931d03db02SHasso Tepper
4941d03db02SHasso Tepper int
def_match(struct lm_softc * sc)4951d03db02SHasso Tepper def_match(struct lm_softc *sc)
4961d03db02SHasso Tepper {
4971d03db02SHasso Tepper int chipid;
4981d03db02SHasso Tepper char fulldesc[64];
4991d03db02SHasso Tepper
5001d03db02SHasso Tepper chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
5011d03db02SHasso Tepper ksnprintf(fulldesc, sizeof(fulldesc),
5021d03db02SHasso Tepper "unknown Hardware Monitor (ID 0x%x)", chipid);
5031d03db02SHasso Tepper device_set_desc_copy(sc->sc_dev, fulldesc);
5041d03db02SHasso Tepper
5051d03db02SHasso Tepper lm_setup_sensors(sc, lm78_sensors);
5061d03db02SHasso Tepper sc->refresh_sensor_data = lm_refresh_sensor_data;
5071d03db02SHasso Tepper return 1;
5081d03db02SHasso Tepper }
5091d03db02SHasso Tepper
5101d03db02SHasso Tepper int
wb_match(struct lm_softc * sc)5111d03db02SHasso Tepper wb_match(struct lm_softc *sc)
5121d03db02SHasso Tepper {
5131d03db02SHasso Tepper int banksel, vendid, devid;
5141d03db02SHasso Tepper const char *cdesc;
5151d03db02SHasso Tepper char desc[64];
5161d03db02SHasso Tepper char fulldesc[64];
5171d03db02SHasso Tepper
5181d03db02SHasso Tepper /* Read vendor ID */
5191d03db02SHasso Tepper banksel = sc->lm_readreg(sc, WB_BANKSEL);
5201d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
5211d03db02SHasso Tepper vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
5221d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, 0);
5231d03db02SHasso Tepper vendid |= sc->lm_readreg(sc, WB_VENDID);
5241d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, banksel);
5251d03db02SHasso Tepper DPRINTF((" winbond vend id 0x%x\n", vendid));
5261d03db02SHasso Tepper if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
5271d03db02SHasso Tepper return 0;
5281d03db02SHasso Tepper
5291d03db02SHasso Tepper /* Read device/chip ID */
5301d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
5311d03db02SHasso Tepper devid = sc->lm_readreg(sc, LM_CHIPID);
5321d03db02SHasso Tepper sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
5331d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, banksel);
5341d03db02SHasso Tepper DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
5351d03db02SHasso Tepper switch(sc->chipid) {
5361d03db02SHasso Tepper case WB_CHIPID_W83627HF:
5371d03db02SHasso Tepper cdesc = "W83627HF";
5381d03db02SHasso Tepper lm_setup_sensors(sc, w83627hf_sensors);
5391d03db02SHasso Tepper break;
5401d03db02SHasso Tepper case WB_CHIPID_W83627THF:
5411d03db02SHasso Tepper cdesc = "W83627THF";
5421d03db02SHasso Tepper lm_setup_sensors(sc, w83637hf_sensors);
5431d03db02SHasso Tepper break;
544e3ff9bd7SConstantine A. Murenin case WB_CHIPID_W83627EHF_A:
545e3ff9bd7SConstantine A. Murenin cdesc = "W83627EHF-A";
546e3ff9bd7SConstantine A. Murenin lm_setup_sensors(sc, w83627ehf_sensors);
547e3ff9bd7SConstantine A. Murenin break;
5481d03db02SHasso Tepper case WB_CHIPID_W83627EHF:
5491d03db02SHasso Tepper cdesc = "W83627EHF";
5501d03db02SHasso Tepper lm_setup_sensors(sc, w83627ehf_sensors);
5511d03db02SHasso Tepper break;
5521d03db02SHasso Tepper case WB_CHIPID_W83627DHG:
553*1d3c4164SMatthew Dillon if (sc->sioid == WBSIO_ID_NCT6776F) {
554*1d3c4164SMatthew Dillon cdesc = "NCT6776F";
555*1d3c4164SMatthew Dillon lm_setup_sensors(sc, nct6776f_sensors);
556*1d3c4164SMatthew Dillon } else {
5571d03db02SHasso Tepper cdesc = "W83627DHG";
5581d03db02SHasso Tepper lm_setup_sensors(sc, w83627dhg_sensors);
559*1d3c4164SMatthew Dillon }
5601d03db02SHasso Tepper break;
5611d03db02SHasso Tepper case WB_CHIPID_W83637HF:
5621d03db02SHasso Tepper cdesc = "W83637HF";
5631d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
5641d03db02SHasso Tepper if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
5651d03db02SHasso Tepper sc->vrm9 = 1;
5661d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, banksel);
5671d03db02SHasso Tepper lm_setup_sensors(sc, w83637hf_sensors);
5681d03db02SHasso Tepper break;
5691d03db02SHasso Tepper case WB_CHIPID_W83697HF:
5701d03db02SHasso Tepper cdesc = "W83697HF";
5711d03db02SHasso Tepper lm_setup_sensors(sc, w83697hf_sensors);
5721d03db02SHasso Tepper break;
5731d03db02SHasso Tepper case WB_CHIPID_W83781D:
5741d03db02SHasso Tepper case WB_CHIPID_W83781D_2:
5751d03db02SHasso Tepper cdesc = "W83781D";
5761d03db02SHasso Tepper lm_setup_sensors(sc, w83781d_sensors);
5771d03db02SHasso Tepper break;
5781d03db02SHasso Tepper case WB_CHIPID_W83782D:
5791d03db02SHasso Tepper cdesc = "W83782D";
5801d03db02SHasso Tepper lm_setup_sensors(sc, w83782d_sensors);
5811d03db02SHasso Tepper break;
5821d03db02SHasso Tepper case WB_CHIPID_W83783S:
5831d03db02SHasso Tepper cdesc = "W83783S";
5841d03db02SHasso Tepper lm_setup_sensors(sc, w83783s_sensors);
5851d03db02SHasso Tepper break;
5861d03db02SHasso Tepper case WB_CHIPID_W83791D:
5871d03db02SHasso Tepper cdesc = "W83791D";
5881d03db02SHasso Tepper lm_setup_sensors(sc, w83791d_sensors);
5891d03db02SHasso Tepper break;
5901d03db02SHasso Tepper case WB_CHIPID_W83791SD:
5911d03db02SHasso Tepper cdesc = "W83791SD";
5921d03db02SHasso Tepper break;
5931d03db02SHasso Tepper case WB_CHIPID_W83792D:
5941d03db02SHasso Tepper if (devid >= 0x10 && devid <= 0x29)
5951d03db02SHasso Tepper ksnprintf(desc, sizeof(desc),
5961d03db02SHasso Tepper "W83792D rev %c", 'A' + devid - 0x10);
5971d03db02SHasso Tepper else
5981d03db02SHasso Tepper ksnprintf(desc, sizeof(desc),
5991d03db02SHasso Tepper "W83792D rev 0x%x", devid);
6001d03db02SHasso Tepper cdesc = desc;
6011d03db02SHasso Tepper lm_setup_sensors(sc, w83792d_sensors);
6021d03db02SHasso Tepper break;
6031d03db02SHasso Tepper case WB_CHIPID_AS99127F:
6041d03db02SHasso Tepper if (vendid == WB_VENDID_ASUS) {
6051d03db02SHasso Tepper cdesc = "AS99127F";
6061d03db02SHasso Tepper lm_setup_sensors(sc, w83781d_sensors);
6071d03db02SHasso Tepper } else {
6081d03db02SHasso Tepper cdesc = "AS99127F rev 2";
6091d03db02SHasso Tepper lm_setup_sensors(sc, as99127f_sensors);
6101d03db02SHasso Tepper }
6111d03db02SHasso Tepper break;
6121d03db02SHasso Tepper default:
6131d03db02SHasso Tepper ksnprintf(fulldesc, sizeof(fulldesc),
6141d03db02SHasso Tepper "unknown Winbond Hardware Monitor (Chip ID 0x%x)",
6151d03db02SHasso Tepper sc->chipid);
6161d03db02SHasso Tepper device_set_desc_copy(sc->sc_dev, fulldesc);
6171d03db02SHasso Tepper /* Handle as a standard LM78. */
6181d03db02SHasso Tepper lm_setup_sensors(sc, lm78_sensors);
6191d03db02SHasso Tepper sc->refresh_sensor_data = lm_refresh_sensor_data;
6201d03db02SHasso Tepper return 1;
6211d03db02SHasso Tepper }
6221d03db02SHasso Tepper
6231d03db02SHasso Tepper if (cdesc[0] == 'W')
6241d03db02SHasso Tepper ksnprintf(fulldesc, sizeof(fulldesc),
6251d03db02SHasso Tepper "Winbond %s Hardware Monitor", cdesc);
6261d03db02SHasso Tepper else
6271d03db02SHasso Tepper ksnprintf(fulldesc, sizeof(fulldesc),
6281d03db02SHasso Tepper "ASUS %s Hardware Monitor", cdesc);
6291d03db02SHasso Tepper device_set_desc_copy(sc->sc_dev, fulldesc);
6301d03db02SHasso Tepper
6311d03db02SHasso Tepper sc->refresh_sensor_data = wb_refresh_sensor_data;
6321d03db02SHasso Tepper return 1;
6331d03db02SHasso Tepper }
6341d03db02SHasso Tepper
6351d03db02SHasso Tepper void
lm_setup_sensors(struct lm_softc * sc,struct lm_sensor * sensors)6361d03db02SHasso Tepper lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
6371d03db02SHasso Tepper {
6381d03db02SHasso Tepper int i;
6391d03db02SHasso Tepper
6401d03db02SHasso Tepper for (i = 0; sensors[i].desc; i++) {
6411d03db02SHasso Tepper sc->sensors[i].type = sensors[i].type;
6421d03db02SHasso Tepper strlcpy(sc->sensors[i].desc, sensors[i].desc,
6431d03db02SHasso Tepper sizeof(sc->sensors[i].desc));
6441d03db02SHasso Tepper sc->numsensors++;
6451d03db02SHasso Tepper }
6461d03db02SHasso Tepper sc->lm_sensors = sensors;
6471d03db02SHasso Tepper }
6481d03db02SHasso Tepper
6491d03db02SHasso Tepper void
lm_refresh(void * arg)6501d03db02SHasso Tepper lm_refresh(void *arg)
6511d03db02SHasso Tepper {
6521d03db02SHasso Tepper struct lm_softc *sc = arg;
6531d03db02SHasso Tepper
6541d03db02SHasso Tepper sc->refresh_sensor_data(sc);
6551d03db02SHasso Tepper }
6561d03db02SHasso Tepper
6571d03db02SHasso Tepper void
lm_refresh_sensor_data(struct lm_softc * sc)6581d03db02SHasso Tepper lm_refresh_sensor_data(struct lm_softc *sc)
6591d03db02SHasso Tepper {
6601d03db02SHasso Tepper int i;
6611d03db02SHasso Tepper
6621d03db02SHasso Tepper for (i = 0; i < sc->numsensors; i++)
6631d03db02SHasso Tepper sc->lm_sensors[i].refresh(sc, i);
6641d03db02SHasso Tepper }
6651d03db02SHasso Tepper
6661d03db02SHasso Tepper void
lm_refresh_volt(struct lm_softc * sc,int n)6671d03db02SHasso Tepper lm_refresh_volt(struct lm_softc *sc, int n)
6681d03db02SHasso Tepper {
6691d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
6701d03db02SHasso Tepper int data;
6711d03db02SHasso Tepper
6721d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
6731d03db02SHasso Tepper sensor->value = (data << 4);
6741d03db02SHasso Tepper sensor->value *= sc->lm_sensors[n].rfact;
6751d03db02SHasso Tepper sensor->value /= 10;
6761d03db02SHasso Tepper }
6771d03db02SHasso Tepper
6781d03db02SHasso Tepper void
lm_refresh_temp(struct lm_softc * sc,int n)6791d03db02SHasso Tepper lm_refresh_temp(struct lm_softc *sc, int n)
6801d03db02SHasso Tepper {
6811d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
6821d03db02SHasso Tepper int sdata;
6831d03db02SHasso Tepper
6841d03db02SHasso Tepper /*
6851d03db02SHasso Tepper * The data sheet suggests that the range of the temperature
6861d03db02SHasso Tepper * sensor is between -55 degC and +125 degC.
6871d03db02SHasso Tepper */
6881d03db02SHasso Tepper sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
6891d03db02SHasso Tepper if (sdata > 0x7d && sdata < 0xc9) {
6901d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
6911d03db02SHasso Tepper sensor->value = 0;
6921d03db02SHasso Tepper } else {
6931d03db02SHasso Tepper if (sdata & 0x80)
6941d03db02SHasso Tepper sdata -= 0x100;
6951d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
6961d03db02SHasso Tepper sensor->value = sdata * 1000000 + 273150000;
6971d03db02SHasso Tepper }
6981d03db02SHasso Tepper }
6991d03db02SHasso Tepper
7001d03db02SHasso Tepper void
lm_refresh_fanrpm(struct lm_softc * sc,int n)7011d03db02SHasso Tepper lm_refresh_fanrpm(struct lm_softc *sc, int n)
7021d03db02SHasso Tepper {
7031d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
7041d03db02SHasso Tepper int data, divisor = 1;
7051d03db02SHasso Tepper
7061d03db02SHasso Tepper /*
7071d03db02SHasso Tepper * We might get more accurate fan readings by adjusting the
7081d03db02SHasso Tepper * divisor, but that might interfere with APM or other SMM
7091d03db02SHasso Tepper * BIOS code reading the fan speeds.
7101d03db02SHasso Tepper */
7111d03db02SHasso Tepper
7121d03db02SHasso Tepper /* FAN3 has a fixed fan divisor. */
7131d03db02SHasso Tepper if (sc->lm_sensors[n].reg == LM_FAN1 ||
7141d03db02SHasso Tepper sc->lm_sensors[n].reg == LM_FAN2) {
7151d03db02SHasso Tepper data = sc->lm_readreg(sc, LM_VIDFAN);
7161d03db02SHasso Tepper if (sc->lm_sensors[n].reg == LM_FAN1)
7171d03db02SHasso Tepper divisor = (data >> 4) & 0x03;
7181d03db02SHasso Tepper else
7191d03db02SHasso Tepper divisor = (data >> 6) & 0x03;
7201d03db02SHasso Tepper }
7211d03db02SHasso Tepper
7221d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
7231d03db02SHasso Tepper if (data == 0xff || data == 0x00) {
7241d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
7251d03db02SHasso Tepper sensor->value = 0;
7261d03db02SHasso Tepper } else {
7271d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
7281d03db02SHasso Tepper sensor->value = 1350000 / (data << divisor);
7291d03db02SHasso Tepper }
7301d03db02SHasso Tepper }
7311d03db02SHasso Tepper
7321d03db02SHasso Tepper void
wb_refresh_sensor_data(struct lm_softc * sc)7331d03db02SHasso Tepper wb_refresh_sensor_data(struct lm_softc *sc)
7341d03db02SHasso Tepper {
7351d03db02SHasso Tepper int banksel, bank, i;
7361d03db02SHasso Tepper
7371d03db02SHasso Tepper /*
7381d03db02SHasso Tepper * Properly save and restore bank selection register.
7391d03db02SHasso Tepper */
7401d03db02SHasso Tepper
7411d03db02SHasso Tepper banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
7421d03db02SHasso Tepper for (i = 0; i < sc->numsensors; i++) {
7431d03db02SHasso Tepper if (bank != sc->lm_sensors[i].bank) {
7441d03db02SHasso Tepper bank = sc->lm_sensors[i].bank;
7451d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, bank);
7461d03db02SHasso Tepper }
7471d03db02SHasso Tepper sc->lm_sensors[i].refresh(sc, i);
7481d03db02SHasso Tepper }
7491d03db02SHasso Tepper sc->lm_writereg(sc, WB_BANKSEL, banksel);
7501d03db02SHasso Tepper }
7511d03db02SHasso Tepper
7521d03db02SHasso Tepper void
wb_w83637hf_refresh_vcore(struct lm_softc * sc,int n)7531d03db02SHasso Tepper wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
7541d03db02SHasso Tepper {
7551d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
7561d03db02SHasso Tepper int data;
7571d03db02SHasso Tepper
7581d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
7591d03db02SHasso Tepper
7601d03db02SHasso Tepper /*
7611d03db02SHasso Tepper * Depending on the voltage detection method,
7621d03db02SHasso Tepper * one of the following formulas is used:
7631d03db02SHasso Tepper * VRM8 method: value = raw * 0.016V
7641d03db02SHasso Tepper * VRM9 method: value = raw * 0.00488V + 0.70V
7651d03db02SHasso Tepper */
7661d03db02SHasso Tepper if (sc->vrm9)
7671d03db02SHasso Tepper sensor->value = (data * 4880) + 700000;
7681d03db02SHasso Tepper else
7691d03db02SHasso Tepper sensor->value = (data * 16000);
7701d03db02SHasso Tepper }
7711d03db02SHasso Tepper
7721d03db02SHasso Tepper void
wb_refresh_nvolt(struct lm_softc * sc,int n)7731d03db02SHasso Tepper wb_refresh_nvolt(struct lm_softc *sc, int n)
7741d03db02SHasso Tepper {
7751d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
7761d03db02SHasso Tepper int data;
7771d03db02SHasso Tepper
7781d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
7791d03db02SHasso Tepper sensor->value = ((data << 4) - WB_VREF);
7801d03db02SHasso Tepper sensor->value *= sc->lm_sensors[n].rfact;
7811d03db02SHasso Tepper sensor->value /= 10;
7821d03db02SHasso Tepper sensor->value += WB_VREF * 1000;
7831d03db02SHasso Tepper }
7841d03db02SHasso Tepper
7851d03db02SHasso Tepper void
wb_w83627ehf_refresh_nvolt(struct lm_softc * sc,int n)7861d03db02SHasso Tepper wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
7871d03db02SHasso Tepper {
7881d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
7891d03db02SHasso Tepper int data;
7901d03db02SHasso Tepper
7911d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
7921d03db02SHasso Tepper sensor->value = ((data << 3) - WB_W83627EHF_VREF);
7931d03db02SHasso Tepper sensor->value *= RFACT(232, 10);
7941d03db02SHasso Tepper sensor->value /= 10;
7951d03db02SHasso Tepper sensor->value += WB_W83627EHF_VREF * 1000;
7961d03db02SHasso Tepper }
7971d03db02SHasso Tepper
7981d03db02SHasso Tepper void
wb_refresh_temp(struct lm_softc * sc,int n)7991d03db02SHasso Tepper wb_refresh_temp(struct lm_softc *sc, int n)
8001d03db02SHasso Tepper {
8011d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
8021d03db02SHasso Tepper int sdata;
8031d03db02SHasso Tepper
8041d03db02SHasso Tepper /*
8051d03db02SHasso Tepper * The data sheet suggests that the range of the temperature
8061d03db02SHasso Tepper * sensor is between -55 degC and +125 degC. However, values
8071d03db02SHasso Tepper * around -48 degC seem to be a very common bogus values.
8081d03db02SHasso Tepper * Since such values are unreasonably low, we use -45 degC for
8091d03db02SHasso Tepper * the lower limit instead.
8101d03db02SHasso Tepper */
8111d03db02SHasso Tepper sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
8121d03db02SHasso Tepper sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
8131d03db02SHasso Tepper if (sdata > 0x0fa && sdata < 0x1a6) {
8141d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
8151d03db02SHasso Tepper sensor->value = 0;
8161d03db02SHasso Tepper } else {
8171d03db02SHasso Tepper if (sdata & 0x100)
8181d03db02SHasso Tepper sdata -= 0x200;
8191d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
8201d03db02SHasso Tepper sensor->value = sdata * 500000 + 273150000;
8211d03db02SHasso Tepper }
8221d03db02SHasso Tepper }
8231d03db02SHasso Tepper
8241d03db02SHasso Tepper void
wb_refresh_fanrpm(struct lm_softc * sc,int n)8251d03db02SHasso Tepper wb_refresh_fanrpm(struct lm_softc *sc, int n)
8261d03db02SHasso Tepper {
8271d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
8281d03db02SHasso Tepper int fan, data, divisor = 0;
8291d03db02SHasso Tepper
8301d03db02SHasso Tepper /*
8311d03db02SHasso Tepper * This is madness; the fan divisor bits are scattered all
8321d03db02SHasso Tepper * over the place.
8331d03db02SHasso Tepper */
8341d03db02SHasso Tepper
8351d03db02SHasso Tepper if (sc->lm_sensors[n].reg == LM_FAN1 ||
8361d03db02SHasso Tepper sc->lm_sensors[n].reg == LM_FAN2 ||
8371d03db02SHasso Tepper sc->lm_sensors[n].reg == LM_FAN3) {
8381d03db02SHasso Tepper data = sc->lm_readreg(sc, WB_BANK0_VBAT);
8391d03db02SHasso Tepper fan = (sc->lm_sensors[n].reg - LM_FAN1);
8401d03db02SHasso Tepper if ((data >> 5) & (1 << fan))
8411d03db02SHasso Tepper divisor |= 0x04;
8421d03db02SHasso Tepper }
8431d03db02SHasso Tepper
8441d03db02SHasso Tepper if (sc->lm_sensors[n].reg == LM_FAN1 ||
8451d03db02SHasso Tepper sc->lm_sensors[n].reg == LM_FAN2) {
8461d03db02SHasso Tepper data = sc->lm_readreg(sc, LM_VIDFAN);
8471d03db02SHasso Tepper if (sc->lm_sensors[n].reg == LM_FAN1)
8481d03db02SHasso Tepper divisor |= (data >> 4) & 0x03;
8491d03db02SHasso Tepper else
8501d03db02SHasso Tepper divisor |= (data >> 6) & 0x03;
8511d03db02SHasso Tepper } else if (sc->lm_sensors[n].reg == LM_FAN3) {
8521d03db02SHasso Tepper data = sc->lm_readreg(sc, WB_PIN);
8531d03db02SHasso Tepper divisor |= (data >> 6) & 0x03;
8541d03db02SHasso Tepper } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
8551d03db02SHasso Tepper sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
8561d03db02SHasso Tepper data = sc->lm_readreg(sc, WB_BANK0_FAN45);
8571d03db02SHasso Tepper if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
8581d03db02SHasso Tepper divisor |= (data >> 0) & 0x07;
8591d03db02SHasso Tepper else
8601d03db02SHasso Tepper divisor |= (data >> 4) & 0x07;
8611d03db02SHasso Tepper }
8621d03db02SHasso Tepper
8631d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
8641d03db02SHasso Tepper if (data == 0xff || data == 0x00) {
8651d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
8661d03db02SHasso Tepper sensor->value = 0;
8671d03db02SHasso Tepper } else {
8681d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
8691d03db02SHasso Tepper sensor->value = 1350000 / (data << divisor);
8701d03db02SHasso Tepper }
8711d03db02SHasso Tepper }
8721d03db02SHasso Tepper
8731d03db02SHasso Tepper void
wb_w83792d_refresh_fanrpm(struct lm_softc * sc,int n)8741d03db02SHasso Tepper wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
8751d03db02SHasso Tepper {
8761d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
8771d03db02SHasso Tepper int reg, shift, data, divisor = 1;
8781d03db02SHasso Tepper
8791d03db02SHasso Tepper switch (sc->lm_sensors[n].reg) {
8801d03db02SHasso Tepper case 0x28:
8811d03db02SHasso Tepper reg = 0x47; shift = 0;
8821d03db02SHasso Tepper break;
8831d03db02SHasso Tepper case 0x29:
8841d03db02SHasso Tepper reg = 0x47; shift = 4;
8851d03db02SHasso Tepper break;
8861d03db02SHasso Tepper case 0x2a:
8871d03db02SHasso Tepper reg = 0x5b; shift = 0;
8881d03db02SHasso Tepper break;
8891d03db02SHasso Tepper case 0xb8:
8901d03db02SHasso Tepper reg = 0x5b; shift = 4;
8911d03db02SHasso Tepper break;
8921d03db02SHasso Tepper case 0xb9:
8931d03db02SHasso Tepper reg = 0x5c; shift = 0;
8941d03db02SHasso Tepper break;
8951d03db02SHasso Tepper case 0xba:
8961d03db02SHasso Tepper reg = 0x5c; shift = 4;
8971d03db02SHasso Tepper break;
8981d03db02SHasso Tepper case 0xbe:
8991d03db02SHasso Tepper reg = 0x9e; shift = 0;
9001d03db02SHasso Tepper break;
9011d03db02SHasso Tepper default:
9021d03db02SHasso Tepper reg = 0; shift = 0;
9031d03db02SHasso Tepper break;
9041d03db02SHasso Tepper }
9051d03db02SHasso Tepper
9061d03db02SHasso Tepper data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
9071d03db02SHasso Tepper if (data == 0xff || data == 0x00) {
9081d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
9091d03db02SHasso Tepper sensor->value = 0;
9101d03db02SHasso Tepper } else {
9111d03db02SHasso Tepper if (reg != 0)
9121d03db02SHasso Tepper divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
9131d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
9141d03db02SHasso Tepper sensor->value = 1350000 / (data << divisor);
9151d03db02SHasso Tepper }
9161d03db02SHasso Tepper }
9171d03db02SHasso Tepper
9181d03db02SHasso Tepper void
wb_nct6776f_refresh_fanrpm(struct lm_softc * sc,int n)919*1d3c4164SMatthew Dillon wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n)
920*1d3c4164SMatthew Dillon {
921*1d3c4164SMatthew Dillon struct ksensor *sensor = &sc->sensors[n];
922*1d3c4164SMatthew Dillon int datah, datal;
923*1d3c4164SMatthew Dillon
924*1d3c4164SMatthew Dillon datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
925*1d3c4164SMatthew Dillon datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1);
926*1d3c4164SMatthew Dillon
927*1d3c4164SMatthew Dillon if (datah == 0xff) {
928*1d3c4164SMatthew Dillon sensor->flags |= SENSOR_FINVALID;
929*1d3c4164SMatthew Dillon sensor->value = 0;
930*1d3c4164SMatthew Dillon } else {
931*1d3c4164SMatthew Dillon sensor->flags &= ~SENSOR_FINVALID;
932*1d3c4164SMatthew Dillon sensor->value = (datah << 8) | datal;
933*1d3c4164SMatthew Dillon }
934*1d3c4164SMatthew Dillon }
935*1d3c4164SMatthew Dillon
936*1d3c4164SMatthew Dillon void
as_refresh_temp(struct lm_softc * sc,int n)9371d03db02SHasso Tepper as_refresh_temp(struct lm_softc *sc, int n)
9381d03db02SHasso Tepper {
9391d03db02SHasso Tepper struct ksensor *sensor = &sc->sensors[n];
9401d03db02SHasso Tepper int sdata;
9411d03db02SHasso Tepper
9421d03db02SHasso Tepper /*
9431d03db02SHasso Tepper * It seems a shorted temperature diode produces an all-ones
9441d03db02SHasso Tepper * bit pattern.
9451d03db02SHasso Tepper */
9461d03db02SHasso Tepper sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
9471d03db02SHasso Tepper sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
9481d03db02SHasso Tepper if (sdata == 0x1ff) {
9491d03db02SHasso Tepper sensor->flags |= SENSOR_FINVALID;
9501d03db02SHasso Tepper sensor->value = 0;
9511d03db02SHasso Tepper } else {
9521d03db02SHasso Tepper if (sdata & 0x100)
9531d03db02SHasso Tepper sdata -= 0x200;
9541d03db02SHasso Tepper sensor->flags &= ~SENSOR_FINVALID;
9551d03db02SHasso Tepper sensor->value = sdata * 500000 + 273150000;
9561d03db02SHasso Tepper }
9571d03db02SHasso Tepper }
958