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/6663cd2e3d86
branches:  trunk
changeset: 812795:6663cd2e3d86
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 8111cd70c1c6 -r 6663cd2e3d86 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