mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 09:12:39 -04:00
iio: adc: ad7124: Implement temperature measurement
If the maximal count of channels the driver supports isn't fully utilized, add an attribute providing the internal temperature. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Link: https://patch.msgid.link/433211af8ac3f02dee58586ecb51d2e98246a095.1733504533.git.u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
committed by
Jonathan Cameron
parent
abc61acde1
commit
6eaf3f60ab
@@ -95,6 +95,10 @@
|
||||
#define AD7124_MAX_CONFIGS 8
|
||||
#define AD7124_MAX_CHANNELS 16
|
||||
|
||||
/* AD7124 input sources */
|
||||
#define AD7124_INPUT_TEMPSENSOR 16
|
||||
#define AD7124_INPUT_AVSS 17
|
||||
|
||||
enum ad7124_ids {
|
||||
ID_AD7124_4,
|
||||
ID_AD7124_8,
|
||||
@@ -589,26 +593,59 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
|
||||
idx = st->channels[chan->address].cfg.pga_bits;
|
||||
*val = st->channels[chan->address].cfg.vref_mv;
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val2 = chan->scan_type.realbits - 1 + idx;
|
||||
else
|
||||
*val2 = chan->scan_type.realbits + idx;
|
||||
idx = st->channels[chan->address].cfg.pga_bits;
|
||||
*val = st->channels[chan->address].cfg.vref_mv;
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val2 = chan->scan_type.realbits - 1 + idx;
|
||||
else
|
||||
*val2 = chan->scan_type.realbits + idx;
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
case IIO_TEMP:
|
||||
/*
|
||||
* According to the data sheet
|
||||
* Temperature (°C)
|
||||
* = ((Conversion − 0x800000)/13584) − 272.5
|
||||
* = (Conversion − 0x800000 - 13584 * 272.5) / 13584
|
||||
* = (Conversion − 12090248) / 13584
|
||||
* So scale with 1000/13584 to yield °mC. Reduce by 8 to
|
||||
* 125/1698.
|
||||
*/
|
||||
*val = 125;
|
||||
*val2 = 1698;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val = -(1 << (chan->scan_type.realbits - 1));
|
||||
else
|
||||
*val = 0;
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val = -(1 << (chan->scan_type.realbits - 1));
|
||||
else
|
||||
*val = 0;
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_INT;
|
||||
|
||||
case IIO_TEMP:
|
||||
/* see calculation above */
|
||||
*val = -12090248;
|
||||
return IIO_VAL_INT;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
*val = st->channels[chan->address].cfg.odr;
|
||||
@@ -826,11 +863,10 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
struct ad7124_channel *channels;
|
||||
struct iio_chan_spec *chan;
|
||||
unsigned int ain[2], channel = 0, tmp;
|
||||
unsigned int num_channels;
|
||||
int ret;
|
||||
|
||||
st->num_channels = device_get_child_node_count(dev);
|
||||
if (!st->num_channels)
|
||||
return dev_err_probe(dev, -ENODEV, "no channel children\n");
|
||||
num_channels = device_get_child_node_count(dev);
|
||||
|
||||
/*
|
||||
* The driver assigns each logical channel defined in the device tree
|
||||
@@ -839,9 +875,12 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
* CHANNEL_15) as an additional channel register. The driver could be
|
||||
* improved to lift this limitation.
|
||||
*/
|
||||
if (st->num_channels > AD7124_MAX_CHANNELS)
|
||||
if (num_channels > AD7124_MAX_CHANNELS)
|
||||
return dev_err_probe(dev, -EINVAL, "Too many channels defined\n");
|
||||
|
||||
/* Add one for temperature */
|
||||
st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS);
|
||||
|
||||
chan = devm_kcalloc(indio_dev->dev.parent, st->num_channels,
|
||||
sizeof(*chan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
@@ -862,7 +901,7 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to parse reg property of %pfwP\n", child);
|
||||
|
||||
if (channel >= indio_dev->num_channels)
|
||||
if (channel >= num_channels)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Channel index >= number of channels in %pfwP\n", child);
|
||||
|
||||
@@ -902,6 +941,37 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
chan[channel].channel2 = ain[1];
|
||||
}
|
||||
|
||||
if (num_channels < AD7124_MAX_CHANNELS) {
|
||||
st->channels[num_channels] = (struct ad7124_channel) {
|
||||
.nr = num_channels,
|
||||
.ain = AD7124_CHANNEL_AINP(AD7124_INPUT_TEMPSENSOR) |
|
||||
AD7124_CHANNEL_AINM(AD7124_INPUT_AVSS),
|
||||
.cfg = {
|
||||
.bipolar = true,
|
||||
},
|
||||
};
|
||||
|
||||
chan[num_channels] = (struct iio_chan_spec) {
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET) |
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
.scan_type = {
|
||||
/*
|
||||
* You might find it strange that a bipolar
|
||||
* measurement yields an unsigned value, but
|
||||
* this matches the device's manual.
|
||||
*/
|
||||
.sign = 'u',
|
||||
.realbits = 24,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
.address = num_channels,
|
||||
.scan_index = num_channels,
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user