Module Name:    src
Committed By:   brad
Date:           Thu Jan 23 19:14:46 UTC 2025

Modified Files:
        src/share/man/man4: sht3xtemp.4
        src/sys/dev/i2c: sht3x.c sht3xvar.h

Log Message:
The SHT3x temperature and humidity sensor has a set of commands that
can do the measurement by using I2C clock stretching in single shot
mode.  Add a sysctl to allow the driver to use those commands.  This
is more efficient than doing the usual polling method of getting the
measurements back from the chip, but only works if the I2C master
supports clock stretching.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/share/man/man4/sht3xtemp.4
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/i2c/sht3x.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/i2c/sht3xvar.h

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

Modified files:

Index: src/share/man/man4/sht3xtemp.4
diff -u src/share/man/man4/sht3xtemp.4:1.3 src/share/man/man4/sht3xtemp.4:1.4
--- src/share/man/man4/sht3xtemp.4:1.3	Wed Apr 27 23:11:25 2022
+++ src/share/man/man4/sht3xtemp.4	Thu Jan 23 19:14:45 2025
@@ -1,4 +1,4 @@
-.\" $NetBSD: sht3xtemp.4,v 1.3 2022/04/27 23:11:25 brad Exp $
+.\" $NetBSD: sht3xtemp.4,v 1.4 2025/01/23 19:14:45 brad Exp $
 .\"
 .\" Copyright (c) 2021 Brad Spencer <b...@anduin.eldar.org>
 .\"
@@ -95,6 +95,14 @@ The delays are documented in the datashe
 The driver will attempt to read back the values readattempts number of
 times.
 The default is 10 which should be more than enough for most purposes.
+.It hw.sht3xtemp0.clockstretch
+The chip supports a set of commands that lets it use I2C clock
+stretching to perform the temperature or humidity measurement.  If
+this is set to 1 then use the clock stretching commands with the
+device.  Note that the I2C controller must support clock stretching
+in order for this to work reliability.  When this option is enabled,
+the readattempts sysctl noted above will not be used.  This option only
+apply to single shot measurements.
 .El
 .Sh FILES
 .Bl -tag -width "/dev/sht3xtempu" -compact

Index: src/sys/dev/i2c/sht3x.c
diff -u src/sys/dev/i2c/sht3x.c:1.9 src/sys/dev/i2c/sht3x.c:1.10
--- src/sys/dev/i2c/sht3x.c:1.9	Wed Jan  8 08:33:34 2025
+++ src/sys/dev/i2c/sht3x.c	Thu Jan 23 19:14:46 2025
@@ -1,5 +1,5 @@
 
-/*	$NetBSD: sht3x.c,v 1.9 2025/01/08 08:33:34 andvar Exp $	*/
+/*	$NetBSD: sht3x.c,v 1.10 2025/01/23 19:14:46 brad Exp $	*/
 
 /*
  * Copyright (c) 2021 Brad Spencer <b...@anduin.eldar.org>
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.9 2025/01/08 08:33:34 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.10 2025/01/23 19:14:46 brad Exp $");
 
 /*
   Driver for the Sensirion SHT30/SHT31/SHT35
@@ -184,14 +184,17 @@ static struct sht3x_repeatability sht3x_
 	{
 		.text = "high",
 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH,
+		.cscmd = SHT3X_MEASURE_REPEATABILITY_CS_HIGH,
 	},
 	{
 		.text = "medium",
 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM,
+		.cscmd = SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM,
 	},
 	{
 		.text = "low",
 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW,
+		.cscmd = SHT3X_MEASURE_REPEATABILITY_CS_LOW,
 	}
 };
 
@@ -865,27 +868,34 @@ sht3x_cmd(i2c_tag_t tag, i2c_addr_t addr
 	cmd8[0] = cmd[0] >> 8;
 	cmd8[1] = cmd[0] & 0x00ff;
 
-	error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd8[0], clen,
-	    NULL, 0, 0);
-	if (error)
-		return error;
+	if (cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_HIGH ||
+	    cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM ||
+	    cmd[0] == SHT3X_MEASURE_REPEATABILITY_CS_LOW) {
+		error = iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, &cmd8[0], clen,
+		    buf, blen, 0);
+	} else {
+		error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd8[0], clen,
+		    NULL, 0, 0);
+		if (error)
+			return error;
 
-	cmddelay = sht3x_cmddelay(cmd[0]);
-	if (cmddelay != -1) {
-		delay(cmddelay);
-	}
+		cmddelay = sht3x_cmddelay(cmd[0]);
+		if (cmddelay != -1) {
+			delay(cmddelay);
+		}
 
-	/* Not all commands return anything  */
-	if (blen == 0) {
-		return 0;
-	}
+		/* Not all commands return anything  */
+		if (blen == 0) {
+			return 0;
+		}
 
-	for (int aint = 0; aint < readattempts; aint++) {
-		error = iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0, buf,
-		    blen, 0);
-		if (error == 0)
-			break;
-		delay(1000);
+		for (int aint = 0; aint < readattempts; aint++) {
+			error = iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0, buf,
+			    blen, 0);
+			if (error == 0)
+				break;
+			delay(1000);
+		}
 	}
 
 	return error;
@@ -955,6 +965,13 @@ sht3x_sysctl_init(struct sht3x_sc *sc)
 #endif
 
 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "clockstretch",
+	    SYSCTL_DESCR("Use clock stretch commands for measurements"), NULL, 0,
+	    &sc->sc_clockstretch, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
+	    CTL_EOL)) != 0)
+		return error;
+
+	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
 	    CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts",
 	    SYSCTL_DESCR("The number of times to attempt to read the values"),
 	    sht3x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW,
@@ -1085,6 +1102,7 @@ sht3x_attach(device_t parent, device_t s
 	sc->sc_stopping = false;
 	sc->sc_initperiodic = false;
 	sc->sc_opened = false;
+	sc->sc_clockstretch = false;
 	sc->sc_dying = false;
 	sc->sc_readpoolname = NULL;
 
@@ -1216,7 +1234,7 @@ out:
 }
 
 static uint16_t
-sht3x_compute_measure_command_ss(const char *repeatability)
+sht3x_compute_measure_command_ss(const char *repeatability, bool clockstretch)
 {
 	int i;
 	uint16_t r;
@@ -1224,7 +1242,10 @@ sht3x_compute_measure_command_ss(const c
 	for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) {
 		if (strncmp(repeatability, sht3x_repeatability_ss[i].text,
 		    SHT3X_REP_NAME) == 0) {
-			r = sht3x_repeatability_ss[i].cmd;
+			if (clockstretch)
+				r = sht3x_repeatability_ss[i].cscmd;
+			else
+				r = sht3x_repeatability_ss[i].cmd;
 			break;
 		}
 	}
@@ -1383,7 +1404,7 @@ sht3x_refresh_oneshot(struct sysmon_envs
 	}
 
 	measurement_command_ss = sht3x_compute_measure_command_ss(
-	    sc->sc_repeatability);
+	    sc->sc_repeatability, sc->sc_clockstretch);
 	error = sht3x_cmdr(sc, measurement_command_ss, rawdata, sizeof(rawdata));
 	DPRINTF(sc, 2, ("%s: Status for single-shot measurement cmd %04x "
 	    "Error %d\n", device_xname(sc->sc_dev), measurement_command_ss, error));

Index: src/sys/dev/i2c/sht3xvar.h
diff -u src/sys/dev/i2c/sht3xvar.h:1.1 src/sys/dev/i2c/sht3xvar.h:1.2
--- src/sys/dev/i2c/sht3xvar.h:1.1	Sat Nov  6 13:34:40 2021
+++ src/sys/dev/i2c/sht3xvar.h	Thu Jan 23 19:14:46 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: sht3xvar.h,v 1.1 2021/11/06 13:34:40 brad Exp $	*/
+/*	$NetBSD: sht3xvar.h,v 1.2 2025/01/23 19:14:46 brad Exp $	*/
 
 /*
  * Copyright (c) 2021 Brad Spencer <b...@anduin.eldar.org>
@@ -57,6 +57,7 @@ struct sht3x_sc {
 	bool		sc_dying;
 	bool		sc_opened;
 	bool		sc_wassingleshot;
+	bool		sc_clockstretch;
 	pool_cache_t	sc_readpool;
 	char		*sc_readpoolname;
 	SIMPLEQ_HEAD(,sht3x_read_q)  sc_read_queue;
@@ -87,6 +88,7 @@ struct sht3x_periodic {
 struct sht3x_repeatability {
 	const char     *text;
 	uint16_t        cmd;
+	uint16_t        cscmd;
 };
 
 #endif

Reply via email to