[PATCH 2/2] hwmon: ina238: use microseconds for update_interval
From: Ferdinand Schwenk via B4 Relay
Date: Fri May 22 2026 - 03:06:21 EST
From: Ferdinand Schwenk <ferdinand.schwenk@xxxxxxxxxxxxx>
The INA238 family supports conversion times as low as 50 us. The
standard hwmon sysfs ABI unit for update_interval is milliseconds,
which causes sub-millisecond conversion times to round to zero and
makes fine-grained control impossible.
Change the unit of chip/update_interval from milliseconds to
microseconds so that all eight conversion-time steps (50, 84, 150,
280, 540, 1052, 2074, 4120 us for INA238 and 66, 118, 310, 566,
1070, 2090, 4140, 8230 us for SQ52206) are accessible without loss
of precision.
Signed-off-by: Ferdinand Schwenk <ferdinand.schwenk@xxxxxxxxxxxxx>
---
drivers/hwmon/ina238.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c
index 7bc18e5445b2..db0c0b5344d6 100644
--- a/drivers/hwmon/ina238.c
+++ b/drivers/hwmon/ina238.c
@@ -310,11 +310,14 @@ static inline u32 ina238_reg_to_interval_us(struct ina238_data *data)
return vbusct + vshct + vtct;
}
-/* Converting update_interval in msec to a single conversion time in usec */
-static inline u32 ina238_interval_ms_to_conv_time(long interval)
+/* Converting update_interval in usec to a single conversion time in usec.
+ * update_interval represents the raw ADC cycle time (VBUSCT + VSHCT + VTCT),
+ * independent of averaging. Since all three fields are always set equal,
+ * the target per-field conversion time is simply interval / 3.
+ */
+static inline u32 ina238_interval_us_to_conv_time(long interval)
{
- /* 3 equal conversion times (VBUSCT, VSHCT, VTCT) cover all measurement types */
- return DIV_ROUND_CLOSEST(interval * 1000, 3);
+ return DIV_ROUND_CLOSEST(interval, 3);
}
static int ina238_read_chip(struct device *dev, u32 attr, long *val)
@@ -327,8 +330,8 @@ static int ina238_read_chip(struct device *dev, u32 attr, long *val)
INA238_ADC_CONFIG_AVG_SHIFT];
return 0;
case hwmon_chip_update_interval:
- /* Return in msec */
- *val = DIV_ROUND_CLOSEST(ina238_reg_to_interval_us(data), 1000);
+ /* Return in usec */
+ *val = ina238_reg_to_interval_us(data);
return 0;
default:
return -EOPNOTSUPP;
@@ -353,7 +356,7 @@ static int ina238_write_chip(struct device *dev, u32 attr, long val)
data->adc_config = adc_config;
return 0;
case hwmon_chip_update_interval:
- val = ina238_interval_ms_to_conv_time(val);
+ val = ina238_interval_us_to_conv_time(val);
idx = find_closest(val, data->config->conv_time,
ARRAY_SIZE(ina238_conv_time));
adc_config = (data->adc_config &
--
2.54.0