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

Cache object: 05ad8e7bd0185083b6a77a476a0f8535


[ 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.