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
75static const struct wb_product *wb_lookup(struct lm_softc *,
76    const struct wb_product *, uint16_t);
77static int wb_match(struct lm_softc *);
78static int wb_attach(struct lm_softc *);
79static int nslm_match(struct lm_softc *);
80static int nslm_attach(struct lm_softc *);
81static int def_match(struct lm_softc *);
82static int def_attach(struct lm_softc *);
83static void wb_temp_diode_type(struct lm_softc *, int);
84static uint16_t wb_read_vendorid(struct lm_softc *);
85
86static void lm_refresh(void *);
87
88static void lm_generic_banksel(struct lm_softc *, uint8_t);
89static void lm_setup_sensors(struct lm_softc *, const struct lm_sensor *);
90static void lm_refresh_sensor_data(struct lm_softc *);
91static void lm_refresh_volt(struct lm_softc *, int);
92static void lm_refresh_temp(struct lm_softc *, int);
93static void lm_refresh_fanrpm(struct lm_softc *, int);
94
95static void wb_refresh_sensor_data(struct lm_softc *);
96static void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
97static void wb_refresh_nvolt(struct lm_softc *, int);
98static void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
99static void wb_refresh_temp(struct lm_softc *, int);
100static void wb_refresh_fanrpm(struct lm_softc *, int);
101static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
102static void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
103
104static void as_refresh_temp(struct lm_softc *, int);
105
106struct lm_chip {
107	int (*chip_match)(struct lm_softc *);
108	int (*chip_attach)(struct lm_softc *);
109};
110
111static 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 */
118static 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 */
217static 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 */
356static 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 */
495static 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 */
626static 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 */
741static 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 */
854static 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 */
969static 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 */
1100static 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 */
1199static 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 */
1354static 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 */
1517static 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 */
1632static 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 */
1780static 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 */
1911static 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
2129static 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
2148static 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
2165static 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
2171static void
2172lm_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 */
2183int
2184lm_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
2207int
2208nslm_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
2227void
2228lm_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 */
2287void
2288lm_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
2298static void
2299lm_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
2307static int
2308nslm_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
2342static int
2343def_match(struct lm_softc *sc)
2344{
2345
2346	return 1;
2347}
2348
2349static int
2350def_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
2364static void
2365wb_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
2412static const struct wb_product *
2413wb_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
2451static uint16_t
2452wb_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
2464retry:
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
2486static uint8_t
2487wb_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
2499retry:
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
2516static int
2517wb_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
2546static int
2547wb_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
2644static void
2645lm_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
2660static void
2661lm_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
2669static void
2670lm_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
2694static void
2695lm_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
2716static void
2717lm_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
2748static void
2749wb_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
2768static void
2769wb_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
2789static void
2790wb_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
2808static void
2809wb_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
2827static void
2828wb_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
2853static void
2854wb_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
2902static void
2903wb_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
2918static void
2919wb_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
2966static void
2967as_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
2989MODULE(MODULE_CLASS_DRIVER, lm, "sysmon_envsys");
2990
2991static int
2992lm_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