Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Add display and setting of chip temperature limi...
details: https://anonhg.NetBSD.org/src/rev/af2d82130411
branches: trunk
changeset: 342653:af2d82130411
user: jdc <jdc%NetBSD.org@localhost>
date: Sun Jan 03 17:27:57 2016 +0000
description:
Add display and setting of chip temperature limit(s) for envsys(4).
diffstat:
sys/dev/i2c/lm75.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 201 insertions(+), 20 deletions(-)
diffs (truncated from 327 to 300 lines):
diff -r afdbaacbdc7b -r af2d82130411 sys/dev/i2c/lm75.c
--- a/sys/dev/i2c/lm75.c Sun Jan 03 17:27:39 2016 +0000
+++ b/sys/dev/i2c/lm75.c Sun Jan 03 17:27:57 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lm75.c,v 1.27 2016/01/01 20:13:50 jdc Exp $ */
+/* $NetBSD: lm75.c,v 1.28 2016/01/03 17:27:57 jdc Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lm75.c,v 1.27 2016/01/01 20:13:50 jdc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lm75.c,v 1.28 2016/01/03 17:27:57 jdc Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -57,8 +57,10 @@
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensor;
int sc_tmax;
+ uint32_t sc_smax, sc_smin, sc_scrit;
uint32_t (*sc_lmtemp_decode)(const uint8_t *, int);
+ void (*sc_lmtemp_encode)(const uint32_t, uint8_t *, int);
};
static int lmtemp_match(device_t, cfdata_t, void *);
@@ -68,14 +70,25 @@
lmtemp_match, lmtemp_attach, NULL, NULL);
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 int lmtemp_temp_write(struct lmtemp_softc *, uint8_t, uint32_t,
+ int);
static int lmtemp_temp_read(struct lmtemp_softc *, uint8_t, uint32_t *,
int);
static uint32_t lmtemp_decode_lm75(const uint8_t *, int);
static uint32_t lmtemp_decode_ds75(const uint8_t *, int);
static uint32_t lmtemp_decode_lm77(const uint8_t *, int);
+static void lmtemp_encode_lm75(const uint32_t, uint8_t *, int);
+static void lmtemp_encode_ds75(const uint32_t, uint8_t *, int);
+static void lmtemp_encode_lm77(const uint32_t, uint8_t *, int);
+static void lmtemp_getlim_lm75(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
+static void lmtemp_getlim_lm77(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
+static void lmtemp_setlim_lm75(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
+static void lmtemp_setlim_lm77(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
static void lmtemp_setup_sysctl(struct lmtemp_softc *);
static int sysctl_lm75_temp(SYSCTLFN_ARGS);
@@ -100,16 +113,24 @@
int lmtemp_addrmask;
int lmtemp_addr;
uint32_t (*lmtemp_decode)(const uint8_t *, int);
+ void (*lmtemp_encode)(const uint32_t, uint8_t *, int);
+ void (*lmtemp_getlim)(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
+ void (*lmtemp_setlim)(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *, uint32_t *);
} lmtemptbl[] = {
- { lmtemp_lm75, "LM75",
- LM75_ADDRMASK, LM75_ADDR, lmtemp_decode_lm75 },
- { lmtemp_ds75, "DS75",
- LM75_ADDRMASK, LM75_ADDR, lmtemp_decode_ds75 },
- { lmtemp_lm77, "LM77",
- LM77_ADDRMASK, LM77_ADDR, lmtemp_decode_lm77 },
-
- { -1, NULL,
- 0, 0, NULL }
+ { lmtemp_lm75, "LM75", LM75_ADDRMASK, LM75_ADDR,
+ lmtemp_decode_lm75, lmtemp_encode_lm75,
+ lmtemp_getlim_lm75, lmtemp_setlim_lm75 },
+ { lmtemp_ds75, "DS75", LM75_ADDRMASK, LM75_ADDR,
+ lmtemp_decode_ds75, lmtemp_encode_ds75,
+ lmtemp_getlim_lm75, lmtemp_setlim_lm75 },
+ { lmtemp_lm77, "LM77", LM77_ADDRMASK, LM77_ADDR,
+ lmtemp_decode_lm77, lmtemp_encode_lm77,
+ lmtemp_getlim_lm77, lmtemp_setlim_lm77 },
+ { -1, NULL, 0, 0,
+ NULL, NULL,
+ NULL, NULL }
};
static int
@@ -180,15 +201,34 @@
}
sc->sc_lmtemp_decode = lmtemptbl[i].lmtemp_decode;
+ sc->sc_lmtemp_encode = lmtemptbl[i].lmtemp_encode;
iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
- /* Read temperature limit and remember initial value. */
- if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &sc->sc_tmax, 1)
+ /* Read temperature limit(s) and remember initial value(s). */
+ if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &sc->sc_smax, 1)
!= 0) {
+ aprint_error_dev(self, "unable to read Tos register\n");
iic_release_bus(sc->sc_tag, I2C_F_POLL);
return;
}
+ sc->sc_tmax = sc->sc_smax;
+ if (i == lmtemp_lm77) {
+ if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT,
+ &sc->sc_smax, 1) != 0) {
+ aprint_error_dev(self,
+ "unable to read low register\n");
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+ return;
+ }
+ if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT,
+ &sc->sc_smax, 1) != 0) {
+ aprint_error_dev(self,
+ "unable to read high register\n");
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+ return;
+ }
+ }
if (i == lmtemp_lm75)
lmtemp_setup_sysctl(sc);
@@ -205,6 +245,7 @@
/* Initialize sensor data. */
sc->sc_sensor.units = ENVSYS_STEMP;
sc->sc_sensor.state = ENVSYS_SINVALID;
+ sc->sc_sensor.flags = ENVSYS_FMONLIMITS;
(void)strlcpy(sc->sc_sensor.desc,
ia->ia_name? ia->ia_name : device_xname(self),
sizeof(sc->sc_sensor.desc));
@@ -217,6 +258,8 @@
sc->sc_sme->sme_name = device_xname(self);
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = lmtemp_refresh;
+ sc->sc_sme->sme_get_limits = lmtemptbl[i].lmtemp_getlim;
+ sc->sc_sme->sme_set_limits = lmtemptbl[i].lmtemp_setlim;
if (sysmon_envsys_register(sc->sc_sme)) {
aprint_error_dev(self, "unable to register with sysmon\n");
@@ -237,13 +280,12 @@
}
static int
-lmtemp_temp_write(struct lmtemp_softc *sc, int reg, uint16_t val)
+lmtemp_temp_write(struct lmtemp_softc *sc, uint8_t reg, uint32_t val, int degc)
{
uint8_t cmdbuf[3];
cmdbuf[0] = reg;
- cmdbuf[1] = (val >> 1) & 0xff;
- cmdbuf[2] = (val & 1) << 7;
+ sc->sc_lmtemp_encode(val, &cmdbuf[1], degc);
return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
sc->sc_address, cmdbuf, 1, &cmdbuf[1], 2, I2C_F_POLL);
@@ -298,6 +340,103 @@
iic_release_bus(sc->sc_tag, 0); /* also unlocks our instance */
}
+static void
+lmtemp_getlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata,
+ sysmon_envsys_lim_t *limits, uint32_t *props)
+{
+ struct lmtemp_softc *sc = sme->sme_cookie;
+ uint32_t val;
+
+ *props &= ~(PROP_CRITMAX);
+
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &val, 0) == 0) {
+ limits->sel_critmax = val;
+ *props |= PROP_CRITMAX;
+ }
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+}
+
+static void
+lmtemp_getlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata,
+ sysmon_envsys_lim_t *limits, uint32_t *props)
+{
+ struct lmtemp_softc *sc = sme->sme_cookie;
+ uint32_t val;
+
+ *props &= ~(PROP_CRITMAX | PROP_WARNMAX | PROP_WARNMIN);
+
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT, &val, 0) == 0) {
+ limits->sel_critmax = val;
+ *props |= PROP_CRITMAX;
+ }
+ if (lmtemp_temp_read(sc, LM77_REG_THIGH_SET_POINT, &val, 0) == 0) {
+ limits->sel_warnmax = val;
+ *props |= PROP_WARNMAX;
+ }
+ if (lmtemp_temp_read(sc, LM77_REG_TLOW_SET_POINT, &val, 0) == 0) {
+ limits->sel_warnmin = val;
+ *props |= PROP_WARNMIN;
+ }
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+}
+
+static void
+lmtemp_setlim_lm75(struct sysmon_envsys *sme, envsys_data_t *edata,
+ sysmon_envsys_lim_t *limits, uint32_t *props)
+{
+ struct lmtemp_softc *sc = sme->sme_cookie;
+ int32_t limit;
+
+ if (*props & PROP_CRITMAX) {
+ if (limits == NULL) /* Restore defaults */
+ limit = sc->sc_smax;
+ else
+ limit = limits->sel_critmax;
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT,
+ limit - 5000000, 0);
+ lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, limit, 0);
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+
+ /* Synchronise sysctl */
+ sc->sc_tmax = (limit - 273150000) / 1000000;
+ }
+}
+
+static void
+lmtemp_setlim_lm77(struct sysmon_envsys *sme, envsys_data_t *edata,
+ sysmon_envsys_lim_t *limits, uint32_t *props)
+{
+ struct lmtemp_softc *sc = sme->sme_cookie;
+ int32_t limit;
+
+ iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
+ if (*props & PROP_CRITMAX) {
+ if (limits == NULL) /* Restore defaults */
+ limit = sc->sc_smax;
+ else
+ limit = limits->sel_critmax;
+ lmtemp_temp_write(sc, LM77_REG_TCRIT_SET_POINT, limit, 0);
+ }
+ if (*props & PROP_WARNMAX) {
+ if (limits == NULL) /* Restore defaults */
+ limit = sc->sc_smax;
+ else
+ limit = limits->sel_warnmax;
+ lmtemp_temp_write(sc, LM77_REG_THIGH_SET_POINT, limit, 0);
+ }
+ if (*props & PROP_WARNMIN) {
+ if (limits == NULL) /* Restore defaults */
+ limit = sc->sc_smax;
+ else
+ limit = limits->sel_warnmin;
+ lmtemp_temp_write(sc, LM77_REG_TLOW_SET_POINT, limit, 0);
+ }
+ iic_release_bus(sc->sc_tag, I2C_F_POLL);
+}
+
static uint32_t
lmtemp_decode_lm75(const uint8_t *buf, int degc)
{
@@ -364,6 +503,45 @@
return val;
}
+static void lmtemp_encode_lm75(const uint32_t val, uint8_t *buf, int degc)
+{
+ int temp;
+
+ /* Convert from C or uK to register format */
+ if (degc)
+ temp = val * 2;
+ else
+ temp = (val - 273150000) / 500000;
+ buf[0] = (temp >> 1) & 0xff;
+ buf[1] = (temp & 1) << 7;
+}
+
+static void lmtemp_encode_ds75(const uint32_t val, uint8_t *buf, int degc)
+{
+ int temp;
+
+ /* Convert from C or uK to register format */
+ if (degc)
+ temp = val * 16;
+ else
+ temp = (val - 273150000) / 62500;
+ buf[0] = (temp >> 4) & 0xff;
+ buf[1] = (temp & 0xf) << 4;
+}
+
+static void lmtemp_encode_lm77(const uint32_t val, uint8_t *buf, int degc)
+{
+ int temp;
+
+ /* Convert from C or uK to register format */
Home |
Main Index |
Thread Index |
Old Index