iio: humidity: hts221: update probe and logging implementations
Subsystems (2)
v2 cover iio: humidity: hts221: update probe and logging implementations
HTS221 is an older driver. This series groups a few small modernizations based on current development practices.
- Report available values via read_avail()
- Add a blank line after variable declarations (style)
- Allow unknown whoami for DT fallback instead of erroring out
- Use dev_err_probe() in probe paths
- Reject calibration data that would cause division by zero
No HTS221 hardware was available. Verified with checkpatch --strict and builds of hts221, hts221_i2c and hts221_spi. Probe and calibration error paths were exercised against i2c-stub with register contents pre-loaded via i2cset.
---
Changes in v2:
- Use a local 'dev' pointer instead of hw->dev in error logging helpers
- Fix punctuation in the commit message of patch 2/5
- Adjust commit message for patch 1/5 to include fixes due to ABI change of in_humidityrelative_oversampling_ratio_available
v1: https://lore.kernel.org/all/[email protected]/
Thanks to the reviewers for all the time you spent going through the code and the comments.
Adi Nata (5):
iio: humidity: hts221: report available values via read_avail()
iio: humidity: hts221: Add a blank line after variable declarations
iio: humidity: hts221: Allow unknown whoami for DT fallback
iio: humidity: hts221: use dev_err_probe() in probe paths
iio: humidity: hts221: fix division by zero in calibration parsing
drivers/iio/humidity/hts221_buffer.c | 1 + drivers/iio/humidity/hts221_core.c | 168 ++++++++++++--------------- drivers/iio/humidity/hts221_i2c.c | 11 +- drivers/iio/humidity/hts221_spi.c | 11 +- 4 files changed, 84 insertions(+), 107 deletions(-)
Signature · 1 line
2.47.3
PATCH v2 1/5 iio: humidity: hts221: report available values via read_avail()
Replace the custom oversampling_ratio_available sysfs attributes with the standard IIO read_avail() callback. This lets the IIO core create and format *_available attributes and exposes the lists to in-kernel consumers.
As a consequence, the incorrectly named in_humidity_oversampling_ratio_available attribute is replaced by the standard in_humidityrelative_oversampling_ratio_available name for the IIO_HUMIDITYRELATIVE channel. The temperature oversampling and sampling frequency available attribute names are unchanged.
--- drivers/iio/humidity/hts221_core.c | 106 +++++++++++------------------ 1 file changed, 40 insertions(+), 66 deletions(-)
drivers/iio/humidity/hts221_core.c +40 -66
@@ -10,7 +10,6 @@#include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> -#include <linux/iio/sysfs.h> #include <linux/delay.h> #include <linux/pm.h> #include <linux/regmap.h>
@@ -49,7 +48,7 @@ struct hts221_odr {struct hts221_avg {u8 addr;u8 mask; -u16 avg_avl[HTS221_AVG_DEPTH ]; +int avg_avl[HTS221_AVG_DEPTH ]; };static const struct hts221_odr hts221_odr_table[] = {
@@ -58,6 +57,8 @@ static const struct hts221_odr hts221_odr_table[] = { { 13, 0x03 }, /* 12.5Hz */ }; +static const int hts221_odr_avail[] = { 1, 7, 13 }; + static const struct hts221_avg hts221_avg_list[] = { { .addr = 0x10,
@@ -97,7 +98,11 @@ static const struct iio_chan_spec hts221_channels[] = {BIT (IIO_CHAN_INFO_OFFSET ) |BIT (IIO_CHAN_INFO_SCALE ) | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ), .scan_index = 0, .scan_type = { .sign = 's',
@@ -113,7 +118,11 @@ static const struct iio_chan_spec hts221_channels[] = {BIT (IIO_CHAN_INFO_OFFSET ) |BIT (IIO_CHAN_INFO_SCALE ) | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ), .scan_index = 1, .scan_type = { .sign = 's',
@@ -192,53 +201,35 @@ static int hts221_update_avg(struct hts221_hw *hw,return 0 ; } -static ssize_t hts221_sysfs_sampling_freq (struct device *dev, -struct device_attribute *attr, -char *buf) -{ -int i; -ssize_t len =0 ; - -for (i =0 ; i <ARRAY_SIZE (hts221_odr_table); i++) - len +=scnprintf (buf + len,PAGE_SIZE - len,"%d " , - hts221_odr_table[i].hz); - buf[len -1 ] ='\n' ; - -return len; -} - -static ssize_t -hts221_sysfs_rh_oversampling_avail (struct device *dev, -struct device_attribute *attr, -char *buf) -{ -const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_H ]; -ssize_t len =0 ; -int i; - -for (i =0 ; i <ARRAY_SIZE (avg->avg_avl); i++) - len +=scnprintf (buf + len,PAGE_SIZE - len,"%d " , - avg->avg_avl[i]); - buf[len -1 ] ='\n' ; - -return len; -} - -static ssize_t -hts221_sysfs_temp_oversampling_avail (struct device *dev, -struct device_attribute *attr, -char *buf) +static int hts221_read_avail (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +const int **vals,int *type,int *length, +long mask) { -const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_T ]; -ssize_t len =0 ; -int i; - -for (i =0 ; i <ARRAY_SIZE (avg->avg_avl); i++) - len +=scnprintf (buf + len,PAGE_SIZE - len,"%d " , - avg->avg_avl[i]); - buf[len -1 ] ='\n' ; - -return len; +switch (mask) { +case IIO_CHAN_INFO_OVERSAMPLING_RATIO : +switch (chan->type) { +case IIO_HUMIDITYRELATIVE : + *vals = hts221_avg_list[HTS221_SENSOR_H ].avg_avl; + *length =ARRAY_SIZE (hts221_avg_list[HTS221_SENSOR_H ].avg_avl); +break ; +case IIO_TEMP : + *vals = hts221_avg_list[HTS221_SENSOR_T ].avg_avl; + *length =ARRAY_SIZE (hts221_avg_list[HTS221_SENSOR_T ].avg_avl); +break ; +default : +return -EINVAL ; + } + *type =IIO_VAL_INT ; +return IIO_AVAIL_LIST ; +case IIO_CHAN_INFO_SAMP_FREQ : + *vals = hts221_odr_avail; + *type =IIO_VAL_INT ; + *length =ARRAY_SIZE (hts221_odr_avail); +return IIO_AVAIL_LIST ; +default : +return -EINVAL ; + } }int hts221_set_enable (struct hts221_hw *hw,bool enable)
@@ -521,27 +512,10 @@ static int hts221_validate_trigger(struct iio_dev *iio_dev,return hw->trig == trig ?0 : -EINVAL ; } -static IIO_DEVICE_ATTR(in_humidity_oversampling_ratio_available, S_IRUGO, - hts221_sysfs_rh_oversampling_avail, NULL, 0); -static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available, S_IRUGO, - hts221_sysfs_temp_oversampling_avail, NULL, 0); -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL (hts221_sysfs_sampling_freq); - -static struct attribute *hts221_attributes[] = { - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_humidity_oversampling_ratio_available.dev_attr.attr, - &iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr, -NULL , -}; - -static const struct attribute_group hts221_attribute_group = { - .attrs = hts221_attributes, -}; -static const struct iio_info hts221_info = { - .attrs = &hts221_attribute_group, .read_raw = hts221_read_raw, .write_raw = hts221_write_raw, + .read_avail = hts221_read_avail, .validate_trigger = hts221_validate_trigger, };
Signature · 1 line
2.47.3
PATCH v2 2/5 iio: humidity: hts221: Add a blank line after variable declarations
In reply to Adi NataImprove code readability per checkpatch warning.
--- drivers/iio/humidity/hts221_buffer.c | 1 + 1 file changed, 1 insertion(+)
drivers/iio/humidity/hts221_buffer.c +1 -0
@@ -194,6 +194,7 @@ static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)int hts221_allocate_buffers (struct iio_dev *iio_dev) {struct hts221_hw *hw =iio_priv (iio_dev); +return devm_iio_triggered_buffer_setup (hw->dev, iio_dev,NULL , hts221_buffer_handler_thread, &hts221_buffer_ops);
Signature · 1 line
2.47.3
PATCH v2 3/5 iio: humidity: hts221: Allow unknown whoami for DT fallback
In reply to Adi NataThe WHOAMI check currently returns -ENODEV when the chip ID is not 0xbc. That rejects Device Tree fallback compatibles.
Keep failing if the WHOAMI register cannot be read. On an unexpected ID, log it and continue so OF fallback matching can work.
Use dev_err_probe() for the read-failure path.
--- drivers/iio/humidity/hts221_core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
drivers/iio/humidity/hts221_core.c +5 -9
@@ -136,19 +136,15 @@ static const struct iio_chan_spec hts221_channels[] = {static int hts221_check_whoami (struct hts221_hw *hw) { +struct device *dev = hw->dev;int err, data; err =regmap_read (hw->regmap,HTS221_REG_WHOAMI_ADDR , &data); -if (err <0 ) { -dev_err (hw->dev,"failed to read whoami register\n" ); -return err; - } +if (err <0 ) +return dev_err_probe (dev, err,"failed to read whoami register\n" ); -if (data !=HTS221_REG_WHOAMI_VAL ) { -dev_err (hw->dev,"wrong whoami {%02x vs %02x}\n" , - data,HTS221_REG_WHOAMI_VAL ); -return -ENODEV ; - } +if (data !=HTS221_REG_WHOAMI_VAL ) +dev_info (dev,"unexpected whoami 0x%02x, continuing\n" , data);return 0 ; }
Signature · 1 line
2.47.3
PATCH v2 4/5 iio: humidity: hts221: use dev_err_probe() in probe paths
In reply to Adi NataConvert remaining probe-time error logs to dev_err_probe() so the errno is included and deferred probe failures stay quiet.
--- drivers/iio/humidity/hts221_core.c | 26 ++++++++------------------ drivers/iio/humidity/hts221_i2c.c | 11 ++++------- drivers/iio/humidity/hts221_spi.c | 11 ++++------- 3 files changed, 16 insertions(+), 32 deletions(-)
drivers/iio/humidity/hts221_core.c +8 -18
@@ -578,33 +578,23 @@ int hts221_probe(struct device *dev, int irq, const char *name,/* configure humidity sensor */ err =hts221_parse_rh_caldata (hw); -if (err <0 ) { -dev_err (hw->dev,"failed to get rh calibration data\n" ); -return err; - } +if (err <0 ) +return dev_err_probe (dev, err,"failed to get rh calibration data\n" ); data = hts221_avg_list[HTS221_SENSOR_H ].avg_avl[3 ]; err =hts221_update_avg (hw,HTS221_SENSOR_H , data); -if (err <0 ) { -dev_err (hw->dev,"failed to set rh oversampling ratio\n" ); -return err; - } +if (err <0 ) +return dev_err_probe (dev, err,"failed to set rh oversampling ratio\n" );/* configure temperature sensor */ err =hts221_parse_temp_caldata (hw); -if (err <0 ) { -dev_err (hw->dev, -"failed to get temperature calibration data\n" ); -return err; - } +if (err <0 ) +return dev_err_probe (dev, err,"failed to get temperature calibration data\n" ); data = hts221_avg_list[HTS221_SENSOR_T ].avg_avl[3 ]; err =hts221_update_avg (hw,HTS221_SENSOR_T , data); -if (err <0 ) { -dev_err (hw->dev, -"failed to set temperature oversampling ratio\n" ); -return err; - } +if (err <0 ) +return dev_err_probe (dev, err,"failed to set temperature oversampling ratio\n" );if (hw->irq >0 ) { err =hts221_allocate_buffers (iio_dev);
drivers/iio/humidity/hts221_i2c.c +4 -7
@@ -26,17 +26,14 @@ static const struct regmap_config hts221_i2c_regmap_config = {static int hts221_i2c_probe (struct i2c_client *client) { +struct device *dev = &client->dev;struct regmap *regmap; regmap =devm_regmap_init_i2c (client, &hts221_i2c_regmap_config); -if (IS_ERR (regmap)) { -dev_err (&client->dev,"Failed to register i2c regmap %ld\n" , -PTR_ERR (regmap)); -return PTR_ERR (regmap); - } +if (IS_ERR (regmap)) +return dev_err_probe (dev,PTR_ERR (regmap),"Failed to register i2c regmap\n" ); -return hts221_probe (&client->dev, client->irq, - client->name, regmap); +return hts221_probe (dev, client->irq, client->name, regmap); }static const struct acpi_device_id hts221_acpi_match[] = {
drivers/iio/humidity/hts221_spi.c +4 -7
@@ -27,17 +27,14 @@ static const struct regmap_config hts221_spi_regmap_config = {static int hts221_spi_probe (struct spi_device *spi) { +struct device *dev = &spi->dev;struct regmap *regmap; regmap =devm_regmap_init_spi (spi, &hts221_spi_regmap_config); -if (IS_ERR (regmap)) { -dev_err (&spi->dev,"Failed to register spi regmap %ld\n" , -PTR_ERR (regmap)); -return PTR_ERR (regmap); - } +if (IS_ERR (regmap)) +return dev_err_probe (dev,PTR_ERR (regmap),"Failed to register spi regmap\n" ); -return hts221_probe (&spi->dev, spi->irq, - spi->modalias, regmap); +return hts221_probe (dev, spi->irq, spi->modalias, regmap); }static const struct of_device_id hts221_spi_of_match[] = {
Signature · 1 line
2.47.3
PATCH v2 5/5 iio: humidity: hts221: fix division by zero in calibration parsing
In reply to Adi Natahts221_parse_rh_caldata() and hts221_parse_temp_caldata() divide by (cal_x1 - cal_x0) without checking that the two calibration points differ can cause division by zero.
Reject zero divisor with -EINVAL, logging the offending calibration values. A device with such calibration data cannot produce meaningful scale or offset values anyway.
--- drivers/iio/humidity/hts221_core.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/iio/humidity/hts221_core.c +22 -0
@@ -245,6 +245,7 @@ int hts221_set_enable(struct hts221_hw *hw, bool enable)static int hts221_parse_temp_caldata (struct hts221_hw *hw) { +struct device *dev = hw->dev;int err, *slope, *b_gen, cal0, cal1;s16 cal_x0, cal_x1, cal_y0, cal_y1;__le16 val;
@@ -275,10 +276,20 @@ static int hts221_parse_temp_caldata(struct hts221_hw *hw)return err; cal_x1 =le16_to_cpu (val); +if (cal_x1 == cal_x0) +return dev_err_probe (dev, -EINVAL , +"invalid temperature calibration points (x0 %d, x1 %d)\n" , + cal_x0, cal_x1); + slope = &hw->sensors[HTS221_SENSOR_T ].slope; b_gen = &hw->sensors[HTS221_SENSOR_T ].b_gen; *slope = ((cal_y1 - cal_y0) *8000 ) / (cal_x1 - cal_x0); +if (!*slope) +return dev_err_probe (dev, -EINVAL , +"invalid temperature calibration slope (y0 %d, y1 %d)\n" , + cal_y0, cal_y1); + *b_gen = (((s32 )cal_x1 * cal_y0 - (s32 )cal_x0 * cal_y1) *1000 ) / (cal_x1 - cal_x0); *b_gen *=8 ;
@@ -288,6 +299,7 @@ static int hts221_parse_temp_caldata(struct hts221_hw *hw)static int hts221_parse_rh_caldata (struct hts221_hw *hw) { +struct device *dev = hw->dev;int err, *slope, *b_gen, data;s16 cal_x0, cal_x1, cal_y0, cal_y1;__le16 val;
@@ -314,10 +326,20 @@ static int hts221_parse_rh_caldata(struct hts221_hw *hw)return err; cal_x1 =le16_to_cpu (val); +if (cal_x1 == cal_x0) +return dev_err_probe (dev, -EINVAL , +"invalid rh calibration points (x0 %d, x1 %d)\n" , + cal_x0, cal_x1); + slope = &hw->sensors[HTS221_SENSOR_H ].slope; b_gen = &hw->sensors[HTS221_SENSOR_H ].b_gen; *slope = ((cal_y1 - cal_y0) *8000 ) / (cal_x1 - cal_x0); +if (!*slope) +return dev_err_probe (dev, -EINVAL , +"invalid rh calibration slope (y0 %d, y1 %d)\n" , + cal_y0, cal_y1); + *b_gen = (((s32 )cal_x1 * cal_y0 - (s32 )cal_x0 * cal_y1) *1000 ) / (cal_x1 - cal_x0); *b_gen *=8 ;
Signature · 1 line
2.47.3
Jonathan Cameron
maintainerQuoted 14 lines · On Thu, 13 Aug 2026 23:31:24 +0800 Adi Nata…
HTS221 is an older driver. This series groups a few small modernizations based on current development practices.
- Report available values via
read_avail()
- Add a blank line after variable declarations (style)
- Allow unknown whoami for DT fallback instead of erroring out
- Usedev_err_probe()in probe paths
- Reject calibration data that would cause division by zeroNo HTS221 hardware was available. Verified with checkpatch --strict and builds of hts221,
hts221_i2candhts221_spi. Probe and calibration error paths were exercised against i2c-stub with register contents pre-loaded via i2cset.
Quoted 7 lines
---
Changes in v2:
- Use a local 'dev' pointer instead ofhw->devin error logging helpers
- Fix punctuation in the commit message of patch 2/5
- Adjust commit message for patch 1/5 to include fixes due to ABI change ofin_humidityrelative_oversampling_ratio_available
Looks like you've fixed up the stuff Andy pointed out in v1 and all looked reasonable to me, so applied to the testing branch of iio.git.
Note that branch will be rebased on 7.3-rc1 once available and only then pushed out for linux-next to pick up.
Thanks,
Jonathan
Quoted 18 lines
v1: https://lore.kernel.org/all/[email protected]/
Thanks to the reviewers for all the time you spent going through the code and the comments.
Adi Nata (5):
iio: humidity: hts221: report available values viaread_avail()
iio: humidity: hts221: Add a blank line after variable declarations
iio: humidity: hts221: Allow unknown whoami for DT fallback
iio: humidity: hts221: usedev_err_probe()in probe paths
iio: humidity: hts221: fix division by zero in calibration parsingdrivers/iio/humidity/hts221_buffer.c | 1 + drivers/iio/humidity/hts221_core.c | 168 ++++++++++++--------------- drivers/iio/humidity/hts221_i2c.c | 11 +- drivers/iio/humidity/hts221_spi.c | 11 +- 4 files changed, 84 insertions(+), 107 deletions(-)
Quoted 9 lines · Adi Nata
HTS221 is an older driver. This series groups a few small modernizations based on current development practices.
- Report available values via
read_avail()
- Add a blank line after variable declarations (style)
- Allow unknown whoami for DT fallback instead of erroring out
- Usedev_err_probe()in probe paths
- Reject calibration data that would cause division by zero
Quoted 4 lines
No HTS221 hardware was available. Verified with checkpatch --strict and builds of hts221,
hts221_i2candhts221_spi. Probe and calibration error paths were exercised against i2c-stub with register contents pre-loaded via i2cset.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 6 lines
Looks like you've fixed up the stuff Andy pointed out in v1 and all looked reasonable to me, so applied to the testing branch of iio.git.
Note that branch will be rebased on 7.3-rc1 once available and only then pushed out for linux-next to pick up.
Reviewed-by Andy Shevchenko <[email protected]>
Thank you for the advice and help.
Regards,
Adi Nata
Jonathan Cameron
maintainerQuoted 9 lines · On Mon, 17 Aug 2026 22:55:17 +0800 Adi <[email protected]>…
Quoted 6 lines
Looks like you've fixed up the stuff Andy pointed out in v1 and all looked reasonable to me, so applied to the testing branch of iio.git.
Note that branch will be rebased on 7.3-rc1 once available and only then pushed out for linux-next to pick up.
Reviewed-by Andy Shevchenko <[email protected]>Thank you for the advice and help.
Added the tag.
Thanks
J
Quoted 2 lines
Regards,
Adi Nata