Skip to content

Commit 696a841

Browse files
machschmittnunojsa
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 9dea539 commit 696a841

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
}
@@ -1862,13 +1895,42 @@ static int ad4170_parse_channels(struct iio_dev *indio_dev)
18621895
if (num_channels > AD4170_MAX_ADC_CHANNELS)
18631896
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
18641897

1898+
/* Add one for temperature */
1899+
num_channels = min(num_channels + 1, AD4170_MAX_ADC_CHANNELS);
1900+
18651901
chan_num = 0;
18661902
device_for_each_child_node_scoped(dev, child) {
18671903
ret = ad4170_parse_channel_node(indio_dev, child, chan_num++);
18681904
if (ret)
18691905
return ret;
18701906
}
18711907

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

0 commit comments

Comments
 (0)