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