LCOV - code coverage report
Current view: top level - dev/ic - lm78.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 285 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: lm78.c,v 1.24 2015/03/14 03:38:47 jsg 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 *, 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             : struct lm_chip lm_chips[] = {
      78             :         { wb_match },
      79             :         { lm_match },
      80             :         { def_match } /* Must be last */
      81             : };
      82             : 
      83             : 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             : 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             : 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             : 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             : 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             : struct lm_sensor w83637hf_sensors[] = {
     219             :         /* Voltage */
     220             :         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
     221             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
     222             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     223             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
     224             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
     225             :         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
     226             :         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
     227             : 
     228             :         /* Temperature */
     229             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     230             :         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
     231             :         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
     232             : 
     233             :         /* Fans */
     234             :         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
     235             :         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
     236             :         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
     237             : 
     238             :         { NULL }
     239             : };
     240             : 
     241             : struct lm_sensor w83697hf_sensors[] = {
     242             :         /* Voltage */
     243             :         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, 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, wb_refresh_nvolt, RFACT(232, 56) },
     248             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
     249             :         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
     250             :         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
     251             : 
     252             :         /* Temperature */
     253             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     254             :         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
     255             : 
     256             :         /* Fans */
     257             :         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
     258             :         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
     259             : 
     260             :         { NULL }
     261             : };
     262             : 
     263             : /*
     264             :  * The datasheet doesn't mention the (internal) resistors used for the
     265             :  * +5V, but using the values from the W83782D datasheets seems to
     266             :  * provide sensible results.
     267             :  */
     268             : struct lm_sensor w83781d_sensors[] = {
     269             :         /* Voltage */
     270             :         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
     271             :         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
     272             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     273             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
     274             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
     275             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
     276             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
     277             : 
     278             :         /* Temperature */
     279             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     280             :         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
     281             :         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
     282             : 
     283             :         /* Fans */
     284             :         { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
     285             :         { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
     286             :         { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
     287             : 
     288             :         { NULL }
     289             : };
     290             : 
     291             : struct lm_sensor w83782d_sensors[] = {
     292             :         /* Voltage */
     293             :         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
     294             :         { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
     295             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     296             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
     297             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
     298             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
     299             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
     300             :         { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
     301             :         { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
     302             : 
     303             :         /* Temperature */
     304             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     305             :         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
     306             :         { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
     307             : 
     308             :         /* Fans */
     309             :         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
     310             :         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
     311             :         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
     312             : 
     313             :         { NULL }
     314             : };
     315             : 
     316             : struct lm_sensor w83783s_sensors[] = {
     317             :         /* Voltage */
     318             :         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
     319             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     320             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
     321             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
     322             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
     323             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
     324             : 
     325             :         /* Temperature */
     326             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     327             :         { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
     328             : 
     329             :         /* Fans */
     330             :         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
     331             :         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
     332             :         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
     333             : 
     334             :         { NULL }
     335             : };
     336             : 
     337             : struct lm_sensor w83791d_sensors[] = {
     338             :         /* Voltage */
     339             :         { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 },
     340             :         { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 },
     341             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 },
     342             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
     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, wb_refresh_nvolt, RFACT(120, 56) },
     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             :         { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
     349             : 
     350             :         /* Temperature */
     351             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     352             :         { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
     353             :         { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
     354             : 
     355             :         /* Fans */
     356             :         { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
     357             :         { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
     358             :         { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
     359             :         { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
     360             :         { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
     361             : 
     362             :         { NULL }
     363             : };
     364             : 
     365             : struct lm_sensor w83792d_sensors[] = {
     366             :         /* Voltage */
     367             :         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
     368             :         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
     369             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     370             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
     371             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
     372             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
     373             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
     374             :         { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
     375             :         { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
     376             : 
     377             :         /* Temperature */
     378             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     379             :         { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
     380             :         { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
     381             : 
     382             :         /* Fans */
     383             :         { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
     384             :         { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
     385             :         { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
     386             :         { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
     387             :         { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
     388             :         { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
     389             :         { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
     390             : 
     391             :         { NULL }
     392             : };
     393             : 
     394             : struct lm_sensor as99127f_sensors[] = {
     395             :         /* Voltage */
     396             :         { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
     397             :         { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
     398             :         { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
     399             :         { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
     400             :         { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
     401             :         { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
     402             :         { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
     403             : 
     404             :         /* Temperature */
     405             :         { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
     406             :         { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
     407             :         { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
     408             : 
     409             :         /* Fans */
     410             :         { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
     411             :         { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
     412             :         { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
     413             : 
     414             :         { NULL }
     415             : };
     416             : 
     417             : void
     418           0 : lm_attach(struct lm_softc *sc)
     419             : {
     420             :         u_int i, config;
     421             : 
     422           0 :         for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
     423           0 :                 if (lm_chips[i].chip_match(sc))
     424             :                         break;
     425             : 
     426             :         /* No point in doing anything if we don't have any sensors. */
     427           0 :         if (sc->numsensors == 0)
     428           0 :                 return;
     429             : 
     430           0 :         sc->sensortask = sensor_task_register(sc, lm_refresh, 5);
     431           0 :         if (sc->sensortask == NULL) {
     432           0 :                 printf("%s: unable to register update task\n",
     433           0 :                     sc->sc_dev.dv_xname);
     434           0 :                 return;
     435             :         }
     436             : 
     437             :         /* Start the monitoring loop */
     438           0 :         config = sc->lm_readreg(sc, LM_CONFIG);
     439           0 :         sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
     440             : 
     441             :         /* Add sensors */
     442           0 :         for (i = 0; i < sc->numsensors; ++i)
     443           0 :                 sensor_attach(&sc->sensordev, &sc->sensors[i]);
     444           0 :         sensordev_install(&sc->sensordev);
     445           0 : }
     446             : 
     447             : int
     448           0 : lm_match(struct lm_softc *sc)
     449             : {
     450             :         int chipid;
     451             : 
     452             :         /* See if we have an LM78 or LM79. */
     453           0 :         chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
     454           0 :         switch(chipid) {
     455             :         case LM_CHIPID_LM78:
     456           0 :                 printf(": LM78\n");
     457           0 :                 break;
     458             :         case LM_CHIPID_LM78J:
     459           0 :                 printf(": LM78J\n");
     460           0 :                 break;
     461             :         case LM_CHIPID_LM79:
     462           0 :                 printf(": LM79\n");
     463           0 :                 break;
     464             :         case LM_CHIPID_LM81:
     465           0 :                 printf(": LM81\n");
     466           0 :                 break;
     467             :         default:
     468           0 :                 return 0;
     469             :         }
     470             : 
     471           0 :         lm_setup_sensors(sc, lm78_sensors);
     472           0 :         sc->refresh_sensor_data = lm_refresh_sensor_data;
     473           0 :         return 1;
     474           0 : }
     475             : 
     476             : int
     477           0 : def_match(struct lm_softc *sc)
     478             : {
     479             :         int chipid;
     480             : 
     481           0 :         chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
     482           0 :         printf(": unknown chip (ID %d)\n", chipid);
     483             : 
     484           0 :         lm_setup_sensors(sc, lm78_sensors);
     485           0 :         sc->refresh_sensor_data = lm_refresh_sensor_data;
     486           0 :         return 1;
     487             : }
     488             : 
     489             : int
     490           0 : wb_match(struct lm_softc *sc)
     491             : {
     492             :         int banksel, vendid, devid;
     493             : 
     494             :         /* Read vendor ID */
     495           0 :         banksel = sc->lm_readreg(sc, WB_BANKSEL);
     496           0 :         sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
     497           0 :         vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
     498           0 :         sc->lm_writereg(sc, WB_BANKSEL, 0);
     499           0 :         vendid |= sc->lm_readreg(sc, WB_VENDID);
     500           0 :         sc->lm_writereg(sc, WB_BANKSEL, banksel);
     501             :         DPRINTF((" winbond vend id 0x%x\n", vendid));
     502           0 :         if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
     503           0 :                 return 0;
     504             : 
     505             :         /* Read device/chip ID */
     506           0 :         sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
     507           0 :         devid = sc->lm_readreg(sc, LM_CHIPID);
     508           0 :         sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
     509           0 :         sc->lm_writereg(sc, WB_BANKSEL, banksel);
     510             :         DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
     511           0 :         switch(sc->chipid) {
     512             :         case WB_CHIPID_W83627HF:
     513           0 :                 printf(": W83627HF\n");
     514           0 :                 lm_setup_sensors(sc, w83627hf_sensors);
     515           0 :                 break;
     516             :         case WB_CHIPID_W83627THF:
     517           0 :                 printf(": W83627THF\n");
     518           0 :                 lm_setup_sensors(sc, w83637hf_sensors);
     519           0 :                 break;
     520             :         case WB_CHIPID_W83627EHF_A:
     521           0 :                 printf(": W83627EHF-A\n");
     522           0 :                 lm_setup_sensors(sc, w83627ehf_sensors);
     523           0 :                 break;
     524             :         case WB_CHIPID_W83627EHF:
     525           0 :                 printf(": W83627EHF\n");
     526           0 :                 lm_setup_sensors(sc, w83627ehf_sensors);
     527           0 :                 break;
     528             :         case WB_CHIPID_W83627DHG:
     529           0 :                 if (sc->sioid == WBSIO_ID_NCT6776F) {
     530           0 :                         printf(": NCT6776F\n");
     531           0 :                         lm_setup_sensors(sc, nct6776f_sensors);
     532           0 :                 } else {
     533           0 :                         printf(": W83627DHG\n");
     534           0 :                         lm_setup_sensors(sc, w83627dhg_sensors);
     535             :                 }
     536             :                 break;
     537             :         case WB_CHIPID_W83637HF:
     538           0 :                 printf(": W83637HF\n");
     539           0 :                 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
     540           0 :                 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
     541           0 :                         sc->vrm9 = 1;
     542           0 :                 sc->lm_writereg(sc, WB_BANKSEL, banksel);
     543           0 :                 lm_setup_sensors(sc, w83637hf_sensors);
     544           0 :                 break;
     545             :         case WB_CHIPID_W83697HF:
     546           0 :                 printf(": W83697HF\n");
     547           0 :                 lm_setup_sensors(sc, w83697hf_sensors);
     548           0 :                 break;
     549             :         case WB_CHIPID_W83781D:
     550             :         case WB_CHIPID_W83781D_2:
     551           0 :                 printf(": W83781D\n");
     552           0 :                 lm_setup_sensors(sc, w83781d_sensors);
     553           0 :                 break;
     554             :         case WB_CHIPID_W83782D:
     555           0 :                 printf(": W83782D\n");
     556           0 :                 lm_setup_sensors(sc, w83782d_sensors);
     557           0 :                 break;
     558             :         case WB_CHIPID_W83783S:
     559           0 :                 printf(": W83783S\n");
     560           0 :                 lm_setup_sensors(sc, w83783s_sensors);
     561           0 :                 break;
     562             :         case WB_CHIPID_W83791D:
     563           0 :                 printf(": W83791D\n");
     564           0 :                 lm_setup_sensors(sc, w83791d_sensors);
     565           0 :                 break;
     566             :         case WB_CHIPID_W83791SD:
     567           0 :                 printf(": W83791SD\n");
     568           0 :                 break;
     569             :         case WB_CHIPID_W83792D:
     570           0 :                 if (devid >= 0x10 && devid <= 0x29)
     571           0 :                         printf(": W83792D rev %c\n", 'A' + devid - 0x10);
     572             :                 else
     573           0 :                         printf(": W83792D rev 0x%x\n", devid);
     574           0 :                 lm_setup_sensors(sc, w83792d_sensors);
     575           0 :                 break;
     576             :         case WB_CHIPID_AS99127F:
     577           0 :                 if (vendid == WB_VENDID_ASUS) {
     578           0 :                         printf(": AS99127F\n");
     579           0 :                         lm_setup_sensors(sc, w83781d_sensors);
     580           0 :                 } else {
     581           0 :                         printf(": AS99127F rev 2\n");
     582           0 :                         lm_setup_sensors(sc, as99127f_sensors);
     583             :                 }
     584             :                 break;
     585             :         default:
     586           0 :                 printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid);
     587             :                 /* Handle as a standard LM78. */
     588           0 :                 lm_setup_sensors(sc, lm78_sensors);
     589           0 :                 sc->refresh_sensor_data = lm_refresh_sensor_data;
     590           0 :                 return 1;
     591             :         }
     592             : 
     593           0 :         sc->refresh_sensor_data = wb_refresh_sensor_data;
     594           0 :         return 1;
     595           0 : }
     596             : 
     597             : void
     598           0 : lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
     599             : {
     600             :         int i;
     601             : 
     602           0 :         strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
     603             :             sizeof(sc->sensordev.xname));
     604             : 
     605           0 :         for (i = 0; sensors[i].desc; i++) {
     606           0 :                 sc->sensors[i].type = sensors[i].type;
     607           0 :                 strlcpy(sc->sensors[i].desc, sensors[i].desc,
     608             :                     sizeof(sc->sensors[i].desc));
     609           0 :                 sc->numsensors++;
     610             :         }
     611           0 :         sc->lm_sensors = sensors;
     612           0 : }
     613             : 
     614             : void
     615           0 : lm_refresh(void *arg)
     616             : {
     617           0 :         struct lm_softc *sc = arg;
     618             : 
     619           0 :         sc->refresh_sensor_data(sc);
     620           0 : }
     621             : 
     622             : void
     623           0 : lm_refresh_sensor_data(struct lm_softc *sc)
     624             : {
     625             :         int i;
     626             : 
     627           0 :         for (i = 0; i < sc->numsensors; i++)
     628           0 :                 sc->lm_sensors[i].refresh(sc, i);
     629           0 : }
     630             : 
     631             : void
     632           0 : lm_refresh_volt(struct lm_softc *sc, int n)
     633             : {
     634           0 :         struct ksensor *sensor = &sc->sensors[n];
     635             :         int data;
     636             : 
     637           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     638           0 :         sensor->value = (data << 4);
     639           0 :         sensor->value *= sc->lm_sensors[n].rfact;
     640           0 :         sensor->value /= 10;
     641           0 : }
     642             : 
     643             : void
     644           0 : lm_refresh_temp(struct lm_softc *sc, int n)
     645             : {
     646           0 :         struct ksensor *sensor = &sc->sensors[n];
     647             :         int sdata;
     648             : 
     649             :         /*
     650             :          * The data sheet suggests that the range of the temperature
     651             :          * sensor is between -55 degC and +125 degC.
     652             :          */
     653           0 :         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     654           0 :         if (sdata > 0x7d && sdata < 0xc9) {
     655           0 :                 sensor->flags |= SENSOR_FINVALID;
     656           0 :                 sensor->value = 0;
     657           0 :         } else {
     658           0 :                 if (sdata & 0x80)
     659           0 :                         sdata -= 0x100;
     660           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     661           0 :                 sensor->value = sdata * 1000000 + 273150000;
     662             :         }
     663           0 : }
     664             : 
     665             : void
     666           0 : lm_refresh_fanrpm(struct lm_softc *sc, int n)
     667             : {
     668           0 :         struct ksensor *sensor = &sc->sensors[n];
     669             :         int data, divisor = 1;
     670             : 
     671             :         /*
     672             :          * We might get more accurate fan readings by adjusting the
     673             :          * divisor, but that might interfere with APM or other SMM
     674             :          * BIOS code reading the fan speeds.
     675             :          */
     676             : 
     677             :         /* FAN3 has a fixed fan divisor. */
     678           0 :         if (sc->lm_sensors[n].reg == LM_FAN1 ||
     679           0 :             sc->lm_sensors[n].reg == LM_FAN2) {
     680           0 :                 data = sc->lm_readreg(sc, LM_VIDFAN);
     681           0 :                 if (sc->lm_sensors[n].reg == LM_FAN1)
     682           0 :                         divisor = (data >> 4) & 0x03;
     683             :                 else
     684           0 :                         divisor = (data >> 6) & 0x03;
     685             :         }
     686             : 
     687           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     688           0 :         if (data == 0xff || data == 0x00) {
     689           0 :                 sensor->flags |= SENSOR_FINVALID;
     690           0 :                 sensor->value = 0;
     691           0 :         } else {
     692           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     693           0 :                 sensor->value = 1350000 / (data << divisor);
     694             :         }
     695           0 : }
     696             : 
     697             : void
     698           0 : wb_refresh_sensor_data(struct lm_softc *sc)
     699             : {
     700             :         int banksel, bank, i;
     701             : 
     702             :         /*
     703             :          * Properly save and restore bank selection register.
     704             :          */
     705             : 
     706           0 :         banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
     707           0 :         for (i = 0; i < sc->numsensors; i++) {
     708           0 :                 if (bank != sc->lm_sensors[i].bank) {
     709             :                         bank = sc->lm_sensors[i].bank;
     710           0 :                         sc->lm_writereg(sc, WB_BANKSEL, bank);
     711           0 :                 }
     712           0 :                 sc->lm_sensors[i].refresh(sc, i);
     713             :         }
     714           0 :         sc->lm_writereg(sc, WB_BANKSEL, banksel);
     715           0 : }
     716             : 
     717             : void
     718           0 : wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
     719             : {
     720           0 :         struct ksensor *sensor = &sc->sensors[n];
     721             :         int data;
     722             : 
     723           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     724             : 
     725             :         /*
     726             :          * Depending on the voltage detection method,
     727             :          * one of the following formulas is used:
     728             :          *      VRM8 method: value = raw * 0.016V
     729             :          *      VRM9 method: value = raw * 0.00488V + 0.70V
     730             :          */
     731           0 :         if (sc->vrm9)
     732           0 :                 sensor->value = (data * 4880) + 700000;
     733             :         else
     734           0 :                 sensor->value = (data * 16000);
     735           0 : }
     736             : 
     737             : void
     738           0 : wb_refresh_nvolt(struct lm_softc *sc, int n)
     739             : {
     740           0 :         struct ksensor *sensor = &sc->sensors[n];
     741             :         int data;
     742             : 
     743           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     744           0 :         sensor->value = ((data << 4) - WB_VREF);
     745           0 :         sensor->value *= sc->lm_sensors[n].rfact;
     746           0 :         sensor->value /= 10;
     747           0 :         sensor->value += WB_VREF * 1000;
     748           0 : }
     749             : 
     750             : void
     751           0 : wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
     752             : {
     753           0 :         struct ksensor *sensor = &sc->sensors[n];
     754             :         int data;
     755             : 
     756           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     757           0 :         sensor->value = ((data << 3) - WB_W83627EHF_VREF);
     758           0 :         sensor->value *= RFACT(232, 10);
     759           0 :         sensor->value /= 10;
     760           0 :         sensor->value += WB_W83627EHF_VREF * 1000;
     761           0 : }
     762             : 
     763             : void
     764           0 : wb_refresh_temp(struct lm_softc *sc, int n)
     765             : {
     766           0 :         struct ksensor *sensor = &sc->sensors[n];
     767             :         int sdata;
     768             : 
     769             :         /*
     770             :          * The data sheet suggests that the range of the temperature
     771             :          * sensor is between -55 degC and +125 degC.  However, values
     772             :          * around -48 degC seem to be a very common bogus values.
     773             :          * Since such values are unreasonably low, we use -45 degC for
     774             :          * the lower limit instead.
     775             :          */
     776           0 :         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
     777           0 :         sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
     778           0 :         if (sdata > 0x0fa && sdata < 0x1a6) {
     779           0 :                 sensor->flags |= SENSOR_FINVALID;
     780           0 :                 sensor->value = 0;
     781           0 :         } else {
     782           0 :                 if (sdata & 0x100)
     783           0 :                         sdata -= 0x200;
     784           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     785           0 :                 sensor->value = sdata * 500000 + 273150000;
     786             :         }
     787           0 : }
     788             : 
     789             : void
     790           0 : wb_refresh_fanrpm(struct lm_softc *sc, int n)
     791             : {
     792           0 :         struct ksensor *sensor = &sc->sensors[n];
     793             :         int fan, data, divisor = 0;
     794             : 
     795             :         /* 
     796             :          * This is madness; the fan divisor bits are scattered all
     797             :          * over the place.
     798             :          */
     799             : 
     800           0 :         if (sc->lm_sensors[n].reg == LM_FAN1 ||
     801           0 :             sc->lm_sensors[n].reg == LM_FAN2 ||
     802           0 :             sc->lm_sensors[n].reg == LM_FAN3) {
     803           0 :                 data = sc->lm_readreg(sc, WB_BANK0_VBAT);
     804           0 :                 fan = (sc->lm_sensors[n].reg - LM_FAN1);
     805           0 :                 if ((data >> 5) & (1 << fan))
     806           0 :                         divisor |= 0x04;
     807             :         }
     808             : 
     809           0 :         if (sc->lm_sensors[n].reg == LM_FAN1 ||
     810           0 :             sc->lm_sensors[n].reg == LM_FAN2) {
     811           0 :                 data = sc->lm_readreg(sc, LM_VIDFAN);
     812           0 :                 if (sc->lm_sensors[n].reg == LM_FAN1)
     813           0 :                         divisor |= (data >> 4) & 0x03;
     814             :                 else
     815           0 :                         divisor |= (data >> 6) & 0x03;
     816           0 :         } else if (sc->lm_sensors[n].reg == LM_FAN3) {
     817           0 :                 data = sc->lm_readreg(sc, WB_PIN);
     818           0 :                 divisor |= (data >> 6) & 0x03;
     819           0 :         } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
     820           0 :                    sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
     821           0 :                 data = sc->lm_readreg(sc, WB_BANK0_FAN45);
     822           0 :                 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
     823           0 :                         divisor |= (data >> 0) & 0x07;
     824             :                 else
     825           0 :                         divisor |= (data >> 4) & 0x07;
     826             :         }
     827             : 
     828           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     829           0 :         if (data == 0xff || data == 0x00) {
     830           0 :                 sensor->flags |= SENSOR_FINVALID;
     831           0 :                 sensor->value = 0;
     832           0 :         } else {
     833           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     834           0 :                 sensor->value = 1350000 / (data << divisor);
     835             :         }
     836           0 : }
     837             : 
     838             : void
     839           0 : wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n)
     840             : {
     841           0 :         struct ksensor *sensor = &sc->sensors[n];
     842             :         int datah, datal;
     843             : 
     844           0 :         datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     845           0 :         datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1);
     846             : 
     847           0 :         if (datah == 0xff) {
     848           0 :                 sensor->flags |= SENSOR_FINVALID;
     849           0 :                 sensor->value = 0;
     850           0 :         } else {
     851           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     852           0 :                 sensor->value = (datah << 8) | datal;
     853             :         }
     854           0 : }
     855             : 
     856             : void
     857           0 : wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
     858             : {
     859           0 :         struct ksensor *sensor = &sc->sensors[n];
     860             :         int reg, shift, data, divisor = 1;
     861             : 
     862           0 :         switch (sc->lm_sensors[n].reg) {
     863             :         case 0x28:
     864             :                 reg = 0x47; shift = 0;
     865           0 :                 break;
     866             :         case 0x29:
     867             :                 reg = 0x47; shift = 4;
     868           0 :                 break;
     869             :         case 0x2a:
     870             :                 reg = 0x5b; shift = 0;
     871           0 :                 break;
     872             :         case 0xb8:
     873             :                 reg = 0x5b; shift = 4;
     874           0 :                 break;
     875             :         case 0xb9:
     876             :                 reg = 0x5c; shift = 0;
     877           0 :                 break;
     878             :         case 0xba:
     879             :                 reg = 0x5c; shift = 4;
     880           0 :                 break;
     881             :         case 0xbe:
     882             :                 reg = 0x9e; shift = 0;
     883           0 :                 break;
     884             :         default:
     885             :                 reg = 0;
     886           0 :                 break;
     887             :         }
     888             : 
     889           0 :         data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
     890           0 :         if (data == 0xff || data == 0x00) {
     891           0 :                 sensor->flags |= SENSOR_FINVALID;
     892           0 :                 sensor->value = 0;
     893           0 :         } else {
     894           0 :                 if (reg != 0)
     895           0 :                         divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
     896           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     897           0 :                 sensor->value = 1350000 / (data << divisor);
     898             :         }
     899           0 : }
     900             : 
     901             : void
     902           0 : as_refresh_temp(struct lm_softc *sc, int n)
     903             : {
     904           0 :         struct ksensor *sensor = &sc->sensors[n];
     905             :         int sdata;
     906             : 
     907             :         /*
     908             :          * It seems a shorted temperature diode produces an all-ones
     909             :          * bit pattern.
     910             :          */
     911           0 :         sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
     912           0 :         sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
     913           0 :         if (sdata == 0x1ff) {
     914           0 :                 sensor->flags |= SENSOR_FINVALID;
     915           0 :                 sensor->value = 0;
     916           0 :         } else {
     917           0 :                 if (sdata & 0x100)
     918           0 :                         sdata -= 0x200;
     919           0 :                 sensor->flags &= ~SENSOR_FINVALID;
     920           0 :                 sensor->value = sdata * 500000 + 273150000;
     921             :         }
     922           0 : }

Generated by: LCOV version 1.13