Skip to content

Commit f4a774d

Browse files
machschmittjic23
authored andcommitted
iio: adc: ad4170-4: Add support for internal temperature sensor
The AD4170-4 has an internal temperature sensor that can be read using the ADC. Whenever possible, configure an IIO channel to provide the chip's temperature. Reviewed-by: Nuno Sá <nuno.sa@analog.com> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com> Link: https://patch.msgid.link/51abd3617dff088981f487b5bdd9e78b26f74929.1751289747.git.marcelo.schmitt@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 3763353 commit f4a774d

File tree

1 file changed

+69
-3
lines changed

1 file changed

+69
-3
lines changed

drivers/iio/adc/ad4170-4.c

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,27 @@ static const struct iio_chan_spec ad4170_channel_template = {
870870
},
871871
};
872872

873+
static const struct iio_chan_spec ad4170_temp_channel_template = {
874+
.type = IIO_TEMP,
875+
.indexed = 0,
876+
.channel = 17,
877+
.channel2 = 17,
878+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
879+
BIT(IIO_CHAN_INFO_SCALE) |
880+
BIT(IIO_CHAN_INFO_OFFSET) |
881+
BIT(IIO_CHAN_INFO_CALIBSCALE) |
882+
BIT(IIO_CHAN_INFO_CALIBBIAS) |
883+
BIT(IIO_CHAN_INFO_SAMP_FREQ),
884+
.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
885+
.scan_type = {
886+
.sign = 's',
887+
.realbits = 24,
888+
.storagebits = 32,
889+
.shift = 8,
890+
.endianness = IIO_BE,
891+
},
892+
};
893+
873894
/*
874895
* Receives the number of a multiplexed AD4170 input (ain_n), and stores the
875896
* voltage (in µV) of the specified input into ain_voltage. If the input number
@@ -1172,9 +1193,27 @@ static int ad4170_read_raw(struct iio_dev *indio_dev,
11721193
return ret;
11731194
case IIO_CHAN_INFO_SCALE:
11741195
pga = FIELD_GET(AD4170_AFE_PGA_GAIN_MSK, setup->afe);
1175-
*val = chan_info->scale_tbl[pga][0];
1176-
*val2 = chan_info->scale_tbl[pga][1];
1177-
return IIO_VAL_INT_PLUS_NANO;
1196+
switch (chan->type) {
1197+
case IIO_VOLTAGE:
1198+
*val = chan_info->scale_tbl[pga][0];
1199+
*val2 = chan_info->scale_tbl[pga][1];
1200+
return IIO_VAL_INT_PLUS_NANO;
1201+
1202+
case IIO_TEMP:
1203+
/*
1204+
* The scale_tbl converts output codes to mV units so
1205+
* multiply by MILLI to make the factor convert to µV.
1206+
* Then, apply the temperature sensor change sensitivity
1207+
* of 477 μV/K. Finally, multiply the result by MILLI
1208+
* again to comply with milli degrees Celsius IIO ABI.
1209+
*/
1210+
*val = 0;
1211+
*val2 = DIV_ROUND_CLOSEST(chan_info->scale_tbl[pga][1] * MILLI, 477) *
1212+
MILLI;
1213+
return IIO_VAL_INT_PLUS_NANO;
1214+
default:
1215+
return -EINVAL;
1216+
}
11781217
case IIO_CHAN_INFO_OFFSET:
11791218
pga = FIELD_GET(AD4170_AFE_PGA_GAIN_MSK, setup->afe);
11801219
*val = chan_info->offset_tbl[pga];
@@ -1842,13 +1881,40 @@ static int ad4170_parse_channels(struct iio_dev *indio_dev)
18421881
if (num_channels > AD4170_MAX_CHANNELS)
18431882
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
18441883

1884+
/* Add one for temperature */
1885+
num_channels = min(num_channels + 1, AD4170_MAX_CHANNELS);
1886+
18451887
chan_num = 0;
18461888
device_for_each_child_node_scoped(dev, child) {
18471889
ret = ad4170_parse_channel_node(indio_dev, child, chan_num++);
18481890
if (ret)
18491891
return ret;
18501892
}
18511893

1894+
/*
1895+
* Add internal temperature sensor channel if the maximum number of
1896+
* channels has not been reached.
1897+
*/
1898+
if (num_channels < AD4170_MAX_CHANNELS) {
1899+
struct ad4170_setup *setup = &st->chan_infos[chan_num].setup;
1900+
1901+
st->chans[chan_num] = ad4170_temp_channel_template;
1902+
st->chans[chan_num].address = chan_num;
1903+
st->chans[chan_num].scan_index = chan_num;
1904+
1905+
st->chan_infos[chan_num].setup_num = AD4170_INVALID_SETUP;
1906+
st->chan_infos[chan_num].initialized = true;
1907+
1908+
setup->afe |= FIELD_PREP(AD4170_AFE_REF_SELECT_MSK,
1909+
AD4170_REF_AVDD);
1910+
1911+
ret = ad4170_get_input_range(st, &st->chans[chan_num], chan_num,
1912+
AD4170_REF_AVDD);
1913+
if (ret < 0)
1914+
return dev_err_probe(dev, ret, "Invalid input config\n");
1915+
1916+
st->chan_infos[chan_num].input_range_uv = ret;
1917+
}
18521918
indio_dev->num_channels = num_channels;
18531919
indio_dev->channels = st->chans;
18541920

0 commit comments

Comments
 (0)