Skip to content

Commit 308abe9

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/71ac994060cf79a6c49f39b0c7d04c6c9cbbab00.1751895245.git.marcelo.schmitt@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent b251c82 commit 308abe9

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

drivers/iio/adc/ad4170-4.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,27 @@ static const struct iio_chan_spec ad4170_channel_template = {
874874
},
875875
};
876876

877+
static const struct iio_chan_spec ad4170_temp_channel_template = {
878+
.type = IIO_TEMP,
879+
.indexed = 0,
880+
.channel = 17,
881+
.channel2 = 17,
882+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
883+
BIT(IIO_CHAN_INFO_SCALE) |
884+
BIT(IIO_CHAN_INFO_OFFSET) |
885+
BIT(IIO_CHAN_INFO_CALIBSCALE) |
886+
BIT(IIO_CHAN_INFO_CALIBBIAS) |
887+
BIT(IIO_CHAN_INFO_SAMP_FREQ),
888+
.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
889+
.scan_type = {
890+
.sign = 's',
891+
.realbits = 24,
892+
.storagebits = 32,
893+
.shift = 8,
894+
.endianness = IIO_BE,
895+
},
896+
};
897+
877898
/*
878899
* Receives the number of a multiplexed AD4170 input (ain_n), and stores the
879900
* voltage (in µV) of the specified input into ain_voltage. If the input number
@@ -1181,6 +1202,18 @@ static int ad4170_read_raw(struct iio_dev *indio_dev,
11811202
*val = chan_info->scale_tbl[pga][0];
11821203
*val2 = chan_info->scale_tbl[pga][1];
11831204
return IIO_VAL_INT_PLUS_NANO;
1205+
case IIO_TEMP:
1206+
/*
1207+
* The scale_tbl converts output codes to mV units so
1208+
* multiply by MILLI to make the factor convert to µV.
1209+
* Then, apply the temperature sensor change sensitivity
1210+
* of 477 μV/K. Finally, multiply the result by MILLI
1211+
* again to comply with milli degrees Celsius IIO ABI.
1212+
*/
1213+
*val = 0;
1214+
*val2 = DIV_ROUND_CLOSEST(chan_info->scale_tbl[pga][1] * MILLI, 477) *
1215+
MILLI;
1216+
return IIO_VAL_INT_PLUS_NANO;
11841217
default:
11851218
return -EINVAL;
11861219
}
@@ -1859,13 +1892,42 @@ static int ad4170_parse_channels(struct iio_dev *indio_dev)
18591892
if (num_channels > AD4170_MAX_ADC_CHANNELS)
18601893
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
18611894

1895+
/* Add one for temperature */
1896+
num_channels = min(num_channels + 1, AD4170_MAX_ADC_CHANNELS);
1897+
18621898
chan_num = 0;
18631899
device_for_each_child_node_scoped(dev, child) {
18641900
ret = ad4170_parse_channel_node(indio_dev, child, chan_num++);
18651901
if (ret)
18661902
return ret;
18671903
}
18681904

1905+
/*
1906+
* Add internal temperature sensor channel if the maximum number of
1907+
* channels has not been reached.
1908+
*/
1909+
if (num_channels < AD4170_MAX_ADC_CHANNELS) {
1910+
struct ad4170_setup *setup = &st->chan_infos[chan_num].setup;
1911+
1912+
st->chans[chan_num] = ad4170_temp_channel_template;
1913+
st->chans[chan_num].address = chan_num;
1914+
st->chans[chan_num].scan_index = chan_num;
1915+
1916+
st->chan_infos[chan_num].setup_num = AD4170_INVALID_SETUP;
1917+
st->chan_infos[chan_num].initialized = true;
1918+
1919+
setup->afe |= FIELD_PREP(AD4170_AFE_REF_SELECT_MSK,
1920+
AD4170_REF_AVDD);
1921+
1922+
ret = ad4170_get_input_range(st, &st->chans[chan_num], chan_num,
1923+
AD4170_REF_AVDD);
1924+
if (ret < 0)
1925+
return dev_err_probe(dev, ret, "Invalid input config\n");
1926+
1927+
st->chan_infos[chan_num].input_range_uv = ret;
1928+
chan_num++;
1929+
}
1930+
18691931
/* Add timestamp channel */
18701932
struct iio_chan_spec ts_chan = IIO_CHAN_SOFT_TIMESTAMP(chan_num);
18711933

0 commit comments

Comments
 (0)