* [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604
@ 2026-05-14 14:46 Liviu Stan
2026-05-14 14:46 ` [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename Liviu Stan
` (6 more replies)
0 siblings, 7 replies; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Liviu Stan, Francesco Lavra, linux-iio,
linux-kernel, linux, devicetree
This series adds support for the ADT7604 multi-sensor temperature
measurement and leak detection system to the existing ltc2983 driver.
The ADT7604 shares the same die as the LTC2984, reusing its register
map and SPI interface. It repurposes the custom RTD sensor type (18)
as a copper trace resistance sensor and the custom thermistor type (27)
as a leak detector, removing thermocouple, diode and direct ADC support.
Patches 1-4 fix pre-existing bugs in the ltc2983 driver: macro
parenthesization and renaming, inconsistent use of the local device
pointer, inconsistent channel wording in log messages, and missing
fwnode_property_present() guards for optional properties.
Patch 5 adds IIO_COVERAGE_PERCENT, a new channel type for sensors
reporting fractional surface coverage as a percentage.
Patch 6 updates the device tree bindings: adds adi,adt7604 compatible,
copper-trace@ and leak-detector@ sensor node types with their respective
properties, and an ADT7604 example.
Patch 7 updates the driver: introduces two new software sensor type
values (LTC2983_SENSOR_COPPER_TRACE = 32, LTC2983_SENSOR_LEAK_DETECTOR
= 33) with dedicated structs and parser functions rather than extending
the existing RTD and thermistor paths. The hardware configuration bits
are fully hardcoded for both sensor types, and several RTD/thermistor
DT properties have no meaning for them. A u64 supported_sensors bitmask
in ltc2983_chip_info gates sensor type validation per chip, replacing
the has_temp bool pattern. BIT_ULL() is used for the new type values
at bits 32 and 33 to avoid shifting beyond 32 bits on 32-bit builds.
Tested on EVAL-ADT7604-AZ connected to Raspberry Pi 5 via SPI.
Changes in v2:
- Patches 1-4: new prerequisite fix patches addressing review comments
on the v1 driver patch.
- Patch 5: new IIO_COVERAGE_PERCENT channel type; replaces the v1
IIO_TEMP workaround for leak detector coverage output.
- Patch 6 (binding):
- Title shortened to "LTC2983 and similar".
- Description device list alphabetised and converted to a bullet list.
- Separate copper-trace@ and leak-detector@ node types retained
(rather than extending rtd@/thermistor@); rationale added to the
commit message.
- "ADT7604 only" wording replaced with "some parts only".
- Patch 7 (driver):
- New software sensor type values LTC2983_SENSOR_COPPER_TRACE = 32
and LTC2983_SENSOR_LEAK_DETECTOR = 33 map to hardware register
values 18 and 27 internally; v1 exposed 18 and 27 directly as
adi,sensor-type values.
- Added n_iio_chan to struct ltc2983_sensor; used in
ltc2983_parse_fw() and ltc2983_setup() to count and assign IIO
channels, removing to_rtd()/to_thermistor() casts from the common
path.
- New sensor types with dedicated structs and functions;
ltc2983_rtd_new() and ltc2983_thermistor_new() are left unchanged.
- has_copper_trace bool replaced by u64 supported_sensors bitmask.
- Both sensor types now share the same 1/1024 resistance scale
(result in ohms); v1 used different scales and incorrectly
described the copper trace result as being in mohms. Since the
sense resistor value is specified in ohms, the output will be in
ohms for both sensor types.
- Leak detector coverage output changed from IIO_TEMP to
IIO_COVERAGE_PERCENT.
- is_sub_ohm replaces sub_ohm in ltc2983_copper_trace struct.
- switch() used for IIO_CHAN_INFO_RAW base register selection.
- Unsupported sensor type validation uses BIT_ULL() checks against
the supported_sensors bitmask.
Liviu Stan (7):
iio: temperature: ltc2983: Fix macro parenthesization and rename
iio: temperature: ltc2983: Use local device pointer consistently
iio: temperature: ltc2983: Fix inconsistent channel wording in
messages
iio: temperature: ltc2983: Use fwnode_property_present() for optional
properties
iio: core: Add IIO_COVERAGE_PERCENT channel type
dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
iio: temperature: ltc2983: Add support for ADT7604
Documentation/ABI/testing/sysfs-bus-iio | 10 +
.../bindings/iio/temperature/adi,ltc2983.yaml | 194 ++++++-
drivers/iio/industrialio-core.c | 1 +
drivers/iio/temperature/ltc2983.c | 532 +++++++++++++++---
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 1 +
6 files changed, 666 insertions(+), 73 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 19:32 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently Liviu Stan
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Francesco Lavra, Liviu Stan, linux-iio,
linux-kernel, linux, devicetree
Wrap the 'chan' parameter in LTC2983_CHAN_START_ADDR() and
LTC2983_CHAN_RES_ADDR() with parentheses to prevent potential
macro argument expansion issues. Also rename LTC2983_CHAN_START_ADDR
to LTC2983_CHAN_ASSIGN_ADDR and LTC2983_CHAN_RES_ADDR to
LTC2983_RESULT_ADDR, to better reflect the datasheet names and avoid
them being confused as related.
Fixes: f110f3188e5639c81c457b2b831d40dfe3891bdb ("iio: temperature: Add support for LTC2983")
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New patch.
drivers/iio/temperature/ltc2983.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index 38e6f8dfd3b8..a292274e6ff0 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -56,10 +56,10 @@
#define LTC2983_EEPROM_WRITE_TIME_MS 2600
#define LTC2983_EEPROM_READ_TIME_MS 20
-#define LTC2983_CHAN_START_ADDR(chan) \
- (((chan - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
-#define LTC2983_CHAN_RES_ADDR(chan) \
- (((chan - 1) * 4) + LTC2983_TEMP_RES_START_REG)
+#define LTC2983_CHAN_ASSIGN_ADDR(chan) \
+ ((((chan) - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
+#define LTC2983_RESULT_ADDR(chan, base) \
+ ((((chan) - 1) * 4) + (base))
#define LTC2983_THERMOCOUPLE_DIFF_MASK BIT(3)
#define LTC2983_THERMOCOUPLE_SGL(x) \
FIELD_PREP(LTC2983_THERMOCOUPLE_DIFF_MASK, x)
@@ -351,7 +351,7 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st,
const struct ltc2983_sensor *sensor,
u32 chan_val)
{
- u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan);
+ u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan);
chan_val |= LTC2983_CHAN_TYPE(sensor->type);
dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
@@ -1197,7 +1197,7 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
}
/* read the converted data */
- ret = regmap_bulk_read(st->regmap, LTC2983_CHAN_RES_ADDR(sensor->chan),
+ ret = regmap_bulk_read(st->regmap, LTC2983_RESULT_ADDR(sensor->chan, base_reg),
&st->temp, sizeof(st->temp));
if (ret)
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
2026-05-14 14:46 ` [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 19:39 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages Liviu Stan
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Francesco Lavra, Liviu Stan, linux-iio,
linux-kernel, linux, devicetree
Some functions define a local 'dev' pointer but still use bare
'&st->spi->dev' in some code paths, and some don't have it at all.
Replace all bare references with the local pointer for consistency.
Fixes: f110f3188e5639c81c457b2b831d40dfe3891bdb ("iio: temperature: Add support for LTC2983")
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New patch.
drivers/iio/temperature/ltc2983.c | 81 ++++++++++++++++++-------------
1 file changed, 46 insertions(+), 35 deletions(-)
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index a292274e6ff0..e74ea4f87ec9 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -351,6 +351,7 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st,
const struct ltc2983_sensor *sensor,
u32 chan_val)
{
+ struct device *dev = &st->spi->dev;
u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan);
chan_val |= LTC2983_CHAN_TYPE(sensor->type);
@@ -656,11 +657,12 @@ static struct ltc2983_sensor *
ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
+ struct device *dev = &st->spi->dev;
struct ltc2983_thermocouple *thermo;
u32 oc_current;
int ret;
- thermo = devm_kzalloc(&st->spi->dev, sizeof(*thermo), GFP_KERNEL);
+ thermo = devm_kzalloc(dev, sizeof(*thermo), GFP_KERNEL);
if (!thermo)
return ERR_PTR(-ENOMEM);
@@ -687,7 +689,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
LTC2983_THERMOCOUPLE_OC_CURR(3);
break;
default:
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid open circuit current:%u\n",
oc_current);
}
@@ -697,7 +699,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
/* validate channel index */
if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chann:%d for differential thermocouple\n",
sensor->chan);
@@ -712,7 +714,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
* This would be caught later but we can just return
* the error right away.
*/
- return dev_err_ptr_probe(&st->spi->dev, ret,
+ return dev_err_ptr_probe(dev, ret,
"Property reg must be given\n");
}
@@ -823,7 +825,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
} else {
/* same as differential case */
if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chann:%d for RTD\n",
sensor->chan);
}
@@ -873,7 +875,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
rtd->excitation_current = 0x08;
break;
default:
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid value for excitation current(%u)\n",
excitation_current);
}
@@ -922,7 +924,7 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s
/* validate channel index */
if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chann:%d for differential thermistor\n",
sensor->chan);
@@ -964,7 +966,7 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s
case 0:
/* auto range */
if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Auto Range not allowed for custom sensors\n");
thermistor->excitation_current = 0x0c;
@@ -1003,7 +1005,7 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s
thermistor->excitation_current = 0x0b;
break;
default:
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid value for excitation current(%u)\n",
excitation_current);
}
@@ -1016,11 +1018,12 @@ static struct ltc2983_sensor *
ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
+ struct device *dev = &st->spi->dev;
struct ltc2983_diode *diode;
u32 temp = 0, excitation_current = 0;
int ret;
- diode = devm_kzalloc(&st->spi->dev, sizeof(*diode), GFP_KERNEL);
+ diode = devm_kzalloc(dev, sizeof(*diode), GFP_KERNEL);
if (!diode)
return ERR_PTR(-ENOMEM);
@@ -1036,7 +1039,7 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *
/* validate channel index */
if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chann:%d for differential thermistor\n",
sensor->chan);
@@ -1061,7 +1064,7 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *
diode->excitation_current = 0x03;
break;
default:
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid value for excitation current(%u)\n",
excitation_current);
}
@@ -1079,23 +1082,24 @@ static struct ltc2983_sensor *ltc2983_r_sense_new(struct fwnode_handle *child,
struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
+ struct device *dev = &st->spi->dev;
struct ltc2983_rsense *rsense;
int ret;
u32 temp;
- rsense = devm_kzalloc(&st->spi->dev, sizeof(*rsense), GFP_KERNEL);
+ rsense = devm_kzalloc(dev, sizeof(*rsense), GFP_KERNEL);
if (!rsense)
return ERR_PTR(-ENOMEM);
/* validate channel index */
if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chann:%d for r_sense\n",
sensor->chan);
ret = fwnode_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp);
if (ret)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Property adi,rsense-val-milli-ohms missing\n");
/*
* Times 1000 because we have milli-ohms and __convert_to_raw
@@ -1115,9 +1119,10 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child,
struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
+ struct device *dev = &st->spi->dev;
struct ltc2983_adc *adc;
- adc = devm_kzalloc(&st->spi->dev, sizeof(*adc), GFP_KERNEL);
+ adc = devm_kzalloc(dev, sizeof(*adc), GFP_KERNEL);
if (!adc)
return ERR_PTR(-ENOMEM);
@@ -1125,7 +1130,7 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child,
adc->single_ended = true;
if (!adc->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chan:%d for differential adc\n",
sensor->chan);
@@ -1140,9 +1145,10 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
+ struct device *dev = &st->spi->dev;
struct ltc2983_temp *temp;
- temp = devm_kzalloc(&st->spi->dev, sizeof(*temp), GFP_KERNEL);
+ temp = devm_kzalloc(dev, sizeof(*temp), GFP_KERNEL);
if (!temp)
return ERR_PTR(-ENOMEM);
@@ -1150,7 +1156,7 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
temp->single_ended = true;
if (!temp->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
- return dev_err_ptr_probe(&st->spi->dev, -EINVAL,
+ return dev_err_ptr_probe(dev, -EINVAL,
"Invalid chan:%d for differential temp\n",
sensor->chan);
@@ -1169,13 +1175,14 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
static int ltc2983_chan_read(struct ltc2983_data *st,
const struct ltc2983_sensor *sensor, int *val)
{
+ struct device *dev = &st->spi->dev;
u32 start_conversion = 0;
int ret;
unsigned long time;
start_conversion = LTC2983_STATUS_START(true);
start_conversion |= LTC2983_STATUS_CHAN_SEL(sensor->chan);
- dev_dbg(&st->spi->dev, "Start conversion on chan:%d, status:%02X\n",
+ dev_dbg(dev, "Start conversion on chan:%d, status:%02X\n",
sensor->chan, start_conversion);
/* start conversion */
ret = regmap_write(st->regmap, LTC2983_STATUS_REG, start_conversion);
@@ -1192,7 +1199,7 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
time = wait_for_completion_timeout(&st->completion,
msecs_to_jiffies(300));
if (!time) {
- dev_warn(&st->spi->dev, "Conversion timed out\n");
+ dev_warn(dev, "Conversion timed out\n");
return -ETIMEDOUT;
}
@@ -1205,7 +1212,7 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
*val = __be32_to_cpu(st->temp);
if (!(LTC2983_RES_VALID_MASK & *val)) {
- dev_err(&st->spi->dev, "Invalid conversion detected\n");
+ dev_err(dev, "Invalid conversion detected\n");
return -EIO;
}
@@ -1222,11 +1229,12 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct ltc2983_data *st = iio_priv(indio_dev);
+ struct device *dev = &st->spi->dev;
int ret;
/* sanity check */
if (chan->address >= st->num_channels) {
- dev_err(&st->spi->dev, "Invalid chan address:%ld",
+ dev_err(dev, "Invalid chan address:%ld",
chan->address);
return -EINVAL;
}
@@ -1303,7 +1311,7 @@ static int ltc2983_parse_fw(struct ltc2983_data *st)
st->num_channels = device_get_child_node_count(dev);
if (!st->num_channels)
- return dev_err_probe(&st->spi->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"At least one channel must be given!\n");
st->sensors = devm_kcalloc(dev, st->num_channels, sizeof(*st->sensors),
@@ -1391,6 +1399,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
unsigned int wait_time, unsigned int status_reg,
unsigned long status_fail_mask)
{
+ struct device *dev = &st->spi->dev;
unsigned long time;
unsigned int val;
int ret;
@@ -1410,7 +1419,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
time = wait_for_completion_timeout(&st->completion,
msecs_to_jiffies(wait_time));
if (!time)
- return dev_err_probe(&st->spi->dev, -ETIMEDOUT,
+ return dev_err_probe(dev, -ETIMEDOUT,
"EEPROM command timed out\n");
ret = regmap_read(st->regmap, status_reg, &val);
@@ -1418,7 +1427,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
return ret;
if (val & status_fail_mask)
- return dev_err_probe(&st->spi->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"EEPROM command failed: 0x%02X\n", val);
return 0;
@@ -1427,6 +1436,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
{
u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status;
+ struct device *dev = &st->spi->dev;
int ret;
/* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */
@@ -1434,7 +1444,7 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
LTC2983_STATUS_UP(status) == 1, 25000,
25000 * 10);
if (ret)
- return dev_err_probe(&st->spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Device startup timed out\n");
ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG,
@@ -1535,12 +1545,13 @@ static const struct iio_info ltc2983_iio_info = {
static int ltc2983_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct ltc2983_data *st;
struct iio_dev *indio_dev;
struct gpio_desc *gpio;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1552,7 +1563,7 @@ static int ltc2983_probe(struct spi_device *spi)
st->regmap = devm_regmap_init_spi(spi, <c2983_regmap_config);
if (IS_ERR(st->regmap))
- return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
+ return dev_err_probe(dev, PTR_ERR(st->regmap),
"Failed to initialize regmap\n");
mutex_init(&st->lock);
@@ -1565,11 +1576,11 @@ static int ltc2983_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_regulator_get_enable(&spi->dev, "vdd");
+ ret = devm_regulator_get_enable(dev, "vdd");
if (ret)
return ret;
- gpio = devm_gpiod_get_optional(&st->spi->dev, "reset", GPIOD_OUT_HIGH);
+ gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
@@ -1579,7 +1590,7 @@ static int ltc2983_probe(struct spi_device *spi)
gpiod_set_value_cansleep(gpio, 0);
}
- st->iio_chan = devm_kzalloc(&spi->dev,
+ st->iio_chan = devm_kzalloc(dev,
st->iio_channels * sizeof(*st->iio_chan),
GFP_KERNEL);
if (!st->iio_chan)
@@ -1589,10 +1600,10 @@ static int ltc2983_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
+ ret = devm_request_irq(dev, spi->irq, ltc2983_irq_handler,
IRQF_TRIGGER_RISING, st->info->name, st);
if (ret)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"failed to request an irq\n");
if (st->info->has_eeprom) {
@@ -1610,7 +1621,7 @@ static int ltc2983_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = <c2983_iio_info;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static int ltc2983_resume(struct device *dev)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
2026-05-14 14:46 ` [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename Liviu Stan
2026-05-14 14:46 ` [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 19:47 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties Liviu Stan
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Liviu Stan, Francesco Lavra, linux-iio,
linux-kernel, linux, devicetree
Replace all occurrences of the abbreviated 'chann' and 'chan' with
'channel' in error and debug messages throughout the driver.
Fixes: f110f3188e5639c81c457b2b831d40dfe3891bdb ("iio: temperature: Add support for LTC2983")
Fixes: a00838cae079b9b9b90969c2b7b031b1bfd9ab3a ("iio: temperature: ltc2983: convert to dev_err_probe()")
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New patch.
drivers/iio/temperature/ltc2983.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index e74ea4f87ec9..f42777c1f3c2 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -700,7 +700,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for differential thermocouple\n",
+ "Invalid channel %d for differential thermocouple\n",
sensor->chan);
struct fwnode_handle *ref __free(fwnode_handle) =
@@ -798,7 +798,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
/*
* rtd channel indexes are a bit more complicated to validate.
* For 4wire RTD with rotation, the channel selection cannot be
- * >=19 since the chann + 1 is used in this configuration.
+ * >=19 since the channel + 1 is used in this configuration.
* For 4wire RTDs with kelvin rsense, the rsense channel cannot be
* <=1 since channel - 1 and channel - 2 are used.
*/
@@ -815,18 +815,18 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
(rtd->r_sense_chan <= min))
/* kelvin rsense*/
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid rsense chann:%d to use in kelvin rsense\n",
+ "Invalid channel %d for kelvin rsense\n",
rtd->r_sense_chan);
if (sensor->chan < min || sensor->chan > max)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for the rtd config\n",
+ "Invalid channel %d for RTD config\n",
sensor->chan);
} else {
/* same as differential case */
if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for RTD\n",
+ "Invalid channel %d for RTD\n",
sensor->chan);
}
@@ -925,7 +925,7 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s
if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for differential thermistor\n",
+ "Invalid channel %d for differential thermistor\n",
sensor->chan);
/* check custom sensor */
@@ -1040,7 +1040,7 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *
if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) &&
sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for differential thermistor\n",
+ "Invalid channel %d for differential thermistor\n",
sensor->chan);
/* set common parameters */
@@ -1094,7 +1094,7 @@ static struct ltc2983_sensor *ltc2983_r_sense_new(struct fwnode_handle *child,
/* validate channel index */
if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chann:%d for r_sense\n",
+ "Invalid channel %d for r_sense\n",
sensor->chan);
ret = fwnode_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp);
@@ -1131,7 +1131,7 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child,
if (!adc->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chan:%d for differential adc\n",
+ "Invalid channel %d for differential ADC\n",
sensor->chan);
/* set common parameters */
@@ -1157,7 +1157,7 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
if (!temp->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
return dev_err_ptr_probe(dev, -EINVAL,
- "Invalid chan:%d for differential temp\n",
+ "Invalid channel %d for differential temp\n",
sensor->chan);
temp->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-temp",
@@ -1182,7 +1182,7 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
start_conversion = LTC2983_STATUS_START(true);
start_conversion |= LTC2983_STATUS_CHAN_SEL(sensor->chan);
- dev_dbg(dev, "Start conversion on chan:%d, status:%02X\n",
+ dev_dbg(dev, "Start conversion on channel:%d, status:%02X\n",
sensor->chan, start_conversion);
/* start conversion */
ret = regmap_write(st->regmap, LTC2983_STATUS_REG, start_conversion);
@@ -1234,7 +1234,7 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev,
/* sanity check */
if (chan->address >= st->num_channels) {
- dev_err(dev, "Invalid chan address:%ld",
+ dev_err(dev, "Invalid channel address: %ld\n",
chan->address);
return -EINVAL;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
` (2 preceding siblings ...)
2026-05-14 14:46 ` [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 20:04 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type Liviu Stan
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Liviu Stan, Francesco Lavra, linux-iio,
linux-kernel, linux, devicetree
Checking fwnode_property_read_u32() return value with if (!ret)
silently swallows meaningful error codes when a property is present
but malformed. Use fwnode_property_present() first so that absence
uses the default while a present but unreadable property returns
a proper error.
Fixes: f110f3188e5639c81c457b2b831d40dfe3891bdb ("iio: temperature: Add support for LTC2983")
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New patch.
drivers/iio/temperature/ltc2983.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index f42777c1f3c2..bf435e965c6d 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -669,8 +669,14 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
if (fwnode_property_read_bool(child, "adi,single-ended"))
thermo->sensor_config = LTC2983_THERMOCOUPLE_SGL(1);
- ret = fwnode_property_read_u32(child, "adi,sensor-oc-current-microamp", &oc_current);
- if (!ret) {
+ if (fwnode_property_present(child, "adi,sensor-oc-current-microamp")) {
+ ret = fwnode_property_read_u32(child,
+ "adi,sensor-oc-current-microamp",
+ &oc_current);
+ if (ret)
+ return dev_err_ptr_probe(dev, ret,
+ "Failed to read adi,sensor-oc-current-microamp\n");
+
switch (oc_current) {
case 10:
thermo->sensor_config |=
@@ -760,8 +766,12 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
return dev_err_ptr_probe(dev, ret,
"Property reg must be given\n");
- ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires);
- if (!ret) {
+ if (fwnode_property_present(child, "adi,number-of-wires")) {
+ ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires);
+ if (ret)
+ return dev_err_ptr_probe(dev, ret,
+ "Failed to read adi,number-of-wires\n");
+
switch (n_wires) {
case 2:
rtd->sensor_config = LTC2983_RTD_N_WIRES(0);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
` (3 preceding siblings ...)
2026-05-14 14:46 ` [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 20:16 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983 Liviu Stan
2026-05-14 14:46 ` [PATCH v2 7/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Liviu Stan, Francesco Lavra, linux-iio,
linux-kernel, linux, devicetree
Add a new channel type for sensors that report fractional coverage as
a percentage. The first user is the ADT7604 leak detector, where the
value represents the portion of the sensing element that is wetted.
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New patch.
Documentation/ABI/testing/sysfs-bus-iio | 10 ++++++++++
drivers/iio/industrialio-core.c | 1 +
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 1 +
4 files changed, 13 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 925a33fd309a..0570e8b8f5e5 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1980,6 +1980,16 @@ Description:
Raw (unscaled no offset etc.) resistance reading.
Units after application of scale and offset are ohms.
+What: /sys/bus/iio/devices/iio:deviceX/in_coveragepercentX_raw
+KernelVersion: 6.15
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw (unscaled no offset etc.) coverage reading. Used for sensors
+ that report fractional coverage as a percentage, such as leak
+ detectors where the value represents what portion of the sensing
+ element is wetted. Units after application of scale and offset are
+ percent.
+
What: /sys/bus/iio/devices/iio:deviceX/heater_enable
KernelVersion: 4.1.0
Contact: linux-iio@vger.kernel.org
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index bd6f4f9f4533..ee8ffa2cfbc5 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -98,6 +98,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CHROMATICITY] = "chromaticity",
[IIO_ATTENTION] = "attention",
[IIO_ALTCURRENT] = "altcurrent",
+ [IIO_COVERAGE_PERCENT] = "coveragepercent",
};
static const char * const iio_modifier_names[] = {
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index d7c2bb223651..39830dc0cfb1 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -53,6 +53,7 @@ enum iio_chan_type {
IIO_CHROMATICITY,
IIO_ATTENTION,
IIO_ALTCURRENT,
+ IIO_COVERAGE_PERCENT,
};
enum iio_modifier {
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index df6c43d7738d..3339be7fe32c 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CHROMATICITY] = "chromaticity",
[IIO_ATTENTION] = "attention",
[IIO_ALTCURRENT] = "altcurrent",
+ [IIO_COVERAGE_PERCENT] = "coveragepercent",
};
static const char * const iio_ev_type_text[] = {
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
` (4 preceding siblings ...)
2026-05-14 14:46 ` [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
2026-05-14 20:43 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 7/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
6 siblings, 1 reply; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Francesco Lavra, Liviu Stan, linux-iio,
linux-kernel, linux, devicetree
The ADT7604 shares the same die as the LTC2984. It repurposes the
custom RTD sensor type (18) as a copper trace resistance sensor
and the custom thermistor type (27) as a leak detector, and
removes thermocouple, diode and direct ADC sensor types.
Add adi,adt7604 to the compatible list and introduce two new
sensor node types specific to this device:
- copper-trace@: maps to the custom RTD sensor type (18). Two
variants: sub-ohm (< 1 ohm, adi,copper-trace-sub-ohm boolean,
no custom table and excitation current) and standard (> 1 ohm,
optional adi,custom-rtd table, optional excitation current
defaulting to the datasheet recommended value). Primary output
is resistance in ohms. When a custom table is provided, the
chip also outputs temperature in millidegrees Celsius.
- leak-detector@: maps to the custom thermistor sensor type (27).
Takes an optional adi,custom-leak-detector lookup table encoding
resistance (uOhm) against coverage data. Primary output is
resistance in ohms. When a custom table is provided, the chip
also outputs coverage in percent.
Separate node types are used rather than extending the existing
rtd@ and thermistor@ nodes because adi,custom-rtd and
adi,custom-thermistor are currently required for types 18 and 27,
and several properties (adi,number-of-wires, adi,rtd-curve,
adi,rsense-share) have no meaning for copper trace and would need
to be explicitly forbidden or ignored in the driver.
allOf conditions are added to restrict thermocouple, diode, direct
ADC and active temperature nodes to non-ADT7604 devices, and to
restrict copper-trace and leak-detector nodes to the ADT7604
(some parts only).
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- Shortened title to "LTC2983 and similar".
- Converted device description list to bullet list in alphabetical
order.
- Retained separate copper-trace@ and leak-detector@ node types rather
than extending rtd@/thermistor@; rationale added to commit message.
- Replaced "ADT7604 only" with "some parts only".
.../bindings/iio/temperature/adi,ltc2983.yaml | 194 +++++++++++++++++-
1 file changed, 191 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
index a22725f7619b..c63b69bd9504 100644
--- a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
+++ b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
@@ -4,14 +4,18 @@
$id: http://devicetree.org/schemas/iio/temperature/adi,ltc2983.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Analog Devices LTC2983, LTC2986, LTM2985 Multi-sensor Temperature system
+title: Analog Devices LTC2983 and similar Multi-sensor Temperature systems
maintainers:
- Nuno Sá <nuno.sa@analog.com>
description: |
- Analog Devices LTC2983, LTC2984, LTC2986, LTM2985 Multi-Sensor Digital
- Temperature Measurement Systems
+ Analog Devices Multi-Sensor Digital Temperature Measurement Systems:
+ - ADT7604
+ - LTC2983
+ - LTC2984
+ - LTC2986
+ - LTM2985
https://www.analog.com/media/en/technical-documentation/data-sheets/2983fc.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/2984fb.pdf
@@ -43,6 +47,7 @@ properties:
compatible:
oneOf:
- enum:
+ - adi,adt7604
- adi,ltc2983
- adi,ltc2986
- adi,ltm2985
@@ -436,6 +441,115 @@ patternProperties:
required:
- adi,custom-temp
+ '^copper-trace@':
+ $ref: '#/$defs/sensor-node'
+ unevaluatedProperties: false
+ description: |
+ Copper trace resistance sensor (some parts only). Two variants exist:
+ sub-ohm (< 1 ohm, no custom table allowed) and standard (> 1 ohm,
+ optional custom table).
+
+ properties:
+ reg:
+ minimum: 2
+ maximum: 20
+
+ adi,sensor-type:
+ description: Sensor type for copper trace sensors.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ const: 32
+
+ adi,rsense-handle:
+ description: Associated sense resistor sensor.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ adi,copper-trace-sub-ohm:
+ description:
+ Select the sub-ohm (< 1 ohm) copper trace variant. Custom table
+ and excitation current are not allowed in this mode.
+ type: boolean
+
+ adi,excitation-current-microamp:
+ description:
+ Excitation current applied to the copper trace. Not used in
+ sub-ohm mode. The datasheet recommends 1mA for copper trace
+ sensors due to their typically small resistance.
+ enum: [5, 10, 25, 50, 100, 250, 500, 1000]
+ default: 1000
+
+ adi,custom-rtd:
+ description:
+ Optional resistance-to-temperature table for copper trace sensors
+ with resistance > 1 ohm. See Page 62 of the datasheet.
+ $ref: /schemas/types.yaml#/definitions/uint64-matrix
+ minItems: 3
+ maxItems: 64
+ items:
+ items:
+ - description: Resistance point in uOhms.
+ - description: Temperature point in uK.
+
+ required:
+ - adi,rsense-handle
+
+ allOf:
+ - if:
+ required:
+ - adi,copper-trace-sub-ohm
+ then:
+ properties:
+ adi,custom-rtd: false
+ adi,excitation-current-microamp: false
+
+ '^leak-detector@':
+ $ref: '#/$defs/sensor-node'
+ unevaluatedProperties: false
+ description: |
+ Leak detector sensor (some parts only). Outputs resistance in ohms and,
+ when a custom table is provided, a coverage percentage via
+ IIO_COVERAGE_PERCENT (raw/1024 = coverage %).
+
+ properties:
+ reg:
+ minimum: 2
+ maximum: 20
+
+ adi,sensor-type:
+ description: Sensor type for leak detector sensors.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ const: 33
+
+ adi,rsense-handle:
+ description: Associated sense resistor sensor.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ adi,excitation-current-nanoamp:
+ description:
+ Excitation current applied to the leak detector. The correct value
+ depends on the electrical characteristics of the liquid being sensed.
+ For example, 10000 (10µA) is recommended for PG25 (see datasheet
+ Table 39).
+ enum: [250, 500, 1000, 5000, 10000, 25000, 50000, 100000, 250000,
+ 500000, 1000000]
+
+ adi,custom-leak-detector:
+ description: |
+ Lookup table mapping resistance to coverage data. Entries must be
+ in ascending resistance order. The coverage data field encodes the
+ coverage percentage P as (P + 273.15) expressed in uK, i.e.
+ (P * 1000000 + 273150000).
+ $ref: /schemas/types.yaml#/definitions/uint64-matrix
+ minItems: 3
+ maxItems: 64
+ items:
+ items:
+ - description: Resistance point in uOhms.
+ - description: Coverage data point (P + 273150000) in uK.
+
+ required:
+ - adi,rsense-handle
+ - adi,excitation-current-nanoamp
+
'^rsense@':
$ref: '#/$defs/sensor-node'
unevaluatedProperties: false
@@ -477,6 +591,22 @@ allOf:
patternProperties:
'^temp@': false
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,adt7604
+ then:
+ patternProperties:
+ '^thermocouple@': false
+ '^diode@': false
+ '^adc@': false
+ '^temp@': false
+ else:
+ patternProperties:
+ '^copper-trace@': false
+ '^leak-detector@': false
+
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
@@ -556,4 +686,62 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ temperature-sensor@0 {
+ compatible = "adi,adt7604";
+ reg = <0>;
+ interrupt-parent = <&gpio>;
+ interrupts = <25 IRQ_TYPE_EDGE_RISING>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vdd-supply = <&supply>;
+
+ trace_rsense: rsense@2 {
+ reg = <2>;
+ adi,sensor-type = <29>;
+ adi,rsense-val-milli-ohms = <100000>; // 100 ohm
+ };
+
+ copper-trace@4 {
+ reg = <4>;
+ adi,sensor-type = <32>;
+ adi,rsense-handle = <&trace_rsense>;
+ adi,copper-trace-sub-ohm;
+ };
+
+ r_sense: rsense@12 {
+ reg = <12>;
+ adi,sensor-type = <29>;
+ adi,rsense-val-milli-ohms = <1000000>; // 1 kohm
+ };
+
+ leak-detector@14 {
+ reg = <14>;
+ adi,sensor-type = <33>;
+ adi,rsense-handle = <&r_sense>;
+ adi,excitation-current-nanoamp = <10000>;
+ adi,custom-leak-detector =
+ /bits/ 64 < 0 373150000>,
+ /bits/ 64 < 202020000 372150000>,
+ /bits/ 64 < 1000000000 293150000>;
+ };
+
+ rtd@18 {
+ reg = <18>;
+ adi,sensor-type = <12>; // PT100
+ adi,rsense-handle = <&r_sense>;
+ adi,number-of-wires = <2>;
+ adi,rsense-share;
+ adi,excitation-current-microamp = <500>;
+ adi,rtd-curve = <0>;
+ };
+ };
+ };
...
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 7/7] iio: temperature: ltc2983: Add support for ADT7604
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
` (5 preceding siblings ...)
2026-05-14 14:46 ` [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983 Liviu Stan
@ 2026-05-14 14:46 ` Liviu Stan
6 siblings, 0 replies; 14+ messages in thread
From: Liviu Stan @ 2026-05-14 14:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Michael Hennerich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Antoniu Miclaus, Francesco Lavra, Liviu Stan, linux-iio,
linux-kernel, linux, devicetree
The ADT7604 shares the same die as the LTC2984. It repurposes the
custom RTD sensor type (18) as a copper trace resistance sensor
and the custom thermistor type (27) as a leak detector, and
removes thermocouple, diode and direct ADC sensor types.
Two new software sensor type values are introduced
(LTC2983_SENSOR_COPPER_TRACE = 32, LTC2983_SENSOR_LEAK_DETECTOR = 33)
that map to the hardware register values 18 and 27 respectively.
Dedicated structs (ltc2983_copper_trace, ltc2983_leak_detector) and
parser functions are added rather than extending the existing RTD and
thermistor paths, as the hardware configuration bits are fully
hardcoded and several RTD/thermistor properties would need to be
explicitly forbidden or ignored.
Custom RTD (type 18) becomes the copper trace sensor. Sensor
configuration bits are hardcoded to 0b1001 per the datasheet.
Two variants are supported via the adi,copper-trace-sub-ohm DT
property: sub-ohm traces (< 1 ohm) have bits 17:0 cleared with no
excitation current or custom table; standard traces (> 1 ohm) accept
an optional resistance-to-temperature table.
Custom thermistor (type 27) becomes the leak detector. Sensor
configuration bits are hardcoded to 0b001. The custom table uses
a resolution of 16 instead of 64, and is specified via the
adi,custom-leak-detector DT property.
Both sensor types expose an IIO_RESISTANCE channel reading from
the resistance result register bank (0x0060-0x00AF). The register
encodes the measured resistance with 10 fractional bits, so
dividing by 1024 gives ohms. Since the sense resistor is specified
in ohms, the output is in ohms for both sensor types and a single
1/1024 scale applies to both. When a custom table is provided,
a secondary channel also appears: IIO_TEMP (millidegrees Celsius)
for copper trace and IIO_COVERAGE_PERCENT (percent) for leak
detector.
The ltc2983_chip_info struct is extended with a u64 supported_sensors
bitmask using BIT_ULL() to safely represent the new sensor type bits
32 and 33 on 32-bit builds.
Tested on EVAL-ADT7604-AZ connected to Raspberry Pi 5 via SPI.
Signed-off-by: Liviu Stan <liviu.stan@analog.com>
---
Changes in v2:
- New software sensor type values LTC2983_SENSOR_COPPER_TRACE = 32 and
LTC2983_SENSOR_LEAK_DETECTOR = 33 map to hardware register values 18
and 27 internally; v1 exposed 18 and 27 directly as adi,sensor-type
values.
- Added n_iio_chan to struct ltc2983_sensor; set in the dedicated
parser functions and used in ltc2983_parse_fw() and ltc2983_setup()
to count and assign IIO channels, removing to_rtd()/to_thermistor()
casts from the common path.
- Replaced has_copper_trace guards in ltc2983_rtd_new() and
ltc2983_thermistor_new() with dedicated structs and functions for
the new sensor types.
- Replaced has_copper_trace bool with u64 supported_sensors bitmask
in ltc2983_chip_info.
- Fixed IIO_RESISTANCE scale: both sensor types now use 1/1024 (ohms);
v1 used 1/1,024,000 for copper trace. But since the sense resistor
value is written in ohms to the register, the output will also be
in ohms for a scale of 1/1024.
- Replaced IIO_TEMP with IIO_COVERAGE_PERCENT for the leak detector
coverage output.
- Renamed sub_ohm to is_sub_ohm.
- Used switch() for IIO_CHAN_INFO_RAW base register selection.
- Used BIT_ULL() checks against supported_sensors for sensor type
validation.
drivers/iio/temperature/ltc2983.c | 401 ++++++++++++++++++++++++++++--
1 file changed, 386 insertions(+), 15 deletions(-)
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index bf435e965c6d..acd043ed62f5 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -28,6 +28,8 @@
#define LTC2983_STATUS_REG 0x0000
#define LTC2983_TEMP_RES_START_REG 0x0010
#define LTC2983_TEMP_RES_END_REG 0x005F
+#define ADT7604_RES_RES_START_REG 0x0060
+#define ADT7604_RES_RES_END_REG 0x00AF
#define LTC2983_EEPROM_KEY_REG 0x00B0
#define LTC2983_EEPROM_READ_STATUS_REG 0x00D0
#define LTC2983_GLOBAL_CONFIG_REG 0x00F0
@@ -186,17 +188,43 @@ enum {
LTC2983_SENSOR_SENSE_RESISTOR = 29,
LTC2983_SENSOR_DIRECT_ADC = 30,
LTC2983_SENSOR_ACTIVE_TEMP = 31,
+ /* Sensor types for some parts only; map to RTD_CUSTOM/THERMISTOR_CUSTOM in HW */
+ LTC2983_SENSOR_COPPER_TRACE = 32,
+ LTC2983_SENSOR_LEAK_DETECTOR = 33,
};
+/* Bitmask of sensor types supported by LTC2983/LTC2984 and derivatives */
+#define LTC2983_COMMON_SENSORS \
+ (GENMASK_ULL(LTC2983_SENSOR_THERMOCOUPLE_CUSTOM, LTC2983_SENSOR_THERMOCOUPLE) | \
+ GENMASK_ULL(LTC2983_SENSOR_RTD_CUSTOM, LTC2983_SENSOR_RTD) | \
+ GENMASK_ULL(LTC2983_SENSOR_THERMISTOR_CUSTOM, LTC2983_SENSOR_THERMISTOR) | \
+ BIT_ULL(LTC2983_SENSOR_DIODE) | \
+ BIT_ULL(LTC2983_SENSOR_SENSE_RESISTOR) | \
+ BIT_ULL(LTC2983_SENSOR_DIRECT_ADC))
+
+/* Bitmask of sensor types supported by ADT7604 */
+#define ADT7604_SENSORS \
+ (GENMASK_ULL(LTC2983_SENSOR_RTD_CUSTOM - 1, LTC2983_SENSOR_RTD) | \
+ GENMASK_ULL(LTC2983_SENSOR_THERMISTOR_CUSTOM - 1, LTC2983_SENSOR_THERMISTOR) | \
+ BIT_ULL(LTC2983_SENSOR_SENSE_RESISTOR) | \
+ BIT_ULL(LTC2983_SENSOR_COPPER_TRACE) | \
+ BIT_ULL(LTC2983_SENSOR_LEAK_DETECTOR))
+
#define to_thermocouple(_sensor) \
container_of(_sensor, struct ltc2983_thermocouple, sensor)
#define to_rtd(_sensor) \
container_of(_sensor, struct ltc2983_rtd, sensor)
+#define to_copper_trace(_sensor) \
+ container_of(_sensor, struct ltc2983_copper_trace, sensor)
+
#define to_thermistor(_sensor) \
container_of(_sensor, struct ltc2983_thermistor, sensor)
+#define to_leak_detector(_sensor) \
+ container_of(_sensor, struct ltc2983_leak_detector, sensor)
+
#define to_diode(_sensor) \
container_of(_sensor, struct ltc2983_diode, sensor)
@@ -212,7 +240,7 @@ enum {
struct ltc2983_chip_info {
const char *name;
unsigned int max_channels_nr;
- bool has_temp;
+ u64 supported_sensors;
bool has_eeprom;
};
@@ -247,6 +275,8 @@ struct ltc2983_sensor {
u32 chan;
/* sensor type */
u32 type;
+ /* number of IIO channels this sensor produces */
+ u8 n_iio_chan;
};
struct ltc2983_custom_sensor {
@@ -274,6 +304,25 @@ struct ltc2983_rtd {
u32 rtd_curve;
};
+struct ltc2983_copper_trace {
+ struct ltc2983_sensor sensor;
+ struct ltc2983_custom_sensor *custom;
+ u32 r_sense_chan;
+ u32 excitation_current;
+ /* selects the <1Ω variant: bits 17:0 of the channel word are zeroed,
+ * disabling excitation current and custom table fields (ADT7604
+ * datasheet Table 26)
+ */
+ bool is_sub_ohm;
+};
+
+struct ltc2983_leak_detector {
+ struct ltc2983_sensor sensor;
+ struct ltc2983_custom_sensor *custom;
+ u32 r_sense_chan;
+ u32 excitation_current;
+};
+
struct ltc2983_thermistor {
struct ltc2983_sensor sensor;
struct ltc2983_custom_sensor *custom;
@@ -354,8 +403,15 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st,
struct device *dev = &st->spi->dev;
u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan);
- chan_val |= LTC2983_CHAN_TYPE(sensor->type);
- dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
+ u32 hw_type = sensor->type;
+
+ if (hw_type == LTC2983_SENSOR_COPPER_TRACE)
+ hw_type = LTC2983_SENSOR_RTD_CUSTOM;
+ else if (hw_type == LTC2983_SENSOR_LEAK_DETECTOR)
+ hw_type = LTC2983_SENSOR_THERMISTOR_CUSTOM;
+
+ chan_val |= LTC2983_CHAN_TYPE(hw_type);
+ dev_dbg(dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
chan_val);
st->chan_val = cpu_to_be32(chan_val);
return regmap_bulk_write(st->regmap, reg, &st->chan_val,
@@ -579,6 +635,32 @@ static int ltc2983_rtd_assign_chan(struct ltc2983_data *st,
return __ltc2983_chan_assign_common(st, sensor, chan_val);
}
+static int ltc2983_copper_trace_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_copper_trace *ct = to_copper_trace(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_CHAN_ASSIGN(ct->r_sense_chan);
+ /* Sensor config bits 21:18 must be 0b1001 (ADT7604 datasheet Table 26) */
+ chan_val |= LTC2983_RTD_CFG(0x9);
+ chan_val |= LTC2983_RTD_EXC_CURRENT(ct->excitation_current);
+
+ if (ct->custom) {
+ int ret;
+
+ ret = __ltc2983_chan_custom_sensor_assign(st, ct->custom,
+ &chan_val);
+ if (ret)
+ return ret;
+ }
+
+ if (ct->is_sub_ohm)
+ chan_val &= ~GENMASK(17, 0);
+
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
static int ltc2983_thermistor_assign_chan(struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
@@ -602,6 +684,29 @@ static int ltc2983_thermistor_assign_chan(struct ltc2983_data *st,
return __ltc2983_chan_assign_common(st, sensor, chan_val);
}
+static int ltc2983_leak_detector_assign_chan(struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct ltc2983_leak_detector *ld = to_leak_detector(sensor);
+ u32 chan_val;
+
+ chan_val = LTC2983_CHAN_ASSIGN(ld->r_sense_chan);
+ /* bits 21:19 must be 0b001 (ADT7604 datasheet Table 38) */
+ chan_val |= LTC2983_THERMISTOR_CFG(1);
+ chan_val |= LTC2983_THERMISTOR_EXC_CURRENT(ld->excitation_current);
+
+ if (ld->custom) {
+ int ret;
+
+ ret = __ltc2983_chan_custom_sensor_assign(st, ld->custom,
+ &chan_val);
+ if (ret)
+ return ret;
+ }
+
+ return __ltc2983_chan_assign_common(st, sensor, chan_val);
+}
+
static int ltc2983_diode_assign_chan(struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
{
@@ -1024,6 +1129,191 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s
return &thermistor->sensor;
}
+static struct ltc2983_sensor *
+ltc2983_copper_trace_new(const struct fwnode_handle *child, struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct device *dev = &st->spi->dev;
+ struct ltc2983_copper_trace *ct;
+ int ret;
+
+ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
+ return dev_err_ptr_probe(dev, -EINVAL,
+ "Invalid channel %d for copper trace\n",
+ sensor->chan);
+
+ ct = devm_kzalloc(dev, sizeof(*ct), GFP_KERNEL);
+ if (!ct)
+ return ERR_PTR(-ENOMEM);
+
+ struct fwnode_handle *ref __free(fwnode_handle) =
+ fwnode_find_reference(child, "adi,rsense-handle", 0);
+ if (IS_ERR(ref))
+ return dev_err_cast_probe(dev, ref,
+ "Property adi,rsense-handle missing or invalid\n");
+
+ ret = fwnode_property_read_u32(ref, "reg", &ct->r_sense_chan);
+ if (ret)
+ return dev_err_ptr_probe(dev, ret, "Property reg must be given\n");
+
+ ct->is_sub_ohm = fwnode_property_read_bool(child, "adi,copper-trace-sub-ohm");
+
+ if (fwnode_property_present(child, "adi,custom-rtd")) {
+ if (ct->is_sub_ohm)
+ return dev_err_ptr_probe(dev, -EINVAL,
+ "sub-ohm copper trace cannot have a custom table\n");
+ ct->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-rtd",
+ false, 2048, false);
+ if (IS_ERR(ct->custom))
+ return ERR_CAST(ct->custom);
+ }
+
+ if (!ct->is_sub_ohm) {
+ u32 excitation_current = 0;
+
+ ret = fwnode_property_read_u32(child,
+ "adi,excitation-current-microamp",
+ &excitation_current);
+ if (ret) {
+ /* default to 1mA per datasheet recommendation for copper trace */
+ ct->excitation_current = 0x08;
+ } else {
+ switch (excitation_current) {
+ case 5:
+ ct->excitation_current = 0x01;
+ break;
+ case 10:
+ ct->excitation_current = 0x02;
+ break;
+ case 25:
+ ct->excitation_current = 0x03;
+ break;
+ case 50:
+ ct->excitation_current = 0x04;
+ break;
+ case 100:
+ ct->excitation_current = 0x05;
+ break;
+ case 250:
+ ct->excitation_current = 0x06;
+ break;
+ case 500:
+ ct->excitation_current = 0x07;
+ break;
+ case 1000:
+ ct->excitation_current = 0x08;
+ break;
+ default:
+ return dev_err_ptr_probe(dev, -EINVAL,
+ "Invalid value for excitation current(%u)\n",
+ excitation_current);
+ }
+ }
+ }
+
+ ct->sensor.fault_handler = ltc2983_common_fault_handler;
+ ct->sensor.assign_chan = ltc2983_copper_trace_assign_chan;
+ if (ct->custom)
+ ct->sensor.n_iio_chan = 2;
+ else
+ ct->sensor.n_iio_chan = 1;
+
+ return &ct->sensor;
+}
+
+static struct ltc2983_sensor *
+ltc2983_leak_detector_new(const struct fwnode_handle *child, struct ltc2983_data *st,
+ const struct ltc2983_sensor *sensor)
+{
+ struct device *dev = &st->spi->dev;
+ struct ltc2983_leak_detector *ld;
+ int ret;
+ u32 excitation_current = 0;
+
+ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN)
+ return dev_err_ptr_probe(dev, -EINVAL,
+ "Invalid channel %d for leak detector\n",
+ sensor->chan);
+
+ ld = devm_kzalloc(dev, sizeof(*ld), GFP_KERNEL);
+ if (!ld)
+ return ERR_PTR(-ENOMEM);
+
+ struct fwnode_handle *ref __free(fwnode_handle) =
+ fwnode_find_reference(child, "adi,rsense-handle", 0);
+ if (IS_ERR(ref))
+ return dev_err_cast_probe(dev, ref,
+ "Property adi,rsense-handle missing or invalid\n");
+
+ ret = fwnode_property_read_u32(ref, "reg", &ld->r_sense_chan);
+ if (ret)
+ return dev_err_ptr_probe(dev, ret,
+ "rsense channel must be configured...\n");
+
+ if (fwnode_property_present(child, "adi,custom-leak-detector")) {
+ ld->custom = __ltc2983_custom_sensor_new(st, child,
+ "adi,custom-leak-detector",
+ false, 16, false);
+ if (IS_ERR(ld->custom))
+ return ERR_CAST(ld->custom);
+ }
+
+ ret = fwnode_property_read_u32(child, "adi,excitation-current-nanoamp",
+ &excitation_current);
+ if (ret)
+ return dev_err_ptr_probe(dev, ret,
+ "adi,excitation-current-nanoamp is required for leak detectors\n");
+
+ switch (excitation_current) {
+ case 250:
+ ld->excitation_current = 0x01;
+ break;
+ case 500:
+ ld->excitation_current = 0x02;
+ break;
+ case 1000:
+ ld->excitation_current = 0x03;
+ break;
+ case 5000:
+ ld->excitation_current = 0x04;
+ break;
+ case 10000:
+ ld->excitation_current = 0x05;
+ break;
+ case 25000:
+ ld->excitation_current = 0x06;
+ break;
+ case 50000:
+ ld->excitation_current = 0x07;
+ break;
+ case 100000:
+ ld->excitation_current = 0x08;
+ break;
+ case 250000:
+ ld->excitation_current = 0x09;
+ break;
+ case 500000:
+ ld->excitation_current = 0x0a;
+ break;
+ case 1000000:
+ ld->excitation_current = 0x0b;
+ break;
+ default:
+ return dev_err_ptr_probe(dev, -EINVAL,
+ "Invalid value for excitation current(%u)\n",
+ excitation_current);
+ }
+
+ ld->sensor.fault_handler = ltc2983_common_fault_handler;
+ ld->sensor.assign_chan = ltc2983_leak_detector_assign_chan;
+ if (ld->custom)
+ ld->sensor.n_iio_chan = 2;
+ else
+ ld->sensor.n_iio_chan = 1;
+
+ return &ld->sensor;
+}
+
static struct ltc2983_sensor *
ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *st,
const struct ltc2983_sensor *sensor)
@@ -1183,7 +1473,8 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
}
static int ltc2983_chan_read(struct ltc2983_data *st,
- const struct ltc2983_sensor *sensor, int *val)
+ const struct ltc2983_sensor *sensor,
+ u32 base_reg, int *val)
{
struct device *dev = &st->spi->dev;
u32 start_conversion = 0;
@@ -1221,6 +1512,16 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
*val = __be32_to_cpu(st->temp);
+ if (base_reg == ADT7604_RES_RES_START_REG) {
+ /*
+ * Resistance result register gives a plain unsigned value,
+ * D31 is always 0, no valid bit, no fault bits. Read bits[30:0]
+ * directly — the temperature result format does not apply here.
+ */
+ *val &= GENMASK(30, 0);
+ return 0;
+ }
+
if (!(LTC2983_RES_VALID_MASK & *val)) {
dev_err(dev, "Invalid conversion detected\n");
return -EIO;
@@ -1252,7 +1553,16 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&st->lock);
- ret = ltc2983_chan_read(st, st->sensors[chan->address], val);
+ switch (chan->type) {
+ case IIO_RESISTANCE:
+ ret = ltc2983_chan_read(st, st->sensors[chan->address],
+ ADT7604_RES_RES_START_REG, val);
+ break;
+ default:
+ ret = ltc2983_chan_read(st, st->sensors[chan->address],
+ LTC2983_TEMP_RES_START_REG, val);
+ break;
+ }
mutex_unlock(&st->lock);
return ret ?: IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -1269,6 +1579,16 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev,
/* 2^21 */
*val2 = 2097152;
return IIO_VAL_FRACTIONAL;
+ case IIO_RESISTANCE:
+ /* value in ohm, 10 fractional bits: divide by 2^10 */
+ *val = 1;
+ *val2 = 1024;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_COVERAGE_PERCENT:
+ /* value in percent, 10 fractional bits: divide by 2^10 */
+ *val = 1;
+ *val2 = 1024;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
@@ -1329,7 +1649,7 @@ static int ltc2983_parse_fw(struct ltc2983_data *st)
if (!st->sensors)
return -ENOMEM;
- st->iio_channels = st->num_channels;
+ st->iio_channels = 0;
device_for_each_child_node_scoped(dev, child) {
struct ltc2983_sensor sensor;
@@ -1357,7 +1677,13 @@ static int ltc2983_parse_fw(struct ltc2983_data *st)
return dev_err_probe(dev, ret,
"adi,sensor-type property must given for child nodes\n");
- dev_dbg(dev, "Create new sensor, type %u, chann %u",
+ if (sensor.type > LTC2983_SENSOR_LEAK_DETECTOR ||
+ !(st->info->supported_sensors & BIT_ULL(sensor.type)))
+ return dev_err_probe(dev, -EINVAL,
+ "sensor type %d not supported on %s\n",
+ sensor.type, st->info->name);
+
+ dev_dbg(dev, "Create new sensor, type %u, channel %u",
sensor.type, sensor.chan);
if (sensor.type >= LTC2983_SENSOR_THERMOCOUPLE &&
@@ -1377,13 +1703,14 @@ static int ltc2983_parse_fw(struct ltc2983_data *st)
} else if (sensor.type == LTC2983_SENSOR_SENSE_RESISTOR) {
st->sensors[chan] = ltc2983_r_sense_new(child, st,
&sensor);
- /* don't add rsense to iio */
- st->iio_channels--;
} else if (sensor.type == LTC2983_SENSOR_DIRECT_ADC) {
st->sensors[chan] = ltc2983_adc_new(child, st, &sensor);
- } else if (st->info->has_temp &&
- sensor.type == LTC2983_SENSOR_ACTIVE_TEMP) {
+ } else if (sensor.type == LTC2983_SENSOR_ACTIVE_TEMP) {
st->sensors[chan] = ltc2983_temp_new(child, st, &sensor);
+ } else if (sensor.type == LTC2983_SENSOR_COPPER_TRACE) {
+ st->sensors[chan] = ltc2983_copper_trace_new(child, st, &sensor);
+ } else if (sensor.type == LTC2983_SENSOR_LEAK_DETECTOR) {
+ st->sensors[chan] = ltc2983_leak_detector_new(child, st, &sensor);
} else {
return dev_err_probe(dev, -EINVAL,
"Unknown sensor type %d\n",
@@ -1398,6 +1725,16 @@ static int ltc2983_parse_fw(struct ltc2983_data *st)
st->sensors[chan]->chan = sensor.chan;
st->sensors[chan]->type = sensor.type;
+ /*
+ * Dedicated functions set n_iio_chan themselves; for all other
+ * sensor types rsense produces 0 channels, everything else 1.
+ */
+ if (!st->sensors[chan]->n_iio_chan) {
+ if (sensor.type != LTC2983_SENSOR_SENSE_RESISTOR)
+ st->sensors[chan]->n_iio_chan = 1;
+ }
+ st->iio_channels += st->sensors[chan]->n_iio_chan;
+
channel_avail_mask |= BIT(sensor.chan);
chan++;
}
@@ -1445,8 +1782,9 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
{
- u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status;
struct device *dev = &st->spi->dev;
+ u32 iio_chan_t = 0, iio_chan_v = 0, iio_chan_r = 0, iio_chan_c = 0;
+ u32 chan, iio_idx = 0, status;
int ret;
/* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */
@@ -1493,8 +1831,26 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
!assign_iio)
continue;
+ /*
+ * Copper trace and leak detector sensors without a custom table
+ * produce only a resistance result; the chip does not populate
+ * the temperature result register. Emit only an IIO_RESISTANCE
+ * channel in this case.
+ */
+ if (st->sensors[chan]->type == LTC2983_SENSOR_COPPER_TRACE ||
+ st->sensors[chan]->type == LTC2983_SENSOR_LEAK_DETECTOR) {
+ if (st->sensors[chan]->n_iio_chan == 1) {
+ st->iio_chan[iio_idx++] =
+ LTC2983_CHAN(IIO_RESISTANCE, iio_chan_r++, chan);
+ continue;
+ }
+ }
+
/* assign iio channel */
- if (st->sensors[chan]->type != LTC2983_SENSOR_DIRECT_ADC) {
+ if (st->sensors[chan]->type == LTC2983_SENSOR_LEAK_DETECTOR) {
+ chan_type = IIO_COVERAGE_PERCENT;
+ iio_chan = &iio_chan_c;
+ } else if (st->sensors[chan]->type != LTC2983_SENSOR_DIRECT_ADC) {
chan_type = IIO_TEMP;
iio_chan = &iio_chan_t;
} else {
@@ -1508,6 +1864,9 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
*/
st->iio_chan[iio_idx++] = LTC2983_CHAN(chan_type, (*iio_chan)++,
chan);
+
+ if (st->sensors[chan]->n_iio_chan == 2)
+ st->iio_chan[iio_idx++] = LTC2983_CHAN(IIO_RESISTANCE, iio_chan_r++, chan);
}
return 0;
@@ -1516,6 +1875,7 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
static const struct regmap_range ltc2983_reg_ranges[] = {
regmap_reg_range(LTC2983_STATUS_REG, LTC2983_STATUS_REG),
regmap_reg_range(LTC2983_TEMP_RES_START_REG, LTC2983_TEMP_RES_END_REG),
+ regmap_reg_range(ADT7604_RES_RES_START_REG, ADT7604_RES_RES_END_REG),
regmap_reg_range(LTC2983_EEPROM_KEY_REG, LTC2983_EEPROM_KEY_REG),
regmap_reg_range(LTC2983_EEPROM_READ_STATUS_REG,
LTC2983_EEPROM_READ_STATUS_REG),
@@ -1658,25 +2018,34 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ltc2983_pm_ops, ltc2983_suspend,
static const struct ltc2983_chip_info ltc2983_chip_info_data = {
.name = "ltc2983",
.max_channels_nr = 20,
+ .supported_sensors = LTC2983_COMMON_SENSORS,
};
static const struct ltc2983_chip_info ltc2984_chip_info_data = {
.name = "ltc2984",
.max_channels_nr = 20,
+ .supported_sensors = LTC2983_COMMON_SENSORS,
.has_eeprom = true,
};
static const struct ltc2983_chip_info ltc2986_chip_info_data = {
.name = "ltc2986",
.max_channels_nr = 10,
- .has_temp = true,
+ .supported_sensors = LTC2983_COMMON_SENSORS | BIT_ULL(LTC2983_SENSOR_ACTIVE_TEMP),
.has_eeprom = true,
};
static const struct ltc2983_chip_info ltm2985_chip_info_data = {
.name = "ltm2985",
.max_channels_nr = 10,
- .has_temp = true,
+ .supported_sensors = LTC2983_COMMON_SENSORS | BIT_ULL(LTC2983_SENSOR_ACTIVE_TEMP),
+ .has_eeprom = true,
+};
+
+static const struct ltc2983_chip_info adt7604_chip_info_data = {
+ .name = "adt7604",
+ .max_channels_nr = 20,
+ .supported_sensors = ADT7604_SENSORS,
.has_eeprom = true,
};
@@ -1685,6 +2054,7 @@ static const struct spi_device_id ltc2983_id_table[] = {
{ "ltc2984", (kernel_ulong_t)<c2984_chip_info_data },
{ "ltc2986", (kernel_ulong_t)<c2986_chip_info_data },
{ "ltm2985", (kernel_ulong_t)<m2985_chip_info_data },
+ { "adt7604", (kernel_ulong_t)&adt7604_chip_info_data },
{ }
};
MODULE_DEVICE_TABLE(spi, ltc2983_id_table);
@@ -1694,6 +2064,7 @@ static const struct of_device_id ltc2983_of_match[] = {
{ .compatible = "adi,ltc2984", .data = <c2984_chip_info_data },
{ .compatible = "adi,ltc2986", .data = <c2986_chip_info_data },
{ .compatible = "adi,ltm2985", .data = <m2985_chip_info_data },
+ { .compatible = "adi,adt7604", .data = &adt7604_chip_info_data },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2983_of_match);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename
2026-05-14 14:46 ` [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename Liviu Stan
@ 2026-05-14 19:32 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 19:32 UTC (permalink / raw)
To: Liviu Stan; +Cc: robh, krzk+dt, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Undocumented API change: addition of the `base` parameter to the `LTC2983_RESULT_ADDR` macro.
- [Low] Compilation failure in `ltc2983_chan_read()` due to undeclared identifier `base_reg`.
--
commit 24bf0bfe00d6f9aa08599e0c812d5f43a2500269
Author: Liviu Stan <liviu.stan@analog.com>
iio: temperature: ltc2983: Fix macro parenthesization and rename
This commit adds parentheses around the chan parameter in macro definitions
to prevent expansion issues and renames the macros to better reflect the
datasheet names.
> Wrap the 'chan' parameter in LTC2983_CHAN_START_ADDR() and
> LTC2983_CHAN_RES_ADDR() with parentheses to prevent potential
> macro argument expansion issues. Also rename LTC2983_CHAN_START_ADDR
> to LTC2983_CHAN_ASSIGN_ADDR and LTC2983_CHAN_RES_ADDR to
> LTC2983_RESULT_ADDR, to better reflect the datasheet names and avoid
> them being confused as related.
Could the commit message be updated to mention the addition of the base
parameter to LTC2983_RESULT_ADDR?
The commit message describes renaming the macro and adding parentheses, but
fails to mention that the macro was also modified to take a new base
parameter. This undocumented change obscures the intent behind the
refactoring.
> diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
> index 38e6f8dfd3b80..a292274e6ff07 100644
> --- a/drivers/iio/temperature/ltc2983.c
> +++ b/drivers/iio/temperature/ltc2983.c
> @@ -56,10 +56,10 @@
> #define LTC2983_EEPROM_WRITE_TIME_MS 2600
> #define LTC2983_EEPROM_READ_TIME_MS 20
>
> -#define LTC2983_CHAN_START_ADDR(chan) \
> - (((chan - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
> -#define LTC2983_CHAN_RES_ADDR(chan) \
> - (((chan - 1) * 4) + LTC2983_TEMP_RES_START_REG)
> +#define LTC2983_CHAN_ASSIGN_ADDR(chan) \
> + ((((chan) - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
> +#define LTC2983_RESULT_ADDR(chan, base) \
> + ((((chan) - 1) * 4) + (base))
> #define LTC2983_THERMOCOUPLE_DIFF_MASK BIT(3)
> #define LTC2983_THERMOCOUPLE_SGL(x) \
> FIELD_PREP(LTC2983_THERMOCOUPLE_DIFF_MASK, x)
[ ... ]
> @@ -1197,7 +1197,7 @@ static int ltc2983_chan_read(struct ltc2983_data *st,
> }
>
> /* read the converted data */
> - ret = regmap_bulk_read(st->regmap, LTC2983_CHAN_RES_ADDR(sensor->chan),
> + ret = regmap_bulk_read(st->regmap, LTC2983_RESULT_ADDR(sensor->chan, base_reg),
> &st->temp, sizeof(st->temp));
> if (ret)
> return ret;
Does this cause a compilation failure because base_reg is undeclared in
ltc2983_chan_read()?
It appears the fix is introduced later in the series in commit 7aff450fb9c7b
("iio: temperature: ltc2983: Add support for ADT7604"), which adds base_reg as
a function parameter. However, each patch in a series must compile
independently.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently
2026-05-14 14:46 ` [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently Liviu Stan
@ 2026-05-14 19:39 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 19:39 UTC (permalink / raw)
To: Liviu Stan; +Cc: conor+dt, robh, devicetree, krzk+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The newly added 'dev' variable in `__ltc2983_chan_assign_common` is declared but never used, leading to compiler warnings.
--
commit cab83c99167bc9d0ae1294b92a3bded27d02aabf
Author: Liviu Stan <liviu.stan@analog.com>
iio: temperature: ltc2983: Use local device pointer consistently
This patch adds local dev pointers across various functions in the driver
to replace bare references to st->spi->dev.
> diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
> --- a/drivers/iio/temperature/ltc2983.c
> +++ b/drivers/iio/temperature/ltc2983.c
> @@ -351,6 +351,7 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st,
> const struct ltc2983_sensor *sensor,
> u32 chan_val)
> {
> + struct device *dev = &st->spi->dev;
> u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan);
>
> chan_val |= LTC2983_CHAN_TYPE(sensor->type);
Does this leave the newly added dev variable entirely unused?
It looks like the dev_dbg() call immediately following this still uses
&st->spi->dev instead of the local dev pointer.
This will cause an unused-variable compiler warning, which breaks builds
configured with W=1 or -Werror and can harm bisectability.
While this oversight is fixed later in the patch series in commit
7aff450fb9c7b5749766cff8040dd8d12bc74f0c, each patch must compile
cleanly and independently.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages
2026-05-14 14:46 ` [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages Liviu Stan
@ 2026-05-14 19:47 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 19:47 UTC (permalink / raw)
To: Liviu Stan; +Cc: conor+dt, robh, devicetree, krzk+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Incomplete refactoring / Commit message mismatch: The commit claims to replace all occurrences of 'chan' and 'chann' with 'channel' in error and debug messages, but misses several occurrences.
--
commit f3ba963d38e5d70969e64d92b33f465e108805e4
Author: Liviu Stan <liviu.stan@analog.com>
iio: temperature: ltc2983: Fix inconsistent channel wording in messages
This commit replaces abbreviations like 'chann' and 'chan' with 'channel'
in error and debug messages across the ltc2983 driver to improve
consistency.
> Replace all occurrences of the abbreviated 'chann' and 'chan' with
> 'channel' in error and debug messages throughout the driver.
This isn't a bug, but since the goal is to replace all occurrences,
should the following instances in ltc2983_parse_fw() also be updated?
drivers/iio/temperature/ltc2983.c:ltc2983_parse_fw() {
...
if (sensor.chan < LTC2983_MIN_CHANNELS_NR ||
sensor.chan > st->info->max_channels_nr)
return dev_err_probe(dev, -EINVAL,
"chan:%d must be from %u to %u\n",
...
if (channel_avail_mask & BIT(sensor.chan))
return dev_err_probe(dev, -EINVAL,
"chan:%d already in use\n",
...
dev_dbg(dev, "Create new sensor, type %u, chann %u",
...
}
It appears these were missed during the refactoring.
While the "chann %u" debug message is coincidentally updated in a later
commit ("iio: temperature: ltc2983: Add support for ADT7604"), the error
messages remain unfixed throughout the patch series.
Could these be updated here to ensure the code fully matches the commit
message?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties
2026-05-14 14:46 ` [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties Liviu Stan
@ 2026-05-14 20:04 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 20:04 UTC (permalink / raw)
To: Liviu Stan; +Cc: devicetree, krzk+dt, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Bypassed software validation for RTD rotation when `adi,number-of-wires` is absent.
- [Medium] The commit only partially implements its stated goal, leaving multiple instances of the exact same error-swallowing anti-pattern throughout the driver.
--
commit 94ec4e6144c071e0f0444b0ad792dffbdf874d09
Author: Liviu Stan <liviu.stan@analog.com>
iio: temperature: ltc2983: Use fwnode_property_present() for optional properties
This commit attempts to fix the silent swallowing of error codes when optional
properties are present but malformed. It updates the property reads for
adi,sensor-oc-current-microamp and adi,number-of-wires to check for presence
first.
> Checking fwnode_property_read_u32() return value with if (!ret)
> silently swallows meaningful error codes when a property is present
> but malformed. Use fwnode_property_present() first so that absence
> uses the default while a present but unreadable property returns
> a proper error.
Does this commit miss updating other optional properties that share the same
error-swallowing pattern?
For example, in ltc2983_rtd_new(), adi,excitation-current-microamp still
falls back to default values on any error:
ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp",
&excitation_current);
if (ret) {
/* default to 5uA */
rtd->excitation_current = 1;
Are there other instances, like in ltc2983_diode_new(), that also need this
update to fully implement the stated goal?
> --- a/drivers/iio/temperature/ltc2983.c
> +++ b/drivers/iio/temperature/ltc2983.c
[ ... ]
> @@ -760,8 +766,12 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
> return dev_err_ptr_probe(dev, ret,
> "Property reg must be given\n");
>
> - ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires);
> - if (!ret) {
> + if (fwnode_property_present(child, "adi,number-of-wires")) {
> + ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires);
> + if (ret)
> + return dev_err_ptr_probe(dev, ret,
> + "Failed to read adi,number-of-wires\n");
> +
> switch (n_wires) {
> case 2:
> rtd->sensor_config = LTC2983_RTD_N_WIRES(0);
If the adi,number-of-wires property is absent, n_wires remains 0. Since
the hardware configuration correctly defaults to a 2-wire setup
(sensor_config is zero-initialized), does leaving n_wires as 0 introduce a
regression where it bypasses the later validation for RTD rotation?
Further down in ltc2983_rtd_new():
if (fwnode_property_read_bool(child, "adi,rsense-share")) {
/* Current rotation is only available with rsense sharing */
if (fwnode_property_read_bool(child, "adi,current-rotate")) {
if (n_wires == 2 || n_wires == 3)
return dev_err_ptr_probe(dev, -EINVAL,
"Rotation not allowed for 2/3 Wire RTDs\n");
If n_wires is 0, this check is bypassed and current rotation is allowed for
a 2-wire RTD configuration. Should n_wires be explicitly set to 2 when the
property is absent to enforce this hardware constraint?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=4
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type
2026-05-14 14:46 ` [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type Liviu Stan
@ 2026-05-14 20:16 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 20:16 UTC (permalink / raw)
To: Liviu Stan; +Cc: devicetree, robh, krzk+dt, conor+dt
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] Embedding the measurement unit ('percent') directly into the IIO channel type name violates IIO UAPI design principles.
- [Medium] The new channel type `IIO_COVERAGE_PERCENT` was not added to the `event_is_known()` switch statement in `tools/iio/iio_event_monitor.c`, breaking the tool for this channel type.
- [Low] The new ABI documentation specifies an incorrect and outdated KernelVersion.
--
commit 705b17eefc8a8d4b3eadfd2e4bd4137ac5a8e6eb
Author: Liviu Stan <liviu.stan@analog.com>
iio: core: Add IIO_COVERAGE_PERCENT channel type
This commit adds a new channel type for sensors that report fractional
coverage as a percentage. The first user is the ADT7604 leak detector,
where the value represents the portion of the sensing element that is
wetted.
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
> index 4fc9f6bd42812..73aa5ac4a91a4 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
[ ... ]
> +What: /sys/bus/iio/devices/iio:deviceX/in_coveragepercentX_raw
> +KernelVersion: 6.15
Is this KernelVersion correct? Given that 6.15 was released in 2025,
shouldn't this reflect the upcoming kernel version for this new interface?
> +Contact: linux-iio@vger.kernel.org
> +Description:
> + Raw (unscaled no offset etc.) coverage reading. Used for sensors
> + that report fractional coverage as a percentage, such as leak
> + detectors where the value represents what portion of the sensing
> + element is wetted. Units after application of scale and offset are
> + percent.
[ ... ]
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 22eefd048ba92..4329d28f78b09 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
[ ... ]
> @@ -98,6 +98,7 @@ static const char * const iio_chan_type_name_spec[] = {
> [IIO_CHROMATICITY] = "chromaticity",
> [IIO_ATTENTION] = "attention",
> [IIO_ALTCURRENT] = "altcurrent",
> + [IIO_COVERAGE_PERCENT] = "coveragepercent",
> };
Does embedding the measurement unit into the IIO channel type name conflict
with the IIO UAPI design?
Typically, channel types represent the physical quantity, while the unit
is determined by applying scale and offset to the raw values.
If a future sensor measures coverage using a different scale, such as a
fractional value from 0.0 to 1.0 or parts-per-million, wouldn't the
coveragepercent string become misleading and inflexible?
[ ... ]
> diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
> index 03ca33869ce85..1ba0386133839 100644
> --- a/tools/iio/iio_event_monitor.c
> +++ b/tools/iio/iio_event_monitor.c
[ ... ]
> @@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = {
> [IIO_CHROMATICITY] = "chromaticity",
> [IIO_ATTENTION] = "attention",
> [IIO_ALTCURRENT] = "altcurrent",
> + [IIO_COVERAGE_PERCENT] = "coveragepercent",
> };
Does this omit an update to the event_is_known() switch statement?
If IIO_COVERAGE_PERCENT is missing from the switch block in event_is_known(),
the statement will fall through to the default case and return false.
Would this cause the iio_event_monitor tool to falsely flag events from
this new channel as unknown and fail to parse or print their information?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=5
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
2026-05-14 14:46 ` [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983 Liviu Stan
@ 2026-05-14 20:43 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-14 20:43 UTC (permalink / raw)
To: Liviu Stan; +Cc: conor+dt, krzk+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Device Tree hardware representation violation: Fake `adi,sensor-type` values used for new sensors
- [High] Device Tree abstraction violation: Encoding coverage percentage as fake Kelvin temperature
- [Medium] Subsystem Guideline Violation: Missing `adi,adt7604` from generational conditional block
- [Medium] Incomplete schema validation for repurposed sensor types on ADT7604
--
commit 29985f1c91396fb1c61d9d6e8e7e4bc36c38266c
Author: Liviu Stan <liviu.stan@analog.com>
dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983
This commit adds device tree bindings support for the ADT7604
multi-sensor temperature system. It introduces new copper trace and leak
detector node types, mapping them to existing hardware capabilities. It also
restricts unsupported node configurations for the ADT7604.
> diff --git a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
> index a22725f7619b7..c63b69bd95045 100644
> --- a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
> +++ b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml
[ ... ]
> @@ -436,6 +441,115 @@ patternProperties:
> required:
> - adi,custom-temp
>
> + '^copper-trace@':
> + $ref: '#/$defs/sensor-node'
> + unevaluatedProperties: false
> + description: |
> + Copper trace resistance sensor (some parts only). Two variants exist:
> + sub-ohm (< 1 ohm, no custom table allowed) and standard (> 1 ohm,
> + optional custom table).
> +
> + properties:
> + reg:
> + minimum: 2
> + maximum: 20
> +
> + adi,sensor-type:
> + description: Sensor type for copper trace sensors.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + const: 32
Is it appropriate to use 32 as the sensor type here?
The commit message indicates the hardware repurposes the custom RTD sensor
type 18 for this. Since the hardware channel assignment field for sensor
types is typically 5 bits with a maximum value of 31, does enforcing 32 in
the device tree leak a virtual driver ID into the ABI rather than describing
the actual hardware registers?
[ ... ]
> + '^leak-detector@':
> + $ref: '#/$defs/sensor-node'
> + unevaluatedProperties: false
> + description: |
> + Leak detector sensor (some parts only). Outputs resistance in ohms and,
> + when a custom table is provided, a coverage percentage via
> + IIO_COVERAGE_PERCENT (raw/1024 = coverage %).
> +
> + properties:
> + reg:
> + minimum: 2
> + maximum: 20
> +
> + adi,sensor-type:
> + description: Sensor type for leak detector sensors.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + const: 33
Similar to the copper trace sensor, the commit message states this
repurposes the custom thermistor type 27. Should this be constrained to 27
instead of 33 to match the hardware register value?
[ ... ]
> + adi,custom-leak-detector:
> + description: |
> + Lookup table mapping resistance to coverage data. Entries must be
> + in ascending resistance order. The coverage data field encodes the
> + coverage percentage P as (P + 273.15) expressed in uK, i.e.
> + (P * 1000000 + 273150000).
> + $ref: /schemas/types.yaml#/definitions/uint64-matrix
> + minItems: 3
> + maxItems: 64
> + items:
> + items:
> + - description: Resistance point in uOhms.
> + - description: Coverage data point (P + 273150000) in uK.
Does this encode non-temperature measurements with arbitrary Kelvin offsets
into the device tree?
It seems this tightly couples the device tree ABI to internal driver
interpolation logic that expects to subtract 273.15. Could the device tree
store the raw coverage percentage mapping instead?
[ ... ]
> @@ -477,6 +591,22 @@ allOf:
> patternProperties:
> '^temp@': false
>
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: adi,adt7604
> + then:
> + patternProperties:
> + '^thermocouple@': false
> + '^diode@': false
> + '^adc@': false
> + '^temp@': false
The DT bindings subsystem guidelines indicate that when a new compatible
string shares constraints with existing generations, it should be added to
the existing conditional blocks.
Since there is an existing block that already restricts ^temp@ for other
compatible strings, should adi,adt7604 be added to the compatible enum in
that existing block rather than duplicating the ^temp@ restriction here?
Additionally, since types 18 and 27 are repurposed on the ADT7604, does
this schema allow device trees with invalid rtd@ nodes using
adi,sensor-type = <18> or thermistor@ nodes using adi,sensor-type = <27>
to silently pass validation?
Should the then clause also restrict the sensor types allowed within rtd@
and thermistor@ for the ADT7604?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514144712.64374-1-liviu.stan@analog.com?part=6
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-05-14 20:43 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 14:46 [PATCH v2 0/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
2026-05-14 14:46 ` [PATCH v2 1/7] iio: temperature: ltc2983: Fix macro parenthesization and rename Liviu Stan
2026-05-14 19:32 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 2/7] iio: temperature: ltc2983: Use local device pointer consistently Liviu Stan
2026-05-14 19:39 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 3/7] iio: temperature: ltc2983: Fix inconsistent channel wording in messages Liviu Stan
2026-05-14 19:47 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 4/7] iio: temperature: ltc2983: Use fwnode_property_present() for optional properties Liviu Stan
2026-05-14 20:04 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 5/7] iio: core: Add IIO_COVERAGE_PERCENT channel type Liviu Stan
2026-05-14 20:16 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 6/7] dt-bindings: iio: temperature: Add ADT7604 support to adi,ltc2983 Liviu Stan
2026-05-14 20:43 ` sashiko-bot
2026-05-14 14:46 ` [PATCH v2 7/7] iio: temperature: ltc2983: Add support for ADT7604 Liviu Stan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox