Message ID | 20241122113322.242875-22-u.kleine-koenig@baylibre.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | iio: adc: ad7124: Various fixes | expand |
On 11/22/24 5:33 AM, Uwe Kleine-König wrote: > If the maximal count of channels the driver supports isn't fully > utilized, add an attribute providing the internal temperature. > ... > @@ -901,6 +945,32 @@ 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 = { > + .sign = 'u', The combination of .bipolar = true and .sign = 'u' looks a bit suspicions. > + .realbits = 24, > + .storagebits = 32, > + .endianness = IIO_BE, > + }, > + .address = num_channels, > + .scan_index = num_channels, > + }; > + }; > + > return 0; > } >
On Fri, Nov 22, 2024 at 1:34 PM Uwe Kleine-König <u.kleine-koenig@baylibre.com> wrote: > > If the maximal count of channels the driver supports isn't fully > utilized, add an attribute providing the internal temperature. ... > case IIO_CHAN_INFO_SCALE: > - mutex_lock(&st->cfgs_lock); > + switch (chan->type) { > + case IIO_VOLTAGE: > + mutex_lock(&st->cfgs_lock); Side note 1: cleanup.h at some point? ... > 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)); Side note 2: BIT() ? ... > case IIO_CHAN_INFO_SAMP_FREQ: > mutex_lock(&st->cfgs_lock); > *val = st->channels[chan->address].cfg.odr; > mutex_unlock(&st->cfgs_lock); > > return IIO_VAL_INT; > + > case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: > mutex_lock(&st->cfgs_lock); > *val = ad7124_get_3db_filter_freq(st, chan->scan_index); > mutex_unlock(&st->cfgs_lock); > > return IIO_VAL_INT; > + Seems like stray / unrelated changes. Do you really want to combine this with style changing? Usually we either change style first followed by featuring, or vice versa. > default: > return -EINVAL; > } > @@ -645,6 +685,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, > > ad7124_set_channel_odr(st, chan->address, val); > break; > + > case IIO_CHAN_INFO_SCALE: > if (val != 0) { > ret = -EINVAL; > @@ -666,6 +707,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, > > st->channels[chan->address].cfg.pga_bits = res; > break; > + > case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: > if (val2 != 0) { > ret = -EINVAL; Ditto. ... > + /* Add one for temperature */ > + st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS); Is the type of both arguments the same?
On Fri, Nov 22, 2024 at 10:31:07PM +0200, Andy Shevchenko wrote: > On Fri, Nov 22, 2024 at 1:34 PM Uwe Kleine-König > <u.kleine-koenig@baylibre.com> wrote: > > + /* Add one for temperature */ > > + st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS); > > Is the type of both arguments the same? Hmm, my compiler is happy with it at least. I don't understand why though. I'll do a few more tests ... Best regards Uwe
On Mon, Nov 25, 2024 at 1:27 PM Uwe Kleine-König <u.kleine-koenig@baylibre.com> wrote: > On Fri, Nov 22, 2024 at 10:31:07PM +0200, Andy Shevchenko wrote: > > On Fri, Nov 22, 2024 at 1:34 PM Uwe Kleine-König > > <u.kleine-koenig@baylibre.com> wrote: > > > + /* Add one for temperature */ > > > + st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS); > > > > Is the type of both arguments the same? > > Hmm, my compiler is happy with it at least. I don't understand why > though. I'll do a few more tests ... If num_channels is signed int or shorter than (independently on the sign) int, then it's obvious why. + 1 makes it int.
On Mon, Nov 25, 2024 at 03:47:25PM +0200, Andy Shevchenko wrote: > On Mon, Nov 25, 2024 at 1:27 PM Uwe Kleine-König > <u.kleine-koenig@baylibre.com> wrote: > > On Fri, Nov 22, 2024 at 10:31:07PM +0200, Andy Shevchenko wrote: > > > On Fri, Nov 22, 2024 at 1:34 PM Uwe Kleine-König > > > <u.kleine-koenig@baylibre.com> wrote: > > > > + /* Add one for temperature */ > > > > + st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS); > > > > > > Is the type of both arguments the same? > > > > Hmm, my compiler is happy with it at least. I don't understand why > > though. I'll do a few more tests ... > > If num_channels is signed int or shorter than (independently on the > sign) int, then it's obvious why. + 1 makes it int. Ah indeed, I should have understood that without that explanation. Thanks! Uwe
On Mon, Nov 25, 2024 at 4:52 PM Uwe Kleine-König <u.kleine-koenig@baylibre.com> wrote: > On Mon, Nov 25, 2024 at 03:47:25PM +0200, Andy Shevchenko wrote: > > On Mon, Nov 25, 2024 at 1:27 PM Uwe Kleine-König > > <u.kleine-koenig@baylibre.com> wrote: > > > On Fri, Nov 22, 2024 at 10:31:07PM +0200, Andy Shevchenko wrote: > > > > On Fri, Nov 22, 2024 at 1:34 PM Uwe Kleine-König > > > > <u.kleine-koenig@baylibre.com> wrote: > > > > > + /* Add one for temperature */ > > > > > + st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS); > > > > > > > > Is the type of both arguments the same? > > > > > > Hmm, my compiler is happy with it at least. I don't understand why > > > though. I'll do a few more tests ... > > > > If num_channels is signed int or shorter than (independently on the > > sign) int, then it's obvious why. + 1 makes it int. > > Ah indeed, I should have understood that without that explanation. Yeah, but a closer look shows to me that num_channels is unsigned int or did I look in the wrong place? If that's true, that should make a warning appear since AD7124_MAX_CHANNELS is signed int...
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index fdbe2806bf11..3eff156b9c00 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -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, @@ -588,39 +592,75 @@ static int ad7124_read_raw(struct iio_dev *indio_dev, return ret; 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; mutex_unlock(&st->cfgs_lock); return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: mutex_lock(&st->cfgs_lock); *val = ad7124_get_3db_filter_freq(st, chan->scan_index); mutex_unlock(&st->cfgs_lock); return IIO_VAL_INT; + default: return -EINVAL; } @@ -645,6 +685,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, ad7124_set_channel_odr(st, chan->address, val); break; + case IIO_CHAN_INFO_SCALE: if (val != 0) { ret = -EINVAL; @@ -666,6 +707,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, st->channels[chan->address].cfg.pga_bits = res; break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: if (val2 != 0) { ret = -EINVAL; @@ -825,11 +867,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 @@ -838,9 +879,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) @@ -861,7 +905,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); @@ -901,6 +945,32 @@ 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 = { + .sign = 'u', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_BE, + }, + .address = num_channels, + .scan_index = num_channels, + }; + }; + return 0; }
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> --- drivers/iio/adc/ad7124.c | 112 +++++++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 21 deletions(-)