mbox series

[v5,00/10] iio: afe: add temperature rescaling support

Message ID 20210715031215.1534938-1-liambeguin@gmail.com (mailing list archive)
Headers show
Series iio: afe: add temperature rescaling support | expand

Message

Liam Beguin July 15, 2021, 3:12 a.m. UTC
From: Liam Beguin <lvb@xiphos.com>

Add temperature rescaling support to the IIO Analog Front End driver.

This series includes minor bug fixes and adds support for RTD temperature
sensors as well as temperature transducers.

At first I tried to use iio_convert_raw_to_processed() to get more
precision out of processed values but ran into issues when one of my
ADCs didn't provide a scale. I tried to address this in the first two
patches.

When adding offset support to iio-rescale, I also noticed that
iio_read_channel_processed() assumes that the offset is always an
integer which I tried to address in the third patch without breaking
valid implicit truncations.

As was suggested by Jonathan [1], I started implementing Kunit tests for
some of these cases[2]. It's pretty far from being ready but it still
helped test things faster this time around!

I'll send another series with the tests once I've cleaned it up and
figured out how to avoid copying part of the driver...

[1] https://patchwork.kernel.org/project/linux-iio/patch/20210701010034.303088-5-liambeguin@gmail.com/#24290449
[2] https://git.sr.ht/~liambeguin/Linux/commit/iio-rescale-test/v1

Changes since v4:
- only use gcd() when necessary in overflow mitigation
- fix INT_PLUS_{MICRO,NANO} support
- apply Reviewed-by
- fix temperature-transducer bindings

Changes since v3:
- drop unnecessary fallthrough statements
- drop redundant local variables in some calculations
- fix s64 divisions on 32bit platforms by using do_div
- add comment describing iio-rescaler offset calculation
- drop unnecessary MAINTAINERS entry

Changes since v2:
- don't break implicit offset truncations
- make a best effort to get a valid value for fractional types
- drop return value change in iio_convert_raw_to_processed_unlocked()
- don't rely on processed value for offset calculation
- add INT_PLUS_{MICRO,NANO} support in iio-rescale
- revert generic implementation in favor of temperature-sense-rtd and
  temperature-transducer
- add separate section to MAINTAINERS file

Changes since v1:
- rebase on latest iio `testing` branch
- also apply consumer scale on integer channel scale types
- don't break implicit truncation in processed channel offset
  calculation
- drop temperature AFE flavors in favor of a simpler generic
  implementation

Thanks for your time

Liam Beguin (10):
  iio: inkern: apply consumer scale on IIO_VAL_INT cases
  iio: inkern: apply consumer scale when no channel scale is available
  iio: inkern: make a best effort on offset calculation
  iio: afe: rescale: reduce risk of integer overflow
  iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
  iio: afe: rescale: add offset support
  iio: afe: rescale: add RTD temperature sensor support
  iio: afe: rescale: add temperature transducers
  dt-bindings: iio: afe: add bindings for temperature-sense-rtd
  dt-bindings: iio: afe: add bindings for temperature transducers

 .../iio/afe/temperature-sense-rtd.yaml        | 101 ++++++++++
 .../iio/afe/temperature-transducer.yaml       | 114 +++++++++++
 drivers/iio/afe/iio-rescale.c                 | 183 +++++++++++++++++-
 drivers/iio/inkern.c                          |  40 +++-
 4 files changed, 426 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
 create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml

Range-diff against v4:
 -:  ------------ >  1:  42a7a1047edc iio: inkern: apply consumer scale on IIO_VAL_INT cases
 -:  ------------ >  2:  a1cd89fdad11 iio: inkern: apply consumer scale when no channel scale is available
 -:  ------------ >  3:  ed0721fb6bd1 iio: inkern: make a best effort on offset calculation
 1:  e23e6cb26b92 !  4:  7b3e374eb7ad iio: afe: rescale: reduce risk of integer overflow
    @@ Commit message
     
         Reduce the risk of integer overflow by doing the scale calculation with
         64bit integers and looking for a Greatest Common Divider for both parts
    -    of the fractional value.
    +    of the fractional value when required.
     
         Signed-off-by: Liam Beguin <lvb@xiphos.com>
     
    @@ drivers/iio/afe/iio-rescale.c: static int rescale_read_raw(struct iio_dev *indio
     -			*val2 *= rescale->denominator;
     +			tmp = (s64)*val * rescale->numerator;
     +			tmp2 = (s64)*val2 * rescale->denominator;
    -+			factor = gcd(tmp, tmp2);
    -+			do_div(tmp, factor);
    ++			if (check_mul_overflow(*val, rescale->numerator, (s32 *)&tmp) ||
    ++			check_mul_overflow(*val2, rescale->denominator, (s32 *)&tmp2)) {
    ++				factor = gcd(tmp, tmp2);
    ++				do_div(tmp, factor);
    ++				do_div(tmp2, factor);
    ++			}
     +			*val = tmp;
    -+			do_div(tmp2, factor);
     +			*val2 = tmp2;
      			return ret;
      		case IIO_VAL_INT:
 2:  28203b672942 !  5:  1d334090e974 iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
    @@ Metadata
      ## Commit message ##
         iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
     
    -    Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.
    -    Scale the integer part and the decimal parts individually and keep the
    -    original scaling type.
    +    Some ADCs use IIO_VAL_INT_PLUS_{NANO,MICRO} scale types.
    +    Add support for these to allow using the iio-rescaler with them.
     
         Signed-off-by: Liam Beguin <lvb@xiphos.com>
     
    @@ drivers/iio/afe/iio-rescale.c: static int rescale_read_raw(struct iio_dev *indio
      			*val = tmp;
      			return ret;
     +		case IIO_VAL_INT_PLUS_NANO:
    ++			tmp = ((s64)*val * 1000000000LL + *val2) * rescale->numerator;
    ++			do_div(tmp, rescale->denominator);
    ++
    ++			*val = div_s64(tmp, 1000000000LL);
    ++			*val2 = tmp - *val * 1000000000LL;
    ++			return ret;
     +		case IIO_VAL_INT_PLUS_MICRO:
    -+			tmp = (s64)*val * rescale->numerator;
    -+			*val = div_s64(tmp, rescale->denominator);
    -+			tmp = (s64)*val2 * rescale->numerator;
    -+			*val2 = div_s64(tmp, rescale->denominator);
    ++			tmp = ((s64)*val * 1000000LL + *val2) * rescale->numerator;
    ++			do_div(tmp, rescale->denominator);
    ++
    ++			*val = div_s64(tmp, 1000000LL);
    ++			*val2 = tmp - *val * 1000000LL;
     +			return ret;
      		default:
     +			dev_err(&indio_dev->dev, "unsupported type %d\n", ret);
 3:  a6c944ae0f99 =  6:  61873203c140 iio: afe: rescale: add offset support
 4:  cc5eb96512d5 =  7:  4e6117b9c663 iio: afe: rescale: add RTD temperature sensor support
 5:  d8aa257aad35 =  8:  bc647d45e293 iio: afe: rescale: add temperature transducers
 6:  f038d6a08ea2 !  9:  570b418eed85 dt-bindings: iio: afe: add bindings for temperature-sense-rtd
    @@ Commit message
         voltage across an RTD resistor such as a PT1000.
     
         Signed-off-by: Liam Beguin <lvb@xiphos.com>
    +    Reviewed-by: Rob Herring <robh@kernel.org>
     
      ## Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml (new) ##
     @@
 7:  1db42cb25254 ! 10:  3c44ea89754e dt-bindings: iio: afe: add bindings for temperature transducers
    @@ Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml (new)
     +
     +  sense-offset-millicelsius:
     +    description: |
    -+      Temperature offset. The default is <0>.
    ++      Temperature offset.
     +      This offset is commonly used to convert from Kelvins to degrees Celsius.
     +      In that case, sense-offset-millicelsius would be set to <(-273150)>.
    ++    default: 0
     +
     +  sense-resistor-ohms:
     +    description: |
    -+      The sense resistor. Defaults to <1>.
    -+      Set sense-resistor-ohms to <1> when using a temperature to voltage
    -+      transducer.
    ++      The sense resistor.
    ++      By default sense-resistor-ohms cancels out the resistor making the
    ++      circuit behave like a temperature transducer.
    ++    default: 1
     +
     +  alpha-ppm-per-celsius:
     +    description: |
    @@ Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml (new)
     +      datasheet.
     +
     +additionalProperties: false
    ++
     +required:
     +  - compatible
     +  - io-channels

base-commit: 6cbb3aa0f9d5d23221df787cf36f74d3866fdb78