2022-02-14 06:53:28

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 00/10] iio: afe: add temperature rescaling support

Jonathan, Peter, Andy,

This series focuses on adding temperature rescaling support to the IIO
Analog Front End (AFE) driver.

The main changes to the AFE driver include an initial Kunit test suite,
support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
and temperature transducer sensors.

Thanks for your time,
Liam

Changes since v14:
- Revert units.h changes in favor of "raw" values

Changes since v13:
- fix SI prefix in rescale_temp_sense_rtd_props()
- add comment explaining SI prefixes are sometimes used as mathematical
multipliers with no particular physical meaning associated.

Changes since v12:
- rebase on latest testing branch
- fix copyright holder in newly created header file
- add myself as a copyright holder of the iio-rescale.c driver at
Peter's suggestion
- fix undefined behavior on left-shift operation

Changes since v11:
- update commits with my personal email since all this work was done on
my own time
- apply Peter's Reviewed-by to my local tree
- fix use of units.h
- make use of units.h more consistently in iio-rescale.c and in the
tests
- fix #include ordering
- treat 04/16 as a fix. Move it, and add a Fixes: tag
- fix undefined behavior on left-shift operation
- add comment about fract_mult with iio_str_to_fixpoint()
- reword commit message for 14/16, based on Andy's comments

Changes since v10:
- apply Andy's suggestion for offset calculations
- make use of units.h more consistently

Changes since v9:
- make use of linux/units.h
- reorder commits, fix fract_log2 before merging fract
- keep fractional representation when not overflowing

Changes since v8:
- reword comment
- fix erroneous 64-bit division
- optimize and use 32-bit divisions when values are know to not overflow
- keep IIO_VAL_FRACTIONAL scale when possible, if not default to fixed
point
- add test cases
- use nano precision in test cases
- simplify offset calculation in rtd_props()

Changes since v7:
- drop gcd() logic in rescale_process_scale()
- use div_s64() instead of do_div() for signed 64-bit divisions
- combine IIO_VAL_FRACTIONAL and IIO_VAL_FRACTIONAL_LOG2 scale cases
- switch to INT_PLUS_NANO when accuracy is lost with FRACTIONAL scales
- rework test logic to allow for small relative error
- rename test variables to align error output messages

Changes since v6:
- rework IIO_VAL_INT_PLUS_{NANO,MICRO} based on Peter's suggestion
- combine IIO_VAL_INT_PLUS_{NANO,MICRO} cases
- add test cases for negative IIO_VAL_INT_PLUS_{NANO,MICRO} corner cases
- force use of positive integers with gcd()
- reduce risk of integer overflow in IIO_VAL_FRACTIONAL_LOG2
- fix duplicate symbol build error
- apply Reviewed-by

Changes since v5:
- add include/linux/iio/afe/rescale.h
- expose functions use to process scale and offset
- add basic iio-rescale kunit test cases
- fix integer overflow case
- improve precision for IIO_VAL_FRACTIONAL_LOG2

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

Liam Beguin (10):
iio: afe: rescale: expose scale processing function
iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
iio: afe: rescale: add offset support
iio: afe: rescale: fix accuracy for small fractional scales
iio: afe: rescale: reduce risk of integer overflow
iio: test: add basic tests for the iio-rescale driver
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 | 283 ++++++-
drivers/iio/test/Kconfig | 10 +
drivers/iio/test/Makefile | 1 +
drivers/iio/test/iio-test-rescale.c | 710 ++++++++++++++++++
include/linux/iio/afe/rescale.h | 36 +
7 files changed, 1220 insertions(+), 35 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
create mode 100644 drivers/iio/test/iio-test-rescale.c
create mode 100644 include/linux/iio/afe/rescale.h

Range-diff against v14:
-: ------------ > 1: ee26b0eeac65 iio: afe: rescale: expose scale processing function
1: a510097c83f1 ! 2: 78f9d37575a5 iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
@@ Commit message
Reviewed-by: Peter Rosin <[email protected]>

## drivers/iio/afe/iio-rescale.c ##
-@@
- #include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/property.h>
-+#include <linux/units.h>
-
- #include <linux/iio/afe/rescale.h>
- #include <linux/iio/consumer.h>
@@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale, int scale_type,
int *val, int *val2)
{
@@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
+ return scale_type;
+ case IIO_VAL_INT_PLUS_NANO:
+ case IIO_VAL_INT_PLUS_MICRO:
-+ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
++ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
+
+ /*
+ * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val
2: 8f2f2699a9b4 ! 3: 5be82bd72453 iio: afe: rescale: add offset support
@@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
+ *val = div_s64(tmp, scale) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_INT_PLUS_NANO:
-+ tmp = (s64)rescale->offset * GIGA;
-+ tmp2 = ((s64)scale * GIGA) + scale2;
++ tmp = (s64)rescale->offset * 1000000000LL;
++ tmp2 = ((s64)scale * 1000000000LL) + scale2;
+ *val = div64_s64(tmp, tmp2) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_INT_PLUS_MICRO:
-+ tmp = (s64)rescale->offset * MEGA;
-+ tmp2 = ((s64)scale * MEGA) + scale2;
++ tmp = (s64)rescale->offset * 1000000LL;
++ tmp2 = ((s64)scale * 1000000LL) + scale2;
+ *val = div64_s64(tmp, tmp2) + schan_off;
+ return IIO_VAL_INT;
+ default:
3: 2efa970bad26 ! 4: 95ec184759f6 iio: afe: rescale: fix accuracy for small fractional scales
@@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
+ return IIO_VAL_INT_PLUS_NANO;
case IIO_VAL_INT_PLUS_NANO:
case IIO_VAL_INT_PLUS_MICRO:
- mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
+ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
4: 201037c0ead8 = 5: 2e1d41ef69d9 iio: afe: rescale: reduce risk of integer overflow
5: a0037cc3ee90 < -: ------------ iio: afe: rescale: make use of units.h
6: f8d47728f482 ! 6: 0b6c029dea1d iio: test: add basic tests for the iio-rescale driver
@@ drivers/iio/test/iio-test-rescale.c (new)
+
+#include <linux/gcd.h>
+#include <linux/overflow.h>
-+#include <linux/units.h>
+
+#include <linux/iio/afe/rescale.h>
+#include <linux/iio/iio.h>
@@ drivers/iio/test/iio-test-rescale.c (new)
+ if (tmp < 0)
+ tmp2 *= -1;
+
-+ *nano = (s64)tmp * GIGA + tmp2;
++ *nano = (s64)tmp * 1000000000UL + tmp2;
+
+ return ret;
+}
@@ drivers/iio/test/iio-test-rescale.c (new)
+ return -EINVAL;
+ }
+
-+ err = MEGA * abs(exp - real);
++ err = 1000000UL * abs(exp - real);
+
+ return (int)div64_u64(err, abs(exp));
+}
7: a04685586340 ! 7: 951ea44d0f5c iio: afe: rescale: add RTD temperature sensor support
@@ drivers/iio/afe/iio-rescale.c: static int rescale_voltage_divider_props(struct d
+ return ret;
+ }
+
-+ tmp = r0 * iexc * alpha / MEGA;
-+ factor = gcd(tmp, MEGA);
-+ rescale->numerator = MEGA / factor;
++ tmp = r0 * iexc * alpha / 1000000;
++ factor = gcd(tmp, 1000000);
++ rescale->numerator = 1000000 / factor;
+ rescale->denominator = tmp / factor;
+
-+ rescale->offset = -1 * ((r0 * iexc) / KILO);
++ rescale->offset = -1 * ((r0 * iexc) / 1000);
+
+ return 0;
+}
8: e3b716aaee50 ! 8: 56516fdc67bf iio: afe: rescale: add temperature transducers
@@ drivers/iio/afe/iio-rescale.c: static int rescale_temp_sense_rtd_props(struct de
+ return ret;
+ }
+
-+ rescale->numerator = MEGA;
++ rescale->numerator = 1000000;
+ rescale->denominator = alpha * sense;
+
+ rescale->offset = div_s64((s64)offset * rescale->denominator,
9: 22ae1458eb8b = 9: 8c409050990b dt-bindings: iio: afe: add bindings for temperature-sense-rtd
10: 33825ad452d6 = 10: bb39296590f3 dt-bindings: iio: afe: add bindings for temperature transducers

base-commit: cd717ac6f69db4953ca701c6220c7cb58e17f35a
--
2.35.1.4.g5d01301f2b86


2022-02-14 09:30:51

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 09/10] dt-bindings: iio: afe: add bindings for temperature-sense-rtd

An ADC is often used to measure other quantities indirectly. This
binding describe one case, the measurement of a temperature through the
voltage across an RTD resistor such as a PT1000.

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
.../iio/afe/temperature-sense-rtd.yaml | 101 ++++++++++++++++++
1 file changed, 101 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml

diff --git a/Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml b/Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
new file mode 100644
index 000000000000..336ce96371db
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/afe/temperature-sense-rtd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Temperature Sense RTD
+
+maintainers:
+ - Liam Beguin <[email protected]>
+
+description: |
+ RTDs (Resistance Temperature Detectors) are a kind of temperature sensors
+ used to get a linear voltage to temperature reading within a give range
+ (usually 0 to 100 degrees Celsius).
+
+ When an io-channel measures the output voltage across an RTD such as a
+ PT1000, the interesting measurement is almost always the corresponding
+ temperature, not the voltage output. This binding describes such a circuit.
+
+ The general transfer function here is (using SI units)
+
+ V = R(T) * iexc
+ R(T) = r0 * (1 + alpha * T)
+ T = 1 / (alpha * r0 * iexc) * (V - r0 * iexc)
+
+ The following circuit matches what's in the examples section.
+
+ 5V0
+ -----
+ |
+ +---+----+
+ | R 5k |
+ +---+----+
+ |
+ V 1mA
+ |
+ +---- Vout
+ |
+ +---+----+
+ | PT1000 |
+ +---+----+
+ |
+ -----
+ GND
+
+properties:
+ compatible:
+ const: temperature-sense-rtd
+
+ io-channels:
+ maxItems: 1
+ description: |
+ Channel node of a voltage io-channel.
+
+ '#io-channel-cells':
+ const: 0
+
+ excitation-current-microamp:
+ description: The current fed through the RTD sensor.
+
+ alpha-ppm-per-celsius:
+ description: |
+ alpha can also be expressed in micro-ohms per ohm Celsius. It's a linear
+ approximation of the resistance versus temperature relationship
+ between 0 and 100 degrees Celsius.
+
+ alpha = (R_100 - R_0) / (100 * R_0)
+
+ Where, R_100 is the resistance of the sensor at 100 degrees Celsius, and
+ R_0 (or r-naught-ohms) is the resistance of the sensor at 0 degrees
+ Celsius.
+
+ Pure platinum has an alpha of 3925. Industry standards such as IEC60751
+ and ASTM E-1137 specify an alpha of 3850.
+
+ r-naught-ohms:
+ description: |
+ Resistance of the sensor at 0 degrees Celsius.
+ Common values are 100 for PT100, 500 for PT500, and 1000 for PT1000
+
+additionalProperties: false
+required:
+ - compatible
+ - io-channels
+ - excitation-current-microamp
+ - alpha-ppm-per-celsius
+ - r-naught-ohms
+
+examples:
+ - |
+ pt1000_1: temperature-sensor0 {
+ compatible = "temperature-sense-rtd";
+ #io-channel-cells = <0>;
+ io-channels = <&temp_adc1 0>;
+
+ excitation-current-microamp = <1000>; /* i = U/R = 5 / 5000 */
+ alpha-ppm-per-celsius = <3908>;
+ r-naught-ohms = <1000>;
+ };
+...
--
2.35.1.4.g5d01301f2b86

2022-02-14 09:57:28

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 01/10] iio: afe: rescale: expose scale processing function

In preparation for the addition of kunit tests, expose the logic
responsible for combining channel scales.

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
drivers/iio/afe/iio-rescale.c | 65 ++++++++++++++-------------------
include/linux/iio/afe/rescale.h | 32 ++++++++++++++++
2 files changed, 60 insertions(+), 37 deletions(-)
create mode 100644 include/linux/iio/afe/rescale.h

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index 69710c481376..65832dd09249 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -15,32 +15,43 @@
#include <linux/platform_device.h>
#include <linux/property.h>

+#include <linux/iio/afe/rescale.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>

-struct rescale;
-
-struct rescale_cfg {
- enum iio_chan_type type;
- int (*props)(struct device *dev, struct rescale *rescale);
-};
+int rescale_process_scale(struct rescale *rescale, int scale_type,
+ int *val, int *val2)
+{
+ s64 tmp;

-struct rescale {
- const struct rescale_cfg *cfg;
- struct iio_channel *source;
- struct iio_chan_spec chan;
- struct iio_chan_spec_ext_info *ext_info;
- bool chan_processed;
- s32 numerator;
- s32 denominator;
-};
+ switch (scale_type) {
+ case IIO_VAL_FRACTIONAL:
+ *val *= rescale->numerator;
+ *val2 *= rescale->denominator;
+ return scale_type;
+ case IIO_VAL_INT:
+ *val *= rescale->numerator;
+ if (rescale->denominator == 1)
+ return scale_type;
+ *val2 = rescale->denominator;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_VAL_FRACTIONAL_LOG2:
+ tmp = (s64)*val * 1000000000LL;
+ tmp = div_s64(tmp, rescale->denominator);
+ tmp *= rescale->numerator;
+ tmp = div_s64(tmp, 1000000000LL);
+ *val = tmp;
+ return scale_type;
+ default:
+ return -EOPNOTSUPP;
+ }
+}

static int rescale_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct rescale *rescale = iio_priv(indio_dev);
- s64 tmp;
int ret;

switch (mask) {
@@ -66,27 +77,7 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
} else {
ret = iio_read_channel_scale(rescale->source, val, val2);
}
- switch (ret) {
- case IIO_VAL_FRACTIONAL:
- *val *= rescale->numerator;
- *val2 *= rescale->denominator;
- return ret;
- case IIO_VAL_INT:
- *val *= rescale->numerator;
- if (rescale->denominator == 1)
- return ret;
- *val2 = rescale->denominator;
- return IIO_VAL_FRACTIONAL;
- case IIO_VAL_FRACTIONAL_LOG2:
- tmp = (s64)*val * 1000000000LL;
- tmp = div_s64(tmp, rescale->denominator);
- tmp *= rescale->numerator;
- tmp = div_s64(tmp, 1000000000LL);
- *val = tmp;
- return ret;
- default:
- return -EOPNOTSUPP;
- }
+ return rescale_process_scale(rescale, ret, val, val2);
default:
return -EINVAL;
}
diff --git a/include/linux/iio/afe/rescale.h b/include/linux/iio/afe/rescale.h
new file mode 100644
index 000000000000..8a2eb34af327
--- /dev/null
+++ b/include/linux/iio/afe/rescale.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2018 Axentia Technologies AB
+ */
+
+#ifndef __IIO_RESCALE_H__
+#define __IIO_RESCALE_H__
+
+#include <linux/types.h>
+#include <linux/iio/iio.h>
+
+struct device;
+struct rescale;
+
+struct rescale_cfg {
+ enum iio_chan_type type;
+ int (*props)(struct device *dev, struct rescale *rescale);
+};
+
+struct rescale {
+ const struct rescale_cfg *cfg;
+ struct iio_channel *source;
+ struct iio_chan_spec chan;
+ struct iio_chan_spec_ext_info *ext_info;
+ bool chan_processed;
+ s32 numerator;
+ s32 denominator;
+};
+
+int rescale_process_scale(struct rescale *rescale, int scale_type,
+ int *val, int *val2);
+#endif /* __IIO_RESCALE_H__ */
--
2.35.1.4.g5d01301f2b86

2022-02-14 09:58:53

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 07/10] iio: afe: rescale: add RTD temperature sensor support

An RTD (Resistance Temperature Detector) is a kind of temperature
sensor used to get a linear voltage to temperature reading within a
give range (usually 0 to 100 degrees Celsius). Common types of RTDs
include PT100, PT500, and PT1000.

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
drivers/iio/afe/iio-rescale.c | 48 +++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index 46947c68d3a9..e31a93435536 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -394,10 +394,52 @@ static int rescale_voltage_divider_props(struct device *dev,
return 0;
}

