* [PATCH v2 0/2] hwmon: Add Sensirion STS4x temperature sensor support
@ 2026-08-21 9:19 Alessandro Zini
2026-08-21 9:19 ` [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
2026-08-21 9:19 ` [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
0 siblings, 2 replies; 5+ messages in thread
From: Alessandro Zini @ 2026-08-21 9:19 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.
Changes in v2:
- Fixed heating_complete initialization in probe to prevent msleep
delays on boot.
- Bypassed heater delay checks in sht4x_read_values() for STS4x.
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 | 62 ++++++++++++++-----
3 files changed, 61 insertions(+), 20 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series
2026-08-21 9:19 [PATCH v2 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
@ 2026-08-21 9:19 ` Alessandro Zini
2026-08-21 9:23 ` sashiko-bot
2026-08-21 9:19 ` [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
1 sibling, 1 reply; 5+ messages in thread
From: Alessandro Zini @ 2026-08-21 9:19 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Alessandro Zini,
Conor Dooley
Add "sensirion,sts40" as compatible for the Sensirion STS4x/STS4xA
series of digital temperature sensors.
Link: https://sensirion.com/resource/datasheet/sts4x
Acked-by: Conor Dooley <conor.dooley@microchip.com>
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] 5+ messages in thread
* [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
2026-08-21 9:19 [PATCH v2 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
2026-08-21 9:19 ` [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
@ 2026-08-21 9:19 ` Alessandro Zini
2026-08-21 9:29 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Alessandro Zini @ 2026-08-21 9:19 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>
---
Changes in v2:
- Unconditionally initialize data->heating_complete in probe to avoid
an msleep delay on boot with INITIAL_JIFFIES.
- Bypass heater delay checks in sht4x_read_values() when chip is sts4x.
Documentation/hwmon/sht4x.rst | 17 ++++++++--
drivers/hwmon/sht4x.c | 62 +++++++++++++++++++++++++----------
2 files changed, 59 insertions(+), 20 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..daca24cfbcd52 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,11 +100,15 @@ 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;
- if (time_before(curr_jiffies, data->heating_complete))
- msleep(jiffies_to_msecs(data->heating_complete - curr_jiffies));
+ if (data->chip_id != sts4x) {
+ curr_jiffies = jiffies;
+ if (time_before(curr_jiffies, data->heating_complete))
+ msleep(jiffies_to_msecs(data->heating_complete - curr_jiffies));
+ }
if (data->data_pending &&
time_before(jiffies, data->heating_complete + data->update_interval)) {
@@ -115,15 +127,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 +142,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 +206,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 +403,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 +422,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;
+ groups = sht4x_groups;
+ }
crc8_populate_msb(sht4x_crc8_table, SHT4X_CRC8_POLYNOMIAL);
@@ -418,19 +444,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] 5+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series
2026-08-21 9:19 ` [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
@ 2026-08-21 9:23 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-21 9:23 UTC (permalink / raw)
To: Alessandro Zini; +Cc: robh, conor+dt, linux-hwmon, devicetree
> Add "sensirion,sts40" as compatible for the Sensirion STS4x/STS4xA
> series of digital temperature sensors.
>
> Link: https://sensirion.com/resource/datasheet/sts4x
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> 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/20260821091924.18975-1-alessandro.zini@siemens.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors
2026-08-21 9:19 ` [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
@ 2026-08-21 9:29 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-21 9:29 UTC (permalink / raw)
To: Alessandro Zini; +Cc: linux-hwmon, robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Sysfs heater attributes registered via extra_groups lack required hwmon locking, causing data races and I2C command interleaving.
- [High] `heater_enable_store` incorrectly returns 0 on success, triggering user-space write loops and false `-EBUSY` errors.
--
--- Patch [2]: [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors ---
commit 19dd0dd408d1f2465639b63b05819b57f722bbcb
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. It shares the same I2C command set, conversion formulas, CRC
checksum, and timing with the SHT4x, but only returns temperature data.
Add support for the STS4x series by dynamically adjusting the read
response length and suppressing humidity and heater sysfs attributes.
Link: https://sensirion.com/resource/datasheet/sts4x
> diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
> index 9cace0e8acdab..daca24cfbcd52 100644
> --- a/drivers/hwmon/sht4x.c
> +++ b/drivers/hwmon/sht4x.c
[ ... ]
> @@ -418,19 +444,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);
> }
[Severity: High]
This is a pre-existing issue, but registering heater attributes via
extra_groups here escapes the hwmon core serialization.
Are the heater sysfs callbacks (heater_enable_store, heater_power_store,
and heater_time_store) exposed to data races without the hwmon lock?
If a user-space process reads hwmon data while another process enables
the heater, heater_enable_store() executes without holding
hwmon_lock(dev). This can interleave I2C commands and mutate shared
state (data->heating_complete and data->data_pending) concurrently
with sht4x_read_values(), leading to corrupted I2C sequences.
[Severity: High]
This is also a pre-existing issue, but could the return value in
heater_enable_store() cause an unexpected write failure in user-space?
When the heater is successfully enabled, the function returns 0
instead of count:
drivers/hwmon/sht4x.c:heater_enable_store() {
...
data->heating_complete = jiffies + msecs_to_jiffies(heating_time_bound);
data->data_pending = true;
return 0;
}
Returning 0 signals to VFS that no bytes were processed. Standard
user-space tools will retry the write with the remaining bytes. On the
retry, time_before(jiffies, data->heating_complete) evaluates to true,
and the function immediately fails with -EBUSY.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260821091924.18975-1-alessandro.zini@siemens.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-21 9:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 9:19 [PATCH v2 0/2] hwmon: Add Sensirion STS4x temperature sensor support Alessandro Zini
2026-08-21 9:19 ` [PATCH v2 1/2] dt-bindings: trivial-devices: Add Sensirion STS4x series Alessandro Zini
2026-08-21 9:23 ` sashiko-bot
2026-08-21 9:19 ` [PATCH v2 2/2] hwmon: (sht4x): Add support for Sensirion STS4x temperature sensors Alessandro Zini
2026-08-21 9:29 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox