* [PATCH 0/2] hwmon: Add Sensirion STS4x temperature sensor support
@ 2026-08-20 14:59 Alessandro Zini
2026-08-20 14:59 ` [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
2026-08-20 14:59 ` [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
0 siblings, 2 replies; 6+ messages in thread
From: Alessandro Zini @ 2026-08-20 14:59 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Alessandro Zini
This patch series adds support for the Sensirion STS4x family of digital
temperature sensors by extending the existing sht4x driver and adding
the "sensirion,sts40" compatible string to trivial-devices.
The STS4x series shares the same I2C commands, conversion formulas,
CRC-8 checksum, and measurement timings with the SHT4x humidity and
temperature sensors, but returns 3 bytes of temperature data instead
of 6 bytes.
Alessandro Zini (2):
dt-bindings: trivial-devices: Add Sensirion STS4x series
hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
.../devicetree/bindings/trivial-devices.yaml | 2 +
Documentation/hwmon/sht4x.rst | 17 +++++-
drivers/hwmon/sht4x.c | 56 ++++++++++++++-----
3 files changed, 57 insertions(+), 18 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series
2026-08-20 14:59 [PATCH 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
@ 2026-08-20 14:59 ` Alessandro Zini
2026-08-20 15:03 ` sashiko-bot
2026-08-20 18:06 ` Conor Dooley
2026-08-20 14:59 ` [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
1 sibling, 2 replies; 6+ messages in thread
From: Alessandro Zini @ 2026-08-20 14:59 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Alessandro Zini
Add "sensirion,sts40" as compatible for the Sensirion STS4x/STS4xA
series of digital temperature sensors.
Link: https://sensirion.com/resource/datasheet/sts4x
Signed-off-by: Alessandro Zini <alessandro.zini@siemens.com>
---
Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 435c4baab4365..48ded1b746723 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -423,6 +423,8 @@ properties:
- sensirion,sht21
- sensirion,sht25
- sensirion,sht4x
+ # Sensirion temperature sensor with I2C interface
+ - sensirion,sts40
# Sensortek 3 axis accelerometer
- sensortek,stk8312
# Sensortek 3 axis accelerometer
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
2026-08-20 14:59 [PATCH 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
2026-08-20 14:59 ` [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
@ 2026-08-20 14:59 ` Alessandro Zini
2026-08-20 15:08 ` sashiko-bot
1 sibling, 1 reply; 6+ messages in thread
From: Alessandro Zini @ 2026-08-20 14:59 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Alessandro Zini
The Sensirion STS4x series is the temperature-only variant of the
SHT4x family. It shares the same I2C command set, conversion formulas,
CRC checksum, and timing with the SHT4x, but only returns temperature
data (3 bytes: 2 data bytes + 1 CRC byte).
Add support for the STS4x series by dynamically adjusting the read
response length, suppressing humidity channel attributes when probed
as STS4x, and omitting heater sysfs attributes.
Link: https://sensirion.com/resource/datasheet/sts4x
Signed-off-by: Alessandro Zini <alessandro.zini@siemens.com>
---
Documentation/hwmon/sht4x.rst | 17 +++++++++--
drivers/hwmon/sht4x.c | 56 +++++++++++++++++++++++++----------
2 files changed, 55 insertions(+), 18 deletions(-)
diff --git a/Documentation/hwmon/sht4x.rst b/Documentation/hwmon/sht4x.rst
index ba094ad0e2816..b9564632a1be2 100644
--- a/Documentation/hwmon/sht4x.rst
+++ b/Documentation/hwmon/sht4x.rst
@@ -15,6 +15,16 @@ Supported Chips:
English: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT4x_Datasheet.pdf
+ * Sensirion STS4X
+
+ Prefix: 'sts4x'
+
+ Addresses scanned: None
+
+ Datasheet:
+
+ English: https://sensirion.com/resource/datasheet/sts4x
+
Author: Navin Sankar Velliangiri <navin@linumiz.com>
@@ -22,9 +32,10 @@ Description
-----------
This driver implements support for the Sensirion SHT4x chip, a humidity
-and temperature sensor. Temperature is measured in degree celsius, relative
-humidity is expressed as a percentage. In sysfs interface, all values are
-scaled by 1000, i.e. the value for 31.5 degrees celsius is 31500.
+and temperature sensor, and the Sensirion STS4x chip, a temperature sensor.
+Temperature is measured in degree celsius, relative humidity is expressed as a
+percentage (on SHT4x only). In sysfs interface, all values are scaled by 1000,
+i.e. the value for 31.5 degrees celsius is 31500.
Usage Notes
-----------
diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
index 9cace0e8acdab..d2b0d79bb7fe0 100644
--- a/drivers/hwmon/sht4x.c
+++ b/drivers/hwmon/sht4x.c
@@ -43,6 +43,7 @@
#define SHT4X_CRC8_LEN 1
#define SHT4X_WORD_LEN 2
#define SHT4X_RESPONSE_LENGTH 6
+#define STS4X_RESPONSE_LENGTH 3
#define SHT4X_CRC8_POLYNOMIAL 0x31
#define SHT4X_CRC8_INIT 0xff
#define SHT4X_MIN_TEMPERATURE -45000
@@ -52,9 +53,15 @@
DECLARE_CRC8_TABLE(sht4x_crc8_table);
+enum sht4x_chips {
+ sht4x,
+ sts4x,
+};
+
/**
* struct sht4x_data - All the data required to operate an SHT4X chip
* @client: the i2c client associated with the SHT4X
+ * @chip_id: the chip type (sht4x or sts4x)
* @heating_complete: the time that the last heating finished
* @data_pending: true if and only if there are measurements to retrieve after heating
* @heater_power: the power at which the heater will be started
@@ -67,6 +74,7 @@ DECLARE_CRC8_TABLE(sht4x_crc8_table);
*/
struct sht4x_data {
struct i2c_client *client;
+ enum sht4x_chips chip_id;
unsigned long heating_complete; /* in jiffies */
bool data_pending;
u32 heater_power; /* in milli-watts */
@@ -92,6 +100,8 @@ static int sht4x_read_values(struct sht4x_data *data)
u8 crc;
u8 cmd[SHT4X_CMD_LEN] = {SHT4X_CMD_MEASURE_HPM};
u8 raw_data[SHT4X_RESPONSE_LENGTH];
+ size_t response_length = data->chip_id == sts4x ?
+ STS4X_RESPONSE_LENGTH : SHT4X_RESPONSE_LENGTH;
unsigned long curr_jiffies;
curr_jiffies = jiffies;
@@ -115,15 +125,14 @@ static int sht4x_read_values(struct sht4x_data *data)
usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA);
}
- ret = i2c_master_recv(client, raw_data, SHT4X_RESPONSE_LENGTH);
- if (ret != SHT4X_RESPONSE_LENGTH) {
+ ret = i2c_master_recv(client, raw_data, response_length);
+ if (ret != response_length) {
if (ret >= 0)
ret = -ENODATA;
return ret;
}
t_ticks = raw_data[0] << 8 | raw_data[1];
- rh_ticks = raw_data[3] << 8 | raw_data[4];
crc = crc8(sht4x_crc8_table, &raw_data[0], SHT4X_WORD_LEN, CRC8_INIT_VALUE);
if (crc != raw_data[2]) {
@@ -131,14 +140,19 @@ static int sht4x_read_values(struct sht4x_data *data)
return -EIO;
}
- crc = crc8(sht4x_crc8_table, &raw_data[3], SHT4X_WORD_LEN, CRC8_INIT_VALUE);
- if (crc != raw_data[5]) {
- dev_err(&client->dev, "data integrity check failed\n");
- return -EIO;
+ data->temperature = ((21875 * (int32_t)t_ticks) >> 13) - 45000;
+
+ if (data->chip_id != sts4x) {
+ rh_ticks = raw_data[3] << 8 | raw_data[4];
+ crc = crc8(sht4x_crc8_table, &raw_data[3], SHT4X_WORD_LEN, CRC8_INIT_VALUE);
+ if (crc != raw_data[5]) {
+ dev_err(&client->dev, "data integrity check failed\n");
+ return -EIO;
+ }
+
+ data->humidity = ((15625 * (int32_t)rh_ticks) >> 13) - 6000;
}
- data->temperature = ((21875 * (int32_t)t_ticks) >> 13) - 45000;
- data->humidity = ((15625 * (int32_t)rh_ticks) >> 13) - 6000;
data->last_updated = jiffies;
data->valid = true;
return 0;
@@ -190,9 +204,14 @@ static umode_t sht4x_hwmon_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
+ const struct sht4x_data *chip_data = data;
+
switch (type) {
case hwmon_temp:
+ return 0444;
case hwmon_humidity:
+ if (chip_data->chip_id == sts4x)
+ return 0;
return 0444;
case hwmon_chip:
return 0644;
@@ -382,6 +401,7 @@ static const struct hwmon_chip_info sht4x_chip_info = {
static int sht4x_probe(struct i2c_client *client)
{
+ const struct attribute_group **groups = NULL;
struct device *device = &client->dev;
struct device *hwmon_dev;
struct sht4x_data *data;
@@ -400,11 +420,15 @@ static int sht4x_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
+ data->chip_id = (uintptr_t)i2c_get_match_data(client);
data->update_interval = SHT4X_MIN_POLL_INTERVAL;
data->client = client;
- data->heater_power = 200;
- data->heater_time = 1000;
- data->heating_complete = jiffies;
+ if (data->chip_id != sts4x) {
+ data->heater_power = 200;
+ data->heater_time = 1000;
+ data->heating_complete = jiffies;
+ groups = sht4x_groups;
+ }
crc8_populate_msb(sht4x_crc8_table, SHT4X_CRC8_POLYNOMIAL);
@@ -418,19 +442,21 @@ static int sht4x_probe(struct i2c_client *client)
client->name,
data,
&sht4x_chip_info,
- sht4x_groups);
+ groups);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id sht4x_id[] = {
- { .name = "sht4x" },
+ { .name = "sht4x", .driver_data = sht4x },
+ { .name = "sts4x", .driver_data = sts4x },
{ }
};
MODULE_DEVICE_TABLE(i2c, sht4x_id);
static const struct of_device_id sht4x_of_match[] = {
- { .compatible = "sensirion,sht4x" },
+ { .compatible = "sensirion,sht4x", .data = (void *)sht4x },
+ { .compatible = "sensirion,sts40", .data = (void *)sts4x },
{ }
};
MODULE_DEVICE_TABLE(of, sht4x_of_match);
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series
2026-08-20 14:59 ` [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
@ 2026-08-20 15:03 ` sashiko-bot
2026-08-20 18:06 ` Conor Dooley
1 sibling, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-20 15:03 UTC (permalink / raw)
To: Alessandro Zini; +Cc: conor+dt, robh, devicetree, linux-hwmon
> Add "sensirion,sts40" as compatible for the Sensirion STS4x/STS4xA
> series of digital temperature sensors.
>
> Link: https://sensirion.com/resource/datasheet/sts4x
> Signed-off-by: Alessandro Zini <alessandro.zini@siemens.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260820145946.35468-1-alessandro.zini@siemens.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
2026-08-20 14:59 ` [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
@ 2026-08-20 15:08 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-20 15:08 UTC (permalink / raw)
To: Alessandro Zini; +Cc: devicetree, linux-hwmon, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Uninitialized `heating_complete` timestamp causes sensor reads to block for up to 5 minutes on boot.
Pre-existing issues:
- [High] Lack of driver-level locking between hwmon core attributes and custom heater attributes leads to I2C race conditions and data corruption.
- [High] `heater_enable_store` incorrectly returns 0 on success, breaking standard userspace write operations.
- [High] Unit mismatch when evaluating timeout with `data->update_interval` leads to HZ-dependent I2C errors.
--
--- Patch [2]: [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors ---
commit ab4b49384ea571fb866537cfb0dea5a4f4296ef8
Author: Alessandro Zini <alessandro.zini@siemens.com>
hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
The Sensirion STS4x series is the temperature-only variant of the
SHT4x family. Add support for the STS4x series by dynamically adjusting
the read response length, suppressing humidity channel attributes when probed
as STS4x, and omitting heater sysfs attributes.
Link: https://sensirion.com/resource/datasheet/sts4x
> diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
> index 9cace0e8acdab..d2b0d79bb7fe0 100644
> --- a/drivers/hwmon/sht4x.c
> +++ b/drivers/hwmon/sht4x.c
[ ... ]
> @@ -400,11 +420,15 @@ static int sht4x_probe(struct i2c_client *client)
> if (!data)
> return -ENOMEM;
>
> + data->chip_id = (uintptr_t)i2c_get_match_data(client);
> data->update_interval = SHT4X_MIN_POLL_INTERVAL;
> data->client = client;
> - data->heater_power = 200;
> - data->heater_time = 1000;
> - data->heating_complete = jiffies;
> + if (data->chip_id != sts4x) {
> + data->heater_power = 200;
> + data->heater_time = 1000;
> + data->heating_complete = jiffies;
> + groups = sht4x_groups;
> + }
[Severity: High]
Since data->heating_complete is bypassed for the sts4x chip, it defaults to 0.
In sht4x_read_values(), the code unconditionally checks this:
curr_jiffies = jiffies;
if (time_before(curr_jiffies, data->heating_complete))
msleep(jiffies_to_msecs(data->heating_complete - curr_jiffies));
Since jiffies is typically initialized to a large negative number at boot, it
evaluates as logically "before" 0.
Will this cause any userspace read of the temperature within the first 5
minutes of system uptime to hang while msleep waits for 0 - curr_jiffies?
[ ... ]
While reviewing this patch, I noticed a few pre-existing issues in the driver:
[Severity: High]
This isn't a bug introduced by this patch, but it looks like the driver lacks
a local mutex to protect I2C transfers.
The hwmon subsystem core only serializes sysfs operations for attributes
registered via the info parameter.
Custom attributes registered via extra_groups (like heater_enable) are not
protected by the hwmon core lock.
If a user writes to heater_enable, it triggers i2c_master_send():
drivers/hwmon/sht4x.c:heater_enable_store() {
...
ret = i2c_master_send(data->client, &cmd, SHT4X_CMD_LEN);
if (ret < 0)
return ret;
data->heating_complete = jiffies + msecs_to_jiffies(heating_time_bound);
data->data_pending = true;
...
}
Can this run concurrently with sht4x_read_values() doing its multi-step
I2C transfers?
drivers/hwmon/sht4x.c:sht4x_read_values() {
...
ret = i2c_master_send(client, cmd, SHT4X_CMD_LEN);
if (ret < 0)
return ret;
usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA);
}
ret = i2c_master_recv(client, raw_data, response_length);
...
}
If so, could this interleave and corrupt the I2C state machine or cause
measurement aborts?
[Severity: High]
This isn't a bug introduced by this patch, but heater_enable_store() returns
0 on success instead of the number of bytes processed (count):
drivers/hwmon/sht4x.c:heater_enable_store() {
...
data->heating_complete = jiffies + msecs_to_jiffies(heating_time_bound);
data->data_pending = true;
return 0;
}
Since standard userspace tools interpret a 0 return from write() as no bytes
consumed, will they loop to retry the write, which will immediately fail with
-EBUSY because data->heating_complete is now in the future?
[Severity: High]
This isn't a bug introduced by this patch, but there appears to be a unit
mismatch when calculating timeouts.
In sht4x_read_values(), data->update_interval (which stores milliseconds)
is added directly to data->heating_complete (which is in jiffies):
drivers/hwmon/sht4x.c:sht4x_read_values() {
...
if (data->data_pending &&
time_before(jiffies, data->heating_complete + data->update_interval)) {
data->data_pending = false;
...
}
On systems with HZ=100, could adding 2000 (the default update_interval)
evaluate to 20 seconds instead of 2 seconds, causing the driver to skip
sending the measurement command and jump straight to i2c_master_recv(),
resulting in I2C NACKs?
Should this be converted using msecs_to_jiffies()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260820145946.35468-1-alessandro.zini@siemens.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series
2026-08-20 14:59 ` [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
2026-08-20 15:03 ` sashiko-bot
@ 2026-08-20 18:06 ` Conor Dooley
1 sibling, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2026-08-20 18:06 UTC (permalink / raw)
To: Alessandro Zini
Cc: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-hwmon, devicetree, linux-doc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-20 18:07 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 14:59 [PATCH 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
2026-08-20 14:59 ` [PATCH 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
2026-08-20 15:03 ` sashiko-bot
2026-08-20 18:06 ` Conor Dooley
2026-08-20 14:59 ` [PATCH 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
2026-08-20 15:08 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox