Skip to content

Commit

Permalink
iio: adc: ad7124: Implement temperature measurement
Browse files Browse the repository at this point in the history
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 <[email protected]>
Link: https://patch.msgid.link/433211af8ac3f02dee58586ecb51d2e98246a095.1733504533.git.u.kleine-koenig@baylibre.com
Signed-off-by: Jonathan Cameron <[email protected]>
Origin: next-20241216~37^2~16, commit:6eaf3f60ab45a5740ed4e1a7d41c4f0c10f6ac3c
  • Loading branch information
Uwe Kleine-König authored and nunojsa committed Dec 17, 2024
1 parent a64317b commit c7fe871
Showing 1 changed file with 91 additions and 23 deletions.
114 changes: 91 additions & 23 deletions drivers/iio/adc/ad7124.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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,
Expand Down Expand Up @@ -596,26 +600,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;
Expand Down Expand Up @@ -837,13 +874,10 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
struct device_node *child;
struct iio_chan_spec *chan;
unsigned int ain[2], channel = 0, tmp;
unsigned int num_channels;
int ret;

st->num_channels = of_get_available_child_count(np);
if (!st->num_channels) {
dev_err(indio_dev->dev.parent, "no channel children\n");
return -ENODEV;
}
num_channels = of_get_available_child_count(np);

/*
* The driver assigns each logical channel defined in the device tree
Expand All @@ -852,9 +886,12 @@ static int ad7124_of_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(indio_dev->dev.parent, -EINVAL, "Too many channels defined\n");

/* Add one for temperature */
st->num_channels = min(num_channels + 1, (unsigned int)AD7124_MAX_CHANNELS);

chan = devm_kcalloc(indio_dev->dev.parent, st->num_channels,
sizeof(*chan), GFP_KERNEL);
if (!chan)
Expand All @@ -874,7 +911,7 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
if (ret)
goto err;

if (channel >= indio_dev->num_channels) {
if (channel >= num_channels) {
dev_err(indio_dev->dev.parent,
"Channel index >= number of channels\n");
ret = -EINVAL;
Expand Down Expand Up @@ -914,6 +951,37 @@ static int ad7124_of_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;
err:
of_node_put(child);
Expand Down

0 comments on commit c7fe871

Please sign in to comment.