+static int rescale_temp_sense_rtd_props(struct device *dev,
+ struct rescale *rescale)
+{
+ u32 factor;
+ u32 alpha;
+ u32 iexc;
+ u32 tmp;
+ int ret;
+ u32 r0;
+
+ ret = device_property_read_u32(dev, "excitation-current-microamp",
+ &iexc);
+ if (ret) {
+ dev_err(dev, "failed to read excitation-current-microamp: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = device_property_read_u32(dev, "alpha-ppm-per-celsius", &alpha);
+ if (ret) {
+ dev_err(dev, "failed to read alpha-ppm-per-celsius: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = device_property_read_u32(dev, "r-naught-ohms", &r0);
+ if (ret) {
+ dev_err(dev, "failed to read r-naught-ohms: %d\n", ret);
+ return ret;
+ }
+
+ tmp = r0 * iexc * alpha / 1000000;
+ factor = gcd(tmp, 1000000);
+ rescale->numerator = 1000000 / factor;
+ rescale->denominator = tmp / factor;
+
+ rescale->offset = -1 * ((r0 * iexc) / 1000);
+
+ return 0;
+}
+
enum rescale_variant {
CURRENT_SENSE_AMPLIFIER,
CURRENT_SENSE_SHUNT,
VOLTAGE_DIVIDER,
+ TEMP_SENSE_RTD,
};

static const struct rescale_cfg rescale_cfg[] = {
@@ -413,6 +455,10 @@ static const struct rescale_cfg rescale_cfg[] = {
.type = IIO_VOLTAGE,
.props = rescale_voltage_divider_props,
},
+ [TEMP_SENSE_RTD] = {
+ .type = IIO_TEMP,
+ .props = rescale_temp_sense_rtd_props,
+ },
};

static const struct of_device_id rescale_match[] = {
@@ -422,6 +468,8 @@ static const struct of_device_id rescale_match[] = {
.data = &rescale_cfg[CURRENT_SENSE_SHUNT], },
{ .compatible = "voltage-divider",
.data = &rescale_cfg[VOLTAGE_DIVIDER], },
+ { .compatible = "temperature-sense-rtd",
+ .data = &rescale_cfg[TEMP_SENSE_RTD], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rescale_match);
--
2.35.1.4.g5d01301f2b86

2022-02-14 10:40:19

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 02/10] iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support

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 <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
drivers/iio/afe/iio-rescale.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index 65832dd09249..e67d9a9e6135 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -23,6 +23,9 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
int *val, int *val2)
{
s64 tmp;
+ s32 rem;
+ u32 mult;
+ u32 neg;

switch (scale_type) {
case IIO_VAL_FRACTIONAL:
@@ -41,6 +44,37 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
tmp *= rescale->numerator;
tmp = div_s64(tmp, 1000000000LL);
*val = tmp;
+ return scale_type;
+ case IIO_VAL_INT_PLUS_NANO:
+ case IIO_VAL_INT_PLUS_MICRO:
+ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
+
+ /*
+ * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val
+ * OR *val2 is negative the schan scale is negative, i.e.
+ * *val = 1 and *val2 = -0.5 yields -1.5 not -0.5.
+ */
+ neg = *val < 0 || *val2 < 0;
+
+ tmp = (s64)abs(*val) * abs(rescale->numerator);
+ *val = div_s64_rem(tmp, abs(rescale->denominator), &rem);
+
+ tmp = (s64)rem * mult + (s64)abs(*val2) * abs(rescale->numerator);
+ tmp = div_s64(tmp, abs(rescale->denominator));
+
+ *val += div_s64_rem(tmp, mult, val2);
+
+ /*
+ * If only one of the rescaler elements or the schan scale is
+ * negative, the combined scale is negative.
+ */
+ if (neg ^ ((rescale->numerator < 0) ^ (rescale->denominator < 0))) {
+ if (*val)
+ *val = -*val;
+ else
+ *val2 = -*val2;
+ }
+
return scale_type;
default:
return -EOPNOTSUPP;
--
2.35.1.4.g5d01301f2b86

2022-02-14 11:43:37

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 03/10] iio: afe: rescale: add offset support

This is a preparatory change required for the addition of temperature
sensing front ends.

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
drivers/iio/afe/iio-rescale.c | 81 +++++++++++++++++++++++++++++++++
include/linux/iio/afe/rescale.h | 4 ++
2 files changed, 85 insertions(+)

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index e67d9a9e6135..8eaf766e28cc 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -3,6 +3,7 @@
* IIO rescale driver
*
* Copyright (C) 2018 Axentia Technologies AB
+ * Copyright (C) 2022 Liam Beguin <[email protected]>
*
* Author: Peter Rosin <[email protected]>
*/
@@ -81,11 +82,46 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
}
}

+int rescale_process_offset(struct rescale *rescale, int scale_type,
+ int scale, int scale2, int schan_off,
+ int *val, int *val2)
+{
+ s64 tmp, tmp2;
+
+ switch (scale_type) {
+ case IIO_VAL_FRACTIONAL:
+ tmp = (s64)rescale->offset * scale2;
+ *val = div_s64(tmp, scale) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_INT:
+ *val = div_s64(rescale->offset, scale) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_FRACTIONAL_LOG2:
+ tmp = (s64)rescale->offset * (1 << scale2);
+ *val = div_s64(tmp, scale) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_INT_PLUS_NANO:
+ tmp = (s64)rescale->offset * 1000000000LL;
+ tmp2 = ((s64)scale * 1000000000LL) + scale2;
+ *val = div64_s64(tmp, tmp2) + schan_off;
+ return IIO_VAL_INT;
+ case IIO_VAL_INT_PLUS_MICRO:
+ tmp = (s64)rescale->offset * 1000000LL;
+ tmp2 = ((s64)scale * 1000000LL) + scale2;
+ *val = div64_s64(tmp, tmp2) + schan_off;
+ return IIO_VAL_INT;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int rescale_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct rescale *rescale = iio_priv(indio_dev);
+ int scale, scale2;
+ int schan_off = 0;
int ret;

switch (mask) {
@@ -112,6 +148,47 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
ret = iio_read_channel_scale(rescale->source, val, val2);
}
return rescale_process_scale(rescale, ret, val, val2);
+ case IIO_CHAN_INFO_OFFSET:
+ /*
+ * Processed channels are scaled 1-to-1 and source offset is
+ * already taken into account.
+ *
+ * In other cases, real world measurement are expressed as:
+ *
+ * schan_scale * (raw + schan_offset)
+ *
+ * Given that the rescaler parameters are applied recursively:
+ *
+ * rescaler_scale * (schan_scale * (raw + schan_offset) +
+ * rescaler_offset)
+ *
+ * Or,
+ *
+ * (rescaler_scale * schan_scale) * (raw +
+ * (schan_offset + rescaler_offset / schan_scale)
+ *
+ * Thus, reusing the original expression the parameters exposed
+ * to userspace are:
+ *
+ * scale = schan_scale * rescaler_scale
+ * offset = schan_offset + rescaler_offset / schan_scale
+ */
+ if (rescale->chan_processed) {
+ *val = rescale->offset;
+ return IIO_VAL_INT;
+ }
+
+ if (iio_channel_has_info(rescale->source->channel,
+ IIO_CHAN_INFO_OFFSET)) {
+ ret = iio_read_channel_offset(rescale->source,
+ &schan_off, NULL);
+ if (ret != IIO_VAL_INT)
+ return ret < 0 ? ret : -EOPNOTSUPP;
+ }
+
+ ret = iio_read_channel_scale(rescale->source, &scale, &scale2);
+ return rescale_process_offset(rescale, ret, scale, scale2,
+ schan_off, val, val2);
default:
return -EINVAL;
}
@@ -188,6 +265,9 @@ static int rescale_configure_channel(struct device *dev,
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE);

+ if (rescale->offset)
+ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OFFSET);
+
/*
* Using .read_avail() is fringe to begin with and makes no sense
* whatsoever for processed channels, so we make sure that this cannot
@@ -352,6 +432,7 @@ static int rescale_probe(struct platform_device *pdev)
rescale->cfg = of_device_get_match_data(dev);
rescale->numerator = 1;
rescale->denominator = 1;
+ rescale->offset = 0;

ret = rescale->cfg->props(dev, rescale);
if (ret)
diff --git a/include/linux/iio/afe/rescale.h b/include/linux/iio/afe/rescale.h
index 8a2eb34af327..6eecb435488f 100644
--- a/include/linux/iio/afe/rescale.h
+++ b/include/linux/iio/afe/rescale.h
@@ -25,8 +25,12 @@ struct rescale {
bool chan_processed;
s32 numerator;
s32 denominator;
+ s32 offset;
};

int rescale_process_scale(struct rescale *rescale, int scale_type,
int *val, int *val2);
+int rescale_process_offset(struct rescale *rescale, int scale_type,
+ int scale, int scale2, int schan_off,
+ int *val, int *val2);
#endif /* __IIO_RESCALE_H__ */
--
2.35.1.4.g5d01301f2b86

2022-02-14 11:45:48

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 05/10] iio: afe: rescale: reduce risk of integer overflow

Reduce the risk of integer overflow by doing the scale calculation on
a 64-bit integer. Since the rescaling is only performed on *val, reuse
the IIO_VAL_FRACTIONAL_LOG2 case.

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
drivers/iio/afe/iio-rescale.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index 5d78f0cf47d2..46947c68d3a9 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -24,21 +24,31 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
int *val, int *val2)
{
s64 tmp;
+ int _val, _val2;
s32 rem, rem2;
u32 mult;
u32 neg;

switch (scale_type) {
- case IIO_VAL_FRACTIONAL:
- *val *= rescale->numerator;
- *val2 *= rescale->denominator;
- return scale_type;
case IIO_VAL_INT:
*val *= rescale->numerator;
if (rescale->denominator == 1)
return scale_type;
*val2 = rescale->denominator;
return IIO_VAL_FRACTIONAL;
+ case IIO_VAL_FRACTIONAL:
+ /*
+ * When the product of both scales doesn't overflow, avoid
+ * potential accuracy loss (for in kernel consumers) by
+ * keeping a fractional representation.
+ */
+ if (!check_mul_overflow(*val, rescale->numerator, &_val) &&
+ !check_mul_overflow(*val2, rescale->denominator, &_val2)) {
+ *val = _val;
+ *val2 = _val2;
+ return IIO_VAL_FRACTIONAL;
+ }
+ fallthrough;
case IIO_VAL_FRACTIONAL_LOG2:
tmp = (s64)*val * 1000000000LL;
tmp = div_s64(tmp, rescale->denominator);
@@ -50,7 +60,10 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
if (!rem)
return scale_type;

- tmp = 1 << *val2;
+ if (scale_type == IIO_VAL_FRACTIONAL)
+ tmp = *val2;
+ else
+ tmp = ULL(1) << *val2;

rem2 = *val % (int)tmp;
*val = *val / (int)tmp;
--
2.35.1.4.g5d01301f2b86

2022-02-14 16:24:13

by Liam Beguin

[permalink] [raw]
Subject: [PATCH v15 10/10] dt-bindings: iio: afe: add bindings for temperature transducers

An ADC is often used to measure other quantities indirectly.
This binding describe one case, the measurement of a temperature
through a temperature transducer (either voltage or current).

Signed-off-by: Liam Beguin <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Peter Rosin <[email protected]>
---
.../iio/afe/temperature-transducer.yaml | 114 ++++++++++++++++++
1 file changed, 114 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml

diff --git a/Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml b/Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
new file mode 100644
index 000000000000..cfbf5350db27
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/afe/temperature-transducer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Temperature Transducer
+
+maintainers:
+ - Liam Beguin <[email protected]>
+
+description: |
+ A temperature transducer is a device that converts a thermal quantity
+ into any other physical quantity. This binding applies to temperature to
+ voltage (like the LTC2997), and temperature to current (like the AD590)
+ linear transducers.
+ In both cases these are assumed to be connected to a voltage ADC.
+
+ When an io-channel measures the output voltage of a temperature analog front
+ end such as a temperature transducer, the interesting measurement is almost
+ always the corresponding temperature, not the voltage output. This binding
+ describes such a circuit.
+
+ The general transfer function here is (using SI units)
+ V(T) = Rsense * Isense(T)
+ T = (Isense(T) / alpha) + offset
+ T = 1 / (Rsense * alpha) * (V + offset * Rsense * alpha)
+
+ When using a temperature to voltage transducer, Rsense is set to 1.
+
+ The following circuits show a temperature to current and a temperature to
+ voltage transducer that can be used with this binding.
+
+ VCC
+ -----
+ |
+ +---+---+
+ | AD590 | VCC
+ +---+---+ -----
+ | |
+ V proportional to T +----+----+
+ | D+ --+ |
+ +---- Vout | LTC2997 +--- Vout
+ | D- --+ |
+ +---+----+ +---------+
+ | Rsense | |
+ +---+----+ -----
+ | GND
+ -----
+ GND
+
+properties:
+ compatible:
+ const: temperature-transducer
+
+ io-channels:
+ maxItems: 1
+ description: |
+ Channel node of a voltage io-channel.
+
+ '#io-channel-cells':
+ const: 0
+
+ sense-offset-millicelsius:
+ description: |
+ 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.
+ By default sense-resistor-ohms cancels out the resistor making the
+ circuit behave like a temperature transducer.
+ default: 1
+
+ alpha-ppm-per-celsius:
+ description: |
+ Sometimes referred to as output gain, slope, or temperature coefficient.
+
+ alpha is expressed in parts per million which can be micro-amps per
+ degrees Celsius or micro-volts per degrees Celsius. The is the main
+ characteristic of a temperature transducer and should be stated in the
+ datasheet.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - io-channels
+ - alpha-ppm-per-celsius
+
+examples:
+ - |
+ ad950: temperature-sensor-0 {
+ compatible = "temperature-transducer";
+ #io-channel-cells = <0>;
+ io-channels = <&temp_adc 3>;
+
+ sense-offset-millicelsius = <(-273150)>; /* Kelvin to degrees Celsius */
+ sense-resistor-ohms = <8060>;
+ alpha-ppm-per-celsius = <1>; /* 1 uA/K */
+ };
+ - |
+ znq_tmp: temperature-sensor-1 {
+ compatible = "temperature-transducer";
+ #io-channel-cells = <0>;
+ io-channels = <&temp_adc 2>;
+
+ sense-offset-millicelsius = <(-273150)>; /* Kelvin to degrees Celsius */
+ alpha-ppm-per-celsius = <4000>; /* 4 mV/K */
+ };
+...
--
2.35.1.4.g5d01301f2b86

2022-02-27 13:53:26

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v15 00/10] iio: afe: add temperature rescaling support

On Sun, 27 Feb 2022 15:25:50 +0200
Andy Shevchenko <[email protected]> wrote:

> On Sun, Feb 27, 2022 at 2:58 PM Jonathan Cameron <[email protected]> wrote:
> > On Sun, 27 Feb 2022 12:55:59 +0000
> > Jonathan Cameron <[email protected]> wrote:
> > > On Sat, 12 Feb 2022 21:57:29 -0500
> > > Liam Beguin <[email protected]> wrote:
> > >
> > > > Jonathan, Peter, Andy,
> > > >
> > > > This series focuses on adding temperature rescaling support to the IIO
> > > > Analog Front End (AFE) driver.
> > > >
> > > > The main changes to the AFE driver include an initial Kunit test suite,
> > > > support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> > > > and temperature transducer sensors.
>
> ...
>
> > > I was waiting for Andy to reply to this. Took a quick look back at
> > > what was outstanding and realised he had given a
> > > Reviewed-by: Andy Shevchenko <[email protected]>
> > > for v13.
> >
> > Actually given the units.h change is a perhaps non trivial perhaps that's
> > why you dropped Andy's RB. I'll still apply the series, but it Andy
> > confirms his view on that tag before I push this out as something I can't
> > rebase I'll add it if appropriate.
>
> Since it was a separate patch, I'm fine with not including it due to
> strong argument from Peter.
Thanks. I've added your Rb and pushed out a fresh testing branch.

Jonathan

>
> > > I'm assuming there wasn't a strong reason to drop that in the meantime
> > > and it's a simple omission / crossed emails issue.
> > >
> > > As such,
> > >
> > > Series applied to the togreg branch of iio.git and pushed out
> > > as testing to get some build coverage from 0-day.
>
>

2022-02-27 13:53:53

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v15 00/10] iio: afe: add temperature rescaling support

On Sun, 27 Feb 2022 12:55:59 +0000
Jonathan Cameron <[email protected]> wrote:

> On Sat, 12 Feb 2022 21:57:29 -0500
> Liam Beguin <[email protected]> wrote:
>
> > Jonathan, Peter, Andy,
> >
> > This series focuses on adding temperature rescaling support to the IIO
> > Analog Front End (AFE) driver.
> >
> > The main changes to the AFE driver include an initial Kunit test suite,
> > support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> > and temperature transducer sensors.
> >
> > Thanks for your time,
> > Liam
>
> Hi Liam,
>
> I was waiting for Andy to reply to this. Took a quick look back at
> what was outstanding and realised he had given a
> Reviewed-by: Andy Shevchenko <[email protected]>
> for v13.

Actually given the units.h change is a perhaps non trivial perhaps that's
why you dropped Andy's RB. I'll still apply the series, but it Andy
confirms his view on that tag before I push this out as something I can't
rebase I'll add it if appropriate.

Thanks,

Jonathan

>
> I'm assuming there wasn't a strong reason to drop that in the meantime
> and it's a simple omission / crossed emails issue.
>
> As such,
>
> Series applied to the togreg branch of iio.git and pushed out
> as testing to get some build coverage from 0-day.
>
> Thanks,
>
> Jonathan
>
> >
> > Changes since v14:
> > - Revert units.h changes in favor of "raw" values
> >
> > Changes since v13:
> > - fix SI prefix in rescale_temp_sense_rtd_props()
> > - add comment explaining SI prefixes are sometimes used as mathematical
> > multipliers with no particular physical meaning associated.
> >
> > Changes since v12:
> > - rebase on latest testing branch
> > - fix copyright holder in newly created header file
> > - add myself as a copyright holder of the iio-rescale.c driver at
> > Peter's suggestion
> > - fix undefined behavior on left-shift operation
> >
> > Changes since v11:
> > - update commits with my personal email since all this work was done on
> > my own time
> > - apply Peter's Reviewed-by to my local tree
> > - fix use of units.h
> > - make use of units.h more consistently in iio-rescale.c and in the
> > tests
> > - fix #include ordering
> > - treat 04/16 as a fix. Move it, and add a Fixes: tag
> > - fix undefined behavior on left-shift operation
> > - add comment about fract_mult with iio_str_to_fixpoint()
> > - reword commit message for 14/16, based on Andy's comments
> >
> > Changes since v10:
> > - apply Andy's suggestion for offset calculations
> > - make use of units.h more consistently
> >
> > Changes since v9:
> > - make use of linux/units.h
> > - reorder commits, fix fract_log2 before merging fract
> > - keep fractional representation when not overflowing
> >
> > Changes since v8:
> > - reword comment
> > - fix erroneous 64-bit division
> > - optimize and use 32-bit divisions when values are know to not overflow
> > - keep IIO_VAL_FRACTIONAL scale when possible, if not default to fixed
> > point
> > - add test cases
> > - use nano precision in test cases
> > - simplify offset calculation in rtd_props()
> >
> > Changes since v7:
> > - drop gcd() logic in rescale_process_scale()
> > - use div_s64() instead of do_div() for signed 64-bit divisions
> > - combine IIO_VAL_FRACTIONAL and IIO_VAL_FRACTIONAL_LOG2 scale cases
> > - switch to INT_PLUS_NANO when accuracy is lost with FRACTIONAL scales
> > - rework test logic to allow for small relative error
> > - rename test variables to align error output messages
> >
> > Changes since v6:
> > - rework IIO_VAL_INT_PLUS_{NANO,MICRO} based on Peter's suggestion
> > - combine IIO_VAL_INT_PLUS_{NANO,MICRO} cases
> > - add test cases for negative IIO_VAL_INT_PLUS_{NANO,MICRO} corner cases
> > - force use of positive integers with gcd()
> > - reduce risk of integer overflow in IIO_VAL_FRACTIONAL_LOG2
> > - fix duplicate symbol build error
> > - apply Reviewed-by
> >
> > Changes since v5:
> > - add include/linux/iio/afe/rescale.h
> > - expose functions use to process scale and offset
> > - add basic iio-rescale kunit test cases
> > - fix integer overflow case
> > - improve precision for IIO_VAL_FRACTIONAL_LOG2
> >
> > 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
> >
> > Liam Beguin (10):
> > iio: afe: rescale: expose scale processing function
> > iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> > iio: afe: rescale: add offset support
> > iio: afe: rescale: fix accuracy for small fractional scales
> > iio: afe: rescale: reduce risk of integer overflow
> > iio: test: add basic tests for the iio-rescale driver
> > 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 | 283 ++++++-
> > drivers/iio/test/Kconfig | 10 +
> > drivers/iio/test/Makefile | 1 +
> > drivers/iio/test/iio-test-rescale.c | 710 ++++++++++++++++++
> > include/linux/iio/afe/rescale.h | 36 +
> > 7 files changed, 1220 insertions(+), 35 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
> > create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
> > create mode 100644 drivers/iio/test/iio-test-rescale.c
> > create mode 100644 include/linux/iio/afe/rescale.h
> >
> > Range-diff against v14:
> > -: ------------ > 1: ee26b0eeac65 iio: afe: rescale: expose scale processing function
> > 1: a510097c83f1 ! 2: 78f9d37575a5 iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> > @@ Commit message
> > Reviewed-by: Peter Rosin <[email protected]>
> >
> > ## drivers/iio/afe/iio-rescale.c ##
> > -@@
> > - #include <linux/of_device.h>
> > - #include <linux/platform_device.h>
> > - #include <linux/property.h>
> > -+#include <linux/units.h>
> > -
> > - #include <linux/iio/afe/rescale.h>
> > - #include <linux/iio/consumer.h>
> > @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale, int scale_type,
> > int *val, int *val2)
> > {
> > @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> > + return scale_type;
> > + case IIO_VAL_INT_PLUS_NANO:
> > + case IIO_VAL_INT_PLUS_MICRO:
> > -+ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
> > ++ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
> > +
> > + /*
> > + * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val
> > 2: 8f2f2699a9b4 ! 3: 5be82bd72453 iio: afe: rescale: add offset support
> > @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> > + *val = div_s64(tmp, scale) + schan_off;
> > + return IIO_VAL_INT;
> > + case IIO_VAL_INT_PLUS_NANO:
> > -+ tmp = (s64)rescale->offset * GIGA;
> > -+ tmp2 = ((s64)scale * GIGA) + scale2;
> > ++ tmp = (s64)rescale->offset * 1000000000LL;
> > ++ tmp2 = ((s64)scale * 1000000000LL) + scale2;
> > + *val = div64_s64(tmp, tmp2) + schan_off;
> > + return IIO_VAL_INT;
> > + case IIO_VAL_INT_PLUS_MICRO:
> > -+ tmp = (s64)rescale->offset * MEGA;
> > -+ tmp2 = ((s64)scale * MEGA) + scale2;
> > ++ tmp = (s64)rescale->offset * 1000000LL;
> > ++ tmp2 = ((s64)scale * 1000000LL) + scale2;
> > + *val = div64_s64(tmp, tmp2) + schan_off;
> > + return IIO_VAL_INT;
> > + default:
> > 3: 2efa970bad26 ! 4: 95ec184759f6 iio: afe: rescale: fix accuracy for small fractional scales
> > @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> > + return IIO_VAL_INT_PLUS_NANO;
> > case IIO_VAL_INT_PLUS_NANO:
> > case IIO_VAL_INT_PLUS_MICRO:
> > - mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
> > + mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
> > 4: 201037c0ead8 = 5: 2e1d41ef69d9 iio: afe: rescale: reduce risk of integer overflow
> > 5: a0037cc3ee90 < -: ------------ iio: afe: rescale: make use of units.h
> > 6: f8d47728f482 ! 6: 0b6c029dea1d iio: test: add basic tests for the iio-rescale driver
> > @@ drivers/iio/test/iio-test-rescale.c (new)
> > +
> > +#include <linux/gcd.h>
> > +#include <linux/overflow.h>
> > -+#include <linux/units.h>
> > +
> > +#include <linux/iio/afe/rescale.h>
> > +#include <linux/iio/iio.h>
> > @@ drivers/iio/test/iio-test-rescale.c (new)
> > + if (tmp < 0)
> > + tmp2 *= -1;
> > +
> > -+ *nano = (s64)tmp * GIGA + tmp2;
> > ++ *nano = (s64)tmp * 1000000000UL + tmp2;
> > +
> > + return ret;
> > +}
> > @@ drivers/iio/test/iio-test-rescale.c (new)
> > + return -EINVAL;
> > + }
> > +
> > -+ err = MEGA * abs(exp - real);
> > ++ err = 1000000UL * abs(exp - real);
> > +
> > + return (int)div64_u64(err, abs(exp));
> > +}
> > 7: a04685586340 ! 7: 951ea44d0f5c iio: afe: rescale: add RTD temperature sensor support
> > @@ drivers/iio/afe/iio-rescale.c: static int rescale_voltage_divider_props(struct d
> > + return ret;
> > + }
> > +
> > -+ tmp = r0 * iexc * alpha / MEGA;
> > -+ factor = gcd(tmp, MEGA);
> > -+ rescale->numerator = MEGA / factor;
> > ++ tmp = r0 * iexc * alpha / 1000000;
> > ++ factor = gcd(tmp, 1000000);
> > ++ rescale->numerator = 1000000 / factor;
> > + rescale->denominator = tmp / factor;
> > +
> > -+ rescale->offset = -1 * ((r0 * iexc) / KILO);
> > ++ rescale->offset = -1 * ((r0 * iexc) / 1000);
> > +
> > + return 0;
> > +}
> > 8: e3b716aaee50 ! 8: 56516fdc67bf iio: afe: rescale: add temperature transducers
> > @@ drivers/iio/afe/iio-rescale.c: static int rescale_temp_sense_rtd_props(struct de
> > + return ret;
> > + }
> > +
> > -+ rescale->numerator = MEGA;
> > ++ rescale->numerator = 1000000;
> > + rescale->denominator = alpha * sense;
> > +
> > + rescale->offset = div_s64((s64)offset * rescale->denominator,
> > 9: 22ae1458eb8b = 9: 8c409050990b dt-bindings: iio: afe: add bindings for temperature-sense-rtd
> > 10: 33825ad452d6 = 10: bb39296590f3 dt-bindings: iio: afe: add bindings for temperature transducers
> >
> > base-commit: cd717ac6f69db4953ca701c6220c7cb58e17f35a
>

2022-02-27 13:54:13

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v15 00/10] iio: afe: add temperature rescaling support

On Sun, Feb 27, 2022 at 2:58 PM Jonathan Cameron <[email protected]> wrote:
> On Sun, 27 Feb 2022 12:55:59 +0000
> Jonathan Cameron <[email protected]> wrote:
> > On Sat, 12 Feb 2022 21:57:29 -0500
> > Liam Beguin <[email protected]> wrote:
> >
> > > Jonathan, Peter, Andy,
> > >
> > > This series focuses on adding temperature rescaling support to the IIO
> > > Analog Front End (AFE) driver.
> > >
> > > The main changes to the AFE driver include an initial Kunit test suite,
> > > support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> > > and temperature transducer sensors.

...

> > I was waiting for Andy to reply to this. Took a quick look back at
> > what was outstanding and realised he had given a
> > Reviewed-by: Andy Shevchenko <[email protected]>
> > for v13.
>
> Actually given the units.h change is a perhaps non trivial perhaps that's
> why you dropped Andy's RB. I'll still apply the series, but it Andy
> confirms his view on that tag before I push this out as something I can't
> rebase I'll add it if appropriate.

Since it was a separate patch, I'm fine with not including it due to
strong argument from Peter.

> > I'm assuming there wasn't a strong reason to drop that in the meantime
> > and it's a simple omission / crossed emails issue.
> >
> > As such,
> >
> > Series applied to the togreg branch of iio.git and pushed out
> > as testing to get some build coverage from 0-day.


--
With Best Regards,
Andy Shevchenko

2022-02-27 13:58:54

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v15 00/10] iio: afe: add temperature rescaling support

On Sat, 12 Feb 2022 21:57:29 -0500
Liam Beguin <[email protected]> wrote:

> Jonathan, Peter, Andy,
>
> This series focuses on adding temperature rescaling support to the IIO
> Analog Front End (AFE) driver.
>
> The main changes to the AFE driver include an initial Kunit test suite,
> support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> and temperature transducer sensors.
>
> Thanks for your time,
> Liam

Hi Liam,

I was waiting for Andy to reply to this. Took a quick look back at
what was outstanding and realised he had given a
Reviewed-by: Andy Shevchenko <[email protected]>
for v13.

I'm assuming there wasn't a strong reason to drop that in the meantime
and it's a simple omission / crossed emails issue.

As such,

Series applied to the togreg branch of iio.git and pushed out
as testing to get some build coverage from 0-day.

Thanks,

Jonathan

>
> Changes since v14:
> - Revert units.h changes in favor of "raw" values
>
> Changes since v13:
> - fix SI prefix in rescale_temp_sense_rtd_props()
> - add comment explaining SI prefixes are sometimes used as mathematical
> multipliers with no particular physical meaning associated.
>
> Changes since v12:
> - rebase on latest testing branch
> - fix copyright holder in newly created header file
> - add myself as a copyright holder of the iio-rescale.c driver at
> Peter's suggestion
> - fix undefined behavior on left-shift operation
>
> Changes since v11:
> - update commits with my personal email since all this work was done on
> my own time
> - apply Peter's Reviewed-by to my local tree
> - fix use of units.h
> - make use of units.h more consistently in iio-rescale.c and in the
> tests
> - fix #include ordering
> - treat 04/16 as a fix. Move it, and add a Fixes: tag
> - fix undefined behavior on left-shift operation
> - add comment about fract_mult with iio_str_to_fixpoint()
> - reword commit message for 14/16, based on Andy's comments
>
> Changes since v10:
> - apply Andy's suggestion for offset calculations
> - make use of units.h more consistently
>
> Changes since v9:
> - make use of linux/units.h
> - reorder commits, fix fract_log2 before merging fract
> - keep fractional representation when not overflowing
>
> Changes since v8:
> - reword comment
> - fix erroneous 64-bit division
> - optimize and use 32-bit divisions when values are know to not overflow
> - keep IIO_VAL_FRACTIONAL scale when possible, if not default to fixed
> point
> - add test cases
> - use nano precision in test cases
> - simplify offset calculation in rtd_props()
>
> Changes since v7:
> - drop gcd() logic in rescale_process_scale()
> - use div_s64() instead of do_div() for signed 64-bit divisions
> - combine IIO_VAL_FRACTIONAL and IIO_VAL_FRACTIONAL_LOG2 scale cases
> - switch to INT_PLUS_NANO when accuracy is lost with FRACTIONAL scales
> - rework test logic to allow for small relative error
> - rename test variables to align error output messages
>
> Changes since v6:
> - rework IIO_VAL_INT_PLUS_{NANO,MICRO} based on Peter's suggestion
> - combine IIO_VAL_INT_PLUS_{NANO,MICRO} cases
> - add test cases for negative IIO_VAL_INT_PLUS_{NANO,MICRO} corner cases
> - force use of positive integers with gcd()
> - reduce risk of integer overflow in IIO_VAL_FRACTIONAL_LOG2
> - fix duplicate symbol build error
> - apply Reviewed-by
>
> Changes since v5:
> - add include/linux/iio/afe/rescale.h
> - expose functions use to process scale and offset
> - add basic iio-rescale kunit test cases
> - fix integer overflow case
> - improve precision for IIO_VAL_FRACTIONAL_LOG2
>
> 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
>
> Liam Beguin (10):
> iio: afe: rescale: expose scale processing function
> iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> iio: afe: rescale: add offset support
> iio: afe: rescale: fix accuracy for small fractional scales
> iio: afe: rescale: reduce risk of integer overflow
> iio: test: add basic tests for the iio-rescale driver
> 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 | 283 ++++++-
> drivers/iio/test/Kconfig | 10 +
> drivers/iio/test/Makefile | 1 +
> drivers/iio/test/iio-test-rescale.c | 710 ++++++++++++++++++
> include/linux/iio/afe/rescale.h | 36 +
> 7 files changed, 1220 insertions(+), 35 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-sense-rtd.yaml
> create mode 100644 Documentation/devicetree/bindings/iio/afe/temperature-transducer.yaml
> create mode 100644 drivers/iio/test/iio-test-rescale.c
> create mode 100644 include/linux/iio/afe/rescale.h
>
> Range-diff against v14:
> -: ------------ > 1: ee26b0eeac65 iio: afe: rescale: expose scale processing function
> 1: a510097c83f1 ! 2: 78f9d37575a5 iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support
> @@ Commit message
> Reviewed-by: Peter Rosin <[email protected]>
>
> ## drivers/iio/afe/iio-rescale.c ##
> -@@
> - #include <linux/of_device.h>
> - #include <linux/platform_device.h>
> - #include <linux/property.h>
> -+#include <linux/units.h>
> -
> - #include <linux/iio/afe/rescale.h>
> - #include <linux/iio/consumer.h>
> @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale, int scale_type,
> int *val, int *val2)
> {
> @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> + return scale_type;
> + case IIO_VAL_INT_PLUS_NANO:
> + case IIO_VAL_INT_PLUS_MICRO:
> -+ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
> ++ mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
> +
> + /*
> + * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val
> 2: 8f2f2699a9b4 ! 3: 5be82bd72453 iio: afe: rescale: add offset support
> @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> + *val = div_s64(tmp, scale) + schan_off;
> + return IIO_VAL_INT;
> + case IIO_VAL_INT_PLUS_NANO:
> -+ tmp = (s64)rescale->offset * GIGA;
> -+ tmp2 = ((s64)scale * GIGA) + scale2;
> ++ tmp = (s64)rescale->offset * 1000000000LL;
> ++ tmp2 = ((s64)scale * 1000000000LL) + scale2;
> + *val = div64_s64(tmp, tmp2) + schan_off;
> + return IIO_VAL_INT;
> + case IIO_VAL_INT_PLUS_MICRO:
> -+ tmp = (s64)rescale->offset * MEGA;
> -+ tmp2 = ((s64)scale * MEGA) + scale2;
> ++ tmp = (s64)rescale->offset * 1000000LL;
> ++ tmp2 = ((s64)scale * 1000000LL) + scale2;
> + *val = div64_s64(tmp, tmp2) + schan_off;
> + return IIO_VAL_INT;
> + default:
> 3: 2efa970bad26 ! 4: 95ec184759f6 iio: afe: rescale: fix accuracy for small fractional scales
> @@ drivers/iio/afe/iio-rescale.c: int rescale_process_scale(struct rescale *rescale
> + return IIO_VAL_INT_PLUS_NANO;
> case IIO_VAL_INT_PLUS_NANO:
> case IIO_VAL_INT_PLUS_MICRO:
> - mult = scale_type == IIO_VAL_INT_PLUS_NANO ? GIGA : MEGA;
> + mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
> 4: 201037c0ead8 = 5: 2e1d41ef69d9 iio: afe: rescale: reduce risk of integer overflow
> 5: a0037cc3ee90 < -: ------------ iio: afe: rescale: make use of units.h
> 6: f8d47728f482 ! 6: 0b6c029dea1d iio: test: add basic tests for the iio-rescale driver
> @@ drivers/iio/test/iio-test-rescale.c (new)
> +
> +#include <linux/gcd.h>
> +#include <linux/overflow.h>
> -+#include <linux/units.h>
> +
> +#include <linux/iio/afe/rescale.h>
> +#include <linux/iio/iio.h>
> @@ drivers/iio/test/iio-test-rescale.c (new)
> + if (tmp < 0)
> + tmp2 *= -1;
> +
> -+ *nano = (s64)tmp * GIGA + tmp2;
> ++ *nano = (s64)tmp * 1000000000UL + tmp2;
> +
> + return ret;
> +}
> @@ drivers/iio/test/iio-test-rescale.c (new)
> + return -EINVAL;
> + }
> +
> -+ err = MEGA * abs(exp - real);
> ++ err = 1000000UL * abs(exp - real);
> +
> + return (int)div64_u64(err, abs(exp));
> +}
> 7: a04685586340 ! 7: 951ea44d0f5c iio: afe: rescale: add RTD temperature sensor support
> @@ drivers/iio/afe/iio-rescale.c: static int rescale_voltage_divider_props(struct d
> + return ret;
> + }
> +
> -+ tmp = r0 * iexc * alpha / MEGA;
> -+ factor = gcd(tmp, MEGA);
> -+ rescale->numerator = MEGA / factor;
> ++ tmp = r0 * iexc * alpha / 1000000;
> ++ factor = gcd(tmp, 1000000);
> ++ rescale->numerator = 1000000 / factor;
> + rescale->denominator = tmp / factor;
> +
> -+ rescale->offset = -1 * ((r0 * iexc) / KILO);
> ++ rescale->offset = -1 * ((r0 * iexc) / 1000);
> +
> + return 0;
> +}
> 8: e3b716aaee50 ! 8: 56516fdc67bf iio: afe: rescale: add temperature transducers
> @@ drivers/iio/afe/iio-rescale.c: static int rescale_temp_sense_rtd_props(struct de
> + return ret;
> + }
> +
> -+ rescale->numerator = MEGA;
> ++ rescale->numerator = 1000000;
> + rescale->denominator = alpha * sense;
> +
> + rescale->offset = div_s64((s64)offset * rescale->denominator,
> 9: 22ae1458eb8b = 9: 8c409050990b dt-bindings: iio: afe: add bindings for temperature-sense-rtd
> 10: 33825ad452d6 = 10: bb39296590f3 dt-bindings: iio: afe: add bindings for temperature transducers
>
> base-commit: cd717ac6f69db4953ca701c6220c7cb58e17f35a

2022-02-28 18:05:36

by Liam Beguin

[permalink] [raw]
Subject: Re: [PATCH v15 00/10] iio: afe: add temperature rescaling support

Hi Jonathan,

On Sun, Feb 27, 2022 at 12:55:59PM +0000, Jonathan Cameron wrote:
> On Sat, 12 Feb 2022 21:57:29 -0500
> Liam Beguin <[email protected]> wrote:
>
> > Jonathan, Peter, Andy,
> >
> > This series focuses on adding temperature rescaling support to the IIO
> > Analog Front End (AFE) driver.
> >
> > The main changes to the AFE driver include an initial Kunit test suite,
> > support for IIO_VAL_INT_PLUS_{NANO,MICRO} scales, and support for RTDs
> > and temperature transducer sensors.
> >
> > Thanks for your time,
> > Liam
>
> Hi Liam,
>
> I was waiting for Andy to reply to this. Took a quick look back at
> what was outstanding and realised he had given a
> Reviewed-by: Andy Shevchenko <[email protected]>
> for v13.
>
> I'm assuming there wasn't a strong reason to drop that in the meantime
> and it's a simple omission / crossed emails issue.
>
> As such,
>
> Series applied to the togreg branch of iio.git and pushed out
> as testing to get some build coverage from 0-day.

Great news! Thanks again for your patience, and review on this work.

I noticed you fixed the CI error. Thanks for doing that, and my
apologies for missing it.

Cheers,
Liam

> Thanks,
>
> Jonathan
>