Commit 6eaf3f60 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Jonathan Cameron
Browse files

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: default avatarUwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://patch.msgid.link/433211af8ac3f02dee58586ecb51d2e98246a095.1733504533.git.u.kleine-koenig@baylibre.com


Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent abc61acd
Loading
Loading
Loading
Loading
+91 −21
Original line number Diff line number Diff line
@@ -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,6 +593,8 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,

		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		switch (chan->type) {
		case IIO_VOLTAGE:
			mutex_lock(&st->cfgs_lock);

			idx = st->channels[chan->address].cfg.pga_bits;
@@ -600,7 +606,28 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,

			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;
		}

	case IIO_CHAN_INFO_OFFSET:
		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));
@@ -609,6 +636,16 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,

			mutex_unlock(&st->cfgs_lock);
			return IIO_VAL_INT;

		case IIO_TEMP:
			/* see calculation above */
			*val = -12090248;
			return IIO_VAL_INT;

		default:
			return -EINVAL;
		}

	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;
}