diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-09-04 20:19:25 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-09-04 20:19:25 +0000 |
commit | d634e3d96597a69b532b1fcabc08cdf3432dacb2 (patch) | |
tree | 63b1eb07a4210fcf1c19771251e66993fbb05261 | |
parent | 2576f1816448a9ac2c0fc40dcca15d4dc48bc823 (diff) |
driver for i2c lm93 sensor; very common on ipmi machines which have i2c
bmc's watching on the shared bus. if you disable ipmi, you might see it
pop up (reminder why ipmi / i2c mixes are disabled: some ipmi's seem to
violate the i2c bus locking protocol). tested by Alexander Lobodzinski
-rw-r--r-- | share/man/man4/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/lmn.4 | 45 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/i386/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/dev/i2c/files.i2c | 7 | ||||
-rw-r--r-- | sys/dev/i2c/lm93.c | 248 |
6 files changed, 305 insertions, 5 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 999aaa5fa0f..f38d6cb0134 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.423 2007/08/14 18:54:39 reyk Exp $ +# $OpenBSD: Makefile,v 1.424 2007/09/04 20:19:24 deraadt Exp $ MAN= aac.4 ac97.4 acphy.4 \ acpi.4 acpiac.4 acpibat.4 acpibtn.4 acpicpu.4 acpidock.4 \ @@ -26,7 +26,7 @@ MAN= aac.4 ac97.4 acphy.4 \ isa.4 isagpio.4 isapnp.4 ises.4 isp.4 it.4 iwi.4 ixgb.4 \ jmb.4 \ ksyms.4 kue.4 lc.4 lge.4 lkm.4 lm.4 \ - lmc.4 lmenv.4 lmtemp.4 lo.4 lofn.4 lpt.4 lxtphy.4 luphy.4 \ + lmc.4 lmenv.4 lmn.4 lmtemp.4 lo.4 lofn.4 lpt.4 lxtphy.4 luphy.4 \ maestro.4 mainbus.4 malo.4 maxds.4 maxtmp.4 mbg.4 midi.4 mii.4 mfi.4 \ moscom.4 mpi.4 mpu.4 msk.4 mtd.4 mtdphy.4 multicast.4 mtio.4 myx.4 \ ne.4 neo.4 netintro.4 nfe.4 nge.4 nmea.4 noct.4 nofn.4 nsclpcsio.4 \ diff --git a/share/man/man4/lmn.4 b/share/man/man4/lmn.4 new file mode 100644 index 00000000000..c19aa21662c --- /dev/null +++ b/share/man/man4/lmn.4 @@ -0,0 +1,45 @@ +.\" $OpenBSD: lmn.4,v 1.1 2007/09/04 20:19:24 deraadt Exp $ +.\" +.\" Copyright (c) 2005 Theo de Raadt <deraadt@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: September 4 2007 $ +.Dt LMN 4 +.Os +.Sh NAME +.Nm lmn +.Nd National Semiconductor LM93 temperature, voltage, and fan sensor +.Sh SYNOPSIS +.Cd "lmn* at iic?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the National Semiconductor LM93 +sensors. +The sensor possesses a collection of sensor values which are +made available through the +.Xr sysctl 8 +interface. +.Sh SEE ALSO +.Xr iic 4 , +.Xr intro 4 , +.Xr sensorsd 8 , +.Xr sysctl 8 +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Theo de Raadt Aq deraadt@openbsd.org . + diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index d5c81a029be..60eff4a96ca 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.191 2007/08/05 17:01:25 mglocker Exp $ +# $OpenBSD: GENERIC,v 1.192 2007/09/04 20:19:24 deraadt Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -101,6 +101,7 @@ adt* at iic? # Analog Devices ADT7460 lm* at iic? # LM78/79 and clones lmenv* at iic? # National Semiconductor LM87 lmtemp* at iic? # NS LM75/LM77 temperature sensor +lmn* at iic? # NS LM93 maxds* at iic? # Maxim DS1631 maxtmp* at iic? # Maxim MAX6642/MAX6690 diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index 7ab27931836..52cc755f2f8 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.569 2007/08/31 16:27:23 marco Exp $ +# $OpenBSD: GENERIC,v 1.570 2007/09/04 20:19:24 deraadt Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -139,6 +139,7 @@ adt* at iic? # Analog Devices ADT7460 lm* at iic? # LM78/79 and clones lmenv* at iic? # National Semiconductor LM87 lmtemp* at iic? # NS LM75/LM77 temperature sensor +lmn* at iic? # NS LM93 maxds* at iic? # Maxim DS1631/1624/1721 maxtmp* at iic? # Maxim MAX6642/MAX6690 asbtm* at iic? # Asus ASB100 diff --git a/sys/dev/i2c/files.i2c b/sys/dev/i2c/files.i2c index bb08971affb..11295d7ffc6 100644 --- a/sys/dev/i2c/files.i2c +++ b/sys/dev/i2c/files.i2c @@ -1,4 +1,4 @@ -# $OpenBSD: files.i2c,v 1.36 2006/06/17 04:43:01 drahn Exp $ +# $OpenBSD: files.i2c,v 1.37 2007/09/04 20:19:22 deraadt Exp $ # $NetBSD: files.i2c,v 1.3 2003/10/20 16:24:10 briggs Exp $ define i2c {[addr = -1], [size = -1]} @@ -19,6 +19,11 @@ device lmtemp attach lmtemp at i2c file dev/i2c/lm75.c lmtemp +# National Semiconductor LM93 sensor +device lmn +attach lmn at i2c +file dev/i2c/lm93.c lmn + # National Semiconductor LM87 sensor device lmenv attach lmenv at i2c diff --git a/sys/dev/i2c/lm93.c b/sys/dev/i2c/lm93.c new file mode 100644 index 00000000000..30e7d3da7a9 --- /dev/null +++ b/sys/dev/i2c/lm93.c @@ -0,0 +1,248 @@ +/* $OpenBSD: lm93.c,v 1.1 2007/09/04 20:19:22 deraadt Exp $ */ + +/* + * Copyright (c) 2005 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/sensors.h> + +#include <dev/i2c/i2cvar.h> + +/* + * iic0: addr 0x2e + * 3e=01 3f=73 50=26 51=28 52=16 54=25 55=27 56=c4 57=c3 58=c1 59=bf 5a=bf + * 5b=bf 5c=d1 5d=d3 5e=c3 5f=c3 60=8c 61=fa 62=f6 63=bd 64=31 65=c4 6b=09 + * 6e=04 6f=03 70=d4 71=03 72=88 73=03 74=fc 78=80 79=80 7a=80 7b=80 7c=80 + * 7d=32 7e=80 7f=80 80=50 81=50 82=7f 83=7f 90=ac 91=d3 92=ac 93=d3 94=ac + * 95=d3 96=ac 97=d3 98=ac 99=d3 9a=ac 9b=d3 9c=a3 9d=f6 9e=a3 9f=f6 a0=ac + * a1=d3 a2=ac a3=d3 a4=ac a5=d3 a6=ac a7=d3 a8=ac a9=d3 aa=ac ab=d3 ac=0f + * ad=70 ae=ac af=d3 b2=17 b3=17 b4=a0 b5=1d b6=a0 b7=1d b8=a0 b9=1d ba=fc + * c0=55 c1=44 c3=3a c7=11 c8=0c c9=02 cc=03 cd=30 d0=37 d1=37 d2=7f d3=7f + * d6=0a db=0a e3=81 e4=02 e6=0f e8=08 e9=07 eb=07 ed=3f f0=91 f1=91 f2=08 + * f3=08 f4=06 f5=10 f6=04 f7=08 f8=0c f9=20 fa=08 fb=08 fc=10 fd=09 fe=91 + * ff=09 +*/ + +/* LM93 registers */ +#define LM93_CPU1_TEMP 0x50 +#define LM93_CPU2_TEMP 0x51 +#define LM93_INT_TEMP 0x52 +#define LM93_EXT_TEMP 0x53 +#define LM93_IN1_V 0x56 +#define LM93_IN2_V 0x57 +#define LM93_IN3_V 0x58 +#define LM93_IN4_V 0x59 +#define LM93_IN5_V 0x5a +#define LM93_IN6_V 0x5b +#define LM93_IN7_V 0x5c +#define LM93_IN8_V 0x5d +#define LM93_IN9_V 0x5e +#define LM93_IN10_V 0x5f +#define LM93_IN11_V 0x60 +#define LM93_IN12_V 0x61 +#define LM93_IN13_V 0x62 +#define LM93_IN14_V 0x63 +#define LM93_IN15_V 0x64 +#define LM93_IN16_V 0x65 +#define LM93_TACH1L 0x6e +#define LM93_TACH1H 0x6f +#define LM93_TACH2L 0x70 +#define LM93_TACH2H 0x71 +#define LM93_TACH3L 0x72 +#define LM93_TACH3H 0x73 +#define LM93_TACH4L 0x74 +#define LM93_TACH4H 0x75 +#define LM93_REVISION 0x3f + +/* Sensors */ +#define LMN_CPU1_TEMP 0 +#define LMN_CPU2_TEMP 1 +#define LMN_INT_TEMP 2 +#define LMN_EXT_TEMP 3 +#define LMN_IN1_V 4 +#define LMN_IN2_V 5 +#define LMN_IN3_V 6 +#define LMN_IN4_V 7 +#define LMN_IN5_V 8 +#define LMN_IN6_V 9 +#define LMN_IN7_V 10 +#define LMN_IN8_V 11 +#define LMN_IN9_V 12 +#define LMN_IN10_V 13 +#define LMN_IN11_V 14 +#define LMN_IN12_V 15 +#define LMN_IN13_V 16 +#define LMN_IN14_V 17 +#define LMN_IN15_V 18 +#define LMN_IN16_V 19 +#define LMN_TACH1 20 +#define LMN_TACH2 21 +#define LMN_TACH3 22 +#define LMN_TACH4 23 +#define LMN_NUM_SENSORS 24 + +struct { + char sensor; + u_int8_t cmd; + char *name; + u_short mVscale; + u_short tempscale; /* else a fan */ +} lmn_worklist[] = { + { LMN_CPU1_TEMP, LM93_CPU1_TEMP, "CPU1", 0, 1 }, + { LMN_CPU2_TEMP, LM93_CPU2_TEMP, "CPU2", 0, 1 }, + { LMN_INT_TEMP, LM93_INT_TEMP, "Internal", 0, 1 }, + { LMN_EXT_TEMP, LM93_EXT_TEMP, "External", 0, 1 }, + + { LMN_IN1_V, LM93_IN1_V, "+12V1", 1236*10, 0 }, + { LMN_IN2_V, LM93_IN2_V, "+12V2", 1236*10, 0 }, + { LMN_IN3_V, LM93_IN3_V, "+12V3", 1236*10, 0 }, + { LMN_IN4_V, LM93_IN4_V, "FSB_Vtt 1.6V", 1600, 0 }, + { LMN_IN5_V, LM93_IN5_V, "3GIO 2V ", 2000, 0 }, + { LMN_IN6_V, LM93_IN6_V, "ICH_Core 2V", 2000, 0 }, + { LMN_IN7_V, LM93_IN7_V, "Vccp1 1.6V", 1600, 0,}, + { LMN_IN8_V, LM93_IN8_V, "Vccp2 1.6V", 1600, 0 }, + { LMN_IN9_V, LM93_IN9_V, "+3.3V", 4400, 0 }, + { LMN_IN10_V, LM93_IN10_V, "+5V", 6667, 0 }, + { LMN_IN11_V, LM93_IN11_V, "SCSI_Core 3.3V", 3333, 0 }, + { LMN_IN12_V, LM93_IN12_V, "Mem_Core 2.6V", 2625, 0 }, + { LMN_IN13_V, LM93_IN13_V, "Mem_Vtt 1.3V", 1312, 0 }, + { LMN_IN14_V, LM93_IN14_V, "Gbit_Core 1.3V", 1312, 0 }, + { LMN_IN15_V, LM93_IN15_V, "-12V", 1236*10, 0 }, + { LMN_IN16_V, LM93_IN16_V, "+3.3V S/B", 3600, 0 }, + + { LMN_TACH1, LM93_TACH1L, "tach1", 0, 0 }, + { LMN_TACH2, LM93_TACH2L, "tach2", 0, 0 }, + { LMN_TACH3, LM93_TACH3L, "tach3", 0, 0 }, + { LMN_TACH4, LM93_TACH4L, "tach4", 0, 0 } +}; + +struct lmn_softc { + struct device sc_dev; + i2c_tag_t sc_tag; + i2c_addr_t sc_addr; + u_int8_t sc_conf; + + struct ksensor sc_sensor[LMN_NUM_SENSORS]; + struct ksensordev sc_sensordev; +}; + +int lmn_match(struct device *, void *, void *); +void lmn_attach(struct device *, struct device *, void *); + +void lmn_refresh(void *); + +struct cfattach lmn_ca = { + sizeof(struct lmn_softc), lmn_match, lmn_attach +}; + +struct cfdriver lmn_cd = { + NULL, "lmn", DV_DULL +}; + +int +lmn_match(struct device *parent, void *match, void *aux) +{ + return (1); +} + +void +lmn_attach(struct device *parent, struct device *self, void *aux) +{ + struct lmn_softc *sc = (struct lmn_softc *)self; + struct i2c_attach_args *ia = aux; + int i; + + sc->sc_tag = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + printf(": %s", ia->ia_name); + + /* Initialize sensor data. */ + strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensordev.xname)); + + if (sensor_task_register(sc, lmn_refresh, 5) == NULL) { + printf(", unable to register update task\n"); + return; + } + + for (i = 0; i < LMN_NUM_SENSORS; i++) { + if (lmn_worklist[i].tempscale) + sc->sc_sensor[i].type = SENSOR_TEMP; + else if (lmn_worklist[i].mVscale) + sc->sc_sensor[i].type = SENSOR_VOLTS_DC; + else + sc->sc_sensor[i].type = SENSOR_FANRPM; + strlcpy(sc->sc_sensor[i].desc, lmn_worklist[i].name, + sizeof(sc->sc_sensor[i].desc)); + + sc->sc_sensor[i].flags &= ~SENSOR_FINVALID; + sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); + } + sensordev_install(&sc->sc_sensordev); + + printf("\n"); +} + +void +lmn_refresh(void *arg) +{ + struct lmn_softc *sc = arg; + u_int8_t cmd, data, data2; + u_int16_t fan; + int i; + + iic_acquire_bus(sc->sc_tag, 0); + + for (i = 0; i < sizeof lmn_worklist / sizeof(lmn_worklist[0]); i++) { + + cmd = lmn_worklist[i].cmd; + if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + continue; + } + + sc->sc_sensor[i].flags &= ~SENSOR_FINVALID; + if (lmn_worklist[i].tempscale) { + if (data == 0x80) + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + else + sc->sc_sensor[i].value = + (int8_t)data * 1000000 + 273150000; + } else if (lmn_worklist[i].mVscale) { + sc->sc_sensor[i].value = lmn_worklist[i].mVscale * + 1000 * (u_int)data / 192; + } else { + cmd = lmn_worklist[i].cmd + 1; /* TACHnH follows TACHnL */ + if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + continue; + } + + fan = data + (data2 << 8); + if (fan == 0 || fan == 0xffff) + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + else + sc->sc_sensor[i].value = (90000 * 60) / fan; + } + } + + iic_release_bus(sc->sc_tag, 0); +} |