Annotation of src/sys/dev/isa/finsio_isa.c, Revision 1.7.12.1
1.1 xtraeme 1: /* $OpenBSD: fins.c,v 1.1 2008/03/19 19:33:09 deraadt Exp $ */
1.7.12.1! jdolecek 2: /* $NetBSD$ */
1.1 xtraeme 3:
4: /*
5: * Copyright (c) 2008 Juan Romero Pardines
6: * Copyright (c) 2007, 2008 Geoff Steckel
7: * Copyright (c) 2005, 2006 Mark Kettenis
8: *
9: * Permission to use, copy, modify, and distribute this software for any
10: * purpose with or without fee is hereby granted, provided that the above
11: * copyright notice and this permission notice appear in all copies.
12: *
13: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20: */
21: #include <sys/cdefs.h>
1.7.12.1! jdolecek 22: __KERNEL_RCSID(0, "$NetBSD$");
1.1 xtraeme 23:
24: #include <sys/param.h>
25: #include <sys/systm.h>
26: #include <sys/device.h>
1.6 jmcneill 27: #include <sys/module.h>
1.1 xtraeme 28: #include <sys/bus.h>
29:
30: #include <dev/isa/isareg.h>
31: #include <dev/isa/isavar.h>
32:
33: #include <dev/sysmon/sysmonvar.h>
34:
35: /* Derived from LM78 code. Only handles chips attached to ISA bus */
36:
37: /*
38: * Fintek F71805/F71883 Super I/O datasheets:
39: * http://www.fintek.com.tw/files/productfiles/F71805F_V025.pdf
40: * http://www.fintek.com.tw/files/productfiles/F71883_V026P.pdf
41: *
42: * This chip is a multi-io chip with many functions.
43: * Each function may be relocated in I/O space by the BIOS.
44: * The base address (2E or 4E) accesses a configuration space which
45: * has pointers to the individual functions. The config space must be
46: * unlocked with a cookie and relocked afterwards. The chip ID is stored
47: * in config space so it is not normally visible.
48: *
49: * The voltage dividers specified are from reading the chips on one board.
50: * There is no way to determine what they are in the general case.
51: */
52:
53: #define FINSIO_UNLOCK 0x87 /* magic constant - write 2x to select chip */
54: #define FINSIO_LOCK 0xaa /* magic constant - write 1x to deselect reg */
55:
56: #define FINSIO_FUNC_SEL 0x07 /* select which subchip to access */
57: # define FINSIO_FUNC_HWMON 0x4
58:
59: /* ISA registers index to an internal register space on chip */
1.7 jakllsch 60: #define FINSIO_DECODE_SIZE (8)
61: #define FINSIO_DECODE_MASK (FINSIO_DECODE_SIZE - 1)
62: #define FINSIO_ADDR 5 /* global configuration index */
63: #define FINSIO_DATA 6 /* and data registers */
1.1 xtraeme 64:
65: /* Global configuration registers */
66: #define FINSIO_MANUF 0x23 /* manufacturer ID */
67: # define FINTEK_ID 0x1934
68: #define FINSIO_CHIP 0x20 /* chip ID */
69: # define FINSIO_IDF71805 0x0406
70: # define FINSIO_IDF71806 0x0341 /* F71872 and F1806 F/FG */
71: # define FINSIO_IDF71883 0x0541 /* F71882 and F1883 */
72: # define FINSIO_IDF71862 0x0601 /* F71862FG */
1.6 jmcneill 73: # define FINSIO_IDF8000 0x0581 /* F8000 */
1.1 xtraeme 74:
75: /* in bank sensors of config space */
76: #define FINSIO_SENSADDR 0x60 /* sensors assigned I/O address (2 bytes) */
77:
78: #define FINSIO_HWMON_CONF 0x01 /* Hardware Monitor Config. Register */
79:
80: /* in sensors space */
81: #define FINSIO_TMODE 0x01 /* temperature mode reg */
82:
83: #define FINSIO_MAX_SENSORS 20
84: /*
85: * Fintek chips typically measure voltages using 8mv steps.
86: * To measure higher voltages the input is attenuated with (external)
87: * resistors. Negative voltages are measured using inverting op amps
88: * and resistors. So we have to convert the sensor values back to
89: * real voltages by applying the appropriate resistor factor.
90: */
91: #define FRFACT_NONE 8000
92: #define FRFACT(x, y) (FRFACT_NONE * ((x) + (y)) / (y))
93: #define FNRFACT(x, y) (-FRFACT_NONE * (x) / (y))
94:
95: #if defined(FINSIODEBUG)
96: #define DPRINTF(x) do { printf x; } while (0)
97: #else
98: #define DPRINTF(x)
99: #endif
100:
101: struct finsio_softc {
102: bus_space_tag_t sc_iot;
103: bus_space_handle_t sc_ioh;
104:
105: struct sysmon_envsys *sc_sme;
106: envsys_data_t sc_sensor[FINSIO_MAX_SENSORS];
107: struct finsio_sensor *sc_finsio_sensors;
108:
109: u_int sc_tempsel;
110: };
111:
112: struct finsio_sensor {
113: const char *fs_desc;
114: u_int fs_type;
115: uint8_t fs_aux;
116: uint8_t fs_reg;
117: void (*fs_refresh)(struct finsio_softc *, envsys_data_t *);
118: int fs_rfact;
119: };
120:
121: static int finsio_isa_match(device_t, cfdata_t, void *);
122: static void finsio_isa_attach(device_t, device_t, void *);
1.3 xtraeme 123: static int finsio_isa_detach(device_t, int);
1.1 xtraeme 124:
125: static void finsio_enter(bus_space_tag_t, bus_space_handle_t);
126: static void finsio_exit(bus_space_tag_t, bus_space_handle_t);
127: static uint8_t finsio_readreg(bus_space_tag_t, bus_space_handle_t, int);
128: static void finsio_writereg(bus_space_tag_t, bus_space_handle_t, int, int);
129:
130: static void finsio_refresh(struct sysmon_envsys *, envsys_data_t *);
131: static void finsio_refresh_volt(struct finsio_softc *, envsys_data_t *);
132: static void finsio_refresh_temp(struct finsio_softc *, envsys_data_t *);
133: static void finsio_refresh_fanrpm(struct finsio_softc *, envsys_data_t *);
134:
135: CFATTACH_DECL_NEW(finsio, sizeof(struct finsio_softc),
1.3 xtraeme 136: finsio_isa_match, finsio_isa_attach, finsio_isa_detach, NULL);
1.1 xtraeme 137:
138: /* Sensors available in F71805/F71806 */
139: static struct finsio_sensor f71805_sensors[] = {
140: /* Voltage */
141: {
142: .fs_desc = "+3.3V",
143: .fs_type = ENVSYS_SVOLTS_DC,
144: .fs_aux = 0,
145: .fs_reg = 0x10,
146: .fs_refresh = finsio_refresh_volt,
147: .fs_rfact = FRFACT(100, 100)
148: },
149: {
150: .fs_desc = "Vtt",
151: .fs_type = ENVSYS_SVOLTS_DC,
152: .fs_aux = 0,
153: .fs_reg = 0x11,
154: .fs_refresh = finsio_refresh_volt,
155: .fs_rfact = FRFACT_NONE
156: },
157: {
158: .fs_desc = "Vram",
159: .fs_type = ENVSYS_SVOLTS_DC,
160: .fs_aux = 0,
161: .fs_reg = 0x12,
162: .fs_refresh = finsio_refresh_volt,
163: .fs_rfact = FRFACT(100, 100)
164: },
165: {
166: .fs_desc = "Vchips",
167: .fs_type = ENVSYS_SVOLTS_DC,
168: .fs_aux = 0,
169: .fs_reg = 0x13,
170: .fs_refresh = finsio_refresh_volt,
171: .fs_rfact = FRFACT(47, 100)
172: },
173: {
174: .fs_desc = "+5V",
175: .fs_type = ENVSYS_SVOLTS_DC,
176: .fs_aux = 0,
177: .fs_reg = 0x14,
178: .fs_refresh = finsio_refresh_volt,
179: .fs_rfact = FRFACT(200, 47)
180: },
181: {
182: .fs_desc = "+12V",
183: .fs_type = ENVSYS_SVOLTS_DC,
184: .fs_aux = 0,
185: .fs_reg = 0x15,
186: .fs_refresh = finsio_refresh_volt,
187: .fs_rfact = FRFACT(200, 20)
188: },
189: {
190: .fs_desc = "Vcc 1.5V",
191: .fs_type = ENVSYS_SVOLTS_DC,
192: .fs_aux = 0,
193: .fs_reg = 0x16,
194: .fs_refresh = finsio_refresh_volt,
195: .fs_rfact = FRFACT_NONE
196: },
197: {
198: .fs_desc = "VCore",
199: .fs_type = ENVSYS_SVOLTS_DC,
200: .fs_aux = 0,
201: .fs_reg = 0x17,
202: .fs_refresh = finsio_refresh_volt,
203: .fs_rfact = FRFACT_NONE
204: },
205: {
206: .fs_desc = "Vsb",
207: .fs_type = ENVSYS_SVOLTS_DC,
208: .fs_aux = 0,
209: .fs_reg = 0x18,
210: .fs_refresh = finsio_refresh_volt,
211: .fs_rfact = FRFACT(200, 47)
212: },
213: {
214: .fs_desc = "Vsbint",
215: .fs_type = ENVSYS_SVOLTS_DC,
216: .fs_aux = 0,
217: .fs_reg = 0x19,
218: .fs_refresh = finsio_refresh_volt,
219: .fs_rfact = FRFACT(200, 47)
220: },
221: {
222: .fs_desc = "Vbat",
223: .fs_type = ENVSYS_SVOLTS_DC,
224: .fs_aux = 0,
225: .fs_reg = 0x1a,
226: .fs_refresh = finsio_refresh_volt,
227: .fs_rfact = FRFACT(200, 47)
228: },
229: /* Temperature */
230: {
231: .fs_desc = "Temp1",
232: .fs_type = ENVSYS_STEMP,
233: .fs_aux = 0x01,
234: .fs_reg = 0x1b,
235: .fs_refresh = finsio_refresh_temp,
236: .fs_rfact = 0
237: },
238: {
239: .fs_desc = "Temp2",
240: .fs_type = ENVSYS_STEMP,
241: .fs_aux = 0x02,
242: .fs_reg = 0x1c,
243: .fs_refresh = finsio_refresh_temp,
244: .fs_rfact = 0
245: },
246: {
247: .fs_desc = "Temp3",
248: .fs_type = ENVSYS_STEMP,
249: .fs_aux = 0x04,
250: .fs_reg = 0x1d,
251: .fs_refresh = finsio_refresh_temp,
252: .fs_rfact = 0
253: },
254: /* Fans */
255: {
256: .fs_desc = "Fan1",
257: .fs_type = ENVSYS_SFANRPM,
258: .fs_aux = 0,
259: .fs_reg = 0x20,
260: .fs_refresh = finsio_refresh_fanrpm,
261: .fs_rfact = 0
262: },
263: {
264: .fs_desc = "Fan2",
265: .fs_type = ENVSYS_SFANRPM,
266: .fs_aux = 0,
267: .fs_reg = 0x22,
268: .fs_refresh = finsio_refresh_fanrpm,
269: .fs_rfact = 0
270: },
271: {
272: .fs_desc = "Fan3",
273: .fs_type = ENVSYS_SFANRPM,
274: .fs_aux = 0,
275: .fs_reg = 0x24,
276: .fs_refresh = finsio_refresh_fanrpm,
277: .fs_rfact = 0
278: },
279:
280: { .fs_desc = NULL }
281: };
282:
283: /* Sensors available in F71862/F71882/F71883 */
284: static struct finsio_sensor f71883_sensors[] = {
285: /* Voltage */
286: {
287: .fs_desc = "+3.3V",
288: .fs_type = ENVSYS_SVOLTS_DC,
289: .fs_aux = 0,
290: .fs_reg = 0x20,
291: .fs_refresh = finsio_refresh_volt,
292: .fs_rfact = FRFACT(100, 100)
293: },
294: {
295: .fs_desc = "Vcore",
296: .fs_type = ENVSYS_SVOLTS_DC,
297: .fs_aux = 0,
298: .fs_reg = 0x21,
299: .fs_refresh = finsio_refresh_volt,
300: .fs_rfact = FRFACT_NONE
301: },
302: {
303: .fs_desc = "VIN2",
304: .fs_type = ENVSYS_SVOLTS_DC,
305: .fs_aux = 0,
306: .fs_reg = 0x22,
307: .fs_refresh = finsio_refresh_volt,
308: .fs_rfact = FRFACT(100, 100)
309: },
310: {
311: .fs_desc = "VIN3",
312: .fs_type = ENVSYS_SVOLTS_DC,
313: .fs_aux = 0,
314: .fs_reg = 0x23,
315: .fs_refresh = finsio_refresh_volt,
316: .fs_rfact = FRFACT(47, 100)
317: },
318: {
319: .fs_desc = "VIN4",
320: .fs_type = ENVSYS_SVOLTS_DC,
321: .fs_aux = 0,
322: .fs_reg = 0x24,
323: .fs_refresh = finsio_refresh_volt,
324: .fs_rfact = FRFACT(200, 47)
325: },
326: {
327: .fs_desc = "VIN5",
328: .fs_type = ENVSYS_SVOLTS_DC,
329: .fs_aux = 0,
330: .fs_reg = 0x25,
331: .fs_refresh = finsio_refresh_volt,
332: .fs_rfact = FRFACT(200, 20)
333: },
334: {
335: .fs_desc = "VIN6",
336: .fs_type = ENVSYS_SVOLTS_DC,
337: .fs_aux = 0,
338: .fs_reg = 0x26,
339: .fs_refresh = finsio_refresh_volt,
340: .fs_rfact = FRFACT(100, 100)
341: },
342: {
343: .fs_desc = "VSB +3.3V",
344: .fs_type = ENVSYS_SVOLTS_DC,
345: .fs_aux = 0,
346: .fs_reg = 0x27,
347: .fs_refresh = finsio_refresh_volt,
348: .fs_rfact = FRFACT(200, 47)
349: },
350: {
351: .fs_desc = "VBAT",
352: .fs_type = ENVSYS_SVOLTS_DC,
353: .fs_aux = 0,
354: .fs_reg = 0x28,
355: .fs_refresh = finsio_refresh_volt,
356: .fs_rfact = FRFACT(200, 47)
357: },
358: /* Temperature */
359: {
360: .fs_desc = "Temp1",
361: .fs_type = ENVSYS_STEMP,
362: .fs_aux = 0x1,
363: .fs_reg = 0x72,
364: .fs_refresh = finsio_refresh_temp,
365: .fs_rfact = 0
366: },
367: {
368: .fs_desc = "Temp2",
369: .fs_type = ENVSYS_STEMP,
370: .fs_aux = 0x2,
371: .fs_reg = 0x74,
372: .fs_refresh = finsio_refresh_temp,
373: .fs_rfact = 0
374: },
375: {
376: .fs_desc = "Temp3",
377: .fs_type = ENVSYS_STEMP,
378: .fs_aux = 0x4,
379: .fs_reg = 0x76,
380: .fs_refresh = finsio_refresh_temp,
381: .fs_rfact = 0
382: },
383: /* Fan */
384: {
385: .fs_desc = "Fan1",
386: .fs_type = ENVSYS_SFANRPM,
387: .fs_aux = 0,
388: .fs_reg = 0xa0,
389: .fs_refresh = finsio_refresh_fanrpm,
390: .fs_rfact = 0
391: },
392: {
393: .fs_desc = "Fan2",
394: .fs_type = ENVSYS_SFANRPM,
395: .fs_aux = 0,
396: .fs_reg = 0xb0,
397: .fs_refresh = finsio_refresh_fanrpm,
398: .fs_rfact = 0
399: },
400: {
401: .fs_desc = "Fan3",
402: .fs_type = ENVSYS_SFANRPM,
403: .fs_aux = 0,
404: .fs_reg = 0xc0,
405: .fs_refresh = finsio_refresh_fanrpm,
406: .fs_rfact = 0
407: },
408: {
409: .fs_desc = "Fan4",
410: .fs_type = ENVSYS_SFANRPM,
411: .fs_aux = 0,
412: .fs_reg = 0xd0,
413: .fs_refresh = finsio_refresh_fanrpm,
414: .fs_rfact = 0
415: },
416:
417: { .fs_desc = NULL }
418: };
1.6 jmcneill 419:
1.1 xtraeme 420: static int
421: finsio_isa_match(device_t parent, cfdata_t match, void *aux)
422: {
423: struct isa_attach_args *ia = aux;
424: bus_space_handle_t ioh;
425: uint16_t val;
426:
427: /* Must supply an address */
428: if (ia->ia_nio < 1)
429: return 0;
430:
431: if (ISA_DIRECT_CONFIG(ia))
432: return 0;
433:
434: if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
435: return 0;
436:
437: if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh))
438: return 0;
439:
440: finsio_enter(ia->ia_iot, ioh);
441: /* Find out Manufacturer ID */
442: val = finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF) << 8;
443: val |= finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF + 1);
444: finsio_exit(ia->ia_iot, ioh);
445: bus_space_unmap(ia->ia_iot, ioh, 2);
446:
447: if (val != FINTEK_ID)
448: return 0;
449:
450: ia->ia_nio = 1;
451: ia->ia_io[0].ir_size = 2;
452: ia->ia_niomem = 0;
453: ia->ia_nirq = 0;
454: ia->ia_ndrq = 0;
455:
456: return 1;
457: }
458:
459: static void
460: finsio_isa_attach(device_t parent, device_t self, void *aux)
461: {
462: struct finsio_softc *sc = device_private(self);
463: struct isa_attach_args *ia = aux;
464: bus_space_handle_t ioh;
465: uint16_t hwmon_baddr, chipid, cr;
466: int i, rv = 0;
467:
468: aprint_naive("\n");
469:
470: sc->sc_iot = ia->ia_iot;
471:
472: /* Map Super I/O configuration space */
473: if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) {
474: aprint_error(": can't map configuration I/O space\n");
475: return;
476: }
477:
478: finsio_enter(sc->sc_iot, ioh);
479: /* Get the Chip ID */
480: chipid = finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP) << 8;
481: chipid |= finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP + 1);
482: /*
483: * Select the Hardware Monitor LDN to find out the I/O
484: * address space.
485: */
486: finsio_writereg(sc->sc_iot, ioh, FINSIO_FUNC_SEL, FINSIO_FUNC_HWMON);
487: hwmon_baddr = finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR) << 8;
488: hwmon_baddr |= finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR + 1);
489: finsio_exit(sc->sc_iot, ioh);
490: bus_space_unmap(sc->sc_iot, ioh, 2);
491:
1.7 jakllsch 492: /*
493: * The address decoder ignores the bottom 3 bits, so do we.
494: */
495: hwmon_baddr &= ~FINSIO_DECODE_MASK;
496:
1.1 xtraeme 497: switch (chipid) {
498: case FINSIO_IDF71805:
499: sc->sc_finsio_sensors = f71805_sensors;
500: aprint_normal(": Fintek F71805 Super I/O\n");
501: break;
502: case FINSIO_IDF71806:
503: sc->sc_finsio_sensors = f71805_sensors;
504: aprint_normal(": Fintek F71806/F71872 Super I/O\n");
505: break;
506: case FINSIO_IDF71862:
507: sc->sc_finsio_sensors = f71883_sensors;
508: aprint_normal(": Fintek F71862 Super I/O\n");
509: break;
510: case FINSIO_IDF71883:
511: sc->sc_finsio_sensors = f71883_sensors;
512: aprint_normal(": Fintek F71882/F71883 Super I/O\n");
513: break;
1.6 jmcneill 514: case FINSIO_IDF8000:
515: sc->sc_finsio_sensors = f71883_sensors;
516: aprint_normal(": ASUS F8000 Super I/O\n");
517: break;
1.1 xtraeme 518: default:
519: /*
520: * Unknown Chip ID, assume the same register layout
521: * than F71805 for now.
522: */
523: sc->sc_finsio_sensors = f71805_sensors;
524: aprint_normal(": Fintek Super I/O (unknown chip ID %x)\n",
525: chipid);
526: break;
527: }
528:
529: /* Map Hardware Monitor I/O space */
1.7 jakllsch 530: if (bus_space_map(sc->sc_iot, hwmon_baddr, FINSIO_DECODE_SIZE,
531: 0, &sc->sc_ioh)) {
1.1 xtraeme 532: aprint_error(": can't map hwmon I/O space\n");
533: return;
534: }
535:
536: /*
537: * Enable Hardware monitoring for fan/temperature and
538: * voltage sensors.
539: */
540: cr = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF);
541: finsio_writereg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF, cr | 0x3);
542:
543: /* Find out the temperature mode */
544: sc->sc_tempsel = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_TMODE);
545:
546: /*
547: * Initialize and attach sensors with sysmon_envsys(9).
548: */
549: sc->sc_sme = sysmon_envsys_create();
550: for (i = 0; sc->sc_finsio_sensors[i].fs_desc; i++) {
1.5 pgoyette 551: sc->sc_sensor[i].state = ENVSYS_SINVALID;
1.1 xtraeme 552: sc->sc_sensor[i].units = sc->sc_finsio_sensors[i].fs_type;
1.4 xtraeme 553: if (sc->sc_sensor[i].units == ENVSYS_SVOLTS_DC)
554: sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT;
1.1 xtraeme 555: strlcpy(sc->sc_sensor[i].desc, sc->sc_finsio_sensors[i].fs_desc,
556: sizeof(sc->sc_sensor[i].desc));
557: if (sysmon_envsys_sensor_attach(sc->sc_sme,
558: &sc->sc_sensor[i]))
559: goto fail;
560: }
561:
562: sc->sc_sme->sme_name = device_xname(self);
563: sc->sc_sme->sme_cookie = sc;
564: sc->sc_sme->sme_refresh = finsio_refresh;
565: if ((rv = sysmon_envsys_register(sc->sc_sme))) {
566: aprint_error(": unable to register with sysmon (%d)\n", rv);
567: goto fail;
568: }
569:
570: aprint_normal_dev(self,
571: "Hardware Monitor registers at 0x%x\n", hwmon_baddr);
572: return;
573:
574: fail:
575: sysmon_envsys_destroy(sc->sc_sme);
1.7 jakllsch 576: bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE);
1.1 xtraeme 577: }
578:
1.3 xtraeme 579: static int
580: finsio_isa_detach(device_t self, int flags)
581: {
582: struct finsio_softc *sc = device_private(self);
583:
584: sysmon_envsys_unregister(sc->sc_sme);
1.7 jakllsch 585: bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE);
1.3 xtraeme 586: return 0;
587: }
588:
1.1 xtraeme 589: /* Enter Super I/O configuration mode */
590: static void
591: finsio_enter(bus_space_tag_t iot, bus_space_handle_t ioh)
592: {
593: bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK);
594: bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK);
595: }
596:
597: /* Exit Super I/O configuration mode */
598: static void
599: finsio_exit(bus_space_tag_t iot, bus_space_handle_t ioh)
600: {
601: bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_LOCK);
602: }
603:
604: static uint8_t
605: finsio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
606: {
607: bus_space_write_1(iot, ioh, FINSIO_ADDR, reg);
608: return bus_space_read_1(iot, ioh, FINSIO_DATA);
609: }
610:
611: static void
612: finsio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val)
613: {
614: bus_space_write_1(iot, ioh, FINSIO_ADDR, reg);
615: bus_space_write_1(iot, ioh, FINSIO_DATA, val);
616: }
617:
618: static void
619: finsio_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
620: {
621: struct finsio_softc *sc = sme->sme_cookie;
622: int i = edata->sensor;
623:
624: sc->sc_finsio_sensors[i].fs_refresh(sc, edata);
625: }
626:
627: static void
628: finsio_refresh_volt(struct finsio_softc *sc, envsys_data_t *edata)
629: {
630: struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor];
631: int data;
632:
633: data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg);
634: DPRINTF(("%s: data 0x%x\n", __func__, data));
635:
636: if (data == 0xff || data == 0)
637: edata->state = ENVSYS_SINVALID;
638: else {
639: edata->state = ENVSYS_SVALID;
1.4 xtraeme 640: if (edata->rfact)
641: edata->value_cur = data * edata->rfact;
642: else
643: edata->value_cur = data * fs->fs_rfact;
1.1 xtraeme 644: }
645: }
646:
647: /* The BIOS seems to add a fudge factor to the CPU temp of +5C */
648: static void
649: finsio_refresh_temp(struct finsio_softc *sc, envsys_data_t *edata)
650: {
651: struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor];
652: u_int data;
653: u_int llmax;
654:
655: /*
656: * The data sheet says that the range of the temperature
657: * sensor is between 0 and 127 or 140 degrees C depending on
658: * what kind of sensor is used.
659: * A disconnected sensor seems to read over 110 or so.
660: */
661: data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) & 0xFF;
662: DPRINTF(("%s: data 0x%x\n", __func__, data));
663:
664: llmax = (sc->sc_tempsel & fs->fs_aux) ? 111 : 128;
665: if (data == 0 || data >= llmax) /* disconnected? */
666: edata->state = ENVSYS_SINVALID;
667: else {
668: edata->state = ENVSYS_SVALID;
669: edata->value_cur = data * 1000000 + 273150000;
670: }
671: }
672:
673: /* fan speed appears to be a 12-bit number */
674: static void
675: finsio_refresh_fanrpm(struct finsio_softc *sc, envsys_data_t *edata)
676: {
677: struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor];
678: int data;
679:
680: data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) << 8;
681: data |= finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg + 1);
682: DPRINTF(("%s: data 0x%x\n", __func__, data));
683:
684: if (data >= 0xfff)
685: edata->state = ENVSYS_SINVALID;
686: else {
687: edata->value_cur = 1500000 / data;
688: edata->state = ENVSYS_SVALID;
689: }
690: }
1.6 jmcneill 691:
1.7.12.1! jdolecek 692: MODULE(MODULE_CLASS_DRIVER, finsio, "sysmon_envsys");
1.6 jmcneill 693:
694: #ifdef _MODULE
695: #include "ioconf.c"
696: #endif
697:
698: static int
699: finsio_modcmd(modcmd_t cmd, void *opaque)
700: {
701: int error = 0;
702:
703: switch (cmd) {
704: case MODULE_CMD_INIT:
705: #ifdef _MODULE
706: error = config_init_component(cfdriver_ioconf_finsio,
707: cfattach_ioconf_finsio, cfdata_ioconf_finsio);
708: #endif
709: return error;
710: case MODULE_CMD_FINI:
711: #ifdef _MODULE
712: error = config_fini_component(cfdriver_ioconf_finsio,
713: cfattach_ioconf_finsio, cfdata_ioconf_finsio);
714: #endif
715: return error;
716: default:
717: return ENOTTY;
718: }
719: }
CVSweb <webmaster@jp.NetBSD.org>