summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2003-05-20 20:26:28 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2003-05-20 20:26:28 +0000
commit265ee732c9164c9129bb636476b6071a07330f83 (patch)
tree160fe6410bf7b70bd97f5a2e9097e8c7978dbb02 /sys
parentb5fc8133df17f0f824497e5ffe0bec3b03009571 (diff)
it(4) driver provides support for ITE IT8705F, IT8712F and SiS SiS950
hardware monitoring chips to be used with hw.sensors sysctl interface. Work by Julien Bordet <zejames@greyhats.org> with my little help.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/isa/files.isa7
-rw-r--r--sys/dev/isa/it.c349
-rw-r--r--sys/dev/isa/itvar.h91
3 files changed, 446 insertions, 1 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index f72f71bd10d..46f637d2368 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.83 2003/04/25 21:24:15 grange Exp $
+# $OpenBSD: files.isa,v 1.84 2003/05/20 20:26:27 grange Exp $
# $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $
#
# Config file and device description for machine-independent ISA code.
@@ -388,6 +388,11 @@ file dev/isa/lpt_isa.c lpt_isa needs-flag
attach lm at isa with lm_isa
file dev/isa/lm_isa.c lm_isa
+# IT8705F, IT8712F and SiS970 hardware monitors
+device it
+attach it at isa
+file dev/isa/it.c it
+
#
# PCMCIA PCIC (i82365SL and compatibles):
#
diff --git a/sys/dev/isa/it.c b/sys/dev/isa/it.c
new file mode 100644
index 00000000000..f78930744ce
--- /dev/null
+++ b/sys/dev/isa/it.c
@@ -0,0 +1,349 @@
+/* $OpenBSD: it.c,v 1.1 2003/05/20 20:26:27 grange Exp $ */
+
+/*
+ * Copyright (c) 2003 Julien Bordet <zejames@greygats.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/sensors.h>
+#include <sys/timeout.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <dev/isa/itvar.h>
+
+#if defined(ITDEBUG)
+#define DPRINTF(x) do { printf x; } while (0)
+#else
+#define DPRINTF(x)
+#endif
+
+int it_match(struct device *, void *, void *);
+void it_attach(struct device *, struct device *, void *);
+u_int8_t it_readreg(struct it_softc *, int);
+void it_writereg(struct it_softc *, int, int);
+void it_setup_volt(struct it_softc *, int, int);
+void it_setup_temp(struct it_softc *, int, int);
+void it_setup_fan(struct it_softc *, int, int);
+
+void it_generic_stemp(struct it_softc *, struct sensor *);
+void it_generic_svolt(struct it_softc *, struct sensor *);
+void it_generic_fanrpm(struct it_softc *, struct sensor *);
+
+void it_refresh_sensor_data(struct it_softc *);
+void it_refresh(void *);
+
+struct cfattach it_ca = {
+ sizeof(struct it_softc),
+ it_match,
+ it_attach
+};
+
+struct cfdriver it_cd = {
+ NULL, "it", DV_DULL
+};
+
+struct timeout it_timeout;
+
+int
+it_match(struct device *parent, void *match, void *aux)
+{
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ struct isa_attach_args *ia = aux;
+ int iobase;
+ int rv;
+ u_int8_t cr;
+
+ /* Must supply an address */
+ if (ia->ipa_nio < 1)
+ return (0);
+
+ iot = ia->ia_iot;
+ iobase = ia->ipa_io[0].base;
+
+ if (bus_space_map(iot, iobase, 8, 0, &ioh))
+ return (0);
+
+ /* Check for some power-on defaults */
+ bus_space_write_1(iot, ioh, ITC_ADDR, ITD_CONFIG);
+ cr = bus_space_read_1(iot, ioh, ITC_DATA);
+
+ /* The monitoring may have been enabled by BIOS */
+ if (cr == 0x18 || cr == 0x19)
+ rv = 1;
+
+ DPRINTF(("it: rv = %d, cr = %x\n", rv, cr));
+
+ bus_space_unmap(iot, ioh, 8);
+
+ if (rv) {
+ ia->ipa_nio = 1;
+ ia->ipa_io[0].length = 8;
+
+ ia->ipa_nmem = 0;
+ ia->ipa_nirq = 0;
+ ia->ipa_ndrq = 0;
+ }
+
+ return (rv);
+}
+
+void
+it_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct it_softc *sc = (void *)self;
+ int iobase;
+ bus_space_tag_t iot;
+ struct isa_attach_args *ia = aux;
+ int i;
+ u_int8_t cr;
+ extern int nsensors;
+ extern struct sensors_head sensors;
+
+ iobase = ia->ipa_io[0].base;
+ iot = sc->it_iot = ia->ia_iot;
+
+ if (bus_space_map(iot, iobase, 8, 0, &sc->it_ioh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ i = it_readreg(sc, ITD_CHIPID);
+ switch (i) {
+ case IT_ID_IT87:
+ printf(": IT87\n");
+ break;
+ default:
+ printf(": unknown chip (ID %d)\n", i);
+ break;
+ }
+
+ sc->numsensors = IT_NUM_SENSORS;
+
+ /* Reset chip */
+ it_writereg(sc, ITD_CONFIG, 0x80);
+
+ it_setup_fan(sc, 0, 3);
+ it_setup_volt(sc, 3, 9);
+ it_setup_temp(sc, 12, 3);
+
+ /* Activate monitoring */
+ cr = it_readreg(sc, ITD_CONFIG);
+ cr |= 0x01 | 0x08;
+ it_writereg(sc, ITD_CONFIG, cr);
+
+ /* Initialize sensors */
+ for (i = 0; i < sc->numsensors; ++i) {
+ strlcpy(sc->sensors[i].device, sc->sc_dev.dv_xname,
+ sizeof(sc->sensors[i].device));
+ sc->sensors[i].num = nsensors++;
+ SLIST_INSERT_HEAD(&sensors, &sc->sensors[i], list);
+ }
+
+ timeout_set(&it_timeout, it_refresh, sc);
+ timeout_add(&it_timeout, (15 * hz) / 10);
+}
+
+u_int8_t
+it_readreg(struct it_softc *sc, int reg)
+{
+ bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
+ return (bus_space_read_1(sc->it_iot, sc->it_ioh, ITC_DATA));
+}
+
+void
+it_writereg(struct it_softc *sc, int reg, int val)
+{
+ bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
+ bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_DATA, val);
+}
+
+void
+it_setup_volt(struct it_softc *sc, int start, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ sc->sensors[start + i].type = SENSOR_VOLTS_DC;
+ }
+
+ sc->sensors[start + 0].rfact = 10000;
+ snprintf(sc->sensors[start + 0].desc, sizeof(sc->sensors[0].desc),
+ "VCORE_A");
+ sc->sensors[start + 1].rfact = 10000;
+ snprintf(sc->sensors[start + 1].desc, sizeof(sc->sensors[1].desc),
+ "VCORE_B");
+ sc->sensors[start + 2].rfact = 10000;
+ snprintf(sc->sensors[start + 2].desc, sizeof(sc->sensors[2].desc),
+ "+3.3V");
+ sc->sensors[start + 3].rfact = (int)(( 16.8 / 10) * 10000);
+ snprintf(sc->sensors[start + 3].desc, sizeof(sc->sensors[3].desc),
+ "+5V");
+ sc->sensors[start + 4].rfact = (int)(( 40 / 10) * 10000);
+ snprintf(sc->sensors[start + 4].desc, sizeof(sc->sensors[4].desc),
+ "+12V");
+ sc->sensors[start + 5].rfact = (int)(( 31.0 / 10) * 10000);
+ snprintf(sc->sensors[start + 5].desc, sizeof(sc->sensors[5].desc),
+ "Unused");
+ sc->sensors[start + 6].rfact = (int)(( 103.0 / 20) * 10000);
+ snprintf(sc->sensors[start + 6].desc, sizeof(sc->sensors[6].desc),
+ "-12V");
+ sc->sensors[start + 7].rfact = (int)(( 16.8 / 10) * 10000);
+ snprintf(sc->sensors[start + 7].desc, sizeof(sc->sensors[7].desc),
+ "+5VSB");
+ sc->sensors[start + 8].rfact = 10000;
+ snprintf(sc->sensors[start + 8].desc, sizeof(sc->sensors[8].desc),
+ "VBAT");
+
+ /* Enable voltage monitoring */
+ it_writereg(sc, ITD_VOLTENABLE, 0xff);
+}
+
+void
+it_setup_temp(struct it_softc *sc, int start, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ sc->sensors[start + i].type = SENSOR_TEMP;
+ snprintf(sc->sensors[start + i].desc,
+ sizeof(sc->sensors[start + i].desc),
+ "Temp%d", i + 1);
+ }
+
+ /* Enable temperature monitoring
+ * bits 7 and 8 are reserved, so we don't change them */
+ i = it_readreg(sc, ITD_TEMPENABLE) & 0xc0;
+ it_writereg(sc, ITD_TEMPENABLE, i | 0x38);
+}
+
+void
+it_setup_fan(struct it_softc *sc, int start, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ sc->sensors[start + i].type = SENSOR_FANRPM;
+ snprintf(sc->sensors[start + i].desc,
+ sizeof(sc->sensors[start + i].desc),
+ "Fan%d", i + 1);
+ }
+
+ /* Enable fan rpm monitoring
+ * bits 4 to 6 are the only interesting bits */
+ i = it_readreg(sc, ITD_FANENABLE) & 0x8f;
+ it_writereg(sc, ITD_FANENABLE, i | 0x70);
+}
+
+void
+it_generic_stemp(struct it_softc *sc, struct sensor *sensors)
+{
+ int i, sdata;
+
+ for (i = 0; i < 3; i++) {
+ sdata = it_readreg(sc, ITD_SENSORTEMPBASE + i);
+ /* Convert temperature to Fahrenheit degres */
+ sensors[i].value = sdata * 1000000 + 273150000;
+ }
+}
+
+void
+it_generic_svolt(struct it_softc *sc, struct sensor *sensors)
+{
+ int i, sdata;
+
+ for (i = 0; i < 9; i++) {
+ sdata = it_readreg(sc, ITD_SENSORVOLTBASE + i);
+ DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
+ /* voltage returned as (mV >> 4) */
+ sensors[i].value = (sdata << 4);
+ /* rfact is (factor * 10^4) */
+ sensors[i].value *= sensors[i].rfact;
+ /* these two values are negative and formula is different */
+ if (i == 5)
+ sensors[i].value -=
+ (int) (21.0 / 10 * IT_VREF * 10000);
+ if (i == 6)
+ sensors[i].value -=
+ (int) (83.0 / 20 * IT_VREF * 10000);
+ /* division by 10 gets us back to uVDC */
+ sensors[i].value /= 10;
+
+ }
+}
+
+void
+it_generic_fanrpm(struct it_softc *sc, struct sensor *sensors)
+{
+ int i, sdata, divisor;
+
+ for (i = 0; i < 2; i++) {
+ sdata = it_readreg(sc, ITD_SENSORFANBASE + i);
+ switch (i) {
+ case 2:
+ divisor = 2;
+ case 1:
+ divisor = (it_readreg(sc,
+ ITD_FAN) >> 3) & 0x7;
+ break;
+ default:
+ divisor = it_readreg(sc, ITD_FAN) & 0x7;
+ break;
+ }
+
+ if (sdata == 0xff || sdata == 0) {
+ sensors[i].value = 0;
+ } else {
+ sensors[i].value = 1350000 / (sdata << divisor);
+ }
+ }
+}
+
+/*
+ * pre: last read occurred >= 1.5 seconds ago
+ * post: sensors[] current data are the latest from the chip
+ */
+void
+it_refresh_sensor_data(struct it_softc *sc)
+{
+ /* Refresh our stored data for every sensor */
+ it_generic_stemp(sc, &sc->sensors[12]);
+ it_generic_svolt(sc, &sc->sensors[3]);
+ it_generic_fanrpm(sc, &sc->sensors[0]);
+}
+
+void
+it_refresh(void *arg)
+{
+ struct it_softc *sc = (struct it_softc *)arg;
+
+ it_refresh_sensor_data(sc);
+ timeout_add(&it_timeout, (15 * hz) / 10);
+}
diff --git a/sys/dev/isa/itvar.h b/sys/dev/isa/itvar.h
new file mode 100644
index 00000000000..573eadfa1b2
--- /dev/null
+++ b/sys/dev/isa/itvar.h
@@ -0,0 +1,91 @@
+/* $OpenBSD: itvar.h,v 1.1 2003/05/20 20:26:27 grange Exp $ */
+
+/*
+ * Copyright (c) 2003 Julien Bordet <zejames@greygats.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ISA_ITVAR_H
+#define _DEV_ISA_ITVAR_H
+
+#define IT_NUM_SENSORS 15
+
+/* chip ids */
+#define IT_ID_IT87 0x90
+
+/* ctl registers */
+
+#define ITC_ADDR 0x05
+#define ITC_DATA 0x06
+
+/* data registers */
+
+#define ITD_CONFIG 0x00
+#define ITD_ISR1 0x01
+#define ITD_ISR2 0x02
+#define ITD_ISR3 0x03
+#define ITD_SMI1 0x04
+#define ITD_SMI2 0x05
+#define ITD_SMI3 0x06
+#define ITD_IMR1 0x07
+#define ITD_IMR2 0x08
+#define ITD_IMR3 0x09
+#define ITD_VID 0x0a
+#define ITD_FAN 0x0b
+
+#define ITD_FANMINBASE 0x10
+#define ITD_FANENABLE 0x13
+
+#define ITD_SENSORFANBASE 0x0d /* Fan from 0x0d to 0x0f */
+#define ITD_SENSORVOLTBASE 0x20 /* Fan from 0x20 to 0x28 */
+#define ITD_SENSORTEMPBASE 0x29 /* Fan from 0x29 to 0x2b */
+
+#define ITD_VOLTMAXBASE 0x30
+#define ITD_VOLTMINBASE 0x31
+
+#define ITD_TEMPMAXBASE 0x40
+#define ITD_TEMPMINBASE 0x41
+
+#define ITD_SBUSADDR 0x48
+#define ITD_VOLTENABLE 0x50
+#define ITD_TEMPENABLE 0x51
+
+#define ITD_CHIPID 0x58
+
+#define IT_VREF (4096) /* Vref = 4.096 V */
+
+struct it_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t it_iot;
+ bus_space_handle_t it_ioh;
+
+ struct sensor sensors[IT_NUM_SENSORS];
+ u_int numsensors;
+ void (*refresh_sensor_data)(struct it_softc *);
+
+ u_int8_t (*it_readreg)(struct it_softc *, int);
+ void (*it_writereg)(struct it_softc *, int, int);
+};
+
+#endif