All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v4] iio: Provide iio_read_channel_processed_scale() API
@ 2021-03-08 10:02 Linus Walleij
  2021-03-08 10:02 ` [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed Linus Walleij
  0 siblings, 1 reply; 5+ messages in thread
From: Linus Walleij @ 2021-03-08 10:02 UTC (permalink / raw)
  To: Jean Delvare, Guenter Roeck, Jonathan Cameron
  Cc: linux-hwmon, Linus Walleij, Peter Rosin, Chris Lesiak, linux-iio

Since the old iio_read_channel_processed() would
lose precision if we fall back to reading raw and
scaling, we introduce a new API that will pass in
a scale factor when reading a processed channel:
iio_read_channel_processed_scale().

Refactor iio_read_channel_processed() as a special
case with scale factor 1.

Cc: Peter Rosin <peda@axentia.se>
Cc: Chris Lesiak <chris.lesiak@licor.com>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: linux-iio@vger.kernel.org
Link: https://lore.kernel.org/linux-iio/20201224011607.1059534-1-linus.walleij@linaro.org/
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v3->v4:
- Split off as separate API-introducing patch.
- Fix a goto err when scaling.
- My suggestion is to apply this patch with Jonathan's ACK
  to the hwmon tree.
---
 drivers/iio/inkern.c         | 16 ++++++++++++++--
 include/linux/iio/consumer.h | 15 +++++++++++++++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index db77a2d4a56b..c61fc06f98b8 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -688,7 +688,8 @@ int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
 }
 EXPORT_SYMBOL_GPL(iio_read_channel_offset);
 
-int iio_read_channel_processed(struct iio_channel *chan, int *val)
+int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
+				     unsigned int scale)
 {
 	int ret;
 
@@ -701,11 +702,15 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val)
 	if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
 		ret = iio_channel_read(chan, val, NULL,
 				       IIO_CHAN_INFO_PROCESSED);
+		if (ret)
+			goto err_unlock;
+		*val *= scale;
 	} else {
 		ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
 		if (ret < 0)
 			goto err_unlock;
-		ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
+		ret = iio_convert_raw_to_processed_unlocked(chan, *val, val,
+							    scale);
 	}
 
 err_unlock:
@@ -713,6 +718,13 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(iio_read_channel_processed_scale);
+
+int iio_read_channel_processed(struct iio_channel *chan, int *val)
+{
+	/* This is just a special case with scale factor 1 */
+	return iio_read_channel_processed_scale(chan, val, 1);
+}
 EXPORT_SYMBOL_GPL(iio_read_channel_processed);
 
 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 0a90ba8fa1bb..5fa5957586cf 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -241,6 +241,21 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val);
  */
 int iio_read_channel_processed(struct iio_channel *chan, int *val);
 
+/**
+ * iio_read_channel_processed_scale() - read and scale a processed value
+ * @chan:		The channel being queried.
+ * @val:		Value read back.
+ * @scale:		Scale factor to apply during the conversion
+ *
+ * Returns an error code or 0.
+ *
+ * This function will read a processed value from a channel. This will work
+ * like @iio_read_channel_processed() but also scale with an additional
+ * scale factor while attempting to minimize any precision loss.
+ */
+int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
+				     unsigned int scale);
+
 /**
  * iio_write_channel_attribute() - Write values to the device attribute.
  * @chan:	The channel being queried.
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed
  2021-03-08 10:02 [PATCH 1/2 v4] iio: Provide iio_read_channel_processed_scale() API Linus Walleij
@ 2021-03-08 10:02 ` Linus Walleij
  2021-03-08 16:24   ` Chris Lesiak
  2021-03-09 17:15   ` Guenter Roeck
  0 siblings, 2 replies; 5+ messages in thread
From: Linus Walleij @ 2021-03-08 10:02 UTC (permalink / raw)
  To: Jean Delvare, Guenter Roeck, Jonathan Cameron
  Cc: linux-hwmon, Linus Walleij, Peter Rosin, Chris Lesiak, linux-iio

Before trying the custom method of reading the sensor
as raw and then converting, we want to use
iio_read_channel_processed_scale() which first tries to
see if the ADC can provide a processed value directly,
else reads raw and applies scaling inside of IIO
using the scale attributes of the ADC. We need to
multiply the scaled value with 1000 to get to
microvolts from millivolts which is what processed
IIO channels returns.

Keep the code that assumes 12bit ADC around as a
fallback.

This gives correct readings on the AB8500 thermistor
inputs used in the Ux500 HREFP520 platform for reading
battery and board temperature.

Cc: Peter Rosin <peda@axentia.se>
Cc: Chris Lesiak <chris.lesiak@licor.com>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: linux-iio@vger.kernel.org
Link: https://lore.kernel.org/linux-iio/20201224011607.1059534-1-linus.walleij@linaro.org/
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v3->v4:
- Split out the new iio_read_channel_processed_scale()
  API addition to a separate patch.
- My suggestion is to apply both patches to the hwmon
  tree.
ChangeLog v2->v3:
- After discussion about v2 we concludes that
  iio_read_channel_processed() could loose precision
  so we introduce a new API to read processed and
  scale.
- Include a link to the v2 discussion for reference.
- For ease of applying to the hwmon tree, keep it all
  in one patch.
- This needs Jonathans ACK to be merged through hwmon.
ChangeLog v1->v2:
- Fix the patch to multiply the processed value by
  1000 to get to microvolts from millivolts.
- Fix up the confusion in the commit message.
- Drop pointless comments about the code, we keep the
  original code path around if processed reads don't
  work, nothing bad with that.
---
 drivers/hwmon/ntc_thermistor.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 3aad62a0e661..8587189c7f15 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -326,18 +326,27 @@ struct ntc_data {
 static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
 {
 	struct iio_channel *channel = pdata->chan;
-	int raw, uv, ret;
+	int uv, ret;
 
-	ret = iio_read_channel_raw(channel, &raw);
+	ret = iio_read_channel_processed_scale(channel, &uv, 1000);
 	if (ret < 0) {
-		pr_err("read channel() error: %d\n", ret);
-		return ret;
-	}
+		int raw;
 
-	ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
-	if (ret < 0) {
-		/* Assume 12 bit ADC with vref at pullup_uv */
-		uv = (pdata->pullup_uv * (s64)raw) >> 12;
+		/*
+		 * This fallback uses a raw read and then
+		 * assumes the ADC is 12 bits, scaling with
+		 * a factor 1000 to get to microvolts.
+		 */
+		ret = iio_read_channel_raw(channel, &raw);
+		if (ret < 0) {
+			pr_err("read channel() error: %d\n", ret);
+			return ret;
+		}
+		ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
+		if (ret < 0) {
+			/* Assume 12 bit ADC with vref at pullup_uv */
+			uv = (pdata->pullup_uv * (s64)raw) >> 12;
+		}
 	}
 
 	return uv;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed
  2021-03-08 10:02 ` [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed Linus Walleij
@ 2021-03-08 16:24   ` Chris Lesiak
  2021-03-09 17:15   ` Guenter Roeck
  1 sibling, 0 replies; 5+ messages in thread
From: Chris Lesiak @ 2021-03-08 16:24 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-hwmon, Peter Rosin, linux-iio, Jean Delvare,
	Jonathan Cameron, Guenter Roeck

I've tested this in a 4.14 based kernel with two different out-of-tree 
iio adcs, neither of which supports IIO_CHAN_INFO_PROCESSED.

Tested-by: Chris Lesiak <chris.lesiak@licor.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed
  2021-03-08 10:02 ` [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed Linus Walleij
  2021-03-08 16:24   ` Chris Lesiak
@ 2021-03-09 17:15   ` Guenter Roeck
  2021-03-13 18:25     ` Jonathan Cameron
  1 sibling, 1 reply; 5+ messages in thread
From: Guenter Roeck @ 2021-03-09 17:15 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jean Delvare, Jonathan Cameron, linux-hwmon, Peter Rosin,
	Chris Lesiak, linux-iio

On Mon, Mar 08, 2021 at 11:02:19AM +0100, Linus Walleij wrote:
> Before trying the custom method of reading the sensor
> as raw and then converting, we want to use
> iio_read_channel_processed_scale() which first tries to
> see if the ADC can provide a processed value directly,
> else reads raw and applies scaling inside of IIO
> using the scale attributes of the ADC. We need to
> multiply the scaled value with 1000 to get to
> microvolts from millivolts which is what processed
> IIO channels returns.
> 
> Keep the code that assumes 12bit ADC around as a
> fallback.
> 
> This gives correct readings on the AB8500 thermistor
> inputs used in the Ux500 HREFP520 platform for reading
> battery and board temperature.
> 
> Cc: Peter Rosin <peda@axentia.se>
> Cc: Chris Lesiak <chris.lesiak@licor.com>
> Cc: Jonathan Cameron <jic23@kernel.org>
> Cc: linux-iio@vger.kernel.org
> Link: https://lore.kernel.org/linux-iio/20201224011607.1059534-1-linus.walleij@linaro.org/
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

Acked-by: Guenter Roeck <linux@roeck-us.net>

Up to Jonathan to decide if he wants to take both patches.

Thanks,
Guenter

> ---
> ChangeLog v3->v4:
> - Split out the new iio_read_channel_processed_scale()
>   API addition to a separate patch.
> - My suggestion is to apply both patches to the hwmon
>   tree.
> ChangeLog v2->v3:
> - After discussion about v2 we concludes that
>   iio_read_channel_processed() could loose precision
>   so we introduce a new API to read processed and
>   scale.
> - Include a link to the v2 discussion for reference.
> - For ease of applying to the hwmon tree, keep it all
>   in one patch.
> - This needs Jonathans ACK to be merged through hwmon.
> ChangeLog v1->v2:
> - Fix the patch to multiply the processed value by
>   1000 to get to microvolts from millivolts.
> - Fix up the confusion in the commit message.
> - Drop pointless comments about the code, we keep the
>   original code path around if processed reads don't
>   work, nothing bad with that.
> ---
>  drivers/hwmon/ntc_thermistor.c | 27 ++++++++++++++++++---------
>  1 file changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index 3aad62a0e661..8587189c7f15 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -326,18 +326,27 @@ struct ntc_data {
>  static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
>  {
>  	struct iio_channel *channel = pdata->chan;
> -	int raw, uv, ret;
> +	int uv, ret;
>  
> -	ret = iio_read_channel_raw(channel, &raw);
> +	ret = iio_read_channel_processed_scale(channel, &uv, 1000);
>  	if (ret < 0) {
> -		pr_err("read channel() error: %d\n", ret);
> -		return ret;
> -	}
> +		int raw;
>  
> -	ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
> -	if (ret < 0) {
> -		/* Assume 12 bit ADC with vref at pullup_uv */
> -		uv = (pdata->pullup_uv * (s64)raw) >> 12;
> +		/*
> +		 * This fallback uses a raw read and then
> +		 * assumes the ADC is 12 bits, scaling with
> +		 * a factor 1000 to get to microvolts.
> +		 */
> +		ret = iio_read_channel_raw(channel, &raw);
> +		if (ret < 0) {
> +			pr_err("read channel() error: %d\n", ret);
> +			return ret;
> +		}
> +		ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
> +		if (ret < 0) {
> +			/* Assume 12 bit ADC with vref at pullup_uv */
> +			uv = (pdata->pullup_uv * (s64)raw) >> 12;
> +		}
>  	}
>  
>  	return uv;
> -- 
> 2.29.2
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed
  2021-03-09 17:15   ` Guenter Roeck
@ 2021-03-13 18:25     ` Jonathan Cameron
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2021-03-13 18:25 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Linus Walleij, Jean Delvare, linux-hwmon, Peter Rosin,
	Chris Lesiak, linux-iio

On Tue, 9 Mar 2021 09:15:01 -0800
Guenter Roeck <linux@roeck-us.net> wrote:

> On Mon, Mar 08, 2021 at 11:02:19AM +0100, Linus Walleij wrote:
> > Before trying the custom method of reading the sensor
> > as raw and then converting, we want to use
> > iio_read_channel_processed_scale() which first tries to
> > see if the ADC can provide a processed value directly,
> > else reads raw and applies scaling inside of IIO
> > using the scale attributes of the ADC. We need to
> > multiply the scaled value with 1000 to get to
> > microvolts from millivolts which is what processed
> > IIO channels returns.
> > 
> > Keep the code that assumes 12bit ADC around as a
> > fallback.
> > 
> > This gives correct readings on the AB8500 thermistor
> > inputs used in the Ux500 HREFP520 platform for reading
> > battery and board temperature.
> > 
> > Cc: Peter Rosin <peda@axentia.se>
> > Cc: Chris Lesiak <chris.lesiak@licor.com>
> > Cc: Jonathan Cameron <jic23@kernel.org>
> > Cc: linux-iio@vger.kernel.org
> > Link: https://lore.kernel.org/linux-iio/20201224011607.1059534-1-linus.walleij@linaro.org/
> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>  
> 
> Acked-by: Guenter Roeck <linux@roeck-us.net>
> 
> Up to Jonathan to decide if he wants to take both patches.
It seems unlikely that it will cause trouble in either tree (as the code
in question isn't changing that often). So on basis Guenter already acked
I'll pick them up through IIO.

Applied to the togreg branch of iio.git and pushed out as testing to
see if the autobuilders notice anything we missed.
thanks,

Jonathan

> 
> Thanks,
> Guenter
> 
> > ---
> > ChangeLog v3->v4:
> > - Split out the new iio_read_channel_processed_scale()
> >   API addition to a separate patch.
> > - My suggestion is to apply both patches to the hwmon
> >   tree.
> > ChangeLog v2->v3:
> > - After discussion about v2 we concludes that
> >   iio_read_channel_processed() could loose precision
> >   so we introduce a new API to read processed and
> >   scale.
> > - Include a link to the v2 discussion for reference.
> > - For ease of applying to the hwmon tree, keep it all
> >   in one patch.
> > - This needs Jonathans ACK to be merged through hwmon.
> > ChangeLog v1->v2:
> > - Fix the patch to multiply the processed value by
> >   1000 to get to microvolts from millivolts.
> > - Fix up the confusion in the commit message.
> > - Drop pointless comments about the code, we keep the
> >   original code path around if processed reads don't
> >   work, nothing bad with that.
> > ---
> >  drivers/hwmon/ntc_thermistor.c | 27 ++++++++++++++++++---------
> >  1 file changed, 18 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> > index 3aad62a0e661..8587189c7f15 100644
> > --- a/drivers/hwmon/ntc_thermistor.c
> > +++ b/drivers/hwmon/ntc_thermistor.c
> > @@ -326,18 +326,27 @@ struct ntc_data {
> >  static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
> >  {
> >  	struct iio_channel *channel = pdata->chan;
> > -	int raw, uv, ret;
> > +	int uv, ret;
> >  
> > -	ret = iio_read_channel_raw(channel, &raw);
> > +	ret = iio_read_channel_processed_scale(channel, &uv, 1000);
> >  	if (ret < 0) {
> > -		pr_err("read channel() error: %d\n", ret);
> > -		return ret;
> > -	}
> > +		int raw;
> >  
> > -	ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
> > -	if (ret < 0) {
> > -		/* Assume 12 bit ADC with vref at pullup_uv */
> > -		uv = (pdata->pullup_uv * (s64)raw) >> 12;
> > +		/*
> > +		 * This fallback uses a raw read and then
> > +		 * assumes the ADC is 12 bits, scaling with
> > +		 * a factor 1000 to get to microvolts.
> > +		 */
> > +		ret = iio_read_channel_raw(channel, &raw);
> > +		if (ret < 0) {
> > +			pr_err("read channel() error: %d\n", ret);
> > +			return ret;
> > +		}
> > +		ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
> > +		if (ret < 0) {
> > +			/* Assume 12 bit ADC with vref at pullup_uv */
> > +			uv = (pdata->pullup_uv * (s64)raw) >> 12;
> > +		}
> >  	}
> >  
> >  	return uv;
> > -- 
> > 2.29.2
> >   


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-03-13 18:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08 10:02 [PATCH 1/2 v4] iio: Provide iio_read_channel_processed_scale() API Linus Walleij
2021-03-08 10:02 ` [PATCH 2/2 v4] hwmon: (ntc_thermistor): try reading processed Linus Walleij
2021-03-08 16:24   ` Chris Lesiak
2021-03-09 17:15   ` Guenter Roeck
2021-03-13 18:25     ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.