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
46struct cfdriver lm_cd = {
47	NULL, "lm", DV_DULL
48};
49
50int  lm_match(struct lm_softc *);
51int  wb_match(struct lm_softc *);
52int  def_match(struct lm_softc *);
53
54void lm_setup_sensors(struct lm_softc *, const struct lm_sensor *);
55void lm_refresh(void *);
56
57void lm_refresh_sensor_data(struct lm_softc *);
58void lm_refresh_volt(struct lm_softc *, int);
59void lm_refresh_temp(struct lm_softc *, int);
60void lm_refresh_fanrpm(struct lm_softc *, int);
61
62void wb_refresh_sensor_data(struct lm_softc *);
63void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
64void wb_refresh_nvolt(struct lm_softc *, int);
65void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
66void wb_refresh_temp(struct lm_softc *, int);
67void wb_refresh_fanrpm(struct lm_softc *, int);
68void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
69void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
70
71void as_refresh_temp(struct lm_softc *, int);
72
73struct lm_chip {
74	int (*chip_match)(struct lm_softc *);
75};
76
77const struct lm_chip lm_chips[] = {
78	{ wb_match },
79	{ lm_match },
80	{ def_match } /* Must be last */
81};
82
83const 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
104const 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 */
136const 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 */
166const 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
191const 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 */
219const 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
255const 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
278const 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 */
305const 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
328const 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
353const 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
374const 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
402const 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
431const 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
454void
455lm_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
484int
485lm_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
513int
514def_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
526int
527wb_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
664void
665lm_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
681void
682lm_refresh(void *arg)
683{
684	struct lm_softc *sc = arg;
685
686	sc->refresh_sensor_data(sc);
687}
688
689void
690lm_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
698void
699lm_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
710void
711lm_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
732void
733lm_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
764void
765wb_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
784void
785wb_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
804void
805wb_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
817void
818wb_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
830void
831wb_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
856void
857wb_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
905void
906wb_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
923void
924wb_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
968void
969as_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