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