Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Support setting the temperature threshold for th...
details: https://anonhg.NetBSD.org/src/rev/7b67118b36e6
branches: trunk
changeset: 771099:7b67118b36e6
user: macallan <macallan%NetBSD.org@localhost>
date: Wed Nov 09 05:47:54 2011 +0000
description:
Support setting the temperature threshold for the LM75's alarm/interrupt
output. Some hardware ( I'm looking at you, Gdium ) abuses it to control
a fan.
diffstat:
sys/dev/i2c/lm75.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 99 insertions(+), 3 deletions(-)
diffs (171 lines):
diff -r 64e71e8b8df3 -r 7b67118b36e6 sys/dev/i2c/lm75.c
--- a/sys/dev/i2c/lm75.c Wed Nov 09 00:51:00 2011 +0000
+++ b/sys/dev/i2c/lm75.c Wed Nov 09 05:47:54 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lm75.c,v 1.22 2011/06/20 20:16:19 pgoyette Exp $ */
+/* $NetBSD: lm75.c,v 1.23 2011/11/09 05:47:54 macallan Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@@ -36,12 +36,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lm75.c,v 1.22 2011/06/20 20:16:19 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lm75.c,v 1.23 2011/11/09 05:47:54 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <dev/sysmon/sysmonvar.h>
@@ -49,11 +50,13 @@
#include <dev/i2c/lm75reg.h>
struct lmtemp_softc {
+ device_t sc_dev;
i2c_tag_t sc_tag;
int sc_address;
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensor;
+ int sc_tmax;
uint32_t (*sc_lmtemp_decode)(const uint8_t *);
};
@@ -67,10 +70,13 @@
static void lmtemp_refresh(struct sysmon_envsys *, envsys_data_t *);
static int lmtemp_config_write(struct lmtemp_softc *, uint8_t);
+static int lmtemp_temp_write(struct lmtemp_softc *, int, uint16_t);
static uint32_t lmtemp_decode_lm75(const uint8_t *);
static uint32_t lmtemp_decode_ds75(const uint8_t *);
static uint32_t lmtemp_decode_lm77(const uint8_t *);
+static void lmtemp_setup_sysctl(struct lmtemp_softc *);
+static int sysctl_lm75_temp(SYSCTLFN_ARGS);
static const char * lmtemp_compats[] = {
"i2c-lm75",
@@ -143,6 +149,7 @@
struct i2c_attach_args *ia = aux;
int i;
+ sc->sc_dev = self;
if (ia->ia_name == NULL) {
for (i = 0; lmtemptbl[i].lmtemp_type != -1 ; i++)
if (lmtemptbl[i].lmtemp_type ==
@@ -165,9 +172,17 @@
lmtemptbl[i].lmtemp_name);
}
+ /*
+ * according to the LM75 data sheet 80C is the default, so leave it
+ * there to avoid unexpected behaviour
+ */
+ sc->sc_tmax = 80;
+ if (i == lmtemp_lm75)
+ lmtemp_setup_sysctl(sc);
+
/* Set the configuration of the LM75 to defaults. */
iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
- if (lmtemp_config_write(sc, 0) != 0) {
+ if (lmtemp_config_write(sc, LM75_CONFIG_FAULT_QUEUE_4) != 0) {
aprint_error_dev(self, "unable to write config register\n");
iic_release_bus(sc->sc_tag, I2C_F_POLL);
return;
@@ -212,6 +227,19 @@
}
static int
+lmtemp_temp_write(struct lmtemp_softc *sc, int reg, uint16_t val)
+{
+ uint8_t cmdbuf[3];
+
+ cmdbuf[0] = reg;
+ cmdbuf[1] = (val >> 1) & 0xff;
+ cmdbuf[2] = (val & 1) << 7;
+
+ return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_address, cmdbuf, 1, &cmdbuf[1], 2, I2C_F_POLL);
+}
+
+static int
lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, uint32_t *valp)
{
int error;
@@ -316,3 +344,71 @@
return val;
}
+static void
+lmtemp_setup_sysctl(struct lmtemp_softc *sc)
+{
+ const struct sysctlnode *me = NULL, *node = NULL;
+
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT, (sc->sc_tmax - 5) * 2);
+ lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, sc->sc_tmax * 2);
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+
+ sysctl_createv(NULL, 0, NULL, &me,
+ CTLFLAG_READWRITE,
+ CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
+ NULL, 0, NULL, 0,
+ CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+
+ sysctl_createv(NULL, 0, NULL, &node,
+ CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
+ CTLTYPE_INT, "temp", "Threshold temperature",
+ sysctl_lm75_temp, 1, sc, 0,
+ CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
+}
+
+static int
+sysctl_lm75_temp(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node = *rnode;
+ struct lmtemp_softc *sc = node.sysctl_data;
+ int temp;
+
+ if (newp) {
+
+ /* we're asked to write */
+ node.sysctl_data = &sc->sc_tmax;
+ if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
+
+ temp = *(int *)node.sysctl_data;
+ sc->sc_tmax = temp;
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT,
+ (sc->sc_tmax - 5) * 2);
+ lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT,
+ sc->sc_tmax * 2);
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+ return 0;
+ }
+ return EINVAL;
+ } else {
+
+ node.sysctl_data = &sc->sc_tmax;
+ node.sysctl_size = 4;
+ return (sysctl_lookup(SYSCTLFN_CALL(&node)));
+ }
+
+ return 0;
+}
+
+SYSCTL_SETUP(sysctl_lmtemp_setup, "sysctl lmtemp subtree setup")
+{
+
+ sysctl_createv(NULL, 0, NULL, NULL,
+ CTLFLAG_PERMANENT,
+ CTLTYPE_NODE, "machdep", NULL,
+ NULL, 0, NULL, 0,
+ CTL_MACHDEP, CTL_EOL);
+}
+
+
Home |
Main Index |
Thread Index |
Old Index