diff options
-rw-r--r-- | sys/dev/isa/files.isa | 7 | ||||
-rw-r--r-- | sys/dev/isa/it.c | 349 | ||||
-rw-r--r-- | sys/dev/isa/itvar.h | 91 |
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 |