The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/lm78.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: lm78.c,v 1.26 2022/04/08 15:02:28 naddy Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2005, 2006 Mark Kettenis
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/device.h>
   22 #include <sys/kernel.h>
   23 #include <sys/queue.h>
   24 #include <sys/sensors.h>
   25 
   26 #include <dev/ic/lm78var.h>
   27 #include <dev/isa/wbsioreg.h>
   28 
   29 #if defined(LMDEBUG)
   30 #define DPRINTF(x)              do { printf x; } while (0)
   31 #else
   32 #define DPRINTF(x)
   33 #endif
   34 
   35 /*
   36  * LM78-compatible chips can typically measure voltages up to 4.096 V.
   37  * To measure higher voltages the input is attenuated with (external)
   38  * resistors.  Negative voltages are measured using inverting op amps
   39  * and resistors.  So we have to convert the sensor values back to
   40  * real voltages by applying the appropriate resistor factor.
   41  */
   42 #define RFACT_NONE      10000
   43 #define RFACT(x, y)     (RFACT_NONE * ((x) + (y)) / (y))
   44 #define NRFACT(x, y)    (-RFACT_NONE * (x) / (y))
   45 
   46 struct cfdriver lm_cd = {
   47         NULL, "lm", DV_DULL
   48 };
   49 
   50 int  lm_match(struct lm_softc *);
   51 int  wb_match(struct lm_softc *);
   52 int  def_match(struct lm_softc *);
   53 
   54 void lm_setup_sensors(struct lm_softc *, const struct lm_sensor *);
   55 void lm_refresh(void *);
   56 
   57 void lm_refresh_sensor_data(struct lm_softc *);
   58 void lm_refresh_volt(struct lm_softc *, int);
   59 void lm_refresh_temp(struct lm_softc *, int);
   60 void lm_refresh_fanrpm(struct lm_softc *, int);
   61 
   62 void wb_refresh_sensor_data(struct lm_softc *);
   63 void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
   64 void wb_refresh_nvolt(struct lm_softc *, int);
   65 void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
   66 void wb_refresh_temp(struct lm_softc *, int);
   67 void wb_refresh_fanrpm(struct lm_softc *, int);
   68 void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
   69 void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
   70 
   71 void as_refresh_temp(struct lm_softc *, int);
   72 
   73 struct lm_chip {
   74         int (*chip_match)(struct lm_softc *);
   75 };
   76 
   77 const struct lm_chip lm_chips[] = {
   78         { wb_match },
   79         { lm_match },
   80         { def_match } /* Must be last */
   81 };
   82 
   83 const struct lm_sensor lm78_sensors[] = {
   84         /* Voltage */
   85         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
   86         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
   87         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
   88         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
   89         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
   90         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
   91         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
   92 
   93         /* Temperature */
   94         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
   95 
   96         /* Fans */
   97         { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
   98         { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
   99         { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
  100 
  101         { NULL }
  102 };
  103 
  104 const struct lm_sensor w83627hf_sensors[] = {
  105         /* Voltage */
  106         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  107         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
  108         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  109         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  110         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  111         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  112         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  113         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
  114         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
  115 
  116         /* Temperature */
  117         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  118         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  119         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  120 
  121         /* Fans */
  122         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  123         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  124         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  125 
  126         { NULL }
  127 };
  128 
  129 /*
  130  * The W83627EHF can measure voltages up to 2.048 V instead of the
  131  * traditional 4.096 V.  For measuring positive voltages, this can be
  132  * accounted for by halving the resistor factor.  Negative voltages
  133  * need special treatment, also because the reference voltage is 2.048 V
  134  * instead of the traditional 3.6 V.
  135  */
  136 const struct lm_sensor w83627ehf_sensors[] = {
  137         /* Voltage */
  138         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
  139         { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
  140         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
  141         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
  142         { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
  143         { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
  144         { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
  145         { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
  146         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
  147         { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
  148 
  149         /* Temperature */
  150         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  151         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  152         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  153 
  154         /* Fans */
  155         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  156         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  157         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  158 
  159         { NULL }
  160 };
  161 
  162 /* 
  163  * w83627dhg is almost identical to w83627ehf, except that 
  164  * it has 9 instead of 10 voltage sensors
  165  */
  166 const struct lm_sensor w83627dhg_sensors[] = {
  167         /* Voltage */
  168         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
  169         { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
  170         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
  171         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
  172         { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
  173         { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
  174         { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
  175         { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
  176         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
  177 
  178         /* Temperature */
  179         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  180         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  181         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  182 
  183         /* Fans */
  184         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  185         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  186         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  187 
  188         { NULL }
  189 };
  190 
  191 const struct lm_sensor nct6776f_sensors[] = {
  192         /* Voltage */
  193         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
  194         { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
  195         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
  196         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
  197         { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
  198         { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
  199         { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
  200         { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
  201         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
  202 
  203         /* Temperature */
  204         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  205         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  206         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  207 
  208         /* Fans */
  209         { "", SENSOR_FANRPM, 6, 0x56, wb_nct6776f_refresh_fanrpm },
  210         { "", SENSOR_FANRPM, 6, 0x58, wb_nct6776f_refresh_fanrpm },
  211         { "", SENSOR_FANRPM, 6, 0x5a, wb_nct6776f_refresh_fanrpm },
  212         { "", SENSOR_FANRPM, 6, 0x5c, wb_nct6776f_refresh_fanrpm },
  213         { "", SENSOR_FANRPM, 6, 0x5e, wb_nct6776f_refresh_fanrpm },
  214 
  215         { NULL }
  216 };
  217 
  218 /* NCT6779D */
  219 const struct lm_sensor nct6779d_sensors[] = {
  220         /* Voltage */
  221         { "VCore", SENSOR_VOLTS_DC, 4, 0x80, lm_refresh_volt, RFACT_NONE },
  222         { "VIN1", SENSOR_VOLTS_DC, 4, 0x81, lm_refresh_volt, RFACT(56, 10) / 2 },
  223         { "AVCC", SENSOR_VOLTS_DC, 4, 0x82, lm_refresh_volt, RFACT(34, 34) / 2 },
  224         { "+3.3V", SENSOR_VOLTS_DC, 4, 0x83, lm_refresh_volt, RFACT(34, 34) / 2 },
  225         { "VIN0", SENSOR_VOLTS_DC, 4, 0x84, lm_refresh_volt, RFACT(48600, 10000) },
  226         { "VIN8", SENSOR_VOLTS_DC, 4, 0x85, lm_refresh_volt, RFACT_NONE / 2 },
  227         { "VIN4", SENSOR_VOLTS_DC, 4, 0x86, lm_refresh_volt, RFACT_NONE / 2 },
  228         { "+3.3VSB", SENSOR_VOLTS_DC, 4, 0x87, lm_refresh_volt, RFACT(34, 34) / 2 },
  229         { "VBAT", SENSOR_VOLTS_DC, 4, 0x88, lm_refresh_volt, RFACT_NONE },
  230         { "VTT", SENSOR_VOLTS_DC, 4, 0x89, lm_refresh_volt, RFACT_NONE },
  231         { "VIN5", SENSOR_VOLTS_DC, 4, 0x8a, lm_refresh_volt, RFACT_NONE / 2 },
  232         { "VIN6", SENSOR_VOLTS_DC, 4, 0x8b, lm_refresh_volt, RFACT_NONE / 2 },
  233         { "VIN2", SENSOR_VOLTS_DC, 4, 0x8c, lm_refresh_volt, RFACT_NONE },
  234         { "VIN3", SENSOR_VOLTS_DC, 4, 0x8d, lm_refresh_volt, RFACT(14414, 10000) },
  235         { "VIN7", SENSOR_VOLTS_DC, 4, 0x8e, lm_refresh_volt, RFACT_NONE / 2 },
  236 
  237         /* Temperature */
  238         { "MB Temperature", SENSOR_TEMP, 4, 0x90, lm_refresh_temp, 0 },
  239         { "CPU Temperature", SENSOR_TEMP, 4, 0x91, wb_refresh_temp, 0 },
  240         { "Aux Temp0", SENSOR_TEMP, 4, 0x92, wb_refresh_temp, 0 },
  241         { "Aux Temp1", SENSOR_TEMP, 4, 0x93, wb_refresh_temp, 0 },
  242         { "Aux Temp2", SENSOR_TEMP, 4, 0x94, wb_refresh_temp, 0 },
  243         { "Aux Temp3", SENSOR_TEMP, 4, 0x95, wb_refresh_temp, 0 },
  244 
  245         /* Fans */
  246         { "System Fan", SENSOR_FANRPM, 4, 0xc0, wb_nct6776f_refresh_fanrpm, 0 },
  247         { "CPU Fan", SENSOR_FANRPM, 4, 0xc2, wb_nct6776f_refresh_fanrpm, 0 },
  248         { "Aux Fan0", SENSOR_FANRPM, 4, 0xc4, wb_nct6776f_refresh_fanrpm, 0 },
  249         { "Aux Fan1", SENSOR_FANRPM, 4, 0xc6, wb_nct6776f_refresh_fanrpm, 0 },
  250         { "Aux Fan2", SENSOR_FANRPM, 4, 0xc8, wb_nct6776f_refresh_fanrpm, 0 },
  251 
  252         {  NULL }
  253 };
  254 
  255 const struct lm_sensor w83637hf_sensors[] = {
  256         /* Voltage */
  257         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
  258         { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
  259         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  260         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
  261         { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
  262         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
  263         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
  264 
  265         /* Temperature */
  266         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  267         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  268         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  269 
  270         /* Fans */
  271         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  272         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  273         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  274 
  275         { NULL }
  276 };
  277 
  278 const struct lm_sensor w83697hf_sensors[] = {
  279         /* Voltage */
  280         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  281         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  282         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  283         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  284         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  285         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  286         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
  287         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
  288 
  289         /* Temperature */
  290         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  291         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  292 
  293         /* Fans */
  294         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  295         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  296 
  297         { NULL }
  298 };
  299 
  300 /*
  301  * The datasheet doesn't mention the (internal) resistors used for the
  302  * +5V, but using the values from the W83782D datasheets seems to
  303  * provide sensible results.
  304  */
  305 const struct lm_sensor w83781d_sensors[] = {
  306         /* Voltage */
  307         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  308         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
  309         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  310         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  311         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  312         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
  313         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
  314 
  315         /* Temperature */
  316         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  317         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  318         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  319 
  320         /* Fans */
  321         { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
  322         { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
  323         { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
  324 
  325         { NULL }
  326 };
  327 
  328 const struct lm_sensor w83782d_sensors[] = {
  329         /* Voltage */
  330         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  331         { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
  332         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  333         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  334         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  335         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  336         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  337         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
  338         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
  339 
  340         /* Temperature */
  341         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  342         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  343         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
  344 
  345         /* Fans */
  346         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  347         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  348         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  349 
  350         { NULL }
  351 };
  352 
  353 const struct lm_sensor w83783s_sensors[] = {
  354         /* Voltage */
  355         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  356         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  357         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  358         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  359         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  360         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  361 
  362         /* Temperature */
  363         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  364         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
  365 
  366         /* Fans */
  367         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  368         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  369         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  370 
  371         { NULL }
  372 };
  373 
  374 const struct lm_sensor w83791d_sensors[] = {
  375         /* Voltage */
  376         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 },
  377         { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 },
  378         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 },
  379         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  380         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  381         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  382         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  383         { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
  384         { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
  385         { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
  386 
  387         /* Temperature */
  388         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  389         { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
  390         { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
  391 
  392         /* Fans */
  393         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
  394         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
  395         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
  396         { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
  397         { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
  398 
  399         { NULL }
  400 };
  401 
  402 const struct lm_sensor w83792d_sensors[] = {
  403         /* Voltage */
  404         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  405         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
  406         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  407         { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
  408         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  409         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  410         { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
  411         { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
  412         { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
  413 
  414         /* Temperature */
  415         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  416         { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
  417         { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
  418 
  419         /* Fans */
  420         { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
  421         { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
  422         { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
  423         { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
  424         { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
  425         { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
  426         { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
  427 
  428         { NULL }
  429 };
  430 
  431 const struct lm_sensor as99127f_sensors[] = {
  432         /* Voltage */
  433         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
  434         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
  435         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
  436         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
  437         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
  438         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
  439         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
  440 
  441         /* Temperature */
  442         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
  443         { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
  444         { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
  445 
  446         /* Fans */
  447         { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
  448         { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
  449         { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
  450 
  451         { NULL }
  452 };
  453 
  454 void
  455 lm_attach(struct lm_softc *sc)
  456 {
  457         u_int i, config;
  458 
  459         for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
  460                 if (lm_chips[i].chip_match(sc))
  461                         break;
  462 
  463         /* No point in doing anything if we don't have any sensors. */
  464         if (sc->numsensors == 0)
  465                 return;
  466 
  467         sc->sensortask = sensor_task_register(sc, lm_refresh, 5);
  468         if (sc->sensortask == NULL) {
  469                 printf("%s: unable to register update task\n",
  470                     sc->sc_dev.dv_xname);
  471                 return;
  472         }
  473 
  474         /* Start the monitoring loop */
  475         config = sc->lm_readreg(sc, LM_CONFIG);
  476         sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
  477 
  478         /* Add sensors */
  479         for (i = 0; i < sc->numsensors; ++i)
  480                 sensor_attach(&sc->sensordev, &sc->sensors[i]);
  481         sensordev_install(&sc->sensordev);
  482 }
  483 
  484 int
  485 lm_match(struct lm_softc *sc)
  486 {
  487         int chipid;
  488 
  489         /* See if we have an LM78 or LM79. */
  490         chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
  491         switch(chipid) {
  492         case LM_CHIPID_LM78:
  493                 printf(": LM78\n");
  494                 break;
  495         case LM_CHIPID_LM78J:
  496                 printf(": LM78J\n");
  497                 break;
  498         case LM_CHIPID_LM79:
  499                 printf(": LM79\n");
  500                 break;
  501         case LM_CHIPID_LM81:
  502                 printf(": LM81\n");
  503                 break;
  504         default:
  505                 return 0;
  506         }
  507 
  508         lm_setup_sensors(sc, lm78_sensors);
  509         sc->refresh_sensor_data = lm_refresh_sensor_data;
  510         return 1;
  511 }
  512 
  513 int
  514 def_match(struct lm_softc *sc)
  515 {
  516         int chipid;
  517 
  518         chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
  519         printf(": unknown chip (ID %d)\n", chipid);
  520 
  521         lm_setup_sensors(sc, lm78_sensors);
  522         sc->refresh_sensor_data = lm_refresh_sensor_data;
  523         return 1;
  524 }
  525 
  526 int
  527 wb_match(struct lm_softc *sc)
  528 {
  529         int banksel, vendid, devid;
  530 
  531         /* Read vendor ID */
  532         banksel = sc->lm_readreg(sc, WB_BANKSEL);
  533         sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
  534         vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
  535         sc->lm_writereg(sc, WB_BANKSEL, 0);
  536         vendid |= sc->lm_readreg(sc, WB_VENDID);
  537         sc->lm_writereg(sc, WB_BANKSEL, banksel);
  538         DPRINTF((" winbond vend id 0x%x\n", vendid));
  539         if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
  540                 return 0;
  541 
  542         /* Read device/chip ID */
  543         sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
  544         devid = sc->lm_readreg(sc, LM_CHIPID);
  545         sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
  546         sc->lm_writereg(sc, WB_BANKSEL, banksel);
  547         DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
  548         switch(sc->chipid) {
  549         case WB_CHIPID_W83627HF:
  550                 printf(": W83627HF\n");
  551                 lm_setup_sensors(sc, w83627hf_sensors);
  552                 break;
  553         case WB_CHIPID_W83627THF:
  554                 printf(": W83627THF\n");
  555                 lm_setup_sensors(sc, w83637hf_sensors);
  556                 break;
  557         case WB_CHIPID_W83627EHF_A:
  558                 printf(": W83627EHF-A\n");
  559                 lm_setup_sensors(sc, w83627ehf_sensors);
  560                 break;
  561         case WB_CHIPID_W83627EHF:
  562                 printf(": W83627EHF\n");
  563                 lm_setup_sensors(sc, w83627ehf_sensors);
  564                 break;
  565         case WB_CHIPID_W83627DHG:
  566                 switch (sc->sioid) {
  567                 case WBSIO_ID_NCT6775F:
  568                         printf(": NCT6775F\n");
  569                         lm_setup_sensors(sc, nct6776f_sensors);
  570                         break;
  571                 case WBSIO_ID_NCT6776F:
  572                         printf(": NCT6776F\n");
  573                         lm_setup_sensors(sc, nct6776f_sensors);
  574                         break;
  575                 case WBSIO_ID_NCT5104D:
  576                         printf(": NCT5104D\n");
  577                         lm_setup_sensors(sc, nct6776f_sensors);
  578                         break;
  579                 case WBSIO_ID_NCT6779D:
  580                         printf(": NCT6779D\n");
  581                         lm_setup_sensors(sc, nct6779d_sensors);
  582                         break;
  583                 case WBSIO_ID_NCT6791D:
  584                         printf(": NCT6791D\n");
  585                         lm_setup_sensors(sc, nct6779d_sensors);
  586                         break;
  587                 case WBSIO_ID_NCT6792D:
  588                         printf(": NCT6792D\n");
  589                         lm_setup_sensors(sc, nct6779d_sensors);
  590                         break;
  591                 case WBSIO_ID_NCT6793D:
  592                         printf(": NCT6793D\n");
  593                         lm_setup_sensors(sc, nct6779d_sensors);
  594                         break;
  595                 case WBSIO_ID_NCT6795D:
  596                         printf(": NCT6795D\n");
  597                         lm_setup_sensors(sc, nct6779d_sensors);
  598                         break;
  599                 default:
  600                         printf(": W83627DHG\n");
  601                         lm_setup_sensors(sc, w83627dhg_sensors);
  602                 }
  603                 break;
  604         case WB_CHIPID_W83637HF:
  605                 printf(": W83637HF\n");
  606                 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
  607                 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
  608                         sc->vrm9 = 1;
  609                 sc->lm_writereg(sc, WB_BANKSEL, banksel);
  610                 lm_setup_sensors(sc, w83637hf_sensors);
  611                 break;
  612         case WB_CHIPID_W83697HF:
  613                 printf(": W83697HF\n");
  614                 lm_setup_sensors(sc, w83697hf_sensors);
  615                 break;
  616         case WB_CHIPID_W83781D:
  617         case WB_CHIPID_W83781D_2:
  618                 printf(": W83781D\n");
  619                 lm_setup_sensors(sc, w83781d_sensors);
  620                 break;
  621         case WB_CHIPID_W83782D:
  622                 printf(": W83782D\n");
  623                 lm_setup_sensors(sc, w83782d_sensors);
  624                 break;
  625         case WB_CHIPID_W83783S:
  626                 printf(": W83783S\n");
  627                 lm_setup_sensors(sc, w83783s_sensors);
  628                 break;
  629         case WB_CHIPID_W83791D:
  630                 printf(": W83791D\n");
  631                 lm_setup_sensors(sc, w83791d_sensors);
  632                 break;
  633         case WB_CHIPID_W83791SD:
  634                 printf(": W83791SD\n");
  635                 break;
  636         case WB_CHIPID_W83792D:
  637                 if (devid >= 0x10 && devid <= 0x29)
  638                         printf(": W83792D rev %c\n", 'A' + devid - 0x10);
  639                 else
  640                         printf(": W83792D rev 0x%x\n", devid);
  641                 lm_setup_sensors(sc, w83792d_sensors);
  642                 break;
  643         case WB_CHIPID_AS99127F:
  644                 if (vendid == WB_VENDID_ASUS) {
  645                         printf(": AS99127F\n");
  646                         lm_setup_sensors(sc, w83781d_sensors);
  647                 } else {
  648                         printf(": AS99127F rev 2\n");
  649                         lm_setup_sensors(sc, as99127f_sensors);
  650                 }
  651                 break;
  652         default:
  653                 printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid);
  654                 /* Handle as a standard LM78. */
  655                 lm_setup_sensors(sc, lm78_sensors);
  656                 sc->refresh_sensor_data = lm_refresh_sensor_data;
  657                 return 1;
  658         }
  659 
  660         sc->refresh_sensor_data = wb_refresh_sensor_data;
  661         return 1;
  662 }
  663 
  664 void
  665 lm_setup_sensors(struct lm_softc *sc, const struct lm_sensor *sensors)
  666 {
  667         int i;
  668 
  669         strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
  670             sizeof(sc->sensordev.xname));
  671 
  672         for (i = 0; sensors[i].desc; i++) {
  673                 sc->sensors[i].type = sensors[i].type;
  674                 strlcpy(sc->sensors[i].desc, sensors[i].desc,
  675                     sizeof(sc->sensors[i].desc));
  676                 sc->numsensors++;
  677         }
  678         sc->lm_sensors = sensors;
  679 }
  680 
  681 void
  682 lm_refresh(void *arg)
  683 {
  684         struct lm_softc *sc = arg;
  685 
  686         sc->refresh_sensor_data(sc);
  687 }
  688 
  689 void
  690 lm_refresh_sensor_data(struct lm_softc *sc)
  691 {
  692         int i;
  693 
  694         for (i = 0; i < sc->numsensors; i++)
  695                 sc->lm_sensors[i].refresh(sc, i);
  696 }
  697 
  698 void
  699 lm_refresh_volt(struct lm_softc *sc, int n)
  700 {
  701         struct ksensor *sensor = &sc->sensors[n];
  702         int data;
  703 
  704         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  705         sensor->value = (data << 4);
  706         sensor->value *= sc->lm_sensors[n].rfact;
  707         sensor->value /= 10;
  708 }
  709 
  710 void
  711 lm_refresh_temp(struct lm_softc *sc, int n)
  712 {
  713         struct ksensor *sensor = &sc->sensors[n];
  714         int sdata;
  715 
  716         /*
  717          * The data sheet suggests that the range of the temperature
  718          * sensor is between -55 degC and +125 degC.
  719          */
  720         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  721         if (sdata > 0x7d && sdata < 0xc9) {
  722                 sensor->flags |= SENSOR_FINVALID;
  723                 sensor->value = 0;
  724         } else {
  725                 if (sdata & 0x80)
  726                         sdata -= 0x100;
  727                 sensor->flags &= ~SENSOR_FINVALID;
  728                 sensor->value = sdata * 1000000 + 273150000;
  729         }
  730 }
  731 
  732 void
  733 lm_refresh_fanrpm(struct lm_softc *sc, int n)
  734 {
  735         struct ksensor *sensor = &sc->sensors[n];
  736         int data, divisor = 1;
  737 
  738         /*
  739          * We might get more accurate fan readings by adjusting the
  740          * divisor, but that might interfere with APM or other SMM
  741          * BIOS code reading the fan speeds.
  742          */
  743 
  744         /* FAN3 has a fixed fan divisor. */
  745         if (sc->lm_sensors[n].reg == LM_FAN1 ||
  746             sc->lm_sensors[n].reg == LM_FAN2) {
  747                 data = sc->lm_readreg(sc, LM_VIDFAN);
  748                 if (sc->lm_sensors[n].reg == LM_FAN1)
  749                         divisor = (data >> 4) & 0x03;
  750                 else
  751                         divisor = (data >> 6) & 0x03;
  752         }
  753 
  754         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  755         if (data == 0xff || data == 0x00) {
  756                 sensor->flags |= SENSOR_FINVALID;
  757                 sensor->value = 0;
  758         } else {
  759                 sensor->flags &= ~SENSOR_FINVALID;
  760                 sensor->value = 1350000 / (data << divisor);
  761         }
  762 }
  763 
  764 void
  765 wb_refresh_sensor_data(struct lm_softc *sc)
  766 {
  767         int banksel, bank, i;
  768 
  769         /*
  770          * Properly save and restore bank selection register.
  771          */
  772 
  773         banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
  774         for (i = 0; i < sc->numsensors; i++) {
  775                 if (bank != sc->lm_sensors[i].bank) {
  776                         bank = sc->lm_sensors[i].bank;
  777                         sc->lm_writereg(sc, WB_BANKSEL, bank);
  778                 }
  779                 sc->lm_sensors[i].refresh(sc, i);
  780         }
  781         sc->lm_writereg(sc, WB_BANKSEL, banksel);
  782 }
  783 
  784 void
  785 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
  786 {
  787         struct ksensor *sensor = &sc->sensors[n];
  788         int data;
  789 
  790         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  791 
  792         /*
  793          * Depending on the voltage detection method,
  794          * one of the following formulas is used:
  795          *      VRM8 method: value = raw * 0.016V
  796          *      VRM9 method: value = raw * 0.00488V + 0.70V
  797          */
  798         if (sc->vrm9)
  799                 sensor->value = (data * 4880) + 700000;
  800         else
  801                 sensor->value = (data * 16000);
  802 }
  803 
  804 void
  805 wb_refresh_nvolt(struct lm_softc *sc, int n)
  806 {
  807         struct ksensor *sensor = &sc->sensors[n];
  808         int data;
  809 
  810         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  811         sensor->value = ((data << 4) - WB_VREF);
  812         sensor->value *= sc->lm_sensors[n].rfact;
  813         sensor->value /= 10;
  814         sensor->value += WB_VREF * 1000;
  815 }
  816 
  817 void
  818 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
  819 {
  820         struct ksensor *sensor = &sc->sensors[n];
  821         int data;
  822 
  823         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  824         sensor->value = ((data << 3) - WB_W83627EHF_VREF);
  825         sensor->value *= RFACT(232, 10);
  826         sensor->value /= 10;
  827         sensor->value += WB_W83627EHF_VREF * 1000;
  828 }
  829 
  830 void
  831 wb_refresh_temp(struct lm_softc *sc, int n)
  832 {
  833         struct ksensor *sensor = &sc->sensors[n];
  834         int sdata;
  835 
  836         /*
  837          * The data sheet suggests that the range of the temperature
  838          * sensor is between -55 degC and +125 degC.  However, values
  839          * around -48 degC seem to be a very common bogus values.
  840          * Since such values are unreasonably low, we use -45 degC for
  841          * the lower limit instead.
  842          */
  843         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
  844         sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
  845         if (sdata > 0x0fa && sdata < 0x1a6) {
  846                 sensor->flags |= SENSOR_FINVALID;
  847                 sensor->value = 0;
  848         } else {
  849                 if (sdata & 0x100)
  850                         sdata -= 0x200;
  851                 sensor->flags &= ~SENSOR_FINVALID;
  852                 sensor->value = sdata * 500000 + 273150000;
  853         }
  854 }
  855 
  856 void
  857 wb_refresh_fanrpm(struct lm_softc *sc, int n)
  858 {
  859         struct ksensor *sensor = &sc->sensors[n];
  860         int fan, data, divisor = 0;
  861 
  862         /* 
  863          * This is madness; the fan divisor bits are scattered all
  864          * over the place.
  865          */
  866 
  867         if (sc->lm_sensors[n].reg == LM_FAN1 ||
  868             sc->lm_sensors[n].reg == LM_FAN2 ||
  869             sc->lm_sensors[n].reg == LM_FAN3) {
  870                 data = sc->lm_readreg(sc, WB_BANK0_VBAT);
  871                 fan = (sc->lm_sensors[n].reg - LM_FAN1);
  872                 if ((data >> 5) & (1 << fan))
  873                         divisor |= 0x04;
  874         }
  875 
  876         if (sc->lm_sensors[n].reg == LM_FAN1 ||
  877             sc->lm_sensors[n].reg == LM_FAN2) {
  878                 data = sc->lm_readreg(sc, LM_VIDFAN);
  879                 if (sc->lm_sensors[n].reg == LM_FAN1)
  880                         divisor |= (data >> 4) & 0x03;
  881                 else
  882                         divisor |= (data >> 6) & 0x03;
  883         } else if (sc->lm_sensors[n].reg == LM_FAN3) {
  884                 data = sc->lm_readreg(sc, WB_PIN);
  885                 divisor |= (data >> 6) & 0x03;
  886         } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
  887                    sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
  888                 data = sc->lm_readreg(sc, WB_BANK0_FAN45);
  889                 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
  890                         divisor |= (data >> 0) & 0x07;
  891                 else
  892                         divisor |= (data >> 4) & 0x07;
  893         }
  894 
  895         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  896         if (data == 0xff || data == 0x00) {
  897                 sensor->flags |= SENSOR_FINVALID;
  898                 sensor->value = 0;
  899         } else {
  900                 sensor->flags &= ~SENSOR_FINVALID;
  901                 sensor->value = 1350000 / (data << divisor);
  902         }
  903 }
  904 
  905 void
  906 wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n)
  907 {
  908         struct ksensor *sensor = &sc->sensors[n];
  909         int datah, datal;
  910 
  911         datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  912         datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1);
  913 
  914         if (datah == 0xff) {
  915                 sensor->flags |= SENSOR_FINVALID;
  916                 sensor->value = 0;
  917         } else {
  918                 sensor->flags &= ~SENSOR_FINVALID;
  919                 sensor->value = (datah << 8) | datal;
  920         }
  921 }
  922 
  923 void
  924 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
  925 {
  926         struct ksensor *sensor = &sc->sensors[n];
  927         int reg, shift, data, divisor = 1;
  928 
  929         switch (sc->lm_sensors[n].reg) {
  930         case 0x28:
  931                 reg = 0x47; shift = 0;
  932                 break;
  933         case 0x29:
  934                 reg = 0x47; shift = 4;
  935                 break;
  936         case 0x2a:
  937                 reg = 0x5b; shift = 0;
  938                 break;
  939         case 0xb8:
  940                 reg = 0x5b; shift = 4;
  941                 break;
  942         case 0xb9:
  943                 reg = 0x5c; shift = 0;
  944                 break;
  945         case 0xba:
  946                 reg = 0x5c; shift = 4;
  947                 break;
  948         case 0xbe:
  949                 reg = 0x9e; shift = 0;
  950                 break;
  951         default:
  952                 reg = 0;
  953                 break;
  954         }
  955 
  956         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
  957         if (data == 0xff || data == 0x00) {
  958                 sensor->flags |= SENSOR_FINVALID;
  959                 sensor->value = 0;
  960         } else {
  961                 if (reg != 0)
  962                         divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
  963                 sensor->flags &= ~SENSOR_FINVALID;
  964                 sensor->value = 1350000 / (data << divisor);
  965         }
  966 }
  967 
  968 void
  969 as_refresh_temp(struct lm_softc *sc, int n)
  970 {
  971         struct ksensor *sensor = &sc->sensors[n];
  972         int sdata;
  973 
  974         /*
  975          * It seems a shorted temperature diode produces an all-ones
  976          * bit pattern.
  977          */
  978         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
  979         sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
  980         if (sdata == 0x1ff) {
  981                 sensor->flags |= SENSOR_FINVALID;
  982                 sensor->value = 0;
  983         } else {
  984                 if (sdata & 0x100)
  985                         sdata -= 0x200;
  986                 sensor->flags &= ~SENSOR_FINVALID;
  987                 sensor->value = sdata * 500000 + 273150000;
  988         }
  989 }

Cache object: 3eac88e17f0a7429ca0154ac60aae1c0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.