root/dev/ic/lm78.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lm_attach
  2. lm_detach
  3. lm_match
  4. def_match
  5. wb_match
  6. lm_setup_sensors
  7. lm_refresh
  8. lm_refresh_sensor_data
  9. lm_refresh_volt
  10. lm_refresh_temp
  11. lm_refresh_fanrpm
  12. wb_refresh_sensor_data
  13. wb_w83637hf_refresh_vcore
  14. wb_refresh_nvolt
  15. wb_w83627ehf_refresh_nvolt
  16. wb_refresh_temp
  17. wb_refresh_fanrpm
  18. wb_w83792d_refresh_fanrpm
  19. as_refresh_temp

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

/* [<][>][^][v][top][bottom][index][help] */