nslm7x.c revision 1.33 1 /* $NetBSD: nslm7x.c,v 1.33 2007/03/13 18:32:35 xtraeme 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.33 2007/03/13 18:32:35 xtraeme Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/device.h>
47 #include <sys/conf.h>
48 #include <sys/time.h>
49
50 #include <machine/bus.h>
51
52 #include <dev/isa/isareg.h>
53 #include <dev/isa/isavar.h>
54
55 #include <dev/sysmon/sysmonvar.h>
56
57 #include <dev/ic/nslm7xvar.h>
58
59 #include <machine/intr.h>
60
61 #if defined(LMDEBUG)
62 #define DPRINTF(x) do { printf x; } while (0)
63 #else
64 #define DPRINTF(x)
65 #endif
66
67 /*
68 * LM78-compatible chips can typically measure voltages up to 4.096 V.
69 * To measure higher voltages the input is attenuated with (external)
70 * resistors. Negative voltages are measured using inverting op amps
71 * and resistors. So we have to convert the sensor values back to
72 * real voltages by applying the appropriate resistor factor.
73 */
74 #define RFACT_NONE 10000
75 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
76 #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
77
78 const struct envsys_range lm_ranges[] = { /* sc->sensors sub-intervals */
79 /* for each unit type */
80 { 7, 7, ENVSYS_STEMP },
81 { 8, 10, ENVSYS_SFANRPM },
82 { 1, 0, ENVSYS_SVOLTS_AC }, /* None */
83 { 0, 6, ENVSYS_SVOLTS_DC },
84 { 1, 0, ENVSYS_SOHMS }, /* None */
85 { 1, 0, ENVSYS_SWATTS }, /* None */
86 { 1, 0, ENVSYS_SAMPS } /* None */
87 };
88
89 static int lm_match(struct lm_softc *);
90 static int wb_match(struct lm_softc *);
91 static int def_match(struct lm_softc *);
92
93 static void lm_generic_banksel(struct lm_softc *, int);
94 static void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
95
96 static void lm_refresh_sensor_data(struct lm_softc *);
97 static void lm_refresh_volt(struct lm_softc *, int);
98 static void lm_refresh_temp(struct lm_softc *, int);
99 static void lm_refresh_fanrpm(struct lm_softc *, int);
100
101 static void wb_refresh_sensor_data(struct lm_softc *);
102 static void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
103 static void wb_refresh_nvolt(struct lm_softc *, int);
104 static void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
105 static void wb_refresh_temp(struct lm_softc *, int);
106 static void wb_refresh_fanrpm(struct lm_softc *, int);
107 static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
108
109 static void as_refresh_temp(struct lm_softc *, int);
110
111 static int lm_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
112 static int generic_streinfo_fan(struct lm_softc *, struct envsys_basic_info *,
113 int, struct envsys_basic_info *);
114 static int lm_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
115 static int wb781_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
116 static int wb782_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
117
118 struct lm_chip {
119 int (*chip_match)(struct lm_softc *);
120 };
121
122 static struct lm_chip lm_chips[] = {
123 { wb_match },
124 { lm_match },
125 { def_match } /* Must be last */
126 };
127
128 /* LM78/78J/79/81 */
129 static struct lm_sensor lm78_sensors[] = {
130 /* Voltage */
131 {
132 .desc = "VCore A",
133 .type = ENVSYS_SVOLTS_DC,
134 .bank = 0,
135 .reg = 0x20,
136 .refresh = lm_refresh_volt,
137 .rfact = RFACT_NONE
138 },
139 {
140 .desc = "VCore B",
141 .type = ENVSYS_SVOLTS_DC,
142 .bank = 0,
143 .reg = 0x21,
144 .refresh = lm_refresh_volt,
145 .rfact = RFACT_NONE
146 },
147 {
148 .desc = "+3.3V",
149 .type = ENVSYS_SVOLTS_DC,
150 .bank = 0,
151 .reg = 0x22,
152 .refresh = lm_refresh_volt,
153 .rfact = RFACT_NONE
154 },
155 {
156 .desc = "+5V",
157 .type = ENVSYS_SVOLTS_DC,
158 .bank = 0,
159 .reg = 0x23,
160 .refresh = lm_refresh_volt,
161 .rfact = RFACT(68, 100)
162 },
163 {
164 .desc = "+12V",
165 .type = ENVSYS_SVOLTS_DC,
166 .bank = 0,
167 .reg = 0x24,
168 .refresh = lm_refresh_volt,
169 .rfact = RFACT(30, 10)
170 },
171 {
172 .desc = "-12V",
173 .type = ENVSYS_SVOLTS_DC,
174 .bank = 0,
175 .reg = 0x25,
176 .refresh = lm_refresh_volt,
177 .rfact = NRFACT(240, 60)
178 },
179 {
180 .desc = "-5V",
181 .type = ENVSYS_SVOLTS_DC,
182 .bank = 0,
183 .reg = 0x26,
184 .refresh = lm_refresh_volt,
185 .rfact = NRFACT(100, 60)
186 },
187
188 /* Temperature */
189 {
190 .desc = "Temp0",
191 .type = ENVSYS_STEMP,
192 .bank = 0,
193 .reg = 0x27,
194 .refresh = lm_refresh_temp,
195 .rfact = 0
196 },
197
198 /* Fans */
199 {
200 .desc = "Fan0",
201 .type = ENVSYS_SFANRPM,
202 .bank = 0,
203 .reg = 0x28,
204 .refresh = lm_refresh_fanrpm,
205 .rfact = 0
206 },
207 {
208 .desc = "Fan1",
209 .type = ENVSYS_SFANRPM,
210 .bank = 0,
211 .reg = 0x29,
212 .refresh = lm_refresh_fanrpm,
213 .rfact = 0
214 },
215 {
216 .desc = "Fan2",
217 .type = ENVSYS_SFANRPM,
218 .bank = 0,
219 .reg = 0x2a,
220 .refresh = lm_refresh_fanrpm,
221 .rfact = 0
222 },
223
224 { .desc = NULL }
225 };
226
227 /* W83627HF */
228 static struct lm_sensor w83627hf_sensors[] = {
229 /* Voltage */
230 {
231 .desc = "VCore A",
232 .type = ENVSYS_SVOLTS_DC,
233 .bank = 0,
234 .reg = 0x20,
235 .refresh = lm_refresh_volt,
236 .rfact = RFACT_NONE
237 },
238 {
239 .desc = "VCore B",
240 .type = ENVSYS_SVOLTS_DC,
241 .bank = 0,
242 .reg = 0x21,
243 .refresh = lm_refresh_volt,
244 .rfact = RFACT_NONE
245 },
246 {
247 .desc = "+3.3V",
248 .type = ENVSYS_SVOLTS_DC,
249 .bank = 0,
250 .reg = 0x22,
251 .refresh = lm_refresh_volt,
252 .rfact = RFACT_NONE
253 },
254 {
255 .desc = "+5V",
256 .type = ENVSYS_SVOLTS_DC,
257 .bank = 0,
258 .reg = 0x23,
259 .refresh = lm_refresh_volt,
260 .rfact = RFACT(34, 50)
261 },
262 {
263 .desc = "+12V",
264 .type = ENVSYS_SVOLTS_DC,
265 .bank = 0,
266 .reg = 0x24,
267 .refresh = lm_refresh_volt,
268 .rfact = RFACT(28, 10)
269 },
270 {
271 .desc = "-12V",
272 .type = ENVSYS_SVOLTS_DC,
273 .bank = 0,
274 .reg = 0x25,
275 .refresh = wb_refresh_nvolt,
276 .rfact = RFACT(232, 56)
277 },
278 {
279 .desc = "-5V",
280 .type = ENVSYS_SVOLTS_DC,
281 .bank = 0,
282 .reg = 0x26,
283 .refresh = wb_refresh_nvolt,
284 .rfact = RFACT(120, 56)
285 },
286 {
287 .desc = "5VSB",
288 .type = ENVSYS_SVOLTS_DC,
289 .bank = 5,
290 .reg = 0x50,
291 .refresh = lm_refresh_volt,
292 .rfact = RFACT(17, 33)
293 },
294 {
295 .desc = "VBAT",
296 .type = ENVSYS_SVOLTS_DC,
297 .bank = 5,
298 .reg = 0x51,
299 .refresh = lm_refresh_volt,
300 .rfact = RFACT_NONE
301 },
302
303 /* Temperature */
304 {
305 .desc = "Temp0",
306 .type = ENVSYS_STEMP,
307 .bank = 0,
308 .reg = 0x27,
309 .refresh = lm_refresh_temp,
310 .rfact = 0
311 },
312 {
313 .desc = "Temp1",
314 .type = ENVSYS_STEMP,
315 .bank = 1,
316 .reg = 0x50,
317 .refresh = wb_refresh_temp,
318 .rfact = 0
319 },
320 {
321 .desc = "Temp2",
322 .type = ENVSYS_STEMP,
323 .bank = 2,
324 .reg = 0x50,
325 .refresh = wb_refresh_temp,
326 .rfact = 0
327 },
328
329 /* Fans */
330 {
331 .desc = "Fan0",
332 .type = ENVSYS_SFANRPM,
333 .bank = 0,
334 .reg = 0x28,
335 .refresh = wb_refresh_fanrpm,
336 .rfact = 0
337 },
338 {
339 .desc = "Fan1",
340 .type = ENVSYS_SFANRPM,
341 .bank = 0,
342 .reg = 0x29,
343 .refresh = wb_refresh_fanrpm,
344 .rfact = 0
345 },
346 {
347 .desc = "Fan2",
348 .type = ENVSYS_SFANRPM,
349 .bank = 0,
350 .reg = 0x2a,
351 .refresh = wb_refresh_fanrpm,
352 .rfact = 0
353 },
354
355 { .desc = NULL }
356 };
357
358 /* W8627EHF */
359
360 /*
361 * The W83627EHF can measure voltages up to 2.048 V instead of the
362 * traditional 4.096 V. For measuring positive voltages, this can be
363 * accounted for by halving the resistor factor. Negative voltages
364 * need special treatment, also because the reference voltage is 2.048 V
365 * instead of the traditional 3.6 V.
366 */
367 static struct lm_sensor w83627ehf_sensors[] = {
368 /* Voltage */
369 {
370 .desc = "VCore",
371 .type = ENVSYS_SVOLTS_DC,
372 .bank = 0,
373 .reg = 0x20,
374 .refresh = lm_refresh_volt,
375 .rfact = RFACT_NONE / 2
376 },
377 {
378 .desc = "+12V",
379 .type = ENVSYS_SVOLTS_DC,
380 .bank = 0,
381 .reg = 0x21,
382 .refresh = lm_refresh_volt,
383 .rfact = RFACT(56, 10) / 2
384 },
385 {
386 .desc = "+3.3V",
387 .type = ENVSYS_SVOLTS_DC,
388 .bank = 0,
389 .reg = 0x22,
390 .refresh = lm_refresh_volt,
391 .rfact = RFACT(34, 34) / 2
392 },
393 {
394 .desc = "+3.3V",
395 .type = ENVSYS_SVOLTS_DC,
396 .bank = 0,
397 .reg = 0x23,
398 .refresh = lm_refresh_volt,
399 .rfact = RFACT(34, 24) / 2
400 },
401 {
402 .desc = "-12V",
403 .type = ENVSYS_SVOLTS_DC,
404 .bank = 0,
405 .reg = 0x24,
406 .refresh = wb_w83627ehf_refresh_nvolt,
407 .rfact = 0
408 },
409 {
410 .desc = "Unknown",
411 .type = ENVSYS_SVOLTS_DC,
412 .bank = 0,
413 .reg = 0x25,
414 .refresh = lm_refresh_volt,
415 .rfact = RFACT_NONE / 2
416 },
417 {
418 .desc = "Unknown",
419 .type = ENVSYS_SVOLTS_DC,
420 .bank = 0,
421 .reg = 0x26,
422 .refresh = lm_refresh_volt,
423 .rfact = RFACT_NONE / 2
424 },
425 {
426 .desc = "3.3VSB",
427 .type = ENVSYS_SVOLTS_DC,
428 .bank = 5,
429 .reg = 0x50,
430 .refresh = lm_refresh_volt,
431 .rfact = RFACT(34, 34) / 2
432 },
433 {
434 .desc = "VBAT",
435 .type = ENVSYS_SVOLTS_DC,
436 .bank = 5,
437 .reg = 0x51,
438 .refresh = lm_refresh_volt,
439 .rfact = RFACT_NONE / 2
440 },
441 {
442 .desc = "Unknown",
443 .type = ENVSYS_SVOLTS_DC,
444 .bank = 5,
445 .reg = 0x52,
446 .refresh = lm_refresh_volt,
447 .rfact = RFACT_NONE / 2
448 },
449
450 /* Temperature */
451 {
452 .desc = "Temp0",
453 .type = ENVSYS_STEMP,
454 .bank = 0,
455 .reg = 0x27,
456 .refresh = lm_refresh_temp,
457 .rfact = 0
458 },
459 {
460 .desc = "Temp1",
461 .type = ENVSYS_STEMP,
462 .bank = 1,
463 .reg = 0x50,
464 .refresh = wb_refresh_temp,
465 .rfact = 0
466 },
467 {
468 .desc = "Temp2",
469 .type = ENVSYS_STEMP,
470 .bank = 2,
471 .reg = 0x50,
472 .refresh = wb_refresh_temp,
473 .rfact = 0
474 },
475
476 /* Fans */
477 {
478 .desc = "Fan0",
479 .type = ENVSYS_SFANRPM,
480 .bank = 0,
481 .reg = 0x28,
482 .refresh = wb_refresh_fanrpm,
483 .rfact = 0
484 },
485 {
486 .desc = "Fan1",
487 .type = ENVSYS_SFANRPM,
488 .bank = 0,
489 .reg = 0x29,
490 .refresh = wb_refresh_fanrpm,
491 .rfact = 0
492 },
493 {
494 .desc = "Fan2",
495 .type = ENVSYS_SFANRPM,
496 .bank = 0,
497 .reg = 0x2a,
498 .refresh = wb_refresh_fanrpm,
499 .rfact = 0
500 },
501
502 { .desc = NULL }
503 };
504
505 /* W83627DHG */
506 static struct lm_sensor w83627dhg_sensors[] = {
507 /* Voltage */
508 {
509 .desc = "VCore",
510 .type = ENVSYS_SVOLTS_DC,
511 .bank = 0,
512 .reg = 0x20,
513 .refresh = lm_refresh_volt,
514 .rfact = RFACT_NONE / 2
515 },
516 {
517 .desc = "+12V",
518 .type = ENVSYS_SVOLTS_DC,
519 .bank = 0,
520 .reg = 0x21,
521 .refresh = lm_refresh_volt,
522 .rfact = RFACT(56, 10) / 2
523 },
524 {
525 .desc = "+3.3V",
526 .type = ENVSYS_SVOLTS_DC,
527 .bank = 0,
528 .reg = 0x22,
529 .refresh = lm_refresh_volt,
530 .rfact = RFACT_NONE
531 },
532 {
533 .desc = "AVCC",
534 .type = ENVSYS_SVOLTS_DC,
535 .bank = 0,
536 .reg = 0x23,
537 .refresh = lm_refresh_volt,
538 .rfact = RFACT_NONE
539 },
540 {
541 .desc = "+5V",
542 .type = ENVSYS_SVOLTS_DC,
543 .bank = 0,
544 .reg = 0x25,
545 .refresh = lm_refresh_volt,
546 .rfact = RFACT(32, 56)
547 },
548 /*
549 * I'm not sure about which one is -12V or -5V.
550 */
551 #if 0
552 {
553 .desc = "-12V",
554 .type = ENVSYS_SVOLTS_DC,
555 .bank = 0,
556 .reg = 0x24,
557 .refresh = wb_refresh_nvolt,
558 .rfact = RFACT(232, 60)
559 },
560 {
561 .desc = "-5V",
562 .type = ENVSYS_SVOLTS_DC,
563 .bank = 0,
564 .reg = 0x26,
565 .refresh = wb_w83627ehf_refresh_nvolt
566 .rfact = 0
567 },
568 #endif
569 {
570 .desc = "+3.3VSB",
571 .type = ENVSYS_SVOLTS_DC,
572 .bank = 5,
573 .reg = 0x50,
574 .refresh = lm_refresh_volt,
575 .rfact = RFACT_NONE
576 },
577 {
578 .desc = "VBAT",
579 .type = ENVSYS_SVOLTS_DC,
580 .bank = 5,
581 .reg = 0x51,
582 .refresh = lm_refresh_volt,
583 .rfact = RFACT_NONE
584 },
585
586 /* Temperature */
587 {
588 .desc = "System Temp",
589 .type = ENVSYS_STEMP,
590 .bank = 0,
591 .reg = 0x27,
592 .refresh = lm_refresh_temp,
593 .rfact = 0
594 },
595 {
596 .desc = "CPU Temp",
597 .type = ENVSYS_STEMP,
598 .bank = 1,
599 .reg = 0x50,
600 .refresh = wb_refresh_temp,
601 .rfact = 0
602 },
603 {
604 .desc = "Aux Temp",
605 .type = ENVSYS_STEMP,
606 .bank = 2,
607 .reg = 0x50,
608 .refresh = wb_refresh_temp,
609 .rfact = 0
610 },
611
612 /* Fans */
613 {
614 .desc = "System Fan",
615 .type = ENVSYS_SFANRPM,
616 .bank = 0,
617 .reg = 0x28,
618 .refresh = wb_refresh_fanrpm,
619 .rfact = 0
620 },
621 {
622 .desc = "CPU Fan",
623 .type = ENVSYS_SFANRPM,
624 .bank = 0,
625 .reg = 0x29,
626 .refresh = wb_refresh_fanrpm,
627 .rfact = 0
628 },
629 {
630 .desc = "Aux Fan",
631 .type = ENVSYS_SFANRPM,
632 .bank = 0,
633 .reg = 0x2a,
634 .refresh = wb_refresh_fanrpm,
635 .rfact = 0
636 },
637
638 { .desc = NULL }
639 };
640
641 /* W83637HF */
642 static struct lm_sensor w83637hf_sensors[] = {
643 /* Voltage */
644 {
645 .desc = "VCore",
646 .type = ENVSYS_SVOLTS_DC,
647 .bank = 0,
648 .reg = 0x20,
649 .refresh = wb_w83637hf_refresh_vcore,
650 .rfact = 0
651 },
652 {
653 .desc = "+12V",
654 .type = ENVSYS_SVOLTS_DC,
655 .bank = 0,
656 .reg = 0x21,
657 .refresh = lm_refresh_volt,
658 .rfact = RFACT(28, 10)
659 },
660 {
661 .desc = "+3.3V",
662 .type = ENVSYS_SVOLTS_DC,
663 .bank = 0,
664 .reg = 0x22,
665 .refresh = lm_refresh_volt,
666 .rfact = RFACT_NONE
667 },
668 {
669 .desc = "+5V",
670 .type = ENVSYS_SVOLTS_DC,
671 .bank = 0,
672 .reg = 0x23,
673 .refresh = lm_refresh_volt,
674 .rfact = RFACT(34, 51)
675 },
676 {
677 .desc = "-12V",
678 .type = ENVSYS_SVOLTS_DC,
679 .bank = 0,
680 .reg = 0x24,
681 .refresh = wb_refresh_nvolt,
682 .rfact = RFACT(232, 56)
683 },
684 {
685 .desc = "5VSB",
686 .type = ENVSYS_SVOLTS_DC,
687 .bank = 5,
688 .reg = 0x50,
689 .refresh = lm_refresh_volt,
690 .rfact = RFACT(34, 51)
691 },
692 {
693 .desc = "VBAT",
694 .type = ENVSYS_SVOLTS_DC,
695 .bank = 5,
696 .reg = 0x51,
697 .refresh = lm_refresh_volt,
698 .rfact = RFACT_NONE
699 },
700
701 /* Temperature */
702 {
703 .desc = "Temp0",
704 .type = ENVSYS_STEMP,
705 .bank = 0,
706 .reg = 0x27,
707 .refresh = lm_refresh_temp,
708 .rfact = 0
709 },
710 {
711 .desc = "Temp1",
712 .type = ENVSYS_STEMP,
713 .bank = 1,
714 .reg = 0x50,
715 .refresh = wb_refresh_temp,
716 .rfact = 0
717 },
718 {
719 .desc = "Temp2",
720 .type = ENVSYS_STEMP,
721 .bank = 2,
722 .reg = 0x50,
723 .refresh = wb_refresh_temp,
724 .rfact = 0
725 },
726
727 /* Fans */
728 {
729 .desc = "Fan0",
730 .type = ENVSYS_SFANRPM,
731 .bank = 0,
732 .reg = 0x28,
733 .refresh = wb_refresh_fanrpm,
734 .rfact = 0
735 },
736 {
737 .desc = "Fan1",
738 .type = ENVSYS_SFANRPM,
739 .bank = 0,
740 .reg = 0x29,
741 .refresh = wb_refresh_fanrpm,
742 .rfact = 0
743 },
744 {
745 .desc = "Fan2",
746 .type = ENVSYS_SFANRPM,
747 .bank = 0,
748 .reg = 0x2a,
749 .refresh = wb_refresh_fanrpm,
750 .rfact = 0
751 },
752
753 { .desc = NULL }
754 };
755
756 /* W83697HF */
757 static struct lm_sensor w83697hf_sensors[] = {
758 /* Voltage */
759 {
760 .desc = "VCore",
761 .type = ENVSYS_SVOLTS_DC,
762 .bank = 0,
763 .reg = 0x20,
764 .refresh = lm_refresh_volt,
765 .rfact = RFACT_NONE
766 },
767 {
768 .desc = "+3.3V",
769 .type = ENVSYS_SVOLTS_DC,
770 .bank = 0,
771 .reg = 0x22,
772 .refresh = lm_refresh_volt,
773 .rfact = RFACT_NONE
774 },
775 {
776 .desc = "+5V",
777 .type = ENVSYS_SVOLTS_DC,
778 .bank = 0,
779 .reg = 0x23,
780 .refresh = lm_refresh_volt,
781 .rfact = RFACT(34, 50)
782 },
783 {
784 .desc = "+12V",
785 .type = ENVSYS_SVOLTS_DC,
786 .bank = 0,
787 .reg = 0x24,
788 .refresh = lm_refresh_volt,
789 .rfact = RFACT(28, 10)
790 },
791 {
792 .desc = "-12V",
793 .type = ENVSYS_SVOLTS_DC,
794 .bank = 0,
795 .reg = 0x25,
796 .refresh = wb_refresh_nvolt,
797 .rfact = RFACT(232, 56)
798 },
799 {
800 .desc = "-5V",
801 .type = ENVSYS_SVOLTS_DC,
802 .bank = 0,
803 .reg = 0x26,
804 .refresh = wb_refresh_nvolt,
805 .rfact = RFACT(120, 56)
806 },
807 {
808 .desc = "5VSB",
809 .type = ENVSYS_SVOLTS_DC,
810 .bank = 5,
811 .reg = 0x50,
812 .refresh = lm_refresh_volt,
813 .rfact = RFACT(17, 33)
814 },
815 {
816 .desc = "VBAT",
817 .type = ENVSYS_SVOLTS_DC,
818 .bank = 5,
819 .reg = 0x51,
820 .refresh = lm_refresh_volt,
821 .rfact = RFACT_NONE
822 },
823
824 /* Temperature */
825 {
826 .desc = "Temp0",
827 .type = ENVSYS_STEMP,
828 .bank = 0,
829 .reg = 0x27,
830 .refresh = lm_refresh_temp,
831 .rfact = 0
832 },
833 {
834 .desc = "Temp1",
835 .type = ENVSYS_STEMP,
836 .bank = 1,
837 .reg = 0x50,
838 .refresh = wb_refresh_temp,
839 .rfact = 0
840 },
841
842 /* Fans */
843 {
844 .desc = "Fan0",
845 .type = ENVSYS_SFANRPM,
846 .bank = 0,
847 .reg = 0x28,
848 .refresh = wb_refresh_fanrpm,
849 .rfact = 0
850 },
851 {
852 .desc = "Fan1",
853 .type = ENVSYS_SFANRPM,
854 .bank = 0,
855 .reg = 0x29,
856 .refresh = wb_refresh_fanrpm,
857 .rfact = 0
858 },
859
860 { .desc = NULL }
861 };
862
863 /* W83781D */
864
865 /*
866 * The datasheet doesn't mention the (internal) resistors used for the
867 * +5V, but using the values from the W83782D datasheets seems to
868 * provide sensible results.
869 */
870 static struct lm_sensor w83781d_sensors[] = {
871 /* Voltage */
872 {
873 .desc = "VCore A",
874 .type = ENVSYS_SVOLTS_DC,
875 .bank = 0,
876 .reg = 0x20,
877 .refresh = lm_refresh_volt,
878 .rfact = RFACT_NONE
879 },
880 {
881 .desc = "VCore B",
882 .type = ENVSYS_SVOLTS_DC,
883 .bank = 0,
884 .reg = 0x21,
885 .refresh = lm_refresh_volt,
886 .rfact = RFACT_NONE
887 },
888 {
889 .desc = "+3.3V",
890 .type = ENVSYS_SVOLTS_DC,
891 .bank = 0,
892 .reg = 0x22,
893 .refresh = lm_refresh_volt,
894 .rfact = RFACT_NONE
895 },
896 {
897 .desc = "+5V",
898 .type = ENVSYS_SVOLTS_DC,
899 .bank = 0,
900 .reg = 0x23,
901 .refresh = lm_refresh_volt,
902 .rfact = RFACT(34, 50)
903 },
904 {
905 .desc = "+12V",
906 .type = ENVSYS_SVOLTS_DC,
907 .bank = 0,
908 .reg = 0x24,
909 .refresh = lm_refresh_volt,
910 .rfact = RFACT(28, 10)
911 },
912 {
913 .desc = "-12V",
914 .type = ENVSYS_SVOLTS_DC,
915 .bank = 0,
916 .reg = 0x25,
917 .refresh = lm_refresh_volt,
918 .rfact = NRFACT(2100, 604)
919 },
920 {
921 .desc = "-5V",
922 .type = ENVSYS_SVOLTS_DC,
923 .bank = 0,
924 .reg = 0x26,
925 .refresh = lm_refresh_volt,
926 .rfact = NRFACT(909, 604)
927 },
928
929 /* Temperature */
930 {
931 .desc = "Temp0",
932 .type = ENVSYS_STEMP,
933 .bank = 0,
934 .reg = 0x27,
935 .refresh = lm_refresh_temp,
936 .rfact = 0
937 },
938 {
939 .desc = "Temp1",
940 .type = ENVSYS_STEMP,
941 .bank = 1,
942 .reg = 0x50,
943 .refresh = wb_refresh_temp,
944 .rfact = 0
945 },
946 {
947 .desc = "Temp2",
948 .type = ENVSYS_STEMP,
949 .bank = 2,
950 .reg = 0x50,
951 .refresh = wb_refresh_temp,
952 .rfact = 0
953 },
954
955 /* Fans */
956 {
957 .desc = "Fan0",
958 .type = ENVSYS_SFANRPM,
959 .bank = 0,
960 .reg = 0x28,
961 .refresh = lm_refresh_fanrpm,
962 .rfact = 0
963 },
964 {
965 .desc = "Fan1",
966 .type = ENVSYS_SFANRPM,
967 .bank = 0,
968 .reg = 0x29,
969 .refresh = lm_refresh_fanrpm,
970 .rfact = 0
971 },
972 {
973 .desc = "Fan2",
974 .type = ENVSYS_SFANRPM,
975 .bank = 0,
976 .reg = 0x2a,
977 .refresh = lm_refresh_fanrpm,
978 .rfact = 0
979 },
980
981 { .desc = NULL }
982 };
983
984 /* W83782D */
985 static struct lm_sensor w83782d_sensors[] = {
986 /* Voltage */
987 {
988 .desc = "VCore",
989 .type = ENVSYS_SVOLTS_DC,
990 .bank = 0,
991 .reg = 0x20,
992 .refresh = lm_refresh_volt,
993 .rfact = RFACT_NONE
994 },
995 {
996 .desc = "VINR0",
997 .type = ENVSYS_SVOLTS_DC,
998 .bank = 0,
999 .reg = 0x21,
1000 .refresh = lm_refresh_volt,
1001 .rfact = RFACT_NONE
1002 },
1003 {
1004 .desc = "+3.3V",
1005 .type = ENVSYS_SVOLTS_DC,
1006 .bank = 0,
1007 .reg = 0x22,
1008 .refresh = lm_refresh_volt,
1009 .rfact = RFACT_NONE
1010 },
1011 {
1012 .desc = "+5V",
1013 .type = ENVSYS_SVOLTS_DC,
1014 .bank = 0,
1015 .reg = 0x23,
1016 .refresh = lm_refresh_volt,
1017 .rfact = RFACT(34, 50)
1018 },
1019 {
1020 .desc = "+12V",
1021 .type = ENVSYS_SVOLTS_DC,
1022 .bank = 0,
1023 .reg = 0x24,
1024 .refresh = lm_refresh_volt,
1025 .rfact = RFACT(28, 10)
1026 },
1027 {
1028 .desc = "-12V",
1029 .type = ENVSYS_SVOLTS_DC,
1030 .bank = 0,
1031 .reg = 0x25,
1032 .refresh = wb_refresh_nvolt,
1033 .rfact = RFACT(232, 56)
1034 },
1035 {
1036 .desc = "-5V",
1037 .type = ENVSYS_SVOLTS_DC,
1038 .bank = 0,
1039 .reg = 0x26,
1040 .refresh = wb_refresh_nvolt,
1041 .rfact = RFACT(120, 56)
1042 },
1043 {
1044 .desc = "5VSB",
1045 .type = ENVSYS_SVOLTS_DC,
1046 .bank = 5,
1047 .reg = 0x50,
1048 .refresh = lm_refresh_volt,
1049 .rfact = RFACT(17, 33)
1050 },
1051 {
1052 .desc = "VBAT",
1053 .type = ENVSYS_SVOLTS_DC,
1054 .bank = 5,
1055 .reg = 0x51,
1056 .refresh = lm_refresh_volt,
1057 .rfact = RFACT_NONE
1058 },
1059
1060 /* Temperature */
1061 {
1062 .desc = "Temp0",
1063 .type = ENVSYS_STEMP,
1064 .bank = 0,
1065 .reg = 0x27,
1066 .refresh = lm_refresh_temp,
1067 .rfact = 0
1068 },
1069 {
1070 .desc = "Temp1",
1071 .type = ENVSYS_STEMP,
1072 .bank = 1,
1073 .reg = 0x50,
1074 .refresh = wb_refresh_temp,
1075 .rfact = 0
1076 },
1077 {
1078 .desc = "Temp2",
1079 .type = ENVSYS_STEMP,
1080 .bank = 2,
1081 .reg = 0x50,
1082 .refresh = wb_refresh_temp,
1083 .rfact = 0
1084 },
1085
1086 /* Fans */
1087 {
1088 .desc = "Fan0",
1089 .type = ENVSYS_SFANRPM,
1090 .bank = 0,
1091 .reg = 0x28,
1092 .refresh = wb_refresh_fanrpm,
1093 .rfact = 0
1094 },
1095 {
1096 .desc = "Fan1",
1097 .type = ENVSYS_SFANRPM,
1098 .bank = 0,
1099 .reg = 0x29,
1100 .refresh = wb_refresh_fanrpm,
1101 .rfact = 0
1102 },
1103 {
1104 .desc = "Fan2",
1105 .type = ENVSYS_SFANRPM,
1106 .bank = 0,
1107 .reg = 0x2a,
1108 .refresh = wb_refresh_fanrpm,
1109 .rfact = 0
1110 },
1111
1112 { .desc = NULL }
1113 };
1114
1115 /* W83783S */
1116 static struct lm_sensor w83783s_sensors[] = {
1117 /* Voltage */
1118 {
1119 .desc = "VCore",
1120 .type = ENVSYS_SVOLTS_DC,
1121 .bank = 0,
1122 .reg = 0x20,
1123 .refresh = lm_refresh_volt,
1124 .rfact = RFACT_NONE
1125 },
1126 {
1127 .desc = "+3.3V",
1128 .type = ENVSYS_SVOLTS_DC,
1129 .bank = 0,
1130 .reg = 0x22,
1131 .refresh = lm_refresh_volt,
1132 .rfact = RFACT_NONE
1133 },
1134 {
1135 .desc = "+5V",
1136 .type = ENVSYS_SVOLTS_DC,
1137 .bank = 0,
1138 .reg = 0x23,
1139 .refresh = lm_refresh_volt,
1140 .rfact = RFACT(34, 50)
1141 },
1142 {
1143 .desc = "+12V",
1144 .type = ENVSYS_SVOLTS_DC,
1145 .bank = 0,
1146 .reg = 0x24,
1147 .refresh = lm_refresh_volt,
1148 .rfact = RFACT(28, 10)
1149 },
1150 {
1151 .desc = "-12V",
1152 .type = ENVSYS_SVOLTS_DC,
1153 .bank = 0,
1154 .reg = 0x25,
1155 .refresh = wb_refresh_nvolt,
1156 .rfact = RFACT(232, 56)
1157 },
1158 {
1159 .desc = "-5V",
1160 .type = ENVSYS_SVOLTS_DC,
1161 .bank = 0,
1162 .reg = 0x26,
1163 .refresh = wb_refresh_nvolt,
1164 .rfact = RFACT(120, 56)
1165 },
1166
1167 /* Temperature */
1168 {
1169 .desc = "Temp0",
1170 .type = ENVSYS_STEMP,
1171 .bank = 0,
1172 .reg = 0x27,
1173 .refresh = lm_refresh_temp,
1174 .rfact = 0
1175 },
1176 {
1177 .desc = "Temp1",
1178 .type = ENVSYS_STEMP,
1179 .bank = 1,
1180 .reg = 0x50,
1181 .refresh = wb_refresh_temp,
1182 .rfact = 0
1183 },
1184
1185 /* Fans */
1186 {
1187 .desc = "Fan0",
1188 .type = ENVSYS_SFANRPM,
1189 .bank = 0,
1190 .reg = 0x28,
1191 .refresh = wb_refresh_fanrpm,
1192 .rfact = 0
1193 },
1194 {
1195 .desc = "Fan1",
1196 .type = ENVSYS_SFANRPM,
1197 .bank = 0,
1198 .reg = 0x29,
1199 .refresh = wb_refresh_fanrpm,
1200 .rfact = 0
1201 },
1202 {
1203 .desc = "Fan2",
1204 .type = ENVSYS_SFANRPM,
1205 .bank = 0,
1206 .reg = 0x2a,
1207 .refresh = wb_refresh_fanrpm,
1208 .rfact = 0
1209 },
1210
1211 { .desc = NULL }
1212 };
1213
1214 /* W83791D */
1215 static struct lm_sensor w83791d_sensors[] = {
1216 /* Voltage */
1217 {
1218 .desc = "VCore",
1219 .type = ENVSYS_SVOLTS_DC,
1220 .bank = 0,
1221 .reg = 0x20,
1222 .refresh = lm_refresh_volt,
1223 .rfact = 10000
1224 },
1225 {
1226 .desc = "VINR0",
1227 .type = ENVSYS_SVOLTS_DC,
1228 .bank = 0,
1229 .reg = 0x21,
1230 .refresh = lm_refresh_volt,
1231 .rfact = 10000
1232 },
1233 {
1234 .desc = "+3.3V",
1235 .type = ENVSYS_SVOLTS_DC,
1236 .bank = 0,
1237 .reg = 0x22,
1238 .refresh = lm_refresh_volt,
1239 .rfact = 10000
1240 },
1241 {
1242 .desc = "+5V",
1243 .type = ENVSYS_SVOLTS_DC,
1244 .bank = 0,
1245 .reg = 0x23,
1246 .refresh = lm_refresh_volt,
1247 .rfact = RFACT(34, 50)
1248 },
1249 {
1250 .desc = "+12V",
1251 .type = ENVSYS_SVOLTS_DC,
1252 .bank = 0,
1253 .reg = 0x24,
1254 .refresh = lm_refresh_volt,
1255 .rfact = RFACT(28, 10)
1256 },
1257 {
1258 .desc = "-12V",
1259 .type = ENVSYS_SVOLTS_DC,
1260 .bank = 0,
1261 .reg = 0x25,
1262 .refresh = wb_refresh_nvolt,
1263 .rfact = RFACT(232, 56)
1264 },
1265 {
1266 .desc = "-5V",
1267 .type = ENVSYS_SVOLTS_DC,
1268 .bank = 0,
1269 .reg = 0x26,
1270 .refresh = wb_refresh_nvolt,
1271 .rfact = RFACT(120, 56)
1272 },
1273 {
1274 .desc = "5VSB",
1275 .type = ENVSYS_SVOLTS_DC,
1276 .bank = 0,
1277 .reg = 0xb0,
1278 .refresh = lm_refresh_volt,
1279 .rfact = RFACT(17, 33)
1280 },
1281 {
1282 .desc = "VBAT",
1283 .type = ENVSYS_SVOLTS_DC,
1284 .bank = 0,
1285 .reg = 0xb1,
1286 .refresh = lm_refresh_volt,
1287 .rfact = RFACT_NONE
1288 },
1289 {
1290 .desc = "VINR1",
1291 .type = ENVSYS_SVOLTS_DC,
1292 .bank = 0,
1293 .reg = 0xb2,
1294 .refresh = lm_refresh_volt,
1295 .rfact = RFACT_NONE
1296 },
1297
1298 /* Temperature */
1299 {
1300 .desc = "Temp0",
1301 .type = ENVSYS_STEMP,
1302 .bank = 0,
1303 .reg = 0x27,
1304 .refresh = lm_refresh_temp,
1305 .rfact = 0
1306 },
1307 {
1308 .desc = "Temp1",
1309 .type = ENVSYS_STEMP,
1310 .bank = 0,
1311 .reg = 0xc0,
1312 .refresh = wb_refresh_temp,
1313 .rfact = 0
1314 },
1315 {
1316 .desc = "Temp2",
1317 .type = ENVSYS_STEMP,
1318 .bank = 0,
1319 .reg = 0xc8,
1320 .refresh = wb_refresh_temp,
1321 .rfact = 0
1322 },
1323
1324 /* Fans */
1325 {
1326 .desc = "Fan0",
1327 .type = ENVSYS_SFANRPM,
1328 .bank = 0,
1329 .reg = 0x28,
1330 .refresh = wb_refresh_fanrpm,
1331 .rfact = 0
1332 },
1333 {
1334 .desc = "Fan1",
1335 .type = ENVSYS_SFANRPM,
1336 .bank = 0,
1337 .reg = 0x29,
1338 .refresh = wb_refresh_fanrpm,
1339 .rfact = 0
1340 },
1341 {
1342 .desc = "Fan2",
1343 .type = ENVSYS_SFANRPM,
1344 .bank = 0,
1345 .reg = 0x2a,
1346 .refresh = wb_refresh_fanrpm,
1347 .rfact = 0
1348 },
1349 {
1350 .desc = "Fan3",
1351 .type = ENVSYS_SFANRPM,
1352 .bank = 0,
1353 .reg = 0xba,
1354 .refresh = wb_refresh_fanrpm,
1355 .rfact = 0
1356 },
1357 {
1358 .desc = "Fan4",
1359 .type = ENVSYS_SFANRPM,
1360 .bank = 0,
1361 .reg = 0xbb,
1362 .refresh = wb_refresh_fanrpm,
1363 .rfact = 0
1364 },
1365
1366 { .desc = NULL }
1367 };
1368
1369 /* W83792D */
1370 static struct lm_sensor w83792d_sensors[] = {
1371 /* Voltage */
1372 {
1373 .desc = "VCore A",
1374 .type = ENVSYS_SVOLTS_DC,
1375 .bank = 0,
1376 .reg = 0x20,
1377 .refresh = lm_refresh_volt,
1378 .rfact = RFACT_NONE
1379 },
1380 {
1381 .desc = "VCore B",
1382 .type = ENVSYS_SVOLTS_DC,
1383 .bank = 0,
1384 .reg = 0x21,
1385 .refresh = lm_refresh_volt,
1386 .rfact = RFACT_NONE
1387 },
1388 {
1389 .desc = "+3.3V",
1390 .type = ENVSYS_SVOLTS_DC,
1391 .bank = 0,
1392 .reg = 0x22,
1393 .refresh = lm_refresh_volt,
1394 .rfact = RFACT_NONE
1395 },
1396 {
1397 .desc = "-5V",
1398 .type = ENVSYS_SVOLTS_DC,
1399 .bank = 0,
1400 .reg = 0x23,
1401 .refresh = wb_refresh_nvolt,
1402 .rfact = RFACT(120, 56)
1403 },
1404 {
1405 .desc = "+12V",
1406 .type = ENVSYS_SVOLTS_DC,
1407 .bank = 0,
1408 .reg = 0x24,
1409 .refresh = lm_refresh_volt,
1410 .rfact = RFACT(28, 10)
1411 },
1412 {
1413 .desc = "-12V",
1414 .type = ENVSYS_SVOLTS_DC,
1415 .bank = 0,
1416 .reg = 0x25,
1417 .refresh = wb_refresh_nvolt,
1418 .rfact = RFACT(232, 56)
1419 },
1420 {
1421 .desc = "+5V",
1422 .type = ENVSYS_SVOLTS_DC,
1423 .bank = 0,
1424 .reg = 0x26,
1425 .refresh = lm_refresh_volt,
1426 .rfact = RFACT(34, 50)
1427 },
1428 {
1429 .desc = "5VSB",
1430 .type = ENVSYS_SVOLTS_DC,
1431 .bank = 0,
1432 .reg = 0xb0,
1433 .refresh = lm_refresh_volt,
1434 .rfact = RFACT(17, 33)
1435 },
1436 {
1437 .desc = "VBAT",
1438 .type = ENVSYS_SVOLTS_DC,
1439 .bank = 0,
1440 .reg = 0xb1,
1441 .refresh = lm_refresh_volt,
1442 .rfact = RFACT_NONE
1443 },
1444
1445 /* Temperature */
1446 {
1447 .desc = "Temp0",
1448 .type = ENVSYS_STEMP,
1449 .bank = 0,
1450 .reg = 0x27,
1451 .refresh = lm_refresh_temp,
1452 .rfact = 0
1453 },
1454 {
1455 .desc = "Temp1",
1456 .type = ENVSYS_STEMP,
1457 .bank = 0,
1458 .reg = 0xc0,
1459 .refresh = wb_refresh_temp,
1460 .rfact = 0
1461 },
1462 {
1463 .desc = "Temp2",
1464 .type = ENVSYS_STEMP,
1465 .bank = 0,
1466 .reg = 0xc8,
1467 .refresh = wb_refresh_temp,
1468 .rfact = 0
1469 },
1470
1471 /* Fans */
1472 {
1473 .desc = "Fan0",
1474 .type = ENVSYS_SFANRPM,
1475 .bank = 0,
1476 .reg = 0x28,
1477 .refresh = wb_w83792d_refresh_fanrpm,
1478 .rfact = 0
1479 },
1480 {
1481 .desc = "Fan1",
1482 .type = ENVSYS_SFANRPM,
1483 .bank = 0,
1484 .reg = 0x29,
1485 .refresh = wb_w83792d_refresh_fanrpm,
1486 .rfact = 0
1487 },
1488 {
1489 .desc = "Fan2",
1490 .type = ENVSYS_SFANRPM,
1491 .bank = 0,
1492 .reg = 0x2a,
1493 .refresh = wb_w83792d_refresh_fanrpm,
1494 .rfact = 0
1495 },
1496 {
1497 .desc = "Fan3",
1498 .type = ENVSYS_SFANRPM,
1499 .bank = 0,
1500 .reg = 0xb8,
1501 .refresh = wb_w83792d_refresh_fanrpm,
1502 .rfact = 0
1503 },
1504 {
1505 .desc = "Fan4",
1506 .type = ENVSYS_SFANRPM,
1507 .bank = 0,
1508 .reg = 0xb9,
1509 .refresh = wb_w83792d_refresh_fanrpm,
1510 .rfact = 0
1511 },
1512 {
1513 .desc = "Fan5",
1514 .type = ENVSYS_SFANRPM,
1515 .bank = 0,
1516 .reg = 0xba,
1517 .refresh = wb_w83792d_refresh_fanrpm,
1518 .rfact = 0
1519 },
1520 {
1521 .desc = "Fan6",
1522 .type = ENVSYS_SFANRPM,
1523 .bank = 0,
1524 .reg = 0xbe,
1525 .refresh = wb_w83792d_refresh_fanrpm,
1526 .rfact = 0
1527 },
1528
1529 { .desc = NULL }
1530 };
1531
1532 /* AS99127F */
1533 static struct lm_sensor as99127f_sensors[] = {
1534 /* Voltage */
1535 {
1536 .desc = "VCore A",
1537 .type = ENVSYS_SVOLTS_DC,
1538 .bank = 0,
1539 .reg = 0x20,
1540 .refresh = lm_refresh_volt,
1541 .rfact = RFACT_NONE
1542 },
1543 {
1544 .desc = "VCore B",
1545 .type = ENVSYS_SVOLTS_DC,
1546 .bank = 0,
1547 .reg = 0x21,
1548 .refresh = lm_refresh_volt,
1549 .rfact = RFACT_NONE
1550 },
1551 {
1552 .desc = "+3.3V",
1553 .type = ENVSYS_SVOLTS_DC,
1554 .bank = 0,
1555 .reg = 0x22,
1556 .refresh = lm_refresh_volt,
1557 .rfact = RFACT_NONE
1558 },
1559 {
1560 .desc = "+5V",
1561 .type = ENVSYS_SVOLTS_DC,
1562 .bank = 0,
1563 .reg = 0x23,
1564 .refresh = lm_refresh_volt,
1565 .rfact = RFACT(34, 50)
1566 },
1567 {
1568 .desc = "+12V",
1569 .type = ENVSYS_SVOLTS_DC,
1570 .bank = 0,
1571 .reg = 0x24,
1572 .refresh = lm_refresh_volt,
1573 .rfact = RFACT(28, 10)
1574 },
1575 {
1576 .desc = "-12V",
1577 .type = ENVSYS_SVOLTS_DC,
1578 .bank = 0,
1579 .reg = 0x25,
1580 .refresh = wb_refresh_nvolt,
1581 .rfact = RFACT(232, 56)
1582 },
1583 {
1584 .desc = "-5V",
1585 .type = ENVSYS_SVOLTS_DC,
1586 .bank = 0,
1587 .reg = 0x26,
1588 .refresh = wb_refresh_nvolt,
1589 .rfact = RFACT(120, 56)
1590 },
1591
1592 /* Temperature */
1593 {
1594 .desc = "Temp0",
1595 .type = ENVSYS_STEMP,
1596 .bank = 0,
1597 .reg = 0x27,
1598 .refresh = lm_refresh_temp,
1599 .rfact = 0
1600 },
1601 {
1602 .desc = "Temp1",
1603 .type = ENVSYS_STEMP,
1604 .bank = 1,
1605 .reg = 0x50,
1606 .refresh = as_refresh_temp,
1607 .rfact = 0
1608 },
1609 {
1610 .desc = "Temp2",
1611 .type = ENVSYS_STEMP,
1612 .bank = 2,
1613 .reg = 0x50,
1614 .refresh = as_refresh_temp,
1615 .rfact = 0
1616 },
1617
1618 /* Fans */
1619 {
1620 .desc = "Fan0",
1621 .type = ENVSYS_SFANRPM,
1622 .bank = 0,
1623 .reg = 0x28,
1624 .refresh = lm_refresh_fanrpm,
1625 .rfact = 0
1626 },
1627 {
1628 .desc = "Fan1",
1629 .type = ENVSYS_SFANRPM,
1630 .bank = 0,
1631 .reg = 0x29,
1632 .refresh = lm_refresh_fanrpm,
1633 .rfact = 0
1634 },
1635 {
1636 .desc = "Fan2",
1637 .type = ENVSYS_SFANRPM,
1638 .bank = 0,
1639 .reg = 0x2a,
1640 .refresh = lm_refresh_fanrpm,
1641 .rfact = 0
1642 },
1643
1644 { .desc = NULL }
1645 };
1646
1647 static void
1648 lm_generic_banksel(struct lm_softc *lmsc, int bank)
1649 {
1650 (*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
1651 }
1652
1653 /*
1654 * bus independent probe
1655 */
1656 int
1657 lm_probe(bus_space_tag_t iot, bus_space_handle_t ioh)
1658 {
1659 uint8_t cr;
1660 int rv;
1661
1662 /* Check for some power-on defaults */
1663 bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
1664
1665 /* Perform LM78 reset */
1666 bus_space_write_1(iot, ioh, LMC_DATA, 0x80);
1667
1668 /* XXX - Why do I have to reselect the register? */
1669 bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
1670 cr = bus_space_read_1(iot, ioh, LMC_DATA);
1671
1672 /* XXX - spec says *only* 0x08! */
1673 if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03))
1674 rv = 1;
1675 else
1676 rv = 0;
1677
1678 DPRINTF(("lm: rv = %d, cr = %x\n", rv, cr));
1679
1680 return rv;
1681 }
1682
1683
1684 /*
1685 * pre: lmsc contains valid busspace tag and handle
1686 */
1687 void
1688 lm_attach(struct lm_softc *lmsc)
1689 {
1690 uint32_t i;
1691
1692 for (i = 0; i < __arraycount(lm_chips); i++)
1693 if (lm_chips[i].chip_match(lmsc))
1694 break;
1695
1696 /* Start the monitoring loop */
1697 (*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
1698
1699 /* Indicate we have never read the registers */
1700 timerclear(&lmsc->lastread);
1701
1702 /* Initialize sensors */
1703 for (i = 0; i < lmsc->numsensors; ++i) {
1704 lmsc->sensors[i].sensor = lmsc->info[i].sensor = i;
1705 lmsc->sensors[i].validflags = (ENVSYS_FVALID|ENVSYS_FCURVALID);
1706 lmsc->info[i].validflags = ENVSYS_FVALID;
1707 lmsc->sensors[i].warnflags = ENVSYS_WARN_OK;
1708 }
1709 /*
1710 * Hook into the System Monitor.
1711 */
1712 lmsc->sc_sysmon.sme_ranges = lm_ranges;
1713 lmsc->sc_sysmon.sme_sensor_info = lmsc->info;
1714 lmsc->sc_sysmon.sme_sensor_data = lmsc->sensors;
1715 lmsc->sc_sysmon.sme_cookie = lmsc;
1716
1717 lmsc->sc_sysmon.sme_gtredata = lm_gtredata;
1718 /* sme_streinfo set in chip-specific attach */
1719
1720 lmsc->sc_sysmon.sme_nsensors = lmsc->numsensors;
1721 lmsc->sc_sysmon.sme_envsys_version = 1000;
1722
1723 if (sysmon_envsys_register(&lmsc->sc_sysmon))
1724 aprint_error("%s: unable to register with sysmon\n",
1725 lmsc->sc_dev.dv_xname);
1726 }
1727
1728 static int
1729 lm_match(struct lm_softc *sc)
1730 {
1731 const char *model = NULL;
1732 int chipid;
1733
1734 /* See if we have an LM78/LM78J/LM79 or LM81 */
1735 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1736 switch(chipid) {
1737 case LM_ID_LM78:
1738 model = "LM78";
1739 break;
1740 case LM_ID_LM78J:
1741 model = "LM78J";
1742 break;
1743 case LM_ID_LM79:
1744 model = "LM79";
1745 break;
1746 case LM_ID_LM81:
1747 model = "LM81";
1748 break;
1749 default:
1750 return 0;
1751 }
1752
1753 aprint_normal(": National Semiconductor %s Hardware monitor\n", model);
1754
1755 lm_setup_sensors(sc, lm78_sensors);
1756 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1757 sc->refresh_sensor_data = lm_refresh_sensor_data;
1758 return 1;
1759 }
1760
1761 static int
1762 def_match(struct lm_softc *sc)
1763 {
1764 int chipid;
1765
1766 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1767 aprint_error(": Unknown chip (ID %d)\n", chipid);
1768
1769 lm_setup_sensors(sc, lm78_sensors);
1770 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1771 sc->refresh_sensor_data = lm_refresh_sensor_data;
1772 return 1;
1773 }
1774
1775 static int
1776 wb_match(struct lm_softc *sc)
1777 {
1778 const char *model;
1779 int banksel, vendid, devid;
1780
1781 model = NULL;
1782
1783 /* Read vendor ID */
1784 banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
1785 lm_generic_banksel(sc, WB_BANKSEL_HBAC);
1786
1787 vendid = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
1788 lm_generic_banksel(sc, 0);
1789 vendid |= (*sc->lm_readreg)(sc, WB_VENDID);
1790 DPRINTF(("winbond vend id 0x%x\n", vendid));
1791 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
1792 return 0;
1793
1794 /* Read device/chip ID */
1795 lm_generic_banksel(sc, WB_BANKSEL_B0);
1796 devid = (*sc->lm_readreg)(sc, LMD_CHIPID);
1797 sc->chipid = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
1798 lm_generic_banksel(sc, banksel);
1799 DPRINTF(("winbond chip id 0x%x\n", sc->chipid));
1800
1801 switch(sc->chipid) {
1802 case WB_CHIPID_W83627HF:
1803 model = "W83627HF";
1804 lm_setup_sensors(sc, w83627hf_sensors);
1805 break;
1806 case WB_CHIPID_W83627THF:
1807 model = "W83627THF";
1808 lm_setup_sensors(sc, w83637hf_sensors);
1809 break;
1810 case WB_CHIPID_W83627EHF:
1811 model = "W83627EHF";
1812 lm_setup_sensors(sc, w83627ehf_sensors);
1813 break;
1814 case WB_CHIPID_W83627DHG:
1815 model = "W83627DHG";
1816 lm_setup_sensors(sc, w83627dhg_sensors);
1817 break;
1818 case WB_CHIPID_W83637HF:
1819 model = "W83637HF";
1820 lm_generic_banksel(sc, WB_BANKSEL_B0);
1821 if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
1822 sc->vrm9 = 1;
1823 lm_generic_banksel(sc, banksel);
1824 lm_setup_sensors(sc, w83637hf_sensors);
1825 break;
1826 case WB_CHIPID_W83697HF:
1827 model = "W83697HF";
1828 lm_setup_sensors(sc, w83697hf_sensors);
1829 break;
1830 case WB_CHIPID_W83781D:
1831 case WB_CHIPID_W83781D_2:
1832 model = "W83781D";
1833 lm_setup_sensors(sc, w83781d_sensors);
1834 sc->sc_sysmon.sme_streinfo = wb781_streinfo;
1835 break;
1836 case WB_CHIPID_W83782D:
1837 model = "W83782D";
1838 lm_setup_sensors(sc, w83782d_sensors);
1839 sc->sc_sysmon.sme_streinfo = wb782_streinfo;
1840 break;
1841 case WB_CHIPID_W83783S:
1842 model = "W83783S";
1843 lm_setup_sensors(sc, w83783s_sensors);
1844 break;
1845 case WB_CHIPID_W83791D:
1846 model = "W83791D";
1847 lm_setup_sensors(sc, w83791d_sensors);
1848 break;
1849 case WB_CHIPID_W83791SD:
1850 model = "W83791SD";
1851 break;
1852 case WB_CHIPID_W83792D:
1853 model = "W83792D";
1854 lm_setup_sensors(sc, w83792d_sensors);
1855 break;
1856 case WB_CHIPID_AS99127F:
1857 if (vendid == WB_VENDID_ASUS) {
1858 model = "AS99127F";
1859 lm_setup_sensors(sc, w83781d_sensors);
1860 } else {
1861 model = "AS99127F rev 2";
1862 lm_setup_sensors(sc, as99127f_sensors);
1863 }
1864 break;
1865 default:
1866 aprint_normal(": unknown Winbond chip (ID 0x%x)\n",
1867 sc->chipid);
1868 /* Handle as a standard LM78. */
1869 lm_setup_sensors(sc, lm78_sensors);
1870 sc->refresh_sensor_data = lm_refresh_sensor_data;
1871 return 1;
1872 }
1873
1874 aprint_normal(": Winbond %s Hardware monitor\n", model);
1875
1876 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1877 sc->refresh_sensor_data = wb_refresh_sensor_data;
1878 return 1;
1879 }
1880
1881 static void
1882 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
1883 {
1884 int i;
1885
1886 for (i = 0; sensors[i].desc; i++) {
1887 sc->sensors[i].units = sc->info[i].units = sensors[i].type;
1888 strlcpy(sc->info[i].desc, sensors[i].desc,
1889 sizeof(sc->info[i].desc));
1890 sc->numsensors++;
1891 }
1892 sc->lm_sensors = sensors;
1893 }
1894
1895 static void
1896 lm_refresh_sensor_data(struct lm_softc *sc)
1897 {
1898 int i;
1899
1900 /* Refresh our stored data for every sensor */
1901 for (i = 0; i < sc->numsensors; i++)
1902 sc->lm_sensors[i].refresh(sc, i);
1903 }
1904
1905 static void
1906 lm_refresh_volt(struct lm_softc *sc, int n)
1907 {
1908 int data;
1909
1910 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1911 DPRINTF(("%s: volt[%d] 0x%x\n", __func__, n, data));
1912 sc->sensors[n].cur.data_s = (data << 4);
1913 sc->sensors[n].cur.data_s *= sc->lm_sensors[n].rfact;
1914 sc->sensors[n].cur.data_s /= 10;
1915 sc->info[n].rfact = sc->lm_sensors[n].rfact;
1916 }
1917
1918 #define INVALIDATE_SENSOR(x) \
1919 do { \
1920 sc->sensors[(x)].validflags &= ~ENVSYS_FCURVALID; \
1921 sc->sensors[(x)].cur.data_us = 0; \
1922 } while (/* CONSTCOND */ 0)
1923
1924 static void
1925 lm_refresh_temp(struct lm_softc *sc, int n)
1926 {
1927 int sdata;
1928
1929 /*
1930 * The data sheet suggests that the range of the temperature
1931 * sensor is between -55 degC and +125 degC.
1932 */
1933 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1934 if (sdata > 0x7d && sdata < 0xc9) {
1935 INVALIDATE_SENSOR(n);
1936 } else {
1937 if (sdata & 0x80)
1938 sdata -= 0x100;
1939 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
1940 sc->sensors[n].cur.data_us = sdata * 1000000 + 273150000;
1941 }
1942 }
1943
1944 static void
1945 lm_refresh_fanrpm(struct lm_softc *sc, int n)
1946 {
1947 int data, divisor = 1;
1948
1949 /*
1950 * We might get more accurate fan readings by adjusting the
1951 * divisor, but that might interfere with APM or other SMM
1952 * BIOS code reading the fan speeds.
1953 */
1954
1955 /* FAN3 has a fixed fan divisor. */
1956 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
1957 sc->lm_sensors[n].reg == LMD_FAN2) {
1958 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
1959 if (sc->lm_sensors[n].reg == LMD_FAN1)
1960 divisor = (data >> 4) & 0x03;
1961 else
1962 divisor = (data >> 6) & 0x03;
1963 }
1964
1965 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1966 if (data == 0xff || data == 0x00) {
1967 INVALIDATE_SENSOR(n);
1968 } else {
1969 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
1970 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
1971 }
1972 }
1973
1974 static void
1975 wb_refresh_sensor_data(struct lm_softc *sc)
1976 {
1977 int banksel, bank, i;
1978
1979 /*
1980 * Properly save and restore bank selection register.
1981 */
1982
1983 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
1984 for (i = 0; i < sc->numsensors; i++) {
1985 if (bank != sc->lm_sensors[i].bank) {
1986 bank = sc->lm_sensors[i].bank;
1987 lm_generic_banksel(sc, bank);
1988 }
1989 sc->lm_sensors[i].refresh(sc, i);
1990 }
1991 lm_generic_banksel(sc, banksel);
1992 }
1993
1994 static void
1995 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
1996 {
1997 int data;
1998
1999 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2000
2001 /*
2002 * Depending on the voltage detection method,
2003 * one of the following formulas is used:
2004 * VRM8 method: value = raw * 0.016V
2005 * VRM9 method: value = raw * 0.00488V + 0.70V
2006 */
2007 if (sc->vrm9)
2008 sc->sensors[n].cur.data_s = (data * 4880) + 700000;
2009 else
2010 sc->sensors[n].cur.data_s = (data * 16000);
2011 }
2012
2013 static void
2014 wb_refresh_nvolt(struct lm_softc *sc, int n)
2015 {
2016 int data;
2017
2018 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2019 sc->sensors[n].cur.data_s = ((data << 4) - WB_VREF);
2020 sc->sensors[n].cur.data_s *= sc->lm_sensors[n].rfact;
2021 sc->sensors[n].cur.data_s /= 10;
2022 sc->sensors[n].cur.data_s += WB_VREF * 1000;
2023 }
2024
2025 static void
2026 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
2027 {
2028 int data;
2029
2030 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2031 sc->sensors[n].cur.data_s = ((data << 3) - WB_W83627EHF_VREF);
2032 sc->sensors[n].cur.data_s *= RFACT(232, 10);
2033 sc->sensors[n].cur.data_s /= 10;
2034 sc->sensors[n].cur.data_s += WB_W83627EHF_VREF * 1000;
2035 }
2036
2037 static void
2038 wb_refresh_temp(struct lm_softc *sc, int n)
2039 {
2040 int sdata;
2041
2042 /*
2043 * The data sheet suggests that the range of the temperature
2044 * sensor is between -55 degC and +125 degC. However, values
2045 * around -48 degC seem to be a very common bogus values.
2046 * Since such values are unreasonably low, we use -45 degC for
2047 * the lower limit instead.
2048 */
2049 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2050 sdata += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2051 if (sdata > 0x0fa && sdata < 0x1a6) {
2052 INVALIDATE_SENSOR(n);
2053 } else {
2054 if (sdata & 0x100)
2055 sdata -= 0x200;
2056 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2057 sc->sensors[n].cur.data_us = sdata * 500000 + 273150000;
2058 }
2059 }
2060
2061 static void
2062 wb_refresh_fanrpm(struct lm_softc *sc, int n)
2063 {
2064 int fan, data, divisor = 0;
2065
2066 /*
2067 * This is madness; the fan divisor bits are scattered all
2068 * over the place.
2069 */
2070
2071 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2072 sc->lm_sensors[n].reg == LMD_FAN2 ||
2073 sc->lm_sensors[n].reg == LMD_FAN3) {
2074 data = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
2075 fan = (sc->lm_sensors[n].reg - LMD_FAN1);
2076 if ((data >> 5) & (1 << fan))
2077 divisor |= 0x04;
2078 }
2079
2080 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2081 sc->lm_sensors[n].reg == LMD_FAN2) {
2082 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2083 if (sc->lm_sensors[n].reg == LMD_FAN1)
2084 divisor |= (data >> 4) & 0x03;
2085 else
2086 divisor |= (data >> 6) & 0x03;
2087 } else if (sc->lm_sensors[n].reg == LMD_FAN3) {
2088 data = (*sc->lm_readreg)(sc, WB_PIN);
2089 divisor |= (data >> 6) & 0x03;
2090 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
2091 sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
2092 data = (*sc->lm_readreg)(sc, WB_BANK0_FAN45);
2093 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
2094 divisor |= (data >> 0) & 0x07;
2095 else
2096 divisor |= (data >> 4) & 0x07;
2097 }
2098
2099 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2100 if (data == 0xff || data == 0x00) {
2101 INVALIDATE_SENSOR(n);
2102 } else {
2103 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2104 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
2105 }
2106 }
2107
2108 static void
2109 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
2110 {
2111 int reg, shift, data, divisor = 1;
2112
2113 shift = 0;
2114
2115 switch (sc->lm_sensors[n].reg) {
2116 case 0x28:
2117 reg = 0x47; shift = 0;
2118 break;
2119 case 0x29:
2120 reg = 0x47; shift = 4;
2121 break;
2122 case 0x2a:
2123 reg = 0x5b; shift = 0;
2124 break;
2125 case 0xb8:
2126 reg = 0x5b; shift = 4;
2127 break;
2128 case 0xb9:
2129 reg = 0x5c; shift = 0;
2130 break;
2131 case 0xba:
2132 reg = 0x5c; shift = 4;
2133 break;
2134 case 0xbe:
2135 reg = 0x9e; shift = 0;
2136 break;
2137 default:
2138 reg = 0;
2139 break;
2140 }
2141
2142 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2143 if (data == 0xff || data == 0x00) {
2144 INVALIDATE_SENSOR(n);
2145 } else {
2146 if (reg != 0)
2147 divisor = ((*sc->lm_readreg)(sc, reg) >> shift) & 0x7;
2148 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2149 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
2150 }
2151 }
2152
2153 static void
2154 as_refresh_temp(struct lm_softc *sc, int n)
2155 {
2156 int sdata;
2157
2158 /*
2159 * It seems a shorted temperature diode produces an all-ones
2160 * bit pattern.
2161 */
2162 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2163 sdata += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2164 if (sdata == 0x1ff) {
2165 INVALIDATE_SENSOR(n);
2166 } else {
2167 if (sdata & 0x100)
2168 sdata -= 0x200;
2169 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2170 sc->sensors[n].cur.data_us = sdata * 500000 + 273150000;
2171 }
2172 }
2173
2174 #undef INVALIDATE_SENSOR
2175
2176 static int
2177 lm_gtredata(struct sysmon_envsys *sme, envsys_tre_data_t *tred)
2178 {
2179 static const struct timeval onepointfive = { 1, 500000 };
2180 struct timeval t, utv;
2181 struct lm_softc *sc = sme->sme_cookie;
2182
2183 /* read new values at most once every 1.5 seconds */
2184 getmicrouptime(&utv);
2185 timeradd(&sc->lastread, &onepointfive, &t);
2186 if (timercmp(&utv, &t, >)) {
2187 sc->lastread = utv;
2188 sc->refresh_sensor_data(sc);
2189 }
2190
2191 *tred = sc->sensors[tred->sensor];
2192
2193 return 0;
2194 }
2195
2196 static int
2197 generic_streinfo_fan(struct lm_softc *sc, envsys_basic_info_t *info, int n,
2198 envsys_basic_info_t *binfo)
2199 {
2200 uint8_t sdata;
2201 int divisor;
2202
2203 /* FAN1 and FAN2 can have divisors set, but not FAN3 */
2204 if ((sc->info[binfo->sensor].units == ENVSYS_SFANRPM)
2205 && (n < 2)) {
2206 if (binfo->rpms == 0) {
2207 binfo->validflags = 0;
2208 return 0;
2209 }
2210
2211 /* write back the nominal FAN speed */
2212 info->rpms = binfo->rpms;
2213
2214 /* 153 is the nominal FAN speed value */
2215 divisor = 1350000 / (binfo->rpms * 153);
2216
2217 /* ...but we need lg(divisor) */
2218 if (divisor <= 1)
2219 divisor = 0;
2220 else if (divisor <= 2)
2221 divisor = 1;
2222 else if (divisor <= 4)
2223 divisor = 2;
2224 else
2225 divisor = 3;
2226
2227 /*
2228 * FAN1 div is in bits <5:4>, FAN2 div is
2229 * in <7:6>
2230 */
2231 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2232 if ( n == 0 ) { /* FAN1 */
2233 divisor <<= 4;
2234 sdata = (sdata & 0xCF) | divisor;
2235 } else { /* FAN2 */
2236 divisor <<= 6;
2237 sdata = (sdata & 0x3F) | divisor;
2238 }
2239
2240 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2241 }
2242 return 0;
2243
2244 }
2245
2246 static int
2247 lm_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2248 {
2249 struct lm_softc *sc = sme->sme_cookie;
2250
2251 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2252 sc->info[binfo->sensor].rfact = binfo->rfact;
2253 else {
2254 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2255 generic_streinfo_fan(sc, &sc->info[binfo->sensor],
2256 binfo->sensor - 8, binfo);
2257 }
2258 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2259 sizeof(sc->info[binfo->sensor].desc));
2260 binfo->validflags = ENVSYS_FVALID;
2261 }
2262 return 0;
2263 }
2264
2265 static int
2266 wb781_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2267 {
2268 struct lm_softc *sc = sme->sme_cookie;
2269 int divisor;
2270 uint8_t sdata;
2271 int i;
2272
2273 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2274 sc->info[binfo->sensor].rfact = binfo->rfact;
2275 else {
2276 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2277 if (binfo->rpms == 0) {
2278 binfo->validflags = 0;
2279 return 0;
2280 }
2281
2282 /* write back the nominal FAN speed */
2283 sc->info[binfo->sensor].rpms = binfo->rpms;
2284
2285 /* 153 is the nominal FAN speed value */
2286 divisor = 1350000 / (binfo->rpms * 153);
2287
2288 /* ...but we need lg(divisor) */
2289 for (i = 0; i < 7; i++) {
2290 if (divisor <= (1 << i))
2291 break;
2292 }
2293 divisor = i;
2294
2295 if (binfo->sensor == 10 || binfo->sensor == 11) {
2296 /*
2297 * FAN1 div is in bits <5:4>, FAN2 div
2298 * is in <7:6>
2299 */
2300 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2301 if ( binfo->sensor == 10 ) { /* FAN1 */
2302 sdata = (sdata & 0xCF) |
2303 ((divisor & 0x3) << 4);
2304 } else { /* FAN2 */
2305 sdata = (sdata & 0x3F) |
2306 ((divisor & 0x3) << 6);
2307 }
2308 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2309 } else {
2310 /* FAN3 is in WB_PIN <7:6> */
2311 sdata = (*sc->lm_readreg)(sc, WB_PIN);
2312 sdata = (sdata & 0x3F) |
2313 ((divisor & 0x3) << 6);
2314 (*sc->lm_writereg)(sc, WB_PIN, sdata);
2315 }
2316 }
2317 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2318 sizeof(sc->info[binfo->sensor].desc));
2319 binfo->validflags = ENVSYS_FVALID;
2320 }
2321 return 0;
2322 }
2323
2324 static int
2325 wb782_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2326 {
2327 struct lm_softc *sc = sme->sme_cookie;
2328 int divisor;
2329 uint8_t sdata;
2330 int i;
2331
2332 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2333 sc->info[binfo->sensor].rfact = binfo->rfact;
2334 else {
2335 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2336 if (binfo->rpms == 0) {
2337 binfo->validflags = 0;
2338 return 0;
2339 }
2340
2341 /* write back the nominal FAN speed */
2342 sc->info[binfo->sensor].rpms = binfo->rpms;
2343
2344 /* 153 is the nominal FAN speed value */
2345 divisor = 1350000 / (binfo->rpms * 153);
2346
2347 /* ...but we need lg(divisor) */
2348 for (i = 0; i < 7; i++) {
2349 if (divisor <= (1 << i))
2350 break;
2351 }
2352 divisor = i;
2353
2354 if (binfo->sensor == 12 || binfo->sensor == 13) {
2355 /*
2356 * FAN1 div is in bits <5:4>, FAN2 div
2357 * is in <7:6>
2358 */
2359 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2360 if ( binfo->sensor == 12 ) { /* FAN1 */
2361 sdata = (sdata & 0xCF) |
2362 ((divisor & 0x3) << 4);
2363 } else { /* FAN2 */
2364 sdata = (sdata & 0x3F) |
2365 ((divisor & 0x3) << 6);
2366 }
2367 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2368 } else {
2369 /* FAN3 is in WB_PIN <7:6> */
2370 sdata = (*sc->lm_readreg)(sc, WB_PIN);
2371 sdata = (sdata & 0x3F) |
2372 ((divisor & 0x3) << 6);
2373 (*sc->lm_writereg)(sc, WB_PIN, sdata);
2374 }
2375 /* Bit 2 of divisor is in WB_BANK0_VBAT */
2376 lm_generic_banksel(sc, WB_BANKSEL_B0);
2377 sdata = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
2378 sdata &= ~(0x20 << (binfo->sensor - 12));
2379 sdata |= (divisor & 0x4) << (binfo->sensor - 9);
2380 (*sc->lm_writereg)(sc, WB_BANK0_VBAT, sdata);
2381 }
2382
2383 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2384 sizeof(sc->info[binfo->sensor].desc));
2385 binfo->validflags = ENVSYS_FVALID;
2386 }
2387 return 0;
2388 }
2389