Home | History | Annotate | Line # | Download | only in ic
      1 /*	$NetBSD: nslm7x.c,v 1.79 2022/12/16 00:02:28 msaitoh Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Bill Squier.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.79 2022/12/16 00:02:28 msaitoh Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 #include <sys/proc.h>
     39 #include <sys/device.h>
     40 #include <sys/module.h>
     41 #include <sys/conf.h>
     42 #include <sys/time.h>
     43 
     44 #include <sys/bus.h>
     45 
     46 #include <dev/isa/isareg.h>
     47 #include <dev/isa/isavar.h>
     48 #include <dev/isa/wbsioreg.h>
     49 
     50 #include <dev/sysmon/sysmonvar.h>
     51 
     52 #include <dev/ic/nslm7xvar.h>
     53 
     54 #include <sys/intr.h>
     55 
     56 #if defined(LMDEBUG)
     57 #define DPRINTF(x)	do { printf x; } while (0)
     58 #else
     59 #define DPRINTF(x)
     60 #endif
     61 
     62 /*
     63  * LM78-compatible chips can typically measure voltages up to 4.096 V.
     64  * To measure higher voltages the input is attenuated with (external)
     65  * resistors.  Negative voltages are measured using inverting op amps
     66  * and resistors.  So we have to convert the sensor values back to
     67  * real voltages by applying the appropriate resistor factor.
     68  */
     69 #define RFACT_NONE	10000
     70 #define RFACT(x, y)	(RFACT_NONE * ((x) + (y)) / (y))
     71 #define NRFACT(x, y)	(-RFACT_NONE * (x) / (y))
     72 
     73 #define LM_REFRESH_TIMO	(2 * hz)	/* 2 seconds */
     74 
     75 static const struct wb_product *wb_lookup(struct lm_softc *,
     76     const struct wb_product *, uint16_t);
     77 static int wb_match(struct lm_softc *);
     78 static int wb_attach(struct lm_softc *);
     79 static int nslm_match(struct lm_softc *);
     80 static int nslm_attach(struct lm_softc *);
     81 static int def_match(struct lm_softc *);
     82 static int def_attach(struct lm_softc *);
     83 static void wb_temp_diode_type(struct lm_softc *, int);
     84 static uint16_t wb_read_vendorid(struct lm_softc *);
     85 
     86 static void lm_refresh(void *);
     87 
     88 static void lm_generic_banksel(struct lm_softc *, uint8_t);
     89 static void lm_setup_sensors(struct lm_softc *, const struct lm_sensor *);
     90 static void lm_refresh_sensor_data(struct lm_softc *);
     91 static void lm_refresh_volt(struct lm_softc *, int);
     92 static void lm_refresh_temp(struct lm_softc *, int);
     93 static void lm_refresh_fanrpm(struct lm_softc *, int);
     94 
     95 static void wb_refresh_sensor_data(struct lm_softc *);
     96 static void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
     97 static void wb_refresh_nvolt(struct lm_softc *, int);
     98 static void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
     99 static void wb_refresh_temp(struct lm_softc *, int);
    100 static void wb_refresh_fanrpm(struct lm_softc *, int);
    101 static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
    102 static void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
    103 
    104 static void as_refresh_temp(struct lm_softc *, int);
    105 
    106 struct lm_chip {
    107 	int (*chip_match)(struct lm_softc *);
    108 	int (*chip_attach)(struct lm_softc *);
    109 };
    110 
    111 static struct lm_chip lm_chips[] = {
    112 	{ wb_match,	wb_attach },
    113 	{ nslm_match,	nslm_attach },
    114 	{ def_match,	def_attach } /* Must be last */
    115 };
    116 
    117 /* LM78/78J/79/81 */
    118 static const struct lm_sensor lm78_sensors[] = {
    119 	/* Voltage */
    120 	{
    121 		.desc = "VCore A",
    122 		.type = ENVSYS_SVOLTS_DC,
    123 		.bank = 0,
    124 		.reg = 0x20,
    125 		.refresh = lm_refresh_volt,
    126 		.rfact = RFACT_NONE
    127 	},
    128 	{
    129 		.desc = "VCore B",
    130 		.type = ENVSYS_SVOLTS_DC,
    131 		.bank = 0,
    132 		.reg = 0x21,
    133 		.refresh = lm_refresh_volt,
    134 		.rfact = RFACT_NONE
    135 	},
    136 	{
    137 		.desc = "+3.3V",
    138 		.type = ENVSYS_SVOLTS_DC,
    139 		.bank = 0,
    140 		.reg = 0x22,
    141 		.refresh = lm_refresh_volt,
    142 		.rfact = RFACT_NONE
    143 	},
    144 	{
    145 		.desc = "+5V",
    146 		.type = ENVSYS_SVOLTS_DC,
    147 		.bank = 0,
    148 		.reg = 0x23,
    149 		.refresh = lm_refresh_volt,
    150 		.rfact = RFACT(68, 100)
    151 	},
    152 	{
    153 		.desc = "+12V",
    154 		.type = ENVSYS_SVOLTS_DC,
    155 		.bank = 0,
    156 		.reg = 0x24,
    157 		.refresh = lm_refresh_volt,
    158 		.rfact = RFACT(30, 10)
    159 	},
    160 	{
    161 		.desc = "-12V",
    162 		.type = ENVSYS_SVOLTS_DC,
    163 		.bank = 0,
    164 		.reg = 0x25,
    165 		.refresh = lm_refresh_volt,
    166 		.rfact = NRFACT(240, 60)
    167 	},
    168 	{
    169 		.desc = "-5V",
    170 		.type = ENVSYS_SVOLTS_DC,
    171 		.bank = 0,
    172 		.reg = 0x26,
    173 		.refresh = lm_refresh_volt,
    174 		.rfact = NRFACT(100, 60)
    175 	},
    176 
    177 	/* Temperature */
    178 	{
    179 		.desc = "Temp0",
    180 		.type = ENVSYS_STEMP,
    181 		.bank = 0,
    182 		.reg = 0x27,
    183 		.refresh = lm_refresh_temp,
    184 		.rfact = 0
    185 	},
    186 
    187 	/* Fans */
    188 	{
    189 		.desc = "Fan0",
    190 		.type = ENVSYS_SFANRPM,
    191 		.bank = 0,
    192 		.reg = 0x28,
    193 		.refresh = lm_refresh_fanrpm,
    194 		.rfact = 0
    195 	},
    196 	{
    197 		.desc = "Fan1",
    198 		.type = ENVSYS_SFANRPM,
    199 		.bank = 0,
    200 		.reg = 0x29,
    201 		.refresh = lm_refresh_fanrpm,
    202 		.rfact = 0
    203 	},
    204 	{
    205 		.desc = "Fan2",
    206 		.type = ENVSYS_SFANRPM,
    207 		.bank = 0,
    208 		.reg = 0x2a,
    209 		.refresh = lm_refresh_fanrpm,
    210 		.rfact = 0
    211 	},
    212 
    213 	{ .desc = NULL }
    214 };
    215 
    216 /* W83627HF */
    217 static const struct lm_sensor w83627hf_sensors[] = {
    218 	/* Voltage */
    219 	{
    220 		.desc = "VCore A",
    221 		.type = ENVSYS_SVOLTS_DC,
    222 		.bank = 0,
    223 		.reg = 0x20,
    224 		.refresh = lm_refresh_volt,
    225 		.rfact = RFACT_NONE
    226 	},
    227 	{
    228 		.desc = "VCore B",
    229 		.type = ENVSYS_SVOLTS_DC,
    230 		.bank = 0,
    231 		.reg = 0x21,
    232 		.refresh = lm_refresh_volt,
    233 		.rfact = RFACT_NONE
    234 	},
    235 	{
    236 		.desc = "+3.3V",
    237 		.type = ENVSYS_SVOLTS_DC,
    238 		.bank = 0,
    239 		.reg = 0x22,
    240 		.refresh = lm_refresh_volt,
    241 		.rfact = RFACT_NONE
    242 	},
    243 	{
    244 		.desc = "+5V",
    245 		.type = ENVSYS_SVOLTS_DC,
    246 		.bank = 0,
    247 		.reg = 0x23,
    248 		.refresh = lm_refresh_volt,
    249 		.rfact = RFACT(34, 50)
    250 	},
    251 	{
    252 		.desc = "+12V",
    253 		.type = ENVSYS_SVOLTS_DC,
    254 		.bank = 0,
    255 		.reg = 0x24,
    256 		.refresh = lm_refresh_volt,
    257 		.rfact = RFACT(28, 10)
    258 	},
    259 	{
    260 		.desc = "-12V",
    261 		.type = ENVSYS_SVOLTS_DC,
    262 		.bank = 0,
    263 		.reg = 0x25,
    264 		.refresh = wb_refresh_nvolt,
    265 		.rfact = RFACT(232, 56)
    266 	},
    267 	{
    268 		.desc = "-5V",
    269 		.type = ENVSYS_SVOLTS_DC,
    270 		.bank = 0,
    271 		.reg = 0x26,
    272 		.refresh = wb_refresh_nvolt,
    273 		.rfact = RFACT(120, 56)
    274 	},
    275 	{
    276 		.desc = "5VSB",
    277 		.type = ENVSYS_SVOLTS_DC,
    278 		.bank = 5,
    279 		.reg = 0x50,
    280 		.refresh = lm_refresh_volt,
    281 		.rfact = RFACT(17, 33)
    282 	},
    283 	{
    284 		.desc = "VBAT",
    285 		.type = ENVSYS_SVOLTS_DC,
    286 		.bank = 5,
    287 		.reg = 0x51,
    288 		.refresh = lm_refresh_volt,
    289 		.rfact = RFACT_NONE
    290 	},
    291 
    292 	/* Temperature */
    293 	{
    294 		.desc = "Temp0",
    295 		.type = ENVSYS_STEMP,
    296 		.bank = 0,
    297 		.reg = 0x27,
    298 		.refresh = lm_refresh_temp,
    299 		.rfact = 0
    300 	},
    301 	{
    302 		.desc = "Temp1",
    303 		.type = ENVSYS_STEMP,
    304 		.bank = 1,
    305 		.reg = 0x50,
    306 		.refresh = wb_refresh_temp,
    307 		.rfact = 0
    308 	},
    309 	{
    310 		.desc = "Temp2",
    311 		.type = ENVSYS_STEMP,
    312 		.bank = 2,
    313 		.reg = 0x50,
    314 		.refresh = wb_refresh_temp,
    315 		.rfact = 0
    316 	},
    317 
    318 	/* Fans */
    319 	{
    320 		.desc = "Fan0",
    321 		.type = ENVSYS_SFANRPM,
    322 		.bank = 0,
    323 		.reg = 0x28,
    324 		.refresh = wb_refresh_fanrpm,
    325 		.rfact = 0
    326 	},
    327 	{
    328 		.desc = "Fan1",
    329 		.type = ENVSYS_SFANRPM,
    330 		.bank = 0,
    331 		.reg = 0x29,
    332 		.refresh = wb_refresh_fanrpm,
    333 		.rfact = 0
    334 	},
    335 	{
    336 		.desc = "Fan2",
    337 		.type = ENVSYS_SFANRPM,
    338 		.bank = 0,
    339 		.reg = 0x2a,
    340 		.refresh = wb_refresh_fanrpm,
    341 		.rfact = 0
    342 	},
    343 
    344 	{ .desc = NULL }
    345 };
    346 
    347 /* W8627EHF */
    348 
    349 /*
    350  * The W83627EHF can measure voltages up to 2.048 V instead of the
    351  * traditional 4.096 V.  For measuring positive voltages, this can be
    352  * accounted for by halving the resistor factor.  Negative voltages
    353  * need special treatment, also because the reference voltage is 2.048 V
    354  * instead of the traditional 3.6 V.
    355  */
    356 static const struct lm_sensor w83627ehf_sensors[] = {
    357 	/* Voltage */
    358 	{
    359 		.desc = "VCore",
    360 		.type = ENVSYS_SVOLTS_DC,
    361 		.bank = 0,
    362 		.reg = 0x20,
    363 		.refresh = lm_refresh_volt,
    364 		.rfact = RFACT_NONE / 2
    365 	},
    366 	{
    367 		.desc = "+12V",
    368 		.type = ENVSYS_SVOLTS_DC,
    369 		.bank = 0,
    370 		.reg = 0x21,
    371 		.refresh = lm_refresh_volt,
    372 		.rfact = RFACT(56, 10) / 2
    373 	},
    374 	{
    375 		.desc = "+3.3V",
    376 		.type = ENVSYS_SVOLTS_DC,
    377 		.bank = 0,
    378 		.reg = 0x22,
    379 		.refresh = lm_refresh_volt,
    380 		.rfact = RFACT(34, 34) / 2
    381 	},
    382 	{
    383 		.desc = "VIN3",
    384 		.type = ENVSYS_SVOLTS_DC,
    385 		.bank = 0,
    386 		.reg = 0x23,
    387 		.refresh = lm_refresh_volt,
    388 		.rfact = RFACT(34, 34) / 2
    389 	},
    390 	{
    391 		.desc = "-12V",
    392 		.type = ENVSYS_SVOLTS_DC,
    393 		.bank = 0,
    394 		.reg = 0x24,
    395 		.refresh = wb_w83627ehf_refresh_nvolt,
    396 		.rfact = 0
    397 	},
    398 	{
    399 		.desc = "VIN5",
    400 		.type = ENVSYS_SVOLTS_DC,
    401 		.bank = 0,
    402 		.reg = 0x25,
    403 		.refresh = lm_refresh_volt,
    404 		.rfact = RFACT_NONE / 2
    405 	},
    406 	{
    407 		.desc = "VIN6",
    408 		.type = ENVSYS_SVOLTS_DC,
    409 		.bank = 0,
    410 		.reg = 0x26,
    411 		.refresh = lm_refresh_volt,
    412 		.rfact = RFACT_NONE / 2
    413 	},
    414 	{
    415 		.desc = "3.3VSB",
    416 		.type = ENVSYS_SVOLTS_DC,
    417 		.bank = 5,
    418 		.reg = 0x50,
    419 		.refresh = lm_refresh_volt,
    420 		.rfact = RFACT(34, 34) / 2
    421 	},
    422 	{
    423 		.desc = "VBAT",
    424 		.type = ENVSYS_SVOLTS_DC,
    425 		.bank = 5,
    426 		.reg = 0x51,
    427 		.refresh = lm_refresh_volt,
    428 		.rfact = RFACT_NONE / 2
    429 	},
    430 	{
    431 		.desc = "VIN8",
    432 		.type = ENVSYS_SVOLTS_DC,
    433 		.bank = 5,
    434 		.reg = 0x52,
    435 		.refresh = lm_refresh_volt,
    436 		.rfact = RFACT_NONE / 2
    437 	},
    438 
    439 	/* Temperature */
    440 	{
    441 		.desc = "Temp0",
    442 		.type = ENVSYS_STEMP,
    443 		.bank = 0,
    444 		.reg = 0x27,
    445 		.refresh = lm_refresh_temp,
    446 		.rfact = 0
    447 	},
    448 	{
    449 		.desc = "Temp1",
    450 		.type = ENVSYS_STEMP,
    451 		.bank = 1,
    452 		.reg = 0x50,
    453 		.refresh = wb_refresh_temp,
    454 		.rfact = 0
    455 	},
    456 	{
    457 		.desc = "Temp2",
    458 		.type = ENVSYS_STEMP,
    459 		.bank = 2,
    460 		.reg = 0x50,
    461 		.refresh = wb_refresh_temp,
    462 		.rfact = 0
    463 	},
    464 
    465 	/* Fans */
    466 	{
    467 		.desc = "Fan0",
    468 		.type = ENVSYS_SFANRPM,
    469 		.bank = 0,
    470 		.reg = 0x28,
    471 		.refresh = wb_refresh_fanrpm,
    472 		.rfact = 0
    473 	},
    474 	{
    475 		.desc = "Fan1",
    476 		.type = ENVSYS_SFANRPM,
    477 		.bank = 0,
    478 		.reg = 0x29,
    479 		.refresh = wb_refresh_fanrpm,
    480 		.rfact = 0
    481 	},
    482 	{
    483 		.desc = "Fan2",
    484 		.type = ENVSYS_SFANRPM,
    485 		.bank = 0,
    486 		.reg = 0x2a,
    487 		.refresh = wb_refresh_fanrpm,
    488 		.rfact = 0
    489 	},
    490 
    491 	{ .desc = NULL }
    492 };
    493 
    494 /*  W83627DHG */
    495 static const struct lm_sensor w83627dhg_sensors[] = {
    496 	/* Voltage */
    497 	{
    498 		.desc = "VCore",
    499 		.type = ENVSYS_SVOLTS_DC,
    500 		.bank = 0,
    501 		.reg = 0x20,
    502 		.refresh = lm_refresh_volt,
    503 		.rfact = RFACT_NONE / 2
    504 	},
    505 	{
    506 		.desc = "+12V",
    507 		.type = ENVSYS_SVOLTS_DC,
    508 		.bank = 0,
    509 		.reg = 0x21,
    510 		.refresh = lm_refresh_volt,
    511 		.rfact = RFACT(56, 10) / 2
    512 	},
    513 	{
    514 		.desc = "AVCC",
    515 		.type = ENVSYS_SVOLTS_DC,
    516 		.bank = 0,
    517 		.reg = 0x22,
    518 		.refresh = lm_refresh_volt,
    519 		.rfact = RFACT(34, 34) / 2
    520 	},
    521 	{
    522 		.desc = "+3.3V",
    523 		.type = ENVSYS_SVOLTS_DC,
    524 		.bank = 0,
    525 		.reg = 0x23,
    526 		.refresh = lm_refresh_volt,
    527 		.rfact = RFACT(34, 34) / 2
    528 	},
    529 	{
    530 		.desc = "-12V",
    531 		.type = ENVSYS_SVOLTS_DC,
    532 		.bank = 0,
    533 		.reg = 0x24,
    534 		.refresh = wb_w83627ehf_refresh_nvolt,
    535 		.rfact = 0
    536 	},
    537 	{
    538 		.desc = "+5V",
    539 		.type = ENVSYS_SVOLTS_DC,
    540 		.bank = 0,
    541 		.reg = 0x25,
    542 		.refresh = lm_refresh_volt,
    543 		.rfact = 16000
    544 	},
    545 	{
    546 		.desc = "VIN3",
    547 		.type = ENVSYS_SVOLTS_DC,
    548 		.bank = 0,
    549 		.reg = 0x26,
    550 		.refresh = lm_refresh_volt,
    551 		.rfact = RFACT_NONE
    552 	},
    553 	{
    554 		.desc = "+3.3VSB",
    555 		.type = ENVSYS_SVOLTS_DC,
    556 		.bank = 5,
    557 		.reg = 0x50,
    558 		.refresh = lm_refresh_volt,
    559 		.rfact = RFACT(34, 34) / 2
    560 	},
    561 	{
    562 		.desc = "VBAT",
    563 		.type = ENVSYS_SVOLTS_DC,
    564 		.bank = 5,
    565 		.reg = 0x51,
    566 		.refresh = lm_refresh_volt,
    567 		.rfact = RFACT(34, 34) / 2
    568 	},
    569 
    570 	/* Temperature */
    571 	{
    572 		.desc = "MB Temperature",
    573 		.type = ENVSYS_STEMP,
    574 		.bank = 0,
    575 		.reg = 0x27,
    576 		.refresh = lm_refresh_temp,
    577 		.rfact = 0
    578 	},
    579 	{
    580 		.desc = "CPU Temperature",
    581 		.type = ENVSYS_STEMP,
    582 		.bank = 1,
    583 		.reg = 0x50,
    584 		.refresh = lm_refresh_temp,
    585 		.rfact = 0
    586 	},
    587 	{
    588 		.desc = "Aux Temp",
    589 		.type = ENVSYS_STEMP,
    590 		.bank = 2,
    591 		.reg = 0x50,
    592 		.refresh = lm_refresh_temp,
    593 		.rfact = 0
    594 	},
    595 
    596 	/* Fans */
    597 	{
    598 		.desc = "System Fan",
    599 		.type = ENVSYS_SFANRPM,
    600 		.bank = 0,
    601 		.reg = 0x28,
    602 		.refresh = wb_refresh_fanrpm,
    603 		.rfact = 0
    604 	},
    605 	{
    606 		.desc = "CPU Fan",
    607 		.type = ENVSYS_SFANRPM,
    608 		.bank = 0,
    609 		.reg = 0x29,
    610 		.refresh = wb_refresh_fanrpm,
    611 		.rfact = 0
    612 	},
    613 	{
    614 		.desc = "Aux Fan",
    615 		.type = ENVSYS_SFANRPM,
    616 		.bank = 0,
    617 		.reg = 0x2a,
    618 		.refresh = wb_refresh_fanrpm,
    619 		.rfact = 0
    620 	},
    621 
    622 	{ .desc = NULL }
    623 };
    624 
    625 /* W83637HF */
    626 static const struct lm_sensor w83637hf_sensors[] = {
    627 	/* Voltage */
    628 	{
    629 		.desc = "VCore",
    630 		.type = ENVSYS_SVOLTS_DC,
    631 		.bank = 0,
    632 		.reg = 0x20,
    633 		.refresh = wb_w83637hf_refresh_vcore,
    634 		.rfact = 0
    635 	},
    636 	{
    637 		.desc = "+12V",
    638 		.type = ENVSYS_SVOLTS_DC,
    639 		.bank = 0,
    640 		.reg = 0x21,
    641 		.refresh = lm_refresh_volt,
    642 		.rfact = RFACT(28, 10)
    643 	},
    644 	{
    645 		.desc = "+3.3V",
    646 		.type = ENVSYS_SVOLTS_DC,
    647 		.bank = 0,
    648 		.reg = 0x22,
    649 		.refresh = lm_refresh_volt,
    650 		.rfact = RFACT_NONE
    651 	},
    652 	{
    653 		.desc = "+5V",
    654 		.type = ENVSYS_SVOLTS_DC,
    655 		.bank = 0,
    656 		.reg = 0x23,
    657 		.refresh = lm_refresh_volt,
    658 		.rfact = RFACT(34, 51)
    659 	},
    660 	{
    661 		.desc = "-12V",
    662 		.type = ENVSYS_SVOLTS_DC,
    663 		.bank = 0,
    664 		.reg = 0x24,
    665 		.refresh = wb_refresh_nvolt,
    666 		.rfact = RFACT(232, 56)
    667 	},
    668 	{
    669 		.desc = "5VSB",
    670 		.type = ENVSYS_SVOLTS_DC,
    671 		.bank = 5,
    672 		.reg = 0x50,
    673 		.refresh = lm_refresh_volt,
    674 		.rfact = RFACT(34, 51)
    675 	},
    676 	{
    677 		.desc = "VBAT",
    678 		.type = ENVSYS_SVOLTS_DC,
    679 		.bank = 5,
    680 		.reg = 0x51,
    681 		.refresh = lm_refresh_volt,
    682 		.rfact = RFACT_NONE
    683 	},
    684 
    685 	/* Temperature */
    686 	{
    687 		.desc = "Temp0",
    688 		.type = ENVSYS_STEMP,
    689 		.bank = 0,
    690 		.reg = 0x27,
    691 		.refresh = lm_refresh_temp,
    692 		.rfact = 0
    693 	},
    694 	{
    695 		.desc = "Temp1",
    696 		.type = ENVSYS_STEMP,
    697 		.bank = 1,
    698 		.reg = 0x50,
    699 		.refresh = wb_refresh_temp,
    700 		.rfact = 0
    701 	},
    702 	{
    703 		.desc = "Temp2",
    704 		.type = ENVSYS_STEMP,
    705 		.bank = 2,
    706 		.reg = 0x50,
    707 		.refresh = wb_refresh_temp,
    708 		.rfact = 0
    709 	},
    710 
    711 	/* Fans */
    712 	{
    713 		.desc = "Fan0",
    714 		.type = ENVSYS_SFANRPM,
    715 		.bank = 0,
    716 		.reg = 0x28,
    717 		.refresh = wb_refresh_fanrpm,
    718 		.rfact = 0
    719 	},
    720 	{
    721 		.desc = "Fan1",
    722 		.type = ENVSYS_SFANRPM,
    723 		.bank = 0,
    724 		.reg = 0x29,
    725 		.refresh = wb_refresh_fanrpm,
    726 		.rfact = 0
    727 	},
    728 	{
    729 		.desc = "Fan2",
    730 		.type = ENVSYS_SFANRPM,
    731 		.bank = 0,
    732 		.reg = 0x2a,
    733 		.refresh = wb_refresh_fanrpm,
    734 		.rfact = 0
    735 	},
    736 
    737 	{ .desc = NULL }
    738 };
    739 
    740 /* W83697HF */
    741 static const struct lm_sensor w83697hf_sensors[] = {
    742 	/* Voltage */
    743 	{
    744 		.desc = "VCore",
    745 		.type = ENVSYS_SVOLTS_DC,
    746 		.bank = 0,
    747 		.reg = 0x20,
    748 		.refresh = lm_refresh_volt,
    749 		.rfact = RFACT_NONE
    750 	},
    751 	{
    752 		.desc = "+3.3V",
    753 		.type = ENVSYS_SVOLTS_DC,
    754 		.bank = 0,
    755 		.reg = 0x22,
    756 		.refresh = lm_refresh_volt,
    757 		.rfact = RFACT_NONE
    758 	},
    759 	{
    760 		.desc = "+5V",
    761 		.type = ENVSYS_SVOLTS_DC,
    762 		.bank = 0,
    763 		.reg = 0x23,
    764 		.refresh = lm_refresh_volt,
    765 		.rfact = RFACT(34, 50)
    766 	},
    767 	{
    768 		.desc = "+12V",
    769 		.type = ENVSYS_SVOLTS_DC,
    770 		.bank = 0,
    771 		.reg = 0x24,
    772 		.refresh = lm_refresh_volt,
    773 		.rfact = RFACT(28, 10)
    774 	},
    775 	{
    776 		.desc = "-12V",
    777 		.type = ENVSYS_SVOLTS_DC,
    778 		.bank = 0,
    779 		.reg = 0x25,
    780 		.refresh = wb_refresh_nvolt,
    781 		.rfact = RFACT(232, 56)
    782 	},
    783 	{
    784 		.desc = "-5V",
    785 		.type = ENVSYS_SVOLTS_DC,
    786 		.bank = 0,
    787 		.reg = 0x26,
    788 		.refresh = wb_refresh_nvolt,
    789 		.rfact = RFACT(120, 56)
    790 	},
    791 	{
    792 		.desc = "5VSB",
    793 		.type = ENVSYS_SVOLTS_DC,
    794 		.bank = 5,
    795 		.reg = 0x50,
    796 		.refresh = lm_refresh_volt,
    797 		.rfact = RFACT(17, 33)
    798 	},
    799 	{
    800 		.desc = "VBAT",
    801 		.type = ENVSYS_SVOLTS_DC,
    802 		.bank = 5,
    803 		.reg = 0x51,
    804 		.refresh = lm_refresh_volt,
    805 		.rfact = RFACT_NONE
    806 	},
    807 
    808 	/* Temperature */
    809 	{
    810 		.desc = "Temp0",
    811 		.type = ENVSYS_STEMP,
    812 		.bank = 0,
    813 		.reg = 0x27,
    814 		.refresh = lm_refresh_temp,
    815 		.rfact = 0
    816 	},
    817 	{
    818 		.desc = "Temp1",
    819 		.type = ENVSYS_STEMP,
    820 		.bank = 1,
    821 		.reg = 0x50,
    822 		.refresh = wb_refresh_temp,
    823 		.rfact = 0
    824 	},
    825 
    826 	/* Fans */
    827 	{
    828 		.desc = "Fan0",
    829 		.type = ENVSYS_SFANRPM,
    830 		.bank = 0,
    831 		.reg = 0x28,
    832 		.refresh = wb_refresh_fanrpm,
    833 		.rfact = 0
    834 	},
    835 	{
    836 		.desc = "Fan1",
    837 		.type = ENVSYS_SFANRPM,
    838 		.bank = 0,
    839 		.reg = 0x29,
    840 		.refresh = wb_refresh_fanrpm,
    841 		.rfact = 0
    842 	},
    843 
    844 	{ .desc = NULL }
    845 };
    846 
    847 /* W83781D */
    848 
    849 /*
    850  * The datasheet doesn't mention the (internal) resistors used for the
    851  * +5V, but using the values from the W83782D datasheets seems to
    852  * provide sensible results.
    853  */
    854 static const struct lm_sensor w83781d_sensors[] = {
    855 	/* Voltage */
    856 	{
    857 		.desc = "VCore A",
    858 		.type = ENVSYS_SVOLTS_DC,
    859 		.bank = 0,
    860 		.reg = 0x20,
    861 		.refresh = lm_refresh_volt,
    862 		.rfact = RFACT_NONE
    863 	},
    864 	{
    865 		.desc = "VCore B",
    866 		.type = ENVSYS_SVOLTS_DC,
    867 		.bank = 0,
    868 		.reg = 0x21,
    869 		.refresh = lm_refresh_volt,
    870 		.rfact = RFACT_NONE
    871 	},
    872 	{
    873 		.desc = "+3.3V",
    874 		.type = ENVSYS_SVOLTS_DC,
    875 		.bank = 0,
    876 		.reg = 0x22,
    877 		.refresh = lm_refresh_volt,
    878 		.rfact = RFACT_NONE
    879 	},
    880 	{
    881 		.desc = "+5V",
    882 		.type = ENVSYS_SVOLTS_DC,
    883 		.bank = 0,
    884 		.reg = 0x23,
    885 		.refresh = lm_refresh_volt,
    886 		.rfact = RFACT(34, 50)
    887 	},
    888 	{
    889 		.desc = "+12V",
    890 		.type = ENVSYS_SVOLTS_DC,
    891 		.bank = 0,
    892 		.reg = 0x24,
    893 		.refresh = lm_refresh_volt,
    894 		.rfact = RFACT(28, 10)
    895 	},
    896 	{
    897 		.desc = "-12V",
    898 		.type = ENVSYS_SVOLTS_DC,
    899 		.bank = 0,
    900 		.reg = 0x25,
    901 		.refresh = lm_refresh_volt,
    902 		.rfact = NRFACT(2100, 604)
    903 	},
    904 	{
    905 		.desc = "-5V",
    906 		.type = ENVSYS_SVOLTS_DC,
    907 		.bank = 0,
    908 		.reg = 0x26,
    909 		.refresh = lm_refresh_volt,
    910 		.rfact = NRFACT(909, 604)
    911 	},
    912 
    913 	/* Temperature */
    914 	{
    915 		.desc = "Temp0",
    916 		.type = ENVSYS_STEMP,
    917 		.bank = 0,
    918 		.reg = 0x27,
    919 		.refresh = lm_refresh_temp,
    920 		.rfact = 0
    921 	},
    922 	{
    923 		.desc = "Temp1",
    924 		.type = ENVSYS_STEMP,
    925 		.bank = 1,
    926 		.reg = 0x50,
    927 		.refresh = wb_refresh_temp,
    928 		.rfact = 0
    929 	},
    930 	{
    931 		.desc = "Temp2",
    932 		.type = ENVSYS_STEMP,
    933 		.bank = 2,
    934 		.reg = 0x50,
    935 		.refresh = wb_refresh_temp,
    936 		.rfact = 0
    937 	},
    938 
    939 	/* Fans */
    940 	{
    941 		.desc = "Fan0",
    942 		.type = ENVSYS_SFANRPM,
    943 		.bank = 0,
    944 		.reg = 0x28,
    945 		.refresh = lm_refresh_fanrpm,
    946 		.rfact = 0
    947 	},
    948 	{
    949 		.desc = "Fan1",
    950 		.type = ENVSYS_SFANRPM,
    951 		.bank = 0,
    952 		.reg = 0x29,
    953 		.refresh = lm_refresh_fanrpm,
    954 		.rfact = 0
    955 	},
    956 	{
    957 		.desc = "Fan2",
    958 		.type = ENVSYS_SFANRPM,
    959 		.bank = 0,
    960 		.reg = 0x2a,
    961 		.refresh = lm_refresh_fanrpm,
    962 		.rfact = 0
    963 	},
    964 
    965 	{ .desc = NULL }
    966 };
    967 
    968 /* W83782D */
    969 static const struct lm_sensor w83782d_sensors[] = {
    970 	/* Voltage */
    971 	{
    972 		.desc = "VCore",
    973 		.type = ENVSYS_SVOLTS_DC,
    974 		.bank = 0,
    975 		.reg = 0x20,
    976 		.refresh = lm_refresh_volt,
    977 		.rfact = RFACT_NONE
    978 	},
    979 	{
    980 		.desc = "VINR0",
    981 		.type = ENVSYS_SVOLTS_DC,
    982 		.bank = 0,
    983 		.reg = 0x21,
    984 		.refresh = lm_refresh_volt,
    985 		.rfact = RFACT_NONE
    986 	},
    987 	{
    988 		.desc = "+3.3V",
    989 		.type = ENVSYS_SVOLTS_DC,
    990 		.bank = 0,
    991 		.reg = 0x22,
    992 		.refresh = lm_refresh_volt,
    993 		.rfact = RFACT_NONE
    994 	},
    995 	{
    996 		.desc = "+5V",
    997 		.type = ENVSYS_SVOLTS_DC,
    998 		.bank = 0,
    999 		.reg = 0x23,
   1000 		.refresh = lm_refresh_volt,
   1001 		.rfact = RFACT(34, 50)
   1002 	},
   1003 	{
   1004 		.desc = "+12V",
   1005 		.type = ENVSYS_SVOLTS_DC,
   1006 		.bank = 0,
   1007 		.reg = 0x24,
   1008 		.refresh = lm_refresh_volt,
   1009 		.rfact = RFACT(28, 10)
   1010 	},
   1011 	{
   1012 		.desc = "-12V",
   1013 		.type = ENVSYS_SVOLTS_DC,
   1014 		.bank = 0,
   1015 		.reg = 0x25,
   1016 		.refresh = wb_refresh_nvolt,
   1017 		.rfact = RFACT(232, 56)
   1018 	},
   1019 	{
   1020 		.desc = "-5V",
   1021 		.type = ENVSYS_SVOLTS_DC,
   1022 		.bank = 0,
   1023 		.reg = 0x26,
   1024 		.refresh = wb_refresh_nvolt,
   1025 		.rfact = RFACT(120, 56)
   1026 	},
   1027 	{
   1028 		.desc = "5VSB",
   1029 		.type = ENVSYS_SVOLTS_DC,
   1030 		.bank = 5,
   1031 		.reg = 0x50,
   1032 		.refresh = lm_refresh_volt,
   1033 		.rfact = RFACT(17, 33)
   1034 	},
   1035 	{
   1036 		.desc = "VBAT",
   1037 		.type = ENVSYS_SVOLTS_DC,
   1038 		.bank = 5,
   1039 		.reg = 0x51,
   1040 		.refresh = lm_refresh_volt,
   1041 		.rfact = RFACT_NONE
   1042 	},
   1043 
   1044 	/* Temperature */
   1045 	{
   1046 		.desc = "Temp0",
   1047 		.type = ENVSYS_STEMP,
   1048 		.bank = 0,
   1049 		.reg = 0x27,
   1050 		.refresh = lm_refresh_temp,
   1051 		.rfact = 0
   1052 	},
   1053 	{
   1054 		.desc = "Temp1",
   1055 		.type = ENVSYS_STEMP,
   1056 		.bank = 1,
   1057 		.reg = 0x50,
   1058 		.refresh = wb_refresh_temp,
   1059 		.rfact = 0
   1060 	},
   1061 	{
   1062 		.desc = "Temp2",
   1063 		.type = ENVSYS_STEMP,
   1064 		.bank = 2,
   1065 		.reg = 0x50,
   1066 		.refresh = wb_refresh_temp,
   1067 		.rfact = 0
   1068 	},
   1069 
   1070 	/* Fans */
   1071 	{
   1072 		.desc = "Fan0",
   1073 		.type = ENVSYS_SFANRPM,
   1074 		.bank = 0,
   1075 		.reg = 0x28,
   1076 		.refresh = wb_refresh_fanrpm,
   1077 		.rfact = 0
   1078 	},
   1079 	{
   1080 		.desc = "Fan1",
   1081 		.type = ENVSYS_SFANRPM,
   1082 		.bank = 0,
   1083 		.reg = 0x29,
   1084 		.refresh = wb_refresh_fanrpm,
   1085 		.rfact = 0
   1086 	},
   1087 	{
   1088 		.desc = "Fan2",
   1089 		.type = ENVSYS_SFANRPM,
   1090 		.bank = 0,
   1091 		.reg = 0x2a,
   1092 		.refresh = wb_refresh_fanrpm,
   1093 		.rfact = 0
   1094 	},
   1095 
   1096 	{ .desc = NULL }
   1097 };
   1098 
   1099 /* W83783S */
   1100 static const struct lm_sensor w83783s_sensors[] = {
   1101 	/* Voltage */
   1102 	{
   1103 		.desc = "VCore",
   1104 		.type = ENVSYS_SVOLTS_DC,
   1105 		.bank = 0,
   1106 		.reg = 0x20,
   1107 		.refresh = lm_refresh_volt,
   1108 		.rfact = RFACT_NONE
   1109 	},
   1110 	{
   1111 		.desc = "+3.3V",
   1112 		.type = ENVSYS_SVOLTS_DC,
   1113 		.bank = 0,
   1114 		.reg = 0x22,
   1115 		.refresh = lm_refresh_volt,
   1116 		.rfact = RFACT_NONE
   1117 	},
   1118 	{
   1119 		.desc = "+5V",
   1120 		.type = ENVSYS_SVOLTS_DC,
   1121 		.bank = 0,
   1122 		.reg = 0x23,
   1123 		.refresh = lm_refresh_volt,
   1124 		.rfact = RFACT(34, 50)
   1125 	},
   1126 	{
   1127 		.desc = "+12V",
   1128 		.type = ENVSYS_SVOLTS_DC,
   1129 		.bank = 0,
   1130 		.reg = 0x24,
   1131 		.refresh = lm_refresh_volt,
   1132 		.rfact = RFACT(28, 10)
   1133 	},
   1134 	{
   1135 		.desc = "-12V",
   1136 		.type = ENVSYS_SVOLTS_DC,
   1137 		.bank = 0,
   1138 		.reg = 0x25,
   1139 		.refresh = wb_refresh_nvolt,
   1140 		.rfact = RFACT(232, 56)
   1141 	},
   1142 	{
   1143 		.desc = "-5V",
   1144 		.type = ENVSYS_SVOLTS_DC,
   1145 		.bank = 0,
   1146 		.reg = 0x26,
   1147 		.refresh = wb_refresh_nvolt,
   1148 		.rfact = RFACT(120, 56)
   1149 	},
   1150 
   1151 	/* Temperature */
   1152 	{
   1153 		.desc = "Temp0",
   1154 		.type = ENVSYS_STEMP,
   1155 		.bank = 0,
   1156 		.reg = 0x27,
   1157 		.refresh = lm_refresh_temp,
   1158 		.rfact = 0
   1159 	},
   1160 	{
   1161 		.desc = "Temp1",
   1162 		.type = ENVSYS_STEMP,
   1163 		.bank = 1,
   1164 		.reg = 0x50,
   1165 		.refresh = wb_refresh_temp,
   1166 		.rfact = 0
   1167 	},
   1168 
   1169 	/* Fans */
   1170 	{
   1171 		.desc = "Fan0",
   1172 		.type = ENVSYS_SFANRPM,
   1173 		.bank = 0,
   1174 		.reg = 0x28,
   1175 		.refresh = wb_refresh_fanrpm,
   1176 		.rfact = 0
   1177 	},
   1178 	{
   1179 		.desc = "Fan1",
   1180 		.type = ENVSYS_SFANRPM,
   1181 		.bank = 0,
   1182 		.reg = 0x29,
   1183 		.refresh = wb_refresh_fanrpm,
   1184 		.rfact = 0
   1185 	},
   1186 	{
   1187 		.desc = "Fan2",
   1188 		.type = ENVSYS_SFANRPM,
   1189 		.bank = 0,
   1190 		.reg = 0x2a,
   1191 		.refresh = wb_refresh_fanrpm,
   1192 		.rfact = 0
   1193 	},
   1194 
   1195 	{ .desc = NULL }
   1196 };
   1197 
   1198 /* W83791D */
   1199 static const struct lm_sensor w83791d_sensors[] = {
   1200 	/* Voltage */
   1201 	{
   1202 		.desc = "VCore",
   1203 		.type = ENVSYS_SVOLTS_DC,
   1204 		.bank = 0,
   1205 		.reg = 0x20,
   1206 		.refresh = lm_refresh_volt,
   1207 		.rfact = 10000
   1208 	},
   1209 	{
   1210 		.desc = "VINR0",
   1211 		.type = ENVSYS_SVOLTS_DC,
   1212 		.bank = 0,
   1213 		.reg = 0x21,
   1214 		.refresh = lm_refresh_volt,
   1215 		.rfact = 10000
   1216 	},
   1217 	{
   1218 		.desc = "+3.3V",
   1219 		.type = ENVSYS_SVOLTS_DC,
   1220 		.bank = 0,
   1221 		.reg = 0x22,
   1222 		.refresh = lm_refresh_volt,
   1223 		.rfact = 10000
   1224 	},
   1225 	{
   1226 		.desc = "+5V",
   1227 		.type = ENVSYS_SVOLTS_DC,
   1228 		.bank = 0,
   1229 		.reg = 0x23,
   1230 		.refresh = lm_refresh_volt,
   1231 		.rfact = RFACT(34, 50)
   1232 	},
   1233 	{
   1234 		.desc = "+12V",
   1235 		.type = ENVSYS_SVOLTS_DC,
   1236 		.bank = 0,
   1237 		.reg = 0x24,
   1238 		.refresh = lm_refresh_volt,
   1239 		.rfact = RFACT(28, 10)
   1240 	},
   1241 	{
   1242 		.desc = "-12V",
   1243 		.type = ENVSYS_SVOLTS_DC,
   1244 		.bank = 0,
   1245 		.reg = 0x25,
   1246 		.refresh = wb_refresh_nvolt,
   1247 		.rfact = RFACT(232, 56)
   1248 	},
   1249 	{
   1250 		.desc = "-5V",
   1251 		.type = ENVSYS_SVOLTS_DC,
   1252 		.bank = 0,
   1253 		.reg = 0x26,
   1254 		.refresh = wb_refresh_nvolt,
   1255 		.rfact = RFACT(120, 56)
   1256 	},
   1257 	{
   1258 		.desc = "5VSB",
   1259 		.type = ENVSYS_SVOLTS_DC,
   1260 		.bank = 0,
   1261 		.reg = 0xb0,
   1262 		.refresh = lm_refresh_volt,
   1263 		.rfact = RFACT(17, 33)
   1264 	},
   1265 	{
   1266 		.desc = "VBAT",
   1267 		.type = ENVSYS_SVOLTS_DC,
   1268 		.bank = 0,
   1269 		.reg = 0xb1,
   1270 		.refresh = lm_refresh_volt,
   1271 		.rfact = RFACT_NONE
   1272 	},
   1273 	{
   1274 		.desc = "VINR1",
   1275 		.type = ENVSYS_SVOLTS_DC,
   1276 		.bank = 0,
   1277 		.reg = 0xb2,
   1278 		.refresh = lm_refresh_volt,
   1279 		.rfact = RFACT_NONE
   1280 	},
   1281 
   1282 	/* Temperature */
   1283 	{
   1284 		.desc = "Temp0",
   1285 		.type = ENVSYS_STEMP,
   1286 		.bank = 0,
   1287 		.reg = 0x27,
   1288 		.refresh = lm_refresh_temp,
   1289 		.rfact = 0
   1290 	},
   1291 	{
   1292 		.desc = "Temp1",
   1293 		.type = ENVSYS_STEMP,
   1294 		.bank = 0,
   1295 		.reg = 0xc0,
   1296 		.refresh = wb_refresh_temp,
   1297 		.rfact = 0
   1298 	},
   1299 	{
   1300 		.desc = "Temp2",
   1301 		.type = ENVSYS_STEMP,
   1302 		.bank = 0,
   1303 		.reg = 0xc8,
   1304 		.refresh = wb_refresh_temp,
   1305 		.rfact = 0
   1306 	},
   1307 
   1308 	/* Fans */
   1309 	{
   1310 		.desc = "Fan0",
   1311 		.type = ENVSYS_SFANRPM,
   1312 		.bank = 0,
   1313 		.reg = 0x28,
   1314 		.refresh = wb_refresh_fanrpm,
   1315 		.rfact = 0
   1316 	},
   1317 	{
   1318 		.desc = "Fan1",
   1319 		.type = ENVSYS_SFANRPM,
   1320 		.bank = 0,
   1321 		.reg = 0x29,
   1322 		.refresh = wb_refresh_fanrpm,
   1323 		.rfact = 0
   1324 	},
   1325 	{
   1326 		.desc = "Fan2",
   1327 		.type = ENVSYS_SFANRPM,
   1328 		.bank = 0,
   1329 		.reg = 0x2a,
   1330 		.refresh = wb_refresh_fanrpm,
   1331 		.rfact = 0
   1332 	},
   1333 	{
   1334 		.desc = "Fan3",
   1335 		.type = ENVSYS_SFANRPM,
   1336 		.bank = 0,
   1337 		.reg = 0xba,
   1338 		.refresh = wb_refresh_fanrpm,
   1339 		.rfact = 0
   1340 	},
   1341 	{
   1342 		.desc = "Fan4",
   1343 		.type = ENVSYS_SFANRPM,
   1344 		.bank = 0,
   1345 		.reg = 0xbb,
   1346 		.refresh = wb_refresh_fanrpm,
   1347 		.rfact = 0
   1348 	},
   1349 
   1350         { .desc = NULL }
   1351 };
   1352 
   1353 /* W83792D */
   1354 static const struct lm_sensor w83792d_sensors[] = {
   1355 	/* Voltage */
   1356 	{
   1357 		.desc = "VCore A",
   1358 		.type = ENVSYS_SVOLTS_DC,
   1359 		.bank = 0,
   1360 		.reg = 0x20,
   1361 		.refresh = lm_refresh_volt,
   1362 		.rfact = RFACT_NONE
   1363 	},
   1364 	{
   1365 		.desc = "VCore B",
   1366 		.type = ENVSYS_SVOLTS_DC,
   1367 		.bank = 0,
   1368 		.reg = 0x21,
   1369 		.refresh = lm_refresh_volt,
   1370 		.rfact = RFACT_NONE
   1371 	},
   1372 	{
   1373 		.desc = "+3.3V",
   1374 		.type = ENVSYS_SVOLTS_DC,
   1375 		.bank = 0,
   1376 		.reg = 0x22,
   1377 		.refresh = lm_refresh_volt,
   1378 		.rfact = RFACT_NONE
   1379 	},
   1380 	{
   1381 		.desc = "-5V",
   1382 		.type = ENVSYS_SVOLTS_DC,
   1383 		.bank = 0,
   1384 		.reg = 0x23,
   1385 		.refresh = wb_refresh_nvolt,
   1386 		.rfact = RFACT(120, 56)
   1387 	},
   1388 	{
   1389 		.desc = "+12V",
   1390 		.type = ENVSYS_SVOLTS_DC,
   1391 		.bank = 0,
   1392 		.reg = 0x24,
   1393 		.refresh = lm_refresh_volt,
   1394 		.rfact = RFACT(28, 10)
   1395 	},
   1396 	{
   1397 		.desc = "-12V",
   1398 		.type = ENVSYS_SVOLTS_DC,
   1399 		.bank = 0,
   1400 		.reg = 0x25,
   1401 		.refresh = wb_refresh_nvolt,
   1402 		.rfact = RFACT(232, 56)
   1403 	},
   1404 	{
   1405 		.desc = "+5V",
   1406 		.type = ENVSYS_SVOLTS_DC,
   1407 		.bank = 0,
   1408 		.reg = 0x26,
   1409 		.refresh = lm_refresh_volt,
   1410 		.rfact = RFACT(34, 50)
   1411 	},
   1412 	{
   1413 		.desc = "5VSB",
   1414 		.type = ENVSYS_SVOLTS_DC,
   1415 		.bank = 0,
   1416 		.reg = 0xb0,
   1417 		.refresh = lm_refresh_volt,
   1418 		.rfact = RFACT(17, 33)
   1419 	},
   1420 	{
   1421 		.desc = "VBAT",
   1422 		.type = ENVSYS_SVOLTS_DC,
   1423 		.bank = 0,
   1424 		.reg = 0xb1,
   1425 		.refresh = lm_refresh_volt,
   1426 		.rfact = RFACT_NONE
   1427 	},
   1428 
   1429 	/* Temperature */
   1430 	{
   1431 		.desc = "Temp0",
   1432 		.type = ENVSYS_STEMP,
   1433 		.bank = 0,
   1434 		.reg = 0x27,
   1435 		.refresh = lm_refresh_temp,
   1436 		.rfact = 0
   1437 	},
   1438 	{
   1439 		.desc = "Temp1",
   1440 		.type = ENVSYS_STEMP,
   1441 		.bank = 0,
   1442 		.reg = 0xc0,
   1443 		.refresh = wb_refresh_temp,
   1444 		.rfact = 0
   1445 	},
   1446 	{
   1447 		.desc = "Temp2",
   1448 		.type = ENVSYS_STEMP,
   1449 		.bank = 0,
   1450 		.reg = 0xc8,
   1451 		.refresh = wb_refresh_temp,
   1452 		.rfact = 0
   1453 	},
   1454 
   1455 	/* Fans */
   1456 	{
   1457 		.desc = "Fan0",
   1458 		.type = ENVSYS_SFANRPM,
   1459 		.bank = 0,
   1460 		.reg = 0x28,
   1461 		.refresh = wb_w83792d_refresh_fanrpm,
   1462 		.rfact = 0
   1463 	},
   1464 	{
   1465 		.desc = "Fan1",
   1466 		.type = ENVSYS_SFANRPM,
   1467 		.bank = 0,
   1468 		.reg = 0x29,
   1469 		.refresh = wb_w83792d_refresh_fanrpm,
   1470 		.rfact = 0
   1471 	},
   1472 	{
   1473 		.desc = "Fan2",
   1474 		.type = ENVSYS_SFANRPM,
   1475 		.bank = 0,
   1476 		.reg = 0x2a,
   1477 		.refresh = wb_w83792d_refresh_fanrpm,
   1478 		.rfact = 0
   1479 	},
   1480 	{
   1481 		.desc = "Fan3",
   1482 		.type = ENVSYS_SFANRPM,
   1483 		.bank = 0,
   1484 		.reg = 0xb8,
   1485 		.refresh = wb_w83792d_refresh_fanrpm,
   1486 		.rfact = 0
   1487 	},
   1488 	{
   1489 		.desc = "Fan4",
   1490 		.type = ENVSYS_SFANRPM,
   1491 		.bank = 0,
   1492 		.reg = 0xb9,
   1493 		.refresh = wb_w83792d_refresh_fanrpm,
   1494 		.rfact = 0
   1495 	},
   1496 	{
   1497 		.desc = "Fan5",
   1498 		.type = ENVSYS_SFANRPM,
   1499 		.bank = 0,
   1500 		.reg = 0xba,
   1501 		.refresh = wb_w83792d_refresh_fanrpm,
   1502 		.rfact = 0
   1503 	},
   1504 	{
   1505 		.desc = "Fan6",
   1506 		.type = ENVSYS_SFANRPM,
   1507 		.bank = 0,
   1508 		.reg = 0xbe,
   1509 		.refresh = wb_w83792d_refresh_fanrpm,
   1510 		.rfact = 0
   1511 	},
   1512 
   1513 	{ .desc = NULL }
   1514 };
   1515 
   1516 /* AS99127F */
   1517 static const struct lm_sensor as99127f_sensors[] = {
   1518 	/* Voltage */
   1519 	{
   1520 		.desc = "VCore A",
   1521 		.type = ENVSYS_SVOLTS_DC,
   1522 		.bank = 0,
   1523 		.reg = 0x20,
   1524 		.refresh = lm_refresh_volt,
   1525 		.rfact = RFACT_NONE
   1526 	},
   1527 	{
   1528 		.desc = "VCore B",
   1529 		.type = ENVSYS_SVOLTS_DC,
   1530 		.bank = 0,
   1531 		.reg = 0x21,
   1532 		.refresh = lm_refresh_volt,
   1533 		.rfact = RFACT_NONE
   1534 	},
   1535 	{
   1536 		.desc = "+3.3V",
   1537 		.type = ENVSYS_SVOLTS_DC,
   1538 		.bank = 0,
   1539 		.reg = 0x22,
   1540 		.refresh = lm_refresh_volt,
   1541 		.rfact = RFACT_NONE
   1542 	},
   1543 	{
   1544 		.desc = "+5V",
   1545 		.type = ENVSYS_SVOLTS_DC,
   1546 		.bank = 0,
   1547 		.reg = 0x23,
   1548 		.refresh = lm_refresh_volt,
   1549 		.rfact = RFACT(34, 50)
   1550 	},
   1551 	{
   1552 		.desc = "+12V",
   1553 		.type = ENVSYS_SVOLTS_DC,
   1554 		.bank = 0,
   1555 		.reg = 0x24,
   1556 		.refresh = lm_refresh_volt,
   1557 		.rfact = RFACT(28, 10)
   1558 	},
   1559 	{
   1560 		.desc = "-12V",
   1561 		.type = ENVSYS_SVOLTS_DC,
   1562 		.bank = 0,
   1563 		.reg = 0x25,
   1564 		.refresh = wb_refresh_nvolt,
   1565 		.rfact = RFACT(232, 56)
   1566 	},
   1567 	{
   1568 		.desc = "-5V",
   1569 		.type = ENVSYS_SVOLTS_DC,
   1570 		.bank = 0,
   1571 		.reg = 0x26,
   1572 		.refresh = wb_refresh_nvolt,
   1573 		.rfact = RFACT(120, 56)
   1574 	},
   1575 
   1576 	/* Temperature */
   1577 	{
   1578 		.desc = "Temp0",
   1579 		.type = ENVSYS_STEMP,
   1580 		.bank = 0,
   1581 		.reg = 0x27,
   1582 		.refresh = lm_refresh_temp,
   1583 		.rfact = 0
   1584 	},
   1585 	{
   1586 		.desc = "Temp1",
   1587 		.type = ENVSYS_STEMP,
   1588 		.bank = 1,
   1589 		.reg = 0x50,
   1590 		.refresh = as_refresh_temp,
   1591 		.rfact = 0
   1592 	},
   1593 	{
   1594 		.desc = "Temp2",
   1595 		.type = ENVSYS_STEMP,
   1596 		.bank = 2,
   1597 		.reg = 0x50,
   1598 		.refresh = as_refresh_temp,
   1599 		.rfact = 0
   1600 	},
   1601 
   1602 	/* Fans */
   1603 	{
   1604 		.desc = "Fan0",
   1605 		.type = ENVSYS_SFANRPM,
   1606 		.bank = 0,
   1607 		.reg = 0x28,
   1608 		.refresh = lm_refresh_fanrpm,
   1609 		.rfact = 0
   1610 	},
   1611 	{
   1612 		.desc = "Fan1",
   1613 		.type = ENVSYS_SFANRPM,
   1614 		.bank = 0,
   1615 		.reg = 0x29,
   1616 		.refresh = lm_refresh_fanrpm,
   1617 		.rfact = 0
   1618 	},
   1619 	{
   1620 		.desc = "Fan2",
   1621 		.type = ENVSYS_SFANRPM,
   1622 		.bank = 0,
   1623 		.reg = 0x2a,
   1624 		.refresh = lm_refresh_fanrpm,
   1625 		.rfact = 0
   1626 	},
   1627 
   1628 	{ .desc = NULL }
   1629 };
   1630 
   1631 /* NCT6776F */
   1632 static const struct lm_sensor nct6776f_sensors[] = {
   1633 	/* Voltage */
   1634 	{
   1635 		.desc = "VCore",
   1636 		.type = ENVSYS_SVOLTS_DC,
   1637 		.bank = 0,
   1638 		.reg = 0x20,
   1639 		.refresh = lm_refresh_volt,
   1640 		.rfact = RFACT_NONE / 2
   1641 	},
   1642 	{
   1643 		.desc = "+12V",
   1644 		.type = ENVSYS_SVOLTS_DC,
   1645 		.bank = 0,
   1646 		.reg = 0x21,
   1647 		.refresh = lm_refresh_volt,
   1648 		.rfact = RFACT(56, 10) / 2
   1649 	},
   1650 	{
   1651 		.desc = "AVCC",
   1652 		.type = ENVSYS_SVOLTS_DC,
   1653 		.bank = 0,
   1654 		.reg = 0x22,
   1655 		.refresh = lm_refresh_volt,
   1656 		.rfact = RFACT(34, 34) / 2
   1657 	},
   1658 	{
   1659 		.desc = "+3.3V",
   1660 		.type = ENVSYS_SVOLTS_DC,
   1661 		.bank = 0,
   1662 		.reg = 0x23,
   1663 		.refresh = lm_refresh_volt,
   1664 		.rfact = RFACT(34, 34) / 2
   1665 	},
   1666 	{
   1667 		.desc = "-12V",
   1668 		.type = ENVSYS_SVOLTS_DC,
   1669 		.bank = 0,
   1670 		.reg = 0x24,
   1671 		.refresh = wb_w83627ehf_refresh_nvolt,
   1672 		.rfact = 0
   1673 	},
   1674 	{
   1675 		.desc = "+5V",
   1676 		.type = ENVSYS_SVOLTS_DC,
   1677 		.bank = 0,
   1678 		.reg = 0x25,
   1679 		.refresh = lm_refresh_volt,
   1680 		.rfact = 16000
   1681 	},
   1682 	{
   1683 		.desc = "VIN3",
   1684 		.type = ENVSYS_SVOLTS_DC,
   1685 		.bank = 0,
   1686 		.reg = 0x26,
   1687 		.refresh = lm_refresh_volt,
   1688 		.rfact = RFACT_NONE
   1689 	},
   1690 	{
   1691 		.desc = "+3.3VSB",
   1692 		.type = ENVSYS_SVOLTS_DC,
   1693 		.bank = 5,
   1694 		.reg = 0x50,
   1695 		.refresh = lm_refresh_volt,
   1696 		.rfact = RFACT(34, 34) / 2
   1697 	},
   1698 	{
   1699 		.desc = "VBAT",
   1700 		.type = ENVSYS_SVOLTS_DC,
   1701 		.bank = 5,
   1702 		.reg = 0x51,
   1703 		.refresh = lm_refresh_volt,
   1704 		.rfact = RFACT(34, 34) / 2
   1705 	},
   1706 
   1707 	/* Temperature */
   1708 	{
   1709 		.desc = "MB Temperature",
   1710 		.type = ENVSYS_STEMP,
   1711 		.bank = 0,
   1712 		.reg = 0x27,
   1713 		.refresh = lm_refresh_temp,
   1714 		.rfact = 0
   1715 	},
   1716 	{
   1717 		.desc = "CPU Temperature",
   1718 		.type = ENVSYS_STEMP,
   1719 		.bank = 1,
   1720 		.reg = 0x50,
   1721 		.refresh = wb_refresh_temp,
   1722 		.rfact = 0
   1723 	},
   1724 	{
   1725 		.desc = "Aux Temp",
   1726 		.type = ENVSYS_STEMP,
   1727 		.bank = 2,
   1728 		.reg = 0x50,
   1729 		.refresh = wb_refresh_temp,
   1730 		.rfact = 0
   1731 	},
   1732 
   1733 	/* Fans */
   1734 	{
   1735 		.desc = "System Fan",
   1736 		.type = ENVSYS_SFANRPM,
   1737 		.bank = 6,
   1738 		.reg = 0x56,
   1739 		.refresh = wb_nct6776f_refresh_fanrpm,
   1740 		.rfact = 0
   1741 	},
   1742 	{
   1743 		.desc = "CPU Fan",
   1744 		.type = ENVSYS_SFANRPM,
   1745 		.bank = 6,
   1746 		.reg = 0x58,
   1747 		.refresh = wb_nct6776f_refresh_fanrpm,
   1748 		.rfact = 0
   1749 	},
   1750 	{
   1751 		.desc = "Aux Fan0",
   1752 		.type = ENVSYS_SFANRPM,
   1753 		.bank = 6,
   1754 		.reg = 0x5a,
   1755 		.refresh = wb_nct6776f_refresh_fanrpm,
   1756 		.rfact = 0
   1757 	},
   1758 	{
   1759 		.desc = "Aux Fan1",
   1760 		.type = ENVSYS_SFANRPM,
   1761 		.bank = 6,
   1762 		.reg = 0x5c,
   1763 		.refresh = wb_nct6776f_refresh_fanrpm,
   1764 		.rfact = 0
   1765 	},
   1766 
   1767 	{
   1768 		.desc = "Aux Fan2",
   1769 		.type = ENVSYS_SFANRPM,
   1770 		.bank = 6,
   1771 		.reg = 0x5e,
   1772 		.refresh = wb_nct6776f_refresh_fanrpm,
   1773 		.rfact = 0
   1774 	},
   1775 
   1776 	{ .desc = NULL }
   1777 };
   1778 
   1779 /* NCT610[246]D */
   1780 static const struct lm_sensor nct6102d_sensors[] = {
   1781 	/* Voltage */
   1782 	{
   1783 		.desc = "VCore",
   1784 		.type = ENVSYS_SVOLTS_DC,
   1785 		.bank = 0,
   1786 		.reg = 0x00,
   1787 		.refresh = lm_refresh_volt,
   1788 		.rfact = RFACT_NONE
   1789 	},
   1790 	{
   1791 		.desc = "VIN0",
   1792 		.type = ENVSYS_SVOLTS_DC,
   1793 		.bank = 0,
   1794 		.reg = 0x01,
   1795 		.refresh = lm_refresh_volt,
   1796 		.rfact = RFACT_NONE
   1797 	},
   1798 	{
   1799 		.desc = "AVCC",
   1800 		.type = ENVSYS_SVOLTS_DC,
   1801 		.bank = 0,
   1802 		.reg = 0x02,
   1803 		.refresh = lm_refresh_volt,
   1804 		.rfact = RFACT(34, 34) / 2
   1805 	},
   1806 	{
   1807 		.desc = "3VCC",
   1808 		.type = ENVSYS_SVOLTS_DC,
   1809 		.bank = 0,
   1810 		.reg = 0x03,
   1811 		.refresh = lm_refresh_volt,
   1812 		.rfact = RFACT(34, 34) / 2
   1813 	},
   1814 	{
   1815 		.desc = "VIN1",
   1816 		.type = ENVSYS_SVOLTS_DC,
   1817 		.bank = 0,
   1818 		.reg = 0x04,
   1819 		.refresh = lm_refresh_volt,
   1820 		.rfact = RFACT_NONE
   1821 	},
   1822 	{
   1823 		.desc = "VIN2",
   1824 		.type = ENVSYS_SVOLTS_DC,
   1825 		.bank = 0,
   1826 		.reg = 0x05,
   1827 		.refresh = lm_refresh_volt,
   1828 		.rfact = RFACT(34, 34) / 2
   1829 	},
   1830 	{
   1831 		.desc = "+3.3VSB",
   1832 		.type = ENVSYS_SVOLTS_DC,
   1833 		.bank = 0,
   1834 		.reg = 0x07,
   1835 		.refresh = lm_refresh_volt,
   1836 		.rfact = RFACT(34, 34) / 2
   1837 	},
   1838 	{
   1839 		.desc = "VBAT",
   1840 		.type = ENVSYS_SVOLTS_DC,
   1841 		.bank = 0,
   1842 		.reg = 0x08,
   1843 		.refresh = lm_refresh_volt,
   1844 		.rfact = RFACT(34, 34) / 2
   1845 	},
   1846 	{
   1847 		.desc = "VTT",
   1848 		.type = ENVSYS_SVOLTS_DC,
   1849 		.bank = 0,
   1850 		.reg = 0x09,
   1851 		.refresh = lm_refresh_volt,
   1852 		.rfact = RFACT_NONE
   1853 	},
   1854 
   1855 	/* Temperature */
   1856 	{
   1857 		.desc = "MB Temperature",
   1858 		.type = ENVSYS_STEMP,
   1859 		.bank = 0,
   1860 		.reg = 0x18,
   1861 		.refresh = lm_refresh_temp,
   1862 		.rfact = 0
   1863 	},
   1864 	{
   1865 		.desc = "CPU Temperature",
   1866 		.type = ENVSYS_STEMP,
   1867 		.bank = 0,
   1868 		.reg = 0x19,
   1869 		.refresh = lm_refresh_temp,
   1870 		.rfact = 0
   1871 	},
   1872 	{
   1873 		.desc = "Aux Temp",
   1874 		.type = ENVSYS_STEMP,
   1875 		.bank = 0,
   1876 		.reg = 0x1a,
   1877 		.refresh = lm_refresh_temp,
   1878 		.rfact = 0
   1879 	},
   1880 
   1881 	/* Fans */
   1882 	{
   1883 		.desc = "System Fan",
   1884 		.type = ENVSYS_SFANRPM,
   1885 		.bank = 0,
   1886 		.reg = 0x30,
   1887 		.refresh = wb_nct6776f_refresh_fanrpm,
   1888 		.rfact = 0
   1889 	},
   1890 	{
   1891 		.desc = "CPU Fan",
   1892 		.type = ENVSYS_SFANRPM,
   1893 		.bank = 0,
   1894 		.reg = 0x32,
   1895 		.refresh = wb_nct6776f_refresh_fanrpm,
   1896 		.rfact = 0
   1897 	},
   1898 	{
   1899 		.desc = "Aux Fan",
   1900 		.type = ENVSYS_SFANRPM,
   1901 		.bank = 0,
   1902 		.reg = 0x34,
   1903 		.refresh = wb_nct6776f_refresh_fanrpm,
   1904 		.rfact = 0
   1905 	},
   1906 
   1907 	{ .desc = NULL }
   1908 };
   1909 
   1910 /* NCT6779D */
   1911 static const struct lm_sensor nct6779d_sensors[] = {
   1912 	/* Voltage */
   1913 	{
   1914 		.desc = "VCore",
   1915 		.type = ENVSYS_SVOLTS_DC,
   1916 		.bank = 4,
   1917 		.reg = 0x80,
   1918 		.refresh = lm_refresh_volt,
   1919 		.rfact = RFACT_NONE / 2
   1920 	},
   1921 	{
   1922 		.desc = "VIN1",
   1923 		.type = ENVSYS_SVOLTS_DC,
   1924 		.bank = 4,
   1925 		.reg = 0x81,
   1926 		.refresh = lm_refresh_volt,
   1927 		.rfact = RFACT(56, 10) / 2
   1928 	},
   1929 	{
   1930 		.desc = "AVCC",
   1931 		.type = ENVSYS_SVOLTS_DC,
   1932 		.bank = 4,
   1933 		.reg = 0x82,
   1934 		.refresh = lm_refresh_volt,
   1935 		.rfact = RFACT(34, 34) / 2
   1936 	},
   1937 	{
   1938 		.desc = "+3.3V",
   1939 		.type = ENVSYS_SVOLTS_DC,
   1940 		.bank = 4,
   1941 		.reg = 0x83,
   1942 		.refresh = lm_refresh_volt,
   1943 		.rfact = RFACT(34, 34) / 2
   1944 	},
   1945 	{
   1946 		.desc = "VIN0",
   1947 		.type = ENVSYS_SVOLTS_DC,
   1948 		.bank = 4,
   1949 		.reg = 0x84,
   1950 		.refresh = lm_refresh_volt,
   1951 		.rfact = RFACT(48600, 10000)
   1952 	},
   1953 	{
   1954 		.desc = "VIN8",
   1955 		.type = ENVSYS_SVOLTS_DC,
   1956 		.bank = 4,
   1957 		.reg = 0x85,
   1958 		.refresh = lm_refresh_volt,
   1959 		.rfact = RFACT_NONE / 2
   1960 	},
   1961 	{
   1962 		.desc = "VIN4",
   1963 		.type = ENVSYS_SVOLTS_DC,
   1964 		.bank = 4,
   1965 		.reg = 0x86,
   1966 		.refresh = lm_refresh_volt,
   1967 		.rfact = RFACT_NONE
   1968 	},
   1969 	{
   1970 		.desc = "+3.3VSB",
   1971 		.type = ENVSYS_SVOLTS_DC,
   1972 		.bank = 4,
   1973 		.reg = 0x87,
   1974 		.refresh = lm_refresh_volt,
   1975 		.rfact = RFACT(34, 34) / 2
   1976 	},
   1977 	{
   1978 		.desc = "VBAT",
   1979 		.type = ENVSYS_SVOLTS_DC,
   1980 		.bank = 4,
   1981 		.reg = 0x88,
   1982 		.refresh = lm_refresh_volt,
   1983 		.rfact = RFACT_NONE
   1984 	},
   1985 	{
   1986 		.desc = "VTT",
   1987 		.type = ENVSYS_SVOLTS_DC,
   1988 		.bank = 4,
   1989 		.reg = 0x89,
   1990 		.refresh = lm_refresh_volt,
   1991 		.rfact = RFACT_NONE
   1992 	},
   1993 	{
   1994 		.desc = "VIN5",
   1995 		.type = ENVSYS_SVOLTS_DC,
   1996 		.bank = 4,
   1997 		.reg = 0x8a,
   1998 		.refresh = lm_refresh_volt,
   1999 		.rfact = RFACT_NONE
   2000 	},
   2001 	{
   2002 		.desc = "VIN6",
   2003 		.type = ENVSYS_SVOLTS_DC,
   2004 		.bank = 4,
   2005 		.reg = 0x8b,
   2006 		.refresh = lm_refresh_volt,
   2007 		.rfact = RFACT_NONE
   2008 	},
   2009 	{
   2010 		.desc = "VIN2",
   2011 		.type = ENVSYS_SVOLTS_DC,
   2012 		.bank = 4,
   2013 		.reg = 0x8c,
   2014 		.refresh = lm_refresh_volt,
   2015 		.rfact = RFACT_NONE
   2016 	},
   2017 	{
   2018 		.desc = "VIN3",
   2019 		.type = ENVSYS_SVOLTS_DC,
   2020 		.bank = 4,
   2021 		.reg = 0x8d,
   2022 		.refresh = lm_refresh_volt,
   2023 		.rfact = RFACT(14414, 10000)
   2024 	},
   2025 	{
   2026 		.desc = "VIN7",
   2027 		.type = ENVSYS_SVOLTS_DC,
   2028 		.bank = 4,
   2029 		.reg = 0x8e,
   2030 		.refresh = lm_refresh_volt,
   2031 		.rfact = RFACT_NONE / 2
   2032 	},
   2033 
   2034 	/* Temperature */
   2035 	{
   2036 		.desc = "MB Temperature",
   2037 		.type = ENVSYS_STEMP,
   2038 		.bank = 4,
   2039 		.reg = 0x90,
   2040 		.refresh = lm_refresh_temp,
   2041 		.rfact = 0
   2042 	},
   2043 	{
   2044 		.desc = "CPU Temperature",
   2045 		.type = ENVSYS_STEMP,
   2046 		.bank = 4,
   2047 		.reg = 0x91,
   2048 		.refresh = wb_refresh_temp,
   2049 		.rfact = 0
   2050 	},
   2051 	{
   2052 		.desc = "Aux Temp0",
   2053 		.type = ENVSYS_STEMP,
   2054 		.bank = 4,
   2055 		.reg = 0x92,
   2056 		.refresh = wb_refresh_temp,
   2057 		.rfact = 0
   2058 	},
   2059 	{
   2060 		.desc = "Aux Temp1",
   2061 		.type = ENVSYS_STEMP,
   2062 		.bank = 4,
   2063 		.reg = 0x93,
   2064 		.refresh = wb_refresh_temp,
   2065 		.rfact = 0
   2066 	},
   2067 	{
   2068 		.desc = "Aux Temp2",
   2069 		.type = ENVSYS_STEMP,
   2070 		.bank = 4,
   2071 		.reg = 0x94,
   2072 		.refresh = wb_refresh_temp,
   2073 		.rfact = 0
   2074 	},
   2075 	{
   2076 		.desc = "Aux Temp3",
   2077 		.type = ENVSYS_STEMP,
   2078 		.bank = 4,
   2079 		.reg = 0x95,
   2080 		.refresh = wb_refresh_temp,
   2081 		.rfact = 0
   2082 	},
   2083 
   2084 	/* Fans */
   2085 	{
   2086 		.desc = "System Fan",
   2087 		.type = ENVSYS_SFANRPM,
   2088 		.bank = 4,
   2089 		.reg = 0xc0,
   2090 		.refresh = wb_nct6776f_refresh_fanrpm,
   2091 		.rfact = 0
   2092 	},
   2093 	{
   2094 		.desc = "CPU Fan",
   2095 		.type = ENVSYS_SFANRPM,
   2096 		.bank = 4,
   2097 		.reg = 0xc2,
   2098 		.refresh = wb_nct6776f_refresh_fanrpm,
   2099 		.rfact = 0
   2100 	},
   2101 	{
   2102 		.desc = "Aux Fan0",
   2103 		.type = ENVSYS_SFANRPM,
   2104 		.bank = 4,
   2105 		.reg = 0xc4,
   2106 		.refresh = wb_nct6776f_refresh_fanrpm,
   2107 		.rfact = 0
   2108 	},
   2109 	{
   2110 		.desc = "Aux Fan1",
   2111 		.type = ENVSYS_SFANRPM,
   2112 		.bank = 4,
   2113 		.reg = 0xc6,
   2114 		.refresh = wb_nct6776f_refresh_fanrpm,
   2115 		.rfact = 0
   2116 	},
   2117 	{
   2118 		.desc = "Aux Fan2",
   2119 		.type = ENVSYS_SFANRPM,
   2120 		.bank = 4,
   2121 		.reg = 0xc8,
   2122 		.refresh = wb_nct6776f_refresh_fanrpm,
   2123 		.rfact = 0
   2124 	},
   2125 
   2126 	{ .desc = NULL }
   2127 };
   2128 
   2129 static const struct wb_product wb_products[] = {
   2130     { WB_CHIPID_W83627HF,   "W83627HF",	w83627hf_sensors, NULL },
   2131     { WB_CHIPID_W83627THF,  "W83627THF",w83637hf_sensors, NULL },
   2132     { WB_CHIPID_W83627EHF_A,"W83627EHF-A",w83627ehf_sensors,NULL },
   2133     { WB_CHIPID_W83627EHF,  "W83627EHF",w83627ehf_sensors,NULL },
   2134     { WB_CHIPID_W83627DHG,  NULL,	NULL,   NULL },
   2135     { WB_CHIPID_W83637HF,   "W83637HF",	w83637hf_sensors, NULL },
   2136     { WB_CHIPID_W83697HF,   "W83697HF",	w83697hf_sensors, NULL },
   2137     { WB_CHIPID_W83781D,    "W83781D",	w83781d_sensors,  NULL },
   2138     { WB_CHIPID_W83781D_2,  "W83781D",	w83781d_sensors,  NULL },
   2139     { WB_CHIPID_W83782D,    "W83782D",	w83782d_sensors,  NULL },
   2140     { WB_CHIPID_W83783S,    "W83783S",	w83783s_sensors,  NULL },
   2141     { WB_CHIPID_W83791D,    "W83791D",	w83791d_sensors,  NULL },
   2142     { WB_CHIPID_W83791SD,   "W83791SD",	NULL,		  NULL },
   2143     { WB_CHIPID_W83792D,    "W83792D",	w83792d_sensors,  NULL },
   2144     { WB_CHIPID_AS99127F,   NULL,	NULL,  NULL },
   2145     { 0, NULL, NULL, NULL }
   2146 };
   2147 
   2148 static const struct wb_product wbsio_products[] = {
   2149     { WBSIO_ID_W83627DHG,   "W83627DHG",w83627dhg_sensors,NULL },
   2150     { WBSIO_ID_NCT6775F,    "NCT6775F", nct6776f_sensors, NULL },
   2151     { WBSIO_ID_NCT6776F,    "NCT6776F", nct6776f_sensors, NULL },
   2152     { WBSIO_ID_NCT5104D,    "NCT5104D or 610[246]D",nct6102d_sensors,NULL },
   2153     { WBSIO_ID_NCT6779D,    "NCT6779D", nct6779d_sensors, NULL },
   2154     { WBSIO_ID_NCT6791D,    "NCT6791D", nct6779d_sensors, NULL },
   2155     { WBSIO_ID_NCT6792D,    "NCT6792D", nct6779d_sensors, NULL },
   2156     { WBSIO_ID_NCT6793D,    "NCT6793D", nct6779d_sensors, NULL },
   2157     { WBSIO_ID_NCT6795D,    "NCT6795D", nct6779d_sensors, NULL },
   2158     { WBSIO_ID_NCT6796D,    "NCT6796D", nct6779d_sensors, NULL },
   2159     { WBSIO_ID_NCT6797D,    "NCT6797D", nct6779d_sensors, NULL },
   2160     { WBSIO_ID_NCT6798D,    "NCT6798D", nct6779d_sensors, NULL },
   2161     { WBSIO_ID_NCT6799D,    "NCT6799D", nct6779d_sensors, NULL },
   2162     { 0, NULL, NULL, NULL }
   2163 };
   2164 
   2165 static const struct wb_product as99127f_products[] = {
   2166     { WB_VENDID_ASUS,       "AS99127F", w83781d_sensors,  NULL },
   2167     { WB_VENDID_WINBOND,    "AS99127F rev 2",as99127f_sensors,NULL },
   2168     { 0, NULL, NULL, NULL }
   2169 };
   2170 
   2171 static void
   2172 lm_generic_banksel(struct lm_softc *lmsc, uint8_t bank)
   2173 {
   2174 	(*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
   2175 }
   2176 
   2177 /*
   2178  * bus independent match
   2179  *
   2180  * prerequisites:  lmsc contains valid lm_{read,write}reg() routines
   2181  * and associated bus access data is present in attachment's softc
   2182  */
   2183 int
   2184 lm_match(struct lm_softc *lmsc)
   2185 {
   2186 	uint8_t cr;
   2187 	int i, rv;
   2188 
   2189 	/* Perform LM78 reset */
   2190 	/*(*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x80); */
   2191 
   2192 	cr = (*lmsc->lm_readreg)(lmsc, LMD_CONFIG);
   2193 
   2194 	/* XXX - spec says *only* 0x08! */
   2195 	if ((cr != 0x08) && (cr != 0x01) && (cr != 0x03) && (cr != 0x06))
   2196 		return 0;
   2197 
   2198 	DPRINTF(("%s: 0x80 check: cr = %x\n", __func__, cr));
   2199 
   2200 	for (i = 0; i < __arraycount(lm_chips); i++)
   2201 		if ((rv = lm_chips[i].chip_match(lmsc)) != 0)
   2202 			return rv;
   2203 
   2204 	return 0;
   2205 }
   2206 
   2207 int
   2208 nslm_match(struct lm_softc *sc)
   2209 {
   2210 	uint8_t chipid;
   2211 
   2212 	/* See if we have an LM78/LM78J/LM79 or LM81 */
   2213 	chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
   2214 	switch(chipid) {
   2215 	case LM_ID_LM78:
   2216 	case LM_ID_LM78J:
   2217 	case LM_ID_LM79:
   2218 	case LM_ID_LM81:
   2219 		break;
   2220 	default:
   2221 		return 0;
   2222 	}
   2223 	DPRINTF(("%s: chipid %x\n", __func__, chipid));
   2224 	return 1;
   2225 }
   2226 
   2227 void
   2228 lm_attach(struct lm_softc *lmsc)
   2229 {
   2230 	uint32_t i;
   2231 	int rv;
   2232 
   2233 	for (i = 0; i < __arraycount(lm_chips); i++) {
   2234 		if (lm_chips[i].chip_match(lmsc) != 0) {
   2235 			if (lm_chips[i].chip_attach(lmsc) == 0)
   2236 				break;
   2237 			else
   2238 				return;
   2239 		}
   2240 	}
   2241 
   2242 	/* Start the monitoring loop */
   2243 	(*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
   2244 
   2245 	lmsc->sc_sme = sysmon_envsys_create();
   2246 	/* Initialize sensors */
   2247 	for (i = 0; i < lmsc->numsensors; i++) {
   2248 		lmsc->sensors[i].state = ENVSYS_SINVALID;
   2249 		if ((rv = sysmon_envsys_sensor_attach(lmsc->sc_sme,
   2250 			    &lmsc->sensors[i])) != 0) {
   2251 			sysmon_envsys_destroy(lmsc->sc_sme);
   2252 			lmsc->sc_sme = NULL;
   2253 			aprint_error_dev(lmsc->sc_dev,
   2254 			    "sysmon_envsys_sensor_attach() returned %d\n", rv);
   2255 			return;
   2256 		}
   2257 	}
   2258 
   2259 	/*
   2260 	 * Setup the callout to refresh sensor data every 2 seconds.
   2261 	 */
   2262 	callout_init(&lmsc->sc_callout, 0);
   2263 	callout_setfunc(&lmsc->sc_callout, lm_refresh, lmsc);
   2264 	callout_schedule(&lmsc->sc_callout, LM_REFRESH_TIMO);
   2265 
   2266 	/*
   2267 	 * Hook into the System Monitor.
   2268 	 */
   2269 	lmsc->sc_sme->sme_name = device_xname(lmsc->sc_dev);
   2270 	lmsc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
   2271 
   2272 	if (sysmon_envsys_register(lmsc->sc_sme)) {
   2273 		aprint_error_dev(lmsc->sc_dev,
   2274 		    "unable to register with sysmon\n");
   2275 		sysmon_envsys_destroy(lmsc->sc_sme);
   2276 		lmsc->sc_sme = NULL;
   2277 	}
   2278 	if (!pmf_device_register(lmsc->sc_dev, NULL, NULL))
   2279 		aprint_error_dev(lmsc->sc_dev,
   2280 		    "couldn't establish power handler\n");
   2281 }
   2282 
   2283 /*
   2284  * Stop, destroy the callout and unregister the driver with the
   2285  * sysmon_envsys(9) framework.
   2286  */
   2287 void
   2288 lm_detach(struct lm_softc *lmsc)
   2289 {
   2290 	callout_halt(&lmsc->sc_callout, NULL);
   2291 	callout_destroy(&lmsc->sc_callout);
   2292 
   2293 	if (lmsc->sc_sme != NULL)
   2294 		sysmon_envsys_unregister(lmsc->sc_sme);
   2295 	pmf_device_deregister(lmsc->sc_dev);
   2296 }
   2297 
   2298 static void
   2299 lm_refresh(void *arg)
   2300 {
   2301 	struct lm_softc *lmsc = arg;
   2302 
   2303 	lmsc->refresh_sensor_data(lmsc);
   2304 	callout_schedule(&lmsc->sc_callout, LM_REFRESH_TIMO);
   2305 }
   2306 
   2307 static int
   2308 nslm_attach(struct lm_softc *sc)
   2309 {
   2310 	const char *model = NULL;
   2311 	uint8_t chipid;
   2312 
   2313 	/* See if we have an LM78/LM78J/LM79 or LM81 */
   2314 	chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
   2315 	switch(chipid) {
   2316 	case LM_ID_LM78:
   2317 		model = "LM78";
   2318 		break;
   2319 	case LM_ID_LM78J:
   2320 		model = "LM78J";
   2321 		break;
   2322 	case LM_ID_LM79:
   2323 		model = "LM79";
   2324 		break;
   2325 	case LM_ID_LM81:
   2326 		model = "LM81";
   2327 		break;
   2328 	default:
   2329 		return -1;
   2330 	}
   2331 
   2332 	aprint_naive("\n");
   2333 	aprint_normal("\n");
   2334 	aprint_normal_dev(sc->sc_dev,
   2335 	    "National Semiconductor %s Hardware monitor\n", model);
   2336 
   2337 	lm_setup_sensors(sc, lm78_sensors);
   2338 	sc->refresh_sensor_data = lm_refresh_sensor_data;
   2339 	return 0;
   2340 }
   2341 
   2342 static int
   2343 def_match(struct lm_softc *sc)
   2344 {
   2345 
   2346 	return 1;
   2347 }
   2348 
   2349 static int
   2350 def_attach(struct lm_softc *sc)
   2351 {
   2352 	uint8_t chipid;
   2353 
   2354 	chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
   2355 	aprint_naive("\n");
   2356 	aprint_normal("\n");
   2357 	aprint_error_dev(sc->sc_dev, "Unknown chip (ID 0x%02x)\n", chipid);
   2358 
   2359 	lm_setup_sensors(sc, lm78_sensors);
   2360 	sc->refresh_sensor_data = lm_refresh_sensor_data;
   2361 	return 0;
   2362 }
   2363 
   2364 static void
   2365 wb_temp_diode_type(struct lm_softc *sc, int diode_type)
   2366 {
   2367 	uint8_t regval, banksel;
   2368 
   2369 	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
   2370 	switch (diode_type) {
   2371 	    case 1:	/* Switch to Pentium-II diode mode */
   2372 		lm_generic_banksel(sc, WB_BANKSEL_B0);
   2373 		regval = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
   2374 		regval |= 0x0e;
   2375 		(*sc->lm_writereg)(sc, WB_BANK0_VBAT, regval);
   2376 		regval = (*sc->lm_readreg)(sc, WB_BANK0_RESVD1);
   2377 		regval |= 0x70;
   2378 		(*sc->lm_writereg)(sc, WB_BANK0_RESVD1, 0x0);
   2379 		lm_generic_banksel(sc, banksel);
   2380 		aprint_verbose_dev(sc->sc_dev, "Pentium-II diode temp sensors\n");
   2381 		break;
   2382 	    case 2:	/* Switch to 2N3904 mode */
   2383 		lm_generic_banksel(sc, WB_BANKSEL_B0);
   2384 		regval = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
   2385 		regval |= 0xe;
   2386 		(*sc->lm_writereg)(sc, WB_BANK0_VBAT, regval);
   2387 		regval = (*sc->lm_readreg)(sc, WB_BANK0_RESVD1);
   2388 		regval &= ~0x70;
   2389 		(*sc->lm_writereg)(sc, WB_BANK0_RESVD1, 0x0);
   2390 		lm_generic_banksel(sc, banksel);
   2391 		aprint_verbose_dev(sc->sc_dev, "2N3904 bipolar temp sensors\n");
   2392 		break;
   2393 	    case 4:	/* Switch to generic thermistor mode */
   2394 		lm_generic_banksel(sc, WB_BANKSEL_B0);
   2395 		regval = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
   2396 		regval &= ~0xe;
   2397 		(*sc->lm_writereg)(sc, WB_BANK0_VBAT, regval);
   2398 		lm_generic_banksel(sc, banksel);
   2399 		aprint_verbose_dev(sc->sc_dev, "Thermistor temp sensors\n");
   2400 		break;
   2401 	    case 0:	/* Unspecified - use default */
   2402 		aprint_verbose_dev(sc->sc_dev, "Using default temp sensors\n");
   2403 		break;
   2404 	    default:
   2405 		aprint_error_dev(sc->sc_dev,
   2406 				 "Ignoring invalid temp sensor mode %d\n",
   2407 				 diode_type);
   2408 		break;
   2409 	}
   2410 }
   2411 
   2412 static const struct wb_product *
   2413 wb_lookup(struct lm_softc *sc, const struct wb_product *products, uint16_t id)
   2414 {
   2415 	const struct wb_product *prod = products;
   2416 	int i = 0;
   2417 
   2418 	while (prod[i].id != 0) {
   2419 		if (prod[i].id != id) {
   2420 			i++;
   2421 			continue;
   2422 		}
   2423 		if (prod[i].str == NULL) {
   2424 			if (products == wb_products) {
   2425 				if (id == WB_CHIPID_W83627DHG) {
   2426 					/*
   2427 					 *  Lookup wbsio_products
   2428 					 * with WBSIO_ID.
   2429 					 */
   2430 					return wb_lookup(sc, wbsio_products,
   2431 					    sc->sioid);
   2432 				} else if (id == WB_CHIPID_AS99127F) {
   2433 					/*
   2434 					 *  Lookup as99127f_products
   2435 					 * with WB_VENDID.
   2436 					 */
   2437 					return wb_lookup(sc, as99127f_products,
   2438 					    wb_read_vendorid(sc));
   2439 				} else
   2440 					return NULL; /* not occur */
   2441 			}
   2442 			return NULL; /* not occur */
   2443 		}
   2444 		return &prod[i];
   2445 	}
   2446 
   2447 	/* Not found */
   2448 	return NULL;
   2449 }
   2450 
   2451 static uint16_t
   2452 wb_read_vendorid(struct lm_softc *sc)
   2453 {
   2454 	uint16_t vendid;
   2455 	uint8_t vendidreg;
   2456 	uint8_t banksel;
   2457 
   2458 	/* Save bank */
   2459 	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
   2460 
   2461 	/* Check default vendor ID register first */
   2462 	vendidreg = WB_VENDID;
   2463 
   2464 retry:
   2465 	/* Read vendor ID */
   2466 	lm_generic_banksel(sc, WB_BANKSEL_HBAC);
   2467 	vendid = (*sc->lm_readreg)(sc, vendidreg) << 8;
   2468 	lm_generic_banksel(sc, 0);
   2469 	vendid |= (*sc->lm_readreg)(sc, vendidreg);
   2470 
   2471 	if ((vendidreg == WB_VENDID)
   2472 	    &&  (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)) {
   2473 		/* If it failed, try NCT6102 vendor ID register */
   2474 		vendidreg = WB_NCT6102_VENDID;
   2475 		goto retry;
   2476 	} else if ((vendidreg == WB_NCT6102_VENDID)
   2477 	    && (vendid != WB_VENDID_WINBOND))
   2478 		vendid = 0; /* XXX */
   2479 
   2480 	/* Restore bank */
   2481 	lm_generic_banksel(sc, banksel);
   2482 
   2483 	return vendid;
   2484 }
   2485 
   2486 static uint8_t
   2487 wb_read_chipid(struct lm_softc *sc)
   2488 {
   2489 	const struct wb_product *prod;
   2490 	uint8_t chipidreg, chipid, banksel;
   2491 
   2492 	/* Save bank */
   2493 	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
   2494 
   2495 	/* Check default vendor ID register first */
   2496 	chipidreg = WB_BANK0_CHIPID;
   2497 	lm_generic_banksel(sc, WB_BANKSEL_B0);
   2498 
   2499 retry:
   2500 	(void)(*sc->lm_readreg)(sc, LMD_CHIPID);
   2501 	chipid = (*sc->lm_readreg)(sc, chipidreg);
   2502 	prod = wb_lookup(sc, wb_products, chipid);
   2503 	if (prod == NULL) {
   2504 		if (chipidreg == WB_BANK0_CHIPID) {
   2505 			chipidreg = WB_BANK0_NCT6102_CHIPID;
   2506 			goto retry;
   2507 		} else
   2508 			chipid = 0;
   2509 	}
   2510 	/* Restore bank */
   2511 	lm_generic_banksel(sc, banksel);
   2512 
   2513 	return chipid;
   2514 }
   2515 
   2516 static int
   2517 wb_match(struct lm_softc *sc)
   2518 {
   2519 	const struct wb_product *prod;
   2520 	uint16_t vendid;
   2521 	uint8_t chipid;
   2522 
   2523 	/* Read vendor ID */
   2524 	vendid = wb_read_vendorid(sc);
   2525 	DPRINTF(("%s: winbond vend id 0x%x\n", __func__, vendid));
   2526 	if ((vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS))
   2527 		return 0;
   2528 
   2529 	/* Read device/chip ID */
   2530 	chipid = wb_read_chipid(sc);
   2531 	DPRINTF(("%s: winbond chip id 0x%x\n", __func__, chipid));
   2532 	prod = wb_lookup(sc, wb_products, chipid);
   2533 
   2534 	if (prod == NULL) {
   2535 		if (vendid == WB_VENDID_WINBOND)
   2536 			return 1; /* Generic match */
   2537 		else
   2538 			return 0;
   2539 	}
   2540 	DPRINTF(("%s: chipid %02x, sioid = %04x\n", __func__, chipid,
   2541 		sc->sioid));
   2542 
   2543 	return 10; /* found */
   2544 }
   2545 
   2546 static int
   2547 wb_attach(struct lm_softc *sc)
   2548 {
   2549 	device_t dev = sc->sc_dev;
   2550 	const struct wb_product *prod;
   2551 	const char *model = NULL;
   2552 	const char *vendor = "Winbond";
   2553 	const struct lm_sensor *sensors;
   2554 	uint16_t vendid;
   2555 	uint8_t banksel;
   2556 	int cf_flags;
   2557 
   2558 	aprint_naive("\n");
   2559 	aprint_normal("\n");
   2560 	/* Read device/chip ID */
   2561 	sc->chipid = wb_read_chipid(sc);
   2562 	DPRINTF(("%s: winbond chip id 0x%x\n", __func__, sc->chipid));
   2563 
   2564 	if ((prod = wb_lookup(sc, wb_products, sc->chipid)) != NULL) {
   2565 		model = prod->str;
   2566 		switch (model[0]) {
   2567 		case 'W':
   2568 			vendor = "Winbond";
   2569 			break;
   2570 		case 'A':
   2571 			vendor = "ASUS";
   2572 			break;
   2573 		case 'N':
   2574 			vendor = "Nuvoton";
   2575 			break;
   2576 		default:
   2577 			aprint_error_dev(dev, "Unknown model (%s)\n", model);
   2578 			return -1;
   2579 		}
   2580 		sensors = prod->sensors;
   2581 		sc->refresh_sensor_data = wb_refresh_sensor_data;
   2582 		if (prod->extattach != NULL)
   2583 			prod->extattach(sc);
   2584 	} else {
   2585 		vendid = wb_read_vendorid(sc);
   2586 		if (vendid == WB_VENDID_WINBOND) {
   2587 			vendor = "Winbond";
   2588 			model = "unknown-model";
   2589 
   2590 			/* Handle as a standard LM78. */
   2591 			sensors = lm78_sensors;
   2592 			sc->refresh_sensor_data = lm_refresh_sensor_data;
   2593 		} else {
   2594 			aprint_error_dev(dev, "Unknown chip (ID %02x)\n",
   2595 			    sc->chipid);
   2596 			return -1;
   2597 		}
   2598 	}
   2599 
   2600 	cf_flags = device_cfdata(dev)->cf_flags;
   2601 
   2602 	if (sensors != NULL) {
   2603 		lm_setup_sensors(sc, sensors);
   2604 
   2605 		/* XXX Is this correct? Check all datasheets. */
   2606 		switch (sc->chipid) {
   2607 		case WB_CHIPID_W83627EHF_A:
   2608 		case WB_CHIPID_W83781D:
   2609 		case WB_CHIPID_W83781D_2:
   2610 		case WB_CHIPID_W83791SD:
   2611 		case WB_CHIPID_W83792D:
   2612 		case WB_CHIPID_AS99127F:
   2613 			break;
   2614 		default:
   2615 			wb_temp_diode_type(sc, cf_flags);
   2616 			break;
   2617 		}
   2618 	}
   2619 
   2620 	/* XXX Is this correct? Check all datasheets. */
   2621 	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
   2622 	switch(sc->chipid) {
   2623 	case WB_CHIPID_W83627THF:
   2624 		lm_generic_banksel(sc, WB_BANKSEL_B0);
   2625 		if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
   2626 			sc->vrm9 = 1;
   2627 		lm_generic_banksel(sc, banksel);
   2628 		break;
   2629 	case WB_CHIPID_W83637HF:
   2630 		lm_generic_banksel(sc, WB_BANKSEL_B0);
   2631 		if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
   2632 			sc->vrm9 = 1;
   2633 		lm_generic_banksel(sc, banksel);
   2634 		break;
   2635 	default:
   2636 		break;
   2637 	}
   2638 
   2639 	aprint_normal_dev(dev, "%s %s Hardware monitor\n", vendor, model);
   2640 
   2641 	return 0;
   2642 }
   2643 
   2644 static void
   2645 lm_setup_sensors(struct lm_softc *sc, const struct lm_sensor *sensors)
   2646 {
   2647 	int i;
   2648 
   2649 	for (i = 0; sensors[i].desc; i++) {
   2650 		sc->sensors[i].units = sensors[i].type;
   2651 		if (sc->sensors[i].units == ENVSYS_SVOLTS_DC)
   2652 			sc->sensors[i].flags = ENVSYS_FCHANGERFACT;
   2653 		strlcpy(sc->sensors[i].desc, sensors[i].desc,
   2654 		    sizeof(sc->sensors[i].desc));
   2655 		sc->numsensors++;
   2656 	}
   2657 	sc->lm_sensors = sensors;
   2658 }
   2659 
   2660 static void
   2661 lm_refresh_sensor_data(struct lm_softc *sc)
   2662 {
   2663 	int i;
   2664 
   2665 	for (i = 0; i < sc->numsensors; i++)
   2666 		sc->lm_sensors[i].refresh(sc, i);
   2667 }
   2668 
   2669 static void
   2670 lm_refresh_volt(struct lm_softc *sc, int n)
   2671 {
   2672 	int data;
   2673 
   2674 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2675 	if (data == 0xff) {
   2676 		sc->sensors[n].state = ENVSYS_SINVALID;
   2677 	} else {
   2678 		sc->sensors[n].value_cur = (data << 4);
   2679 		if (sc->sensors[n].rfact) {
   2680 			sc->sensors[n].value_cur *= sc->sensors[n].rfact;
   2681 			sc->sensors[n].value_cur /= 10;
   2682 		} else {
   2683 			sc->sensors[n].value_cur *= sc->lm_sensors[n].rfact;
   2684 			sc->sensors[n].value_cur /= 10;
   2685 			sc->sensors[n].rfact = sc->lm_sensors[n].rfact;
   2686 		}
   2687 		sc->sensors[n].state = ENVSYS_SVALID;
   2688 	}
   2689 
   2690 	DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
   2691 	    __func__, n, data, sc->sensors[n].value_cur));
   2692 }
   2693 
   2694 static void
   2695 lm_refresh_temp(struct lm_softc *sc, int n)
   2696 {
   2697 	int data;
   2698 
   2699 	/*
   2700 	 * The data sheet suggests that the range of the temperature
   2701 	 * sensor is between -55 degC and +125 degC.
   2702 	 */
   2703 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2704 	if (data > 0x7d && data < 0xc9)
   2705 		sc->sensors[n].state = ENVSYS_SINVALID;
   2706 	else {
   2707 		if (data & 0x80)
   2708 			data -= 0x100;
   2709 		sc->sensors[n].state = ENVSYS_SVALID;
   2710 		sc->sensors[n].value_cur = data * 1000000 + 273150000;
   2711 	}
   2712 	DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
   2713 	    __func__, n, data, sc->sensors[n].value_cur));
   2714 }
   2715 
   2716 static void
   2717 lm_refresh_fanrpm(struct lm_softc *sc, int n)
   2718 {
   2719 	int data, divisor = 1;
   2720 
   2721 	/*
   2722 	 * We might get more accurate fan readings by adjusting the
   2723 	 * divisor, but that might interfere with APM or other SMM
   2724 	 * BIOS code reading the fan speeds.
   2725 	 */
   2726 
   2727 	/* FAN3 has a fixed fan divisor. */
   2728 	if (sc->lm_sensors[n].reg == LMD_FAN1 ||
   2729 	    sc->lm_sensors[n].reg == LMD_FAN2) {
   2730 		data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
   2731 		if (sc->lm_sensors[n].reg == LMD_FAN1)
   2732 			divisor = (data >> 4) & 0x03;
   2733 		else
   2734 			divisor = (data >> 6) & 0x03;
   2735 	}
   2736 
   2737 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2738 	if (data == 0xff || data == 0x00)
   2739 		sc->sensors[n].state = ENVSYS_SINVALID;
   2740 	else {
   2741 		sc->sensors[n].state = ENVSYS_SVALID;
   2742 		sc->sensors[n].value_cur = 1350000 / (data << divisor);
   2743 	}
   2744 	DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
   2745 	    __func__, n, data, sc->sensors[n].value_cur));
   2746 }
   2747 
   2748 static void
   2749 wb_refresh_sensor_data(struct lm_softc *sc)
   2750 {
   2751 	uint8_t banksel, bank;
   2752 	int i;
   2753 
   2754 	/*
   2755 	 * Properly save and restore bank selection register.
   2756 	 */
   2757 	banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
   2758 	for (i = 0; i < sc->numsensors; i++) {
   2759 		if (bank != sc->lm_sensors[i].bank) {
   2760 			bank = sc->lm_sensors[i].bank;
   2761 			lm_generic_banksel(sc, bank);
   2762 		}
   2763 		sc->lm_sensors[i].refresh(sc, i);
   2764 	}
   2765 	lm_generic_banksel(sc, banksel);
   2766 }
   2767 
   2768 static void
   2769 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
   2770 {
   2771 	int data;
   2772 
   2773 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2774 	/*
   2775 	 * Depending on the voltage detection method,
   2776 	 * one of the following formulas is used:
   2777 	 *	VRM8 method: value = raw * 0.016V
   2778 	 *	VRM9 method: value = raw * 0.00488V + 0.70V
   2779 	 */
   2780 	if (sc->vrm9)
   2781 		sc->sensors[n].value_cur = (data * 4880) + 700000;
   2782 	else
   2783 		sc->sensors[n].value_cur = (data * 16000);
   2784 	sc->sensors[n].state = ENVSYS_SVALID;
   2785 	DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
   2786 	   __func__, n, data, sc->sensors[n].value_cur));
   2787 }
   2788 
   2789 static void
   2790 wb_refresh_nvolt(struct lm_softc *sc, int n)
   2791 {
   2792 	int data;
   2793 
   2794 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2795 	sc->sensors[n].value_cur = ((data << 4) - WB_VREF);
   2796 	if (sc->sensors[n].rfact)
   2797 		sc->sensors[n].value_cur *= sc->sensors[n].rfact;
   2798 	else
   2799 		sc->sensors[n].value_cur *= sc->lm_sensors[n].rfact;
   2800 
   2801 	sc->sensors[n].value_cur /= 10;
   2802 	sc->sensors[n].value_cur += WB_VREF * 1000;
   2803 	sc->sensors[n].state = ENVSYS_SVALID;
   2804 	DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
   2805 	     __func__, n , data, sc->sensors[n].value_cur));
   2806 }
   2807 
   2808 static void
   2809 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
   2810 {
   2811 	int data;
   2812 
   2813 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2814 	sc->sensors[n].value_cur = ((data << 3) - WB_W83627EHF_VREF);
   2815 	if (sc->sensors[n].rfact)
   2816 		sc->sensors[n].value_cur *= sc->sensors[n].rfact;
   2817 	else
   2818 		sc->sensors[n].value_cur *= RFACT(232, 10);
   2819 
   2820 	sc->sensors[n].value_cur /= 10;
   2821 	sc->sensors[n].value_cur += WB_W83627EHF_VREF * 1000;
   2822 	sc->sensors[n].state = ENVSYS_SVALID;
   2823 	DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
   2824 	    __func__, n , data, sc->sensors[n].value_cur));
   2825 }
   2826 
   2827 static void
   2828 wb_refresh_temp(struct lm_softc *sc, int n)
   2829 {
   2830 	int data;
   2831 
   2832 	/*
   2833 	 * The data sheet suggests that the range of the temperature
   2834 	 * sensor is between -55 degC and +125 degC.  However, values
   2835 	 * around -48 degC seem to be a very common bogus values.
   2836 	 * Since such values are unreasonably low, we use -45 degC for
   2837 	 * the lower limit instead.
   2838 	 */
   2839 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
   2840 	data += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
   2841 	if (data > 0xfffffff || (data > 0x0fa && data < 0x1a6)) {
   2842 		sc->sensors[n].state = ENVSYS_SINVALID;
   2843 	} else {
   2844 		if (data & 0x100)
   2845 			data -= 0x200;
   2846 		sc->sensors[n].state = ENVSYS_SVALID;
   2847 		sc->sensors[n].value_cur = data * 500000 + 273150000;
   2848 	}
   2849 	DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
   2850 	    __func__, n , data, sc->sensors[n].value_cur));
   2851 }
   2852 
   2853 static void
   2854 wb_refresh_fanrpm(struct lm_softc *sc, int n)
   2855 {
   2856 	int fan, data, divisor = 0;
   2857 
   2858 	/*
   2859 	 * This is madness; the fan divisor bits are scattered all
   2860 	 * over the place.
   2861 	 */
   2862 
   2863 	if (sc->lm_sensors[n].reg == LMD_FAN1 ||
   2864 	    sc->lm_sensors[n].reg == LMD_FAN2 ||
   2865 	    sc->lm_sensors[n].reg == LMD_FAN3) {
   2866 		data = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
   2867 		fan = (sc->lm_sensors[n].reg - LMD_FAN1);
   2868 		if ((data >> 5) & (1 << fan))
   2869 			divisor |= 0x04;
   2870 	}
   2871 
   2872 	if (sc->lm_sensors[n].reg == LMD_FAN1 ||
   2873 	    sc->lm_sensors[n].reg == LMD_FAN2) {
   2874 		data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
   2875 		if (sc->lm_sensors[n].reg == LMD_FAN1)
   2876 			divisor |= (data >> 4) & 0x03;
   2877 		else
   2878 			divisor |= (data >> 6) & 0x03;
   2879 	} else if (sc->lm_sensors[n].reg == LMD_FAN3) {
   2880 		data = (*sc->lm_readreg)(sc, WB_PIN);
   2881 		divisor |= (data >> 6) & 0x03;
   2882 	} else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
   2883 		   sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
   2884 		data = (*sc->lm_readreg)(sc, WB_BANK0_FAN45);
   2885 		if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
   2886 			divisor |= (data >> 0) & 0x07;
   2887 		else
   2888 			divisor |= (data >> 4) & 0x07;
   2889 	}
   2890 
   2891 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2892 	if (data >= 0xff || data == 0x00)
   2893 		sc->sensors[n].state = ENVSYS_SINVALID;
   2894 	else {
   2895 		sc->sensors[n].state = ENVSYS_SVALID;
   2896 		sc->sensors[n].value_cur = 1350000 / (data << divisor);
   2897 	}
   2898 	DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
   2899 	    __func__, n , data, sc->sensors[n].value_cur));
   2900 }
   2901 
   2902 static void
   2903 wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n)
   2904 {
   2905 	int datah, datal;
   2906 
   2907 	datah = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2908 	datal = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1);
   2909 
   2910 	if ((datah == 0xff) || (datah == 0)) {
   2911 		sc->sensors[n].state = ENVSYS_SINVALID;
   2912 	} else {
   2913 		sc->sensors[n].state = ENVSYS_SVALID;
   2914 		sc->sensors[n].value_cur = (datah << 8) | datal;
   2915 	}
   2916 }
   2917 
   2918 static void
   2919 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
   2920 {
   2921 	int shift, data, divisor = 1;
   2922 	uint8_t reg;
   2923 
   2924 	shift = 0;
   2925 
   2926 	switch (sc->lm_sensors[n].reg) {
   2927 	case 0x28:
   2928 		reg = 0x47; shift = 0;
   2929 		break;
   2930 	case 0x29:
   2931 		reg = 0x47; shift = 4;
   2932 		break;
   2933 	case 0x2a:
   2934 		reg = 0x5b; shift = 0;
   2935 		break;
   2936 	case 0xb8:
   2937 		reg = 0x5b; shift = 4;
   2938 		break;
   2939 	case 0xb9:
   2940 		reg = 0x5c; shift = 0;
   2941 		break;
   2942 	case 0xba:
   2943 		reg = 0x5c; shift = 4;
   2944 		break;
   2945 	case 0xbe:
   2946 		reg = 0x9e; shift = 0;
   2947 		break;
   2948 	default:
   2949 		reg = 0;
   2950 		break;
   2951 	}
   2952 
   2953 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
   2954 	if (data == 0xff || data == 0x00)
   2955 		sc->sensors[n].state = ENVSYS_SINVALID;
   2956 	else {
   2957 		if (reg != 0)
   2958 			divisor = ((*sc->lm_readreg)(sc, reg) >> shift) & 0x7;
   2959 		sc->sensors[n].state = ENVSYS_SVALID;
   2960 		sc->sensors[n].value_cur = 1350000 / (data << divisor);
   2961 	}
   2962 	DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
   2963 	    __func__, n , data, sc->sensors[n].value_cur));
   2964 }
   2965 
   2966 static void
   2967 as_refresh_temp(struct lm_softc *sc, int n)
   2968 {
   2969 	int data;
   2970 
   2971 	/*
   2972 	 * It seems a shorted temperature diode produces an all-ones
   2973 	 * bit pattern.
   2974 	 */
   2975 	data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
   2976 	data += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
   2977 	if (data == 0x1ff)
   2978 		sc->sensors[n].state = ENVSYS_SINVALID;
   2979 	else {
   2980 		if (data & 0x100)
   2981 			data -= 0x200;
   2982 		sc->sensors[n].state = ENVSYS_SVALID;
   2983 		sc->sensors[n].value_cur = data * 500000 + 273150000;
   2984 	}
   2985 	DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
   2986 	    __func__, n, data, sc->sensors[n].value_cur));
   2987 }
   2988 
   2989 MODULE(MODULE_CLASS_DRIVER, lm, "sysmon_envsys");
   2990 
   2991 static int
   2992 lm_modcmd(modcmd_t cmd, void *opaque)
   2993 {
   2994 	switch (cmd) {
   2995 	case MODULE_CMD_INIT:
   2996 	case MODULE_CMD_FINI:
   2997 		return 0;
   2998 	default:
   2999 		return ENOTTY;
   3000 	}
   3001 }
   3002