This source file includes following definitions.
- viasio_conf_enable
- viasio_conf_disable
- viasio_conf_read
- viasio_conf_write
- viasio_raw2temp
- viasio_probe
- viasio_attach
- viasio_hm_init
- viasio_hm_refresh
- viasio_wdg_init
- viasio_wdg_cb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/device.h>
25 #include <sys/kernel.h>
26 #include <sys/sensors.h>
27 #include <sys/timeout.h>
28
29 #include <machine/bus.h>
30
31 #include <dev/isa/isareg.h>
32 #include <dev/isa/isavar.h>
33
34 #include <dev/isa/viasioreg.h>
35
36 #ifdef VIASIO_DEBUG
37 #define DPRINTF(x) printf x
38 #else
39 #define DPRINTF(x)
40 #endif
41
42
43 #define VIASIO_CFFLAGS_HM_ENABLE 0x0001
44 #define VIASIO_CFFLAGS_WDG_ENABLE 0x0002
45
46 struct viasio_softc {
47 struct device sc_dev;
48
49 bus_space_tag_t sc_iot;
50 bus_space_handle_t sc_ioh;
51
52
53 bus_space_handle_t sc_hm_ioh;
54 int sc_hm_clock;
55 struct ksensor sc_hm_sensors[VT1211_HM_NSENSORS];
56 struct ksensordev sc_sensordev;
57 struct timeout sc_hm_timo;
58
59
60 bus_space_handle_t sc_wdg_ioh;
61 };
62
63 int viasio_probe(struct device *, void *, void *);
64 void viasio_attach(struct device *, struct device *, void *);
65
66 void viasio_hm_init(struct viasio_softc *);
67 void viasio_hm_refresh(void *);
68
69 void viasio_wdg_init(struct viasio_softc *);
70 int viasio_wdg_cb(void *, int);
71
72 struct cfattach viasio_ca = {
73 sizeof(struct viasio_softc),
74 viasio_probe,
75 viasio_attach
76 };
77
78 struct cfdriver viasio_cd = {
79 NULL, "viasio", DV_DULL
80 };
81
82 static __inline void
83 viasio_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh)
84 {
85 bus_space_write_1(iot, ioh, VT1211_INDEX, VT1211_CONF_EN_MAGIC);
86 bus_space_write_1(iot, ioh, VT1211_INDEX, VT1211_CONF_EN_MAGIC);
87 }
88
89 static __inline void
90 viasio_conf_disable(bus_space_tag_t iot, bus_space_handle_t ioh)
91 {
92 bus_space_write_1(iot, ioh, VT1211_INDEX, VT1211_CONF_DS_MAGIC);
93 }
94
95 static __inline u_int8_t
96 viasio_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index)
97 {
98 bus_space_write_1(iot, ioh, VT1211_INDEX, index);
99 return (bus_space_read_1(iot, ioh, VT1211_DATA));
100 }
101
102 static __inline void
103 viasio_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index,
104 u_int8_t data)
105 {
106 bus_space_write_1(iot, ioh, VT1211_INDEX, index);
107 bus_space_write_1(iot, ioh, VT1211_DATA, data);
108 }
109
110 static __inline int64_t
111 viasio_raw2temp(int raw)
112 {
113 int tblsize = sizeof(vt1211_hm_temptbl) / sizeof(vt1211_hm_temptbl[0]);
114 int i;
115 int raw1, raw2;
116 int64_t temp = -1, temp1, temp2;
117
118 if (raw < vt1211_hm_temptbl[0].raw ||
119 raw > vt1211_hm_temptbl[tblsize - 1].raw)
120 return (-1);
121
122 for (i = 0; i < tblsize - 1; i++) {
123 raw1 = vt1211_hm_temptbl[i].raw;
124 temp1 = vt1211_hm_temptbl[i].temp;
125 raw2 = vt1211_hm_temptbl[i + 1].raw;
126 temp2 = vt1211_hm_temptbl[i + 1].temp;
127
128 if (raw >= raw1 && raw <= raw2) {
129
130 temp = temp1 + ((raw - raw1) * (temp2 - temp1)) /
131 (raw2 - raw1);
132 break;
133 }
134 }
135
136 return (temp);
137 }
138
139 int
140 viasio_probe(struct device *parent, void *match, void *aux)
141 {
142 struct isa_attach_args *ia = aux;
143 bus_space_tag_t iot;
144 bus_space_handle_t ioh;
145 u_int8_t reg;
146
147
148 iot = ia->ia_iot;
149 if (bus_space_map(iot, ia->ipa_io[0].base, VT1211_IOSIZE, 0, &ioh))
150 return (0);
151 viasio_conf_enable(iot, ioh);
152 reg = viasio_conf_read(iot, ioh, VT1211_ID);
153 DPRINTF(("viasio_probe: id 0x%02x\n", reg));
154 viasio_conf_disable(iot, ioh);
155 bus_space_unmap(iot, ioh, VT1211_IOSIZE);
156 if (reg == VT1211_ID_VT1211) {
157 ia->ipa_nio = 1;
158 ia->ipa_io[0].length = VT1211_IOSIZE;
159 ia->ipa_nmem = 0;
160 ia->ipa_nirq = 0;
161 ia->ipa_ndrq = 0;
162 return (1);
163 }
164
165 return (0);
166 }
167
168 void
169 viasio_attach(struct device *parent, struct device *self, void *aux)
170 {
171 struct viasio_softc *sc = (void *)self;
172 struct isa_attach_args *ia = aux;
173 u_int8_t reg;
174
175
176 sc->sc_iot = ia->ia_iot;
177 if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base,
178 VT1211_IOSIZE, 0, &sc->sc_ioh)) {
179 printf(": can't map I/O space\n");
180 return;
181 }
182
183
184 viasio_conf_enable(sc->sc_iot, sc->sc_ioh);
185
186
187 reg = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_REV);
188 printf(": VT1211 rev 0x%02x", reg);
189
190
191 viasio_hm_init(sc);
192 viasio_wdg_init(sc);
193 printf("\n");
194
195
196 viasio_conf_disable(sc->sc_iot, sc->sc_ioh);
197 }
198
199 void
200 viasio_hm_init(struct viasio_softc *sc)
201 {
202 u_int8_t reg0, reg1;
203 u_int16_t iobase;
204 int i;
205
206 printf(", HM");
207
208
209 viasio_conf_write(sc->sc_iot, sc->sc_ioh, VT1211_LDN, VT1211_LDN_HM);
210
211
212
213
214
215 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_HM_ACT);
216 DPRINTF((": ACT 0x%02x", reg0));
217 if ((reg0 & VT1211_HM_ACT_EN) == 0) {
218 if ((sc->sc_dev.dv_cfdata->cf_flags &
219 VIASIO_CFFLAGS_HM_ENABLE) != 0) {
220 reg0 |= VT1211_HM_ACT_EN;
221 viasio_conf_write(sc->sc_iot, sc->sc_ioh,
222 VT1211_HM_ACT, reg0);
223 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh,
224 VT1211_HM_ACT);
225 DPRINTF((", new ACT 0x%02x", reg0));
226 if ((reg0 & VT1211_HM_ACT_EN) == 0) {
227 printf(" failed to activate");
228 return;
229 }
230 } else {
231 printf(" not activated");
232 return;
233 }
234 }
235
236
237 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_HM_ADDR_LSB);
238 reg1 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_HM_ADDR_MSB);
239 iobase = (reg1 << 8) | reg0;
240 DPRINTF((", addr 0x%04x", iobase));
241
242
243 if (bus_space_map(sc->sc_iot, iobase, VT1211_HM_IOSIZE, 0,
244 &sc->sc_hm_ioh)) {
245 printf(" can't map I/O space");
246 return;
247 }
248
249
250
251
252
253 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_CONF);
254 DPRINTF((", CONF 0x%02x", reg0));
255 if ((reg0 & VT1211_HM_CONF_START) == 0) {
256 if ((sc->sc_dev.dv_cfdata->cf_flags &
257 VIASIO_CFFLAGS_HM_ENABLE) != 0) {
258 reg0 |= VT1211_HM_CONF_START;
259 bus_space_write_1(sc->sc_iot, sc->sc_hm_ioh,
260 VT1211_HM_CONF, reg0);
261 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh,
262 VT1211_HM_CONF);
263 DPRINTF((", new CONF 0x%02x", reg0));
264 if ((reg0 & VT1211_HM_CONF_START) == 0) {
265 printf(" failed to enable monitoring");
266 return;
267 }
268 } else {
269 printf(" monitoring not enabled");
270 return;
271 }
272 }
273
274
275 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_PWMCS);
276 sc->sc_hm_clock = vt1211_hm_clock[reg0 & 0x07];
277 DPRINTF((", PWMCS 0x%02x, %dHz", reg0, sc->sc_hm_clock));
278
279
280 sc->sc_hm_sensors[VT1211_HMS_TEMP1].type = SENSOR_TEMP;
281
282
283 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_UCHCONF);
284 DPRINTF((", UCHCONF 0x%02x", reg0));
285 for (i = 1; i <= 5; i++) {
286
287 if (VT1211_HM_UCHCONF_ISTEMP(reg0, i)) {
288 sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].type =
289 SENSOR_TEMP;
290 } else {
291 sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].type =
292 SENSOR_VOLTS_DC;
293 }
294 snprintf(sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].desc,
295 sizeof(sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].desc),
296 "UCH%d", i);
297 }
298
299
300 sc->sc_hm_sensors[VT1211_HMS_33V].type = SENSOR_VOLTS_DC;
301 strlcpy(sc->sc_hm_sensors[VT1211_HMS_33V].desc, "+3.3V",
302 sizeof(sc->sc_hm_sensors[VT1211_HMS_33V].desc));
303
304
305 sc->sc_hm_sensors[VT1211_HMS_FAN1].type = SENSOR_FANRPM;
306 sc->sc_hm_sensors[VT1211_HMS_FAN2].type = SENSOR_FANRPM;
307
308
309 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
310 sizeof(sc->sc_sensordev.xname));
311 for (i = 0; i < VT1211_HM_NSENSORS; i++)
312 sensor_attach(&sc->sc_sensordev, &sc->sc_hm_sensors[i]);
313 sensordev_install(&sc->sc_sensordev);
314 timeout_set(&sc->sc_hm_timo, viasio_hm_refresh, sc);
315 timeout_add(&sc->sc_hm_timo, hz);
316 }
317
318 void
319 viasio_hm_refresh(void *arg)
320 {
321 struct viasio_softc *sc = arg;
322 u_int8_t reg0, reg1;
323 int64_t val, rfact;
324 int i;
325
326
327 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_TEMP1);
328 reg1 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_TCONF1);
329 reg1 = VT1211_HM_TCONF1_TEMP1(reg1);
330 val = (reg0 << 2) | reg1;
331
332
333
334 val = viasio_raw2temp(val);
335 if (val == -1) {
336 sc->sc_hm_sensors[VT1211_HMS_TEMP1].flags |= SENSOR_FINVALID;
337 } else {
338 sc->sc_hm_sensors[VT1211_HMS_TEMP1].flags &= ~SENSOR_FINVALID;
339 sc->sc_hm_sensors[VT1211_HMS_TEMP1].value = val;
340 }
341
342
343 for (i = 1; i <= 5; i++) {
344 if (sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].type ==
345 SENSOR_TEMP) {
346
347 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh,
348 VT1211_HM_UCH1 + i - 1);
349 if (i == 1) {
350 reg1 = bus_space_read_1(sc->sc_iot,
351 sc->sc_hm_ioh, VT1211_HM_VID4);
352 reg1 = VT1211_HM_VID4_UCH1(reg1);
353 } else {
354 reg1 = bus_space_read_1(sc->sc_iot,
355 sc->sc_hm_ioh, VT1211_HM_ETR);
356 reg1 = VT1211_HM_ETR_UCH(reg1, i);
357 }
358 val = (reg0 << 2) | reg1;
359
360
361
362 val = viasio_raw2temp(val);
363 if (val == -1) {
364 sc->sc_hm_sensors[VT1211_HMS_UCH1 +
365 i - 1].flags |= SENSOR_FINVALID;
366 } else {
367 sc->sc_hm_sensors[VT1211_HMS_UCH1 +
368 i - 1].flags &= ~SENSOR_FINVALID;
369 sc->sc_hm_sensors[VT1211_HMS_UCH1 +
370 i - 1].value = val;
371 }
372 } else {
373
374 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh,
375 VT1211_HM_UCH1 + i - 1);
376 val = reg0;
377
378
379
380 rfact = vt1211_hm_vrfact[i - 1];
381 sc->sc_hm_sensors[VT1211_HMS_UCH1 + i - 1].value =
382 ((val * 100000000000ULL) / (rfact * 958));
383 }
384 }
385
386
387 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_33V);
388 val = reg0;
389
390
391
392 rfact = vt1211_hm_vrfact[5];
393 sc->sc_hm_sensors[VT1211_HMS_33V].value = ((val * 100000000000ULL) /
394 (rfact * 958));
395
396
397 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_FAN1);
398 reg1 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_FSCTL);
399 reg1 = VT1211_HM_FSCTL_DIV1(reg1);
400 val = reg0 << reg1;
401
402
403
404 if (val != 0) {
405 sc->sc_hm_sensors[VT1211_HMS_FAN1].value =
406 (sc->sc_hm_clock * 60 / 2) / val;
407 sc->sc_hm_sensors[VT1211_HMS_FAN1].flags &= ~SENSOR_FINVALID;
408 } else {
409 sc->sc_hm_sensors[VT1211_HMS_FAN1].flags |= SENSOR_FINVALID;
410 }
411
412
413 reg0 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_FAN2);
414 reg1 = bus_space_read_1(sc->sc_iot, sc->sc_hm_ioh, VT1211_HM_FSCTL);
415 reg1 = VT1211_HM_FSCTL_DIV2(reg1);
416 val = reg0 << reg1;
417
418
419
420 if (val != 0) {
421 sc->sc_hm_sensors[VT1211_HMS_FAN2].value =
422 (sc->sc_hm_clock * 60 / 2) / val;
423 sc->sc_hm_sensors[VT1211_HMS_FAN2].flags &= ~SENSOR_FINVALID;
424 } else {
425 sc->sc_hm_sensors[VT1211_HMS_FAN2].flags |= SENSOR_FINVALID;
426 }
427
428 timeout_add(&sc->sc_hm_timo, hz);
429 }
430
431 void
432 viasio_wdg_init(struct viasio_softc *sc)
433 {
434 u_int8_t reg0, reg1;
435 u_int16_t iobase;
436
437 printf(", WDG");
438
439
440 viasio_conf_write(sc->sc_iot, sc->sc_ioh, VT1211_LDN, VT1211_LDN_WDG);
441
442
443
444
445
446 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ACT);
447 DPRINTF((": ACT 0x%02x", reg0));
448 if ((reg0 & VT1211_WDG_ACT_EN) == 0) {
449 if ((sc->sc_dev.dv_cfdata->cf_flags &
450 VIASIO_CFFLAGS_WDG_ENABLE) != 0) {
451 reg0 |= VT1211_WDG_ACT_EN;
452 viasio_conf_write(sc->sc_iot, sc->sc_ioh,
453 VT1211_WDG_ACT, reg0);
454 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh,
455 VT1211_WDG_ACT);
456 DPRINTF((", new ACT 0x%02x", reg0));
457 if ((reg0 & VT1211_WDG_ACT_EN) == 0) {
458 printf(" failed to activate");
459 return;
460 }
461 } else {
462 printf(" not activated");
463 return;
464 }
465 }
466
467
468 reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_LSB);
469 reg1 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_MSB);
470 iobase = (reg1 << 8) | reg0;
471 DPRINTF((", addr 0x%04x", iobase));
472
473
474 if (bus_space_map(sc->sc_iot, iobase, VT1211_WDG_IOSIZE, 0,
475 &sc->sc_wdg_ioh)) {
476 printf(" can't map I/O space");
477 return;
478 }
479
480
481 wdog_register(sc, viasio_wdg_cb);
482 }
483
484 int
485 viasio_wdg_cb(void *arg, int period)
486 {
487 struct viasio_softc *sc = arg;
488 int mins;
489
490 mins = (period + 59) / 60;
491 if (mins > 255)
492 mins = 255;
493
494 bus_space_write_1(sc->sc_iot, sc->sc_wdg_ioh, VT1211_WDG_TIMEOUT, mins);
495 DPRINTF(("viasio_wdg_cb: %d mins\n", mins));
496
497 return (mins * 60);
498 }