Module Name:    src
Committed By:   pgoyette
Date:           Sat Jun 13 19:02:34 UTC 2009

Modified Files:
        src/sys/dev/i2c: sdtemp.c sdtemp_reg.h

Log Message:
Update sdtemp driver to use sysmon_envsys(9) for setting temp sensor
limits.  Remove sysctl(9) interface to the limit registers since it's
no longer needed.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/i2c/sdtemp.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/i2c/sdtemp_reg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/sdtemp.c
diff -u src/sys/dev/i2c/sdtemp.c:1.3 src/sys/dev/i2c/sdtemp.c:1.4
--- src/sys/dev/i2c/sdtemp.c:1.3	Mon Jun  1 20:08:44 2009
+++ src/sys/dev/i2c/sdtemp.c	Sat Jun 13 19:02:33 2009
@@ -1,4 +1,4 @@
-/*      $NetBSD: sdtemp.c,v 1.3 2009/06/01 20:08:44 pgoyette Exp $        */
+/*      $NetBSD: sdtemp.c,v 1.4 2009/06/13 19:02:33 pgoyette Exp $        */
 
 /*
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdtemp.c,v 1.3 2009/06/01 20:08:44 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdtemp.c,v 1.4 2009/06/13 19:02:33 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -38,7 +38,6 @@
 #include <sys/device.h>
 #include <sys/kernel.h>
 #include <sys/endian.h>
-#include <sys/sysctl.h>
 
 #include <dev/sysmon/sysmonvar.h>
 
@@ -54,7 +53,6 @@
 	envsys_data_t *sc_sensor;
 	int sc_resolution;
 	uint16_t sc_capability;
-	uint16_t sc_low_lim, sc_high_lim, sc_crit_lim;
 };
 
 static int  sdtemp_match(device_t, cfdata_t, void *);
@@ -64,6 +62,10 @@
 	sdtemp_match, sdtemp_attach, NULL, NULL);
 
 static void	sdtemp_refresh(struct sysmon_envsys *, envsys_data_t *);
+static void	sdtemp_get_limits(struct sysmon_envsys *,
+				  sysmon_envsys_lim_t *);
+static void	sdtemp_set_limits(struct sysmon_envsys *,
+				  sysmon_envsys_lim_t *);
 #ifdef NOT_YET
 static int	sdtemp_read_8(struct sdtemp_softc *, uint8_t, uint8_t *);
 static int	sdtemp_write_8(struct sdtemp_softc *, uint8_t, uint8_t);
@@ -71,13 +73,9 @@
 static int	sdtemp_read_16(struct sdtemp_softc *, uint8_t, uint16_t *);
 static int	sdtemp_write_16(struct sdtemp_softc *, uint8_t, uint16_t);
 static uint32_t	sdtemp_decode_temp(struct sdtemp_softc *, uint16_t);
-static void	sdtemp_set_thresh(struct sdtemp_softc *, int, uint16_t);
 static bool	sdtemp_pmf_suspend(device_t PMF_FN_PROTO);
 static bool	sdtemp_pmf_resume(device_t PMF_FN_PROTO);
 
-SYSCTL_SETUP_PROTO(sysctl_sdtemp_setup);
-static int sdtemp_sysctl_helper(SYSCTLFN_PROTO);
-
 struct sdtemp_dev_entry {
 	const uint16_t sdtemp_mfg_id;
 	const uint8_t  sdtemp_dev_id;
@@ -86,8 +84,9 @@
 	const char    *sdtemp_desc;
 };
 
-/* sysctl stuff */
-static int hw_node = CTL_EOL;
+/* Convert sysmon_envsys uKelvin value to simple degC */
+
+#define	__UK2C(uk) (((uk) - 273150000) / 1000000)
 
 /*
  * List of devices known to conform to JEDEC JC42.4
@@ -172,9 +171,8 @@
 {
 	struct sdtemp_softc *sc = device_private(self);
 	struct i2c_attach_args *ia = aux;
-	const struct sysctlnode *node = NULL;
+	sysmon_envsys_lim_t limits;
 	uint16_t mfgid, devid;
-	int32_t	dev_sysctl_num;
 	int i, error;
 
 	sc->sc_tag = ia->ia_tag;
@@ -236,6 +234,12 @@
 
 	/* Hook us into the sysmon_envsys subsystem */
 	sc->sc_sme = sysmon_envsys_create();
+	sc->sc_sme->sme_name = device_xname(self);
+	sc->sc_sme->sme_cookie = sc;
+	sc->sc_sme->sme_refresh = sdtemp_refresh;
+	sc->sc_sme->sme_get_limits = sdtemp_get_limits;
+	sc->sc_sme->sme_set_limits = sdtemp_set_limits;
+
 	sc->sc_sensor = kmem_zalloc(sizeof(envsys_data_t), KM_NOSLEEP);
 	if (!sc->sc_sensor) {
 		aprint_error_dev(self, "unable to allocate sc_sensor\n");
@@ -246,6 +250,7 @@
 	sc->sc_sensor->units =  ENVSYS_STEMP;
 	sc->sc_sensor->state = ENVSYS_SINVALID;
 	sc->sc_sensor->flags |= ENVSYS_FMONLIMITS;
+	sc->sc_sensor->monitor = true;
 	(void)strlcpy(sc->sc_sensor->desc, device_xname(self),
 	    sizeof(sc->sc_sensor->desc));
 
@@ -256,10 +261,6 @@
 	}
 
 	/* Register the device */
-	sc->sc_sme->sme_name = device_xname(self);
-	sc->sc_sme->sme_cookie = sc;
-	sc->sc_sme->sme_refresh = sdtemp_refresh;
-
 	error = sysmon_envsys_register(sc->sc_sme);
 	if (error) {
 		aprint_error_dev(self, "error %d registering with sysmon\n",
@@ -270,76 +271,29 @@
 	if (!pmf_device_register(self, sdtemp_pmf_suspend, sdtemp_pmf_resume))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 
-
 	/* Retrieve and display hardware monitor limits */
-	i = 0;
+	sdtemp_get_limits(sc->sc_sme, &limits);
 	aprint_normal_dev(self, "");
-	iic_acquire_bus(sc->sc_tag, 0);
-	if (sdtemp_read_16(sc, SDTEMP_REG_LOWER_LIM, &sc->sc_low_lim) == 0 &&
-	    sc->sc_low_lim != 0) {
-		sc->sc_low_lim >>= 4;
-		aprint_normal("low limit %dC ", sc->sc_low_lim);
+	i = 0;
+	if (limits.sel_flags & PROP_WARNMIN) {
+		aprint_normal("low limit %dC", __UK2C(limits.sel_warnmin));
 		i++;
 	}
-	if (sdtemp_read_16(sc, SDTEMP_REG_UPPER_LIM, &sc->sc_high_lim) == 0 &&
-	    sc->sc_high_lim != 0) {
-		sc->sc_high_lim >>= 4;
-		aprint_normal("high limit %dC ", sc->sc_high_lim);
+	if (limits.sel_flags & PROP_WARNMAX) {
+		aprint_normal("%shigh limit %dC ", (i)?", ":"",
+			      __UK2C(limits.sel_warnmax));
 		i++;
 	}
-	if (sdtemp_read_16(sc, SDTEMP_REG_CRIT_LIM, &sc->sc_crit_lim) == 0 &&
-	    sc->sc_crit_lim != 0) {
-		sc->sc_crit_lim >>= 4;
-		aprint_normal("critical limit %dC ", sc->sc_crit_lim);
+	if (limits.sel_flags & PROP_CRITMAX) {
+		aprint_normal("%scritical limit %dC ", (i)?", ":"",
+			      __UK2C(limits.sel_critmax));
 		i++;
 	}
-	iic_release_bus(sc->sc_tag, 0);
 	if (i == 0)
 		aprint_normal("no hardware limits set\n");
 	else
 		aprint_normal("\n");
 
-	/* Create our sysctl tree.  We just store the softc pointer for
-	 * now;  the sysctl_helper function will take care of creating
-	 * a real string on the fly.  We explicitly specify the new nodes'
-	 * sysctl_num in order to identify the specific limit rather than
-	 * using CTL_CREATE;  this is OK since we're the only place that
-	 * touches the sysctl tree for the device.
-	 */
-
-	if (hw_node != CTL_EOL)
-		sysctl_createv(NULL, 0, NULL, &node, 0,
-		    CTLTYPE_NODE, device_xname(self),
-		    NULL, NULL, 0, NULL, 0,
-		    CTL_HW, CTL_CREATE, CTL_EOL);
-	if (node != NULL) {
-		dev_sysctl_num = node->sysctl_num;
-		sysctl_createv(NULL, 0, NULL, &node, 0,
-		    CTLTYPE_NODE, "limits",
-		    SYSCTL_DESCR("temperature limits"),
-		    NULL, 0, NULL, 0, 
-		    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
-	}
-	if (node != NULL) {
-		sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READWRITE,
-		    CTLTYPE_INT, "low_limit",
-		    SYSCTL_DESCR("alarm window lower limit"),
-		    sdtemp_sysctl_helper, 0, sc, sizeof(int),
-		    CTL_HW, dev_sysctl_num, node->sysctl_num,
-			SDTEMP_REG_LOWER_LIM, CTL_EOL);
-		sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READWRITE,
-		    CTLTYPE_INT, "high_limit",
-		    SYSCTL_DESCR("alarm window upper limit"),
-		    sdtemp_sysctl_helper, 0, sc, sizeof(int),
-		    CTL_HW, dev_sysctl_num, node->sysctl_num, 
-			SDTEMP_REG_UPPER_LIM, CTL_EOL);
-		sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READWRITE,
-		    CTLTYPE_INT, "crit_limit",
-		    SYSCTL_DESCR("critical alarm limit"),
-		    sdtemp_sysctl_helper, 0, sc, sizeof(int),
-		    CTL_HW, dev_sysctl_num, node->sysctl_num,
-			SDTEMP_REG_CRIT_LIM, CTL_EOL);
-	}
 	return;
 
 bad:
@@ -348,33 +302,66 @@
 	sysmon_envsys_destroy(sc->sc_sme);
 }
 
-/* Set up the threshold registers */
+/* Retrieve current limits from device, and encode in uKelvins */
 static void
-sdtemp_set_thresh(struct sdtemp_softc *sc, int reg, uint16_t val)
+sdtemp_get_limits(struct sysmon_envsys *sme, sysmon_envsys_lim_t *limits)
 {
-	int error;
-	uint16_t *valp;
+	struct sdtemp_softc *sc = sme->sme_cookie;
+	uint16_t lim;
 
-	switch (reg) {
-	case SDTEMP_REG_LOWER_LIM:
-		valp = &sc->sc_low_lim;
-		break;
-	case SDTEMP_REG_UPPER_LIM:
-		valp = &sc->sc_high_lim;
-		break;
-	case SDTEMP_REG_CRIT_LIM:
-		valp = &sc->sc_crit_lim;
-		break;
-	default:
-		return;
+	limits->sel_flags = PROP_DRIVER_LIMITS;
+	iic_acquire_bus(sc->sc_tag, 0);
+	if (sdtemp_read_16(sc, SDTEMP_REG_LOWER_LIM, &lim) == 0 && lim != 0) {
+		limits->sel_warnmin = sdtemp_decode_temp(sc, lim);
+		limits->sel_flags |= PROP_WARNMIN;
+	}
+	if (sdtemp_read_16(sc, SDTEMP_REG_UPPER_LIM, &lim) == 0 && lim != 0) {
+		limits->sel_warnmax = sdtemp_decode_temp(sc, lim);
+		limits->sel_flags |= PROP_WARNMAX;
+	}
+	if (sdtemp_read_16(sc, SDTEMP_REG_CRIT_LIM, &lim) == 0 && lim != 0) {
+		limits->sel_critmax = sdtemp_decode_temp(sc, lim);
+		limits->sel_flags |= PROP_CRITMAX;
 	}
+	iic_release_bus(sc->sc_tag, 0);
+}
+
+/* Send current limit values to the device */
+static void
+sdtemp_set_limits(struct sysmon_envsys *sme, sysmon_envsys_lim_t *limits)
+{
+	uint16_t val;
+	struct sdtemp_softc *sc = sme->sme_cookie;
 
 	iic_acquire_bus(sc->sc_tag, 0);
-	error = sdtemp_write_16(sc, reg, (val << 4) & SDTEMP_TEMP_MASK);
+	if (limits->sel_flags & PROP_WARNMIN) {
+		val = __UK2C(limits->sel_warnmin);
+		(void)sdtemp_write_16(sc, SDTEMP_REG_LOWER_LIM,
+					(val << 4) & SDTEMP_TEMP_MASK);
+	}
+	if (limits->sel_flags & PROP_WARNMAX) {
+		val = __UK2C(limits->sel_warnmax);
+		(void)sdtemp_write_16(sc, SDTEMP_REG_UPPER_LIM,
+					(val << 4) & SDTEMP_TEMP_MASK);
+	}
+	if (limits->sel_flags & PROP_CRITMAX) {
+		val = __UK2C(limits->sel_critmax);
+		(void)sdtemp_write_16(sc, SDTEMP_REG_CRIT_LIM,
+					(val << 4) & SDTEMP_TEMP_MASK);
+	}
 	iic_release_bus(sc->sc_tag, 0);
 
-	if (error == 0)
-		*valp = val;
+	/*
+	 * If at least one limit is set that we can handle, and no
+	 * limits are set that we cannot handle, tell sysmon that
+	 * the driver will take care of monitoring the limits!
+	 */
+	if (limits->sel_flags & (PROP_CRITMIN | PROP_BATTCAP | PROP_BATTWARN))
+		limits->sel_flags &= ~PROP_DRIVER_LIMITS;
+	else if (limits->sel_flags & PROP_LIMITS)
+		limits->sel_flags |= PROP_DRIVER_LIMITS;
+	else
+		limits->sel_flags &= ~PROP_DRIVER_LIMITS;
 }
 
 #ifdef NOT_YET	/* All registers on these sensors are 16-bits */
@@ -470,7 +457,9 @@
 	edata->value_cur = sdtemp_decode_temp(sc, val);
 
 	/* Now check for limits */
-	if (val & SDTEMP_ABOVE_CRIT)
+	if ((edata->upropset & PROP_DRIVER_LIMITS) == 0)
+		edata->state = ENVSYS_SVALID;
+	else if (val & SDTEMP_ABOVE_CRIT)
 		edata->state = ENVSYS_SCRITOVER;
 	else if (val & SDTEMP_ABOVE_UPPER)
 		edata->state = ENVSYS_SWARNOVER;
@@ -480,70 +469,6 @@
 		edata->state = ENVSYS_SVALID;
 }
 
-SYSCTL_SETUP(sysctl_sdtemp_setup, "sysctl hw.sdtemp subtree setup")
-{
-	const struct sysctlnode *node;
-
-	if (sysctl_createv(clog, 0, NULL, &node,
-			   CTLFLAG_PERMANENT,
-			   CTLTYPE_NODE, "hw", NULL,
-			   NULL, 0, NULL, 0,
-			   CTL_HW, CTL_EOL) != 0)
-		return;
-
-	hw_node = node->sysctl_num;
-}
-
-/*
- * The sysctl node actually contains just a pointer to our softc.  We
- * extract the individual limits on the fly, and if necessary replace
- * the value with the new value specified by the user.
- *
- * Inspired by similar code in sys/net/if_tap.c
- */
-static int
-sdtemp_sysctl_helper(SYSCTLFN_ARGS)
-{
-	struct sdtemp_softc *sc;
-	struct sysctlnode node;
-	int error, reg;
-	uint16_t reg_value;
-	int lim_value;
-
-	node = *rnode;
-	sc = node.sysctl_data;
-	reg = node.sysctl_num;
-
-	iic_acquire_bus(sc->sc_tag, 0);
-	error = sdtemp_read_16(sc, reg, &reg_value);
-	iic_release_bus(sc->sc_tag, 0);
-
-#ifdef DEBUG
-	aprint_verbose_dev(sc->sc_dev, "(%s) sc %p reg %d val 0x%04x err %d\n",
-	    __func__, sc, reg, reg_value, error);
-#endif
-
-	if (error == 0) {
-		lim_value = reg_value >> 4;
-		node.sysctl_data = &lim_value;
-		error = sysctl_lookup(SYSCTLFN_CALL(&node));
-	}
-	if (error || newp == NULL)
-		return (error);
-
-	/*
-	 * We're being asked to update the sysctl value, so retrieve
-	 * the new value and check for valid range
-	 */
-	lim_value = *(int *)node.sysctl_data;
-	if (lim_value < -256 || lim_value > 255)
-		return (EINVAL);
-
-	sdtemp_set_thresh(sc, reg, (uint16_t)lim_value);
-
-	return (0);
-}
-
 /*
  * power management functions
  *

Index: src/sys/dev/i2c/sdtemp_reg.h
diff -u src/sys/dev/i2c/sdtemp_reg.h:1.1 src/sys/dev/i2c/sdtemp_reg.h:1.2
--- src/sys/dev/i2c/sdtemp_reg.h:1.1	Sat May  9 15:04:25 2009
+++ src/sys/dev/i2c/sdtemp_reg.h	Sat Jun 13 19:02:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdtemp_reg.h,v 1.1 2009/05/09 15:04:25 pgoyette Exp $	*/
+/*	$NetBSD: sdtemp_reg.h,v 1.2 2009/06/13 19:02:33 pgoyette Exp $	*/
 
 /*
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -72,7 +72,7 @@
 #define	SDTEMP_HYSTERESIS_60		0x0600
 
 /*
- * Temperature is a 12-bit value in the range of -256 <= x < +256 degrees.
+ * Temperature is a 13-bit value in the range of -256 <= x < +256 degrees.
  * Maximum resolution is 0.0625C (1/16th degree, 4 bits), but some devices
  * may have only 0.2500C or 0.1250C (1 or 2 bits), and some devices may not
  * be able to represent negative values (not that we'd expect them, anyway).
@@ -82,7 +82,7 @@
 #define	SDTEMP_TEMP_SIGN_EXT		0xF000
 
 /*
- * Status bits set in MCP98XX_REG_AMBIENT_TEMP only
+ * Status bits set in SDTEMP_REG_AMBIENT_TEMP only
  */
 #define	SDTEMP_ABOVE_CRIT		0x8000
 #define	SDTEMP_ABOVE_UPPER		0x4000

Reply via email to