linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] iio: adc: ad4695: implement calibration support
@ 2024-08-20 15:58 David Lechner
  2024-08-20 15:58 ` [PATCH 1/4] iio: adc: ad4695: add 2nd regmap for 16-bit registers David Lechner
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: David Lechner @ 2024-08-20 15:58 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc, David Lechner

This series adds calibration support to the ad4695 driver.

This has the same "odd" gain and offset registers that are being used
for calibration as discussed recently in the ad4030 series [1]. So if
the ranges in the *_available attributes seem a bit big for calibration,
that is why. The official datasheet explanation for this feature is,
"The AD4695/AD4696 include offset and gain error correction
functionality to correct for first-order nonidealities in a full
[analog front end] signal chain."

[1]: https://lore.kernel.org/linux-iio/20240814193814.78fe45cc@jic23-huawei/

---
David Lechner (4):
      iio: adc: ad4695: add 2nd regmap for 16-bit registers
      iio: adc: ad4695: implement calibration support
      doc: iio: ad4695: update for calibration support
      iio: ABI: document ad4695 new attributes

 Documentation/ABI/testing/sysfs-bus-iio |   3 +
 Documentation/iio/ad4695.rst            |   7 +-
 drivers/iio/adc/ad4695.c                | 242 +++++++++++++++++++++++++++++---
 3 files changed, 234 insertions(+), 18 deletions(-)
---
base-commit: 0f718e10da81446df0909c9939dff2b77e3b4e95
change-id: 20240819-ad4695-gain-offset-c748d7addf27

Best regards,
-- 
David Lechner <dlechner@baylibre.com>


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

* [PATCH 1/4] iio: adc: ad4695: add 2nd regmap for 16-bit registers
  2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
@ 2024-08-20 15:58 ` David Lechner
  2024-08-20 15:58 ` [PATCH 2/4] iio: adc: ad4695: implement calibration support David Lechner
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: David Lechner @ 2024-08-20 15:58 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc, David Lechner

The AD4695 and similar chips have some multibyte registers that have
to be read/written in a single operation. So we need to add a 2nd regmap
for these registers.

These registers are removed from the 8-bit regmap allowable ranges and
AD4695_MAX_REG is dropped since it would be ambiguous now.

debugfs register access is also updated to automatically use the correct
regmap depending on the register address.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 drivers/iio/adc/ad4695.c | 83 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 68 insertions(+), 15 deletions(-)

diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c
index b8547914f00f..63d816ad2d1f 100644
--- a/drivers/iio/adc/ad4695.c
+++ b/drivers/iio/adc/ad4695.c
@@ -34,6 +34,7 @@
 /* AD4695 registers */
 #define AD4695_REG_SPI_CONFIG_A				0x0000
 #define   AD4695_REG_SPI_CONFIG_A_SW_RST		  (BIT(7) | BIT(0))
+#define   AD4695_REG_SPI_CONFIG_A_ADDR_DIR		  BIT(5)
 #define AD4695_REG_SPI_CONFIG_B				0x0001
 #define   AD4695_REG_SPI_CONFIG_B_INST_MODE		  BIT(7)
 #define AD4695_REG_DEVICE_TYPE				0x0003
@@ -77,7 +78,6 @@
 #define AD4695_REG_GAIN_IN(n)				(0x00C0 | (2 * (n)))
 #define AD4695_REG_AS_SLOT(n)				(0x0100 | (n))
 #define   AD4695_REG_AS_SLOT_INX			  GENMASK(3, 0)
-#define AD4695_MAX_REG					0x017F
 
 /* Conversion mode commands */
 #define AD4695_CMD_EXIT_CNV_MODE	0x0A
@@ -121,6 +121,7 @@ struct ad4695_channel_config {
 struct ad4695_state {
 	struct spi_device *spi;
 	struct regmap *regmap;
+	struct regmap *regmap16;
 	struct gpio_desc *reset_gpio;
 	/* voltages channels plus temperature and timestamp */
 	struct iio_chan_spec iio_chan[AD4695_MAX_CHANNELS + 2];
@@ -150,8 +151,10 @@ static const struct regmap_range ad4695_regmap_rd_ranges[] = {
 	regmap_reg_range(AD4695_REG_SPI_CONFIG_C, AD4695_REG_SPI_STATUS),
 	regmap_reg_range(AD4695_REG_STATUS, AD4695_REG_ALERT_STATUS2),
 	regmap_reg_range(AD4695_REG_CLAMP_STATUS, AD4695_REG_CLAMP_STATUS),
-	regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_TEMP_CTRL),
-	regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_MAX_REG),
+	regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_AC_CTRL),
+	regmap_reg_range(AD4695_REG_GPIO_CTRL, AD4695_REG_TEMP_CTRL),
+	regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_REG_CONFIG_IN(15)),
+	regmap_reg_range(AD4695_REG_AS_SLOT(0), AD4695_REG_AS_SLOT(127)),
 };
 
 static const struct regmap_access_table ad4695_regmap_rd_table = {
@@ -164,8 +167,10 @@ static const struct regmap_range ad4695_regmap_wr_ranges[] = {
 	regmap_reg_range(AD4695_REG_SCRATCH_PAD, AD4695_REG_SCRATCH_PAD),
 	regmap_reg_range(AD4695_REG_LOOP_MODE, AD4695_REG_LOOP_MODE),
 	regmap_reg_range(AD4695_REG_SPI_CONFIG_C, AD4695_REG_SPI_STATUS),
-	regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_TEMP_CTRL),
-	regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_MAX_REG),
+	regmap_reg_range(AD4695_REG_SETUP, AD4695_REG_AC_CTRL),
+	regmap_reg_range(AD4695_REG_GPIO_CTRL, AD4695_REG_TEMP_CTRL),
+	regmap_reg_range(AD4695_REG_CONFIG_IN(0), AD4695_REG_CONFIG_IN(15)),
+	regmap_reg_range(AD4695_REG_AS_SLOT(0), AD4695_REG_AS_SLOT(127)),
 };
 
 static const struct regmap_access_table ad4695_regmap_wr_table = {
@@ -174,15 +179,47 @@ static const struct regmap_access_table ad4695_regmap_wr_table = {
 };
 
 static const struct regmap_config ad4695_regmap_config = {
-	.name = "ad4695",
+	.name = "ad4695-8",
 	.reg_bits = 16,
 	.val_bits = 8,
-	.max_register = AD4695_MAX_REG,
+	.max_register = AD4695_REG_AS_SLOT(127),
 	.rd_table = &ad4695_regmap_rd_table,
 	.wr_table = &ad4695_regmap_wr_table,
 	.can_multi_write = true,
 };
 
+static const struct regmap_range ad4695_regmap16_rd_ranges[] = {
+	regmap_reg_range(AD4695_REG_STD_SEQ_CONFIG, AD4695_REG_STD_SEQ_CONFIG),
+	regmap_reg_range(AD4695_REG_UPPER_IN(0), AD4695_REG_GAIN_IN(15)),
+};
+
+static const struct regmap_access_table ad4695_regmap16_rd_table = {
+	.yes_ranges = ad4695_regmap16_rd_ranges,
+	.n_yes_ranges = ARRAY_SIZE(ad4695_regmap16_rd_ranges),
+};
+
+static const struct regmap_range ad4695_regmap16_wr_ranges[] = {
+	regmap_reg_range(AD4695_REG_STD_SEQ_CONFIG, AD4695_REG_STD_SEQ_CONFIG),
+	regmap_reg_range(AD4695_REG_UPPER_IN(0), AD4695_REG_GAIN_IN(15)),
+};
+
+static const struct regmap_access_table ad4695_regmap16_wr_table = {
+	.yes_ranges = ad4695_regmap16_wr_ranges,
+	.n_yes_ranges = ARRAY_SIZE(ad4695_regmap16_wr_ranges),
+};
+
+static const struct regmap_config ad4695_regmap16_config = {
+	.name = "ad4695-16",
+	.reg_bits = 16,
+	.reg_stride = 2,
+	.val_bits = 16,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
+	.max_register = AD4695_REG_GAIN_IN(15),
+	.rd_table = &ad4695_regmap16_rd_table,
+	.wr_table = &ad4695_regmap16_wr_table,
+	.can_multi_write = true,
+};
+
 static const struct iio_chan_spec ad4695_channel_template = {
 	.type = IIO_VOLTAGE,
 	.indexed = 1,
@@ -646,13 +683,24 @@ static int ad4695_debugfs_reg_access(struct iio_dev *indio_dev,
 	struct ad4695_state *st = iio_priv(indio_dev);
 
 	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
-		if (readval)
-			return regmap_read(st->regmap, reg, readval);
-
-		return regmap_write(st->regmap, reg, writeval);
+		if (readval) {
+			if (regmap_check_range_table(st->regmap, reg,
+						     &ad4695_regmap_rd_table))
+				return regmap_read(st->regmap, reg, readval);
+			if (regmap_check_range_table(st->regmap16, reg,
+						     &ad4695_regmap16_rd_table))
+				return regmap_read(st->regmap16, reg, readval);
+		} else {
+			if (regmap_check_range_table(st->regmap, reg,
+						     &ad4695_regmap_wr_table))
+				return regmap_write(st->regmap, reg, writeval);
+			if (regmap_check_range_table(st->regmap16, reg,
+						     &ad4695_regmap16_wr_table))
+				return regmap_write(st->regmap16, reg, writeval);
+		}
 	}
 
-	unreachable();
+	return -EINVAL;
 }
 
 static const struct iio_info ad4695_info = {
@@ -807,6 +855,11 @@ static int ad4695_probe(struct spi_device *spi)
 		return dev_err_probe(dev, PTR_ERR(st->regmap),
 				     "Failed to initialize regmap\n");
 
+	st->regmap16 = devm_regmap_init_spi(spi, &ad4695_regmap16_config);
+	if (IS_ERR(st->regmap16))
+		return dev_err_probe(dev, PTR_ERR(st->regmap16),
+				     "Failed to initialize regmap16\n");
+
 	ret = devm_regulator_bulk_get_enable(dev,
 					     ARRAY_SIZE(ad4695_power_supplies),
 					     ad4695_power_supplies);
@@ -876,9 +929,9 @@ static int ad4695_probe(struct spi_device *spi)
 		msleep(AD4695_T_WAKEUP_SW_MS);
 	}
 
-	/* Needed for debugfs since it only access registers 1 byte at a time. */
-	ret = regmap_set_bits(st->regmap, AD4695_REG_SPI_CONFIG_C,
-			      AD4695_REG_SPI_CONFIG_C_MB_STRICT);
+	/* Needed for regmap16 to be able to work correctly. */
+	ret = regmap_set_bits(st->regmap, AD4695_REG_SPI_CONFIG_A,
+			      AD4695_REG_SPI_CONFIG_A_ADDR_DIR);
 	if (ret)
 		return ret;
 

-- 
2.43.0


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

* [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
  2024-08-20 15:58 ` [PATCH 1/4] iio: adc: ad4695: add 2nd regmap for 16-bit registers David Lechner
@ 2024-08-20 15:58 ` David Lechner
  2024-08-21  4:21   ` kernel test robot
  2024-08-21 13:16   ` Jonathan Cameron
  2024-08-20 15:58 ` [PATCH 3/4] doc: iio: ad4695: update for " David Lechner
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 11+ messages in thread
From: David Lechner @ 2024-08-20 15:58 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc, David Lechner

The AD4695 has a calibration feature that allows the user to compensate
for variations in the analog front end. This implements this feature in
the driver using the standard `calibgain` and `calibbias` attributes.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 drivers/iio/adc/ad4695.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 157 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c
index 63d816ad2d1f..181c4146188c 100644
--- a/drivers/iio/adc/ad4695.c
+++ b/drivers/iio/adc/ad4695.c
@@ -23,6 +23,7 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
+#include <linux/minmax.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
@@ -225,7 +226,11 @@ static const struct iio_chan_spec ad4695_channel_template = {
 	.indexed = 1,
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			      BIT(IIO_CHAN_INFO_SCALE) |
-			      BIT(IIO_CHAN_INFO_OFFSET),
+			      BIT(IIO_CHAN_INFO_OFFSET) |
+			      BIT(IIO_CHAN_INFO_CALIBSCALE) |
+			      BIT(IIO_CHAN_INFO_CALIBBIAS),
+	.info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBSCALE) |
+					BIT(IIO_CHAN_INFO_CALIBBIAS),
 	.scan_type = {
 		.sign = 'u',
 		.realbits = 16,
@@ -619,7 +624,8 @@ static int ad4695_read_raw(struct iio_dev *indio_dev,
 	struct ad4695_state *st = iio_priv(indio_dev);
 	struct ad4695_channel_config *cfg = &st->channels_cfg[chan->scan_index];
 	u8 realbits = chan->scan_type.realbits;
-	int ret;
+	unsigned int reg_val;
+	int ret, tmp;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -670,6 +676,153 @@ static int ad4695_read_raw(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_CALIBSCALE:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+				ret = regmap_read(st->regmap16,
+					AD4695_REG_GAIN_IN(chan->scan_index),
+					&reg_val);
+				if (ret)
+					return ret;
+
+				*val = reg_val;
+				*val2 = 15;
+
+				return IIO_VAL_FRACTIONAL_LOG2;
+			}
+			unreachable();
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+				ret = regmap_read(st->regmap16,
+					AD4695_REG_OFFSET_IN(chan->scan_index),
+					&reg_val);
+				if (ret)
+					return ret;
+
+				tmp = sign_extend32(reg_val, 15);
+
+				*val = tmp / 4;
+				*val2 = abs(tmp) % 4 * MICRO / 4;
+
+				if (tmp < 0 && *val2) {
+					*val *= -1;
+					*val2 *= -1;
+				}
+
+				return IIO_VAL_INT_PLUS_MICRO;
+			}
+			unreachable();
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad4695_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct ad4695_state *st = iio_priv(indio_dev);
+	unsigned int reg_val;
+	int ret;
+
+	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+		switch (mask) {
+		case IIO_CHAN_INFO_CALIBSCALE:
+			switch (chan->type) {
+			case IIO_VOLTAGE:
+				if (val < 0 || val2 < 0)
+					reg_val = 0;
+				else if (val > 1)
+					reg_val = U16_MAX;
+				else
+					reg_val = (val * (1 << 16) +
+						   mul_u64_u32_div(val2, 1 << 16,
+								   MICRO)) / 2;
+
+				return regmap_write(st->regmap16,
+					AD4695_REG_GAIN_IN(chan->scan_index),
+					reg_val);
+			default:
+				return -EINVAL;
+			}
+		case IIO_CHAN_INFO_CALIBBIAS:
+			switch (chan->type) {
+			case IIO_VOLTAGE:
+				if (val2 >= 0 && val > S16_MAX / 4)
+					reg_val = S16_MAX;
+				else if ((val2 < 0 ? -val : val) < S16_MIN / 4)
+					reg_val = S16_MIN;
+				else if (val2 < 0)
+					reg_val = clamp_t(int,
+						-(val * 4 + -val2 * 4 / MICRO),
+						S16_MIN, S16_MAX);
+				else if (val < 0)
+					reg_val = clamp_t(int,
+						val * 4 - val2 * 4 / MICRO,
+						S16_MIN, S16_MAX);
+				else
+					reg_val = clamp_t(int,
+						val * 4 + val2 * 4 / MICRO,
+						S16_MIN, S16_MAX);
+
+				return regmap_write(st->regmap16,
+					AD4695_REG_OFFSET_IN(chan->scan_index),
+					reg_val);
+			default:
+				return -EINVAL;
+			}
+		default:
+			return -EINVAL;
+		}
+	}
+	unreachable();
+}
+
+static int ad4695_read_avail(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     const int **vals, int *type, int *length,
+			     long mask)
+{
+	static const int ad4695_calibscale_available[6] = {
+		/* Range of 0 (inclusive) to 2 (exclusive) */
+		0, 15, 1, 15, U16_MAX, 15
+	};
+	static const int ad4695_calibbias_available[6] = {
+		/*
+		 * Datasheet says FSR/8 which translates to signed/4. The step
+		 * depends on oversampling ratio which is always 1 for now.
+		 */
+		S16_MIN / 4, 0, 0, MICRO / 4, S16_MAX / 4, S16_MAX % 4 * MICRO / 4
+	};
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBSCALE:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			*vals = ad4695_calibscale_available;
+			*type = IIO_VAL_FRACTIONAL_LOG2;
+			return IIO_AVAIL_RANGE;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			*vals = ad4695_calibbias_available;
+			*type = IIO_VAL_INT_PLUS_MICRO;
+			return IIO_AVAIL_RANGE;
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -705,6 +858,8 @@ static int ad4695_debugfs_reg_access(struct iio_dev *indio_dev,
 
 static const struct iio_info ad4695_info = {
 	.read_raw = &ad4695_read_raw,
+	.write_raw = &ad4695_write_raw,
+	.read_avail = &ad4695_read_avail,
 	.debugfs_reg_access = &ad4695_debugfs_reg_access,
 };
 

-- 
2.43.0


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

* [PATCH 3/4] doc: iio: ad4695: update for calibration support
  2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
  2024-08-20 15:58 ` [PATCH 1/4] iio: adc: ad4695: add 2nd regmap for 16-bit registers David Lechner
  2024-08-20 15:58 ` [PATCH 2/4] iio: adc: ad4695: implement calibration support David Lechner
@ 2024-08-20 15:58 ` David Lechner
  2024-08-20 15:58 ` [PATCH 4/4] iio: ABI: document ad4695 new attributes David Lechner
  2024-08-26 10:46 ` [PATCH 0/4] iio: adc: ad4695: implement calibration support Jonathan Cameron
  4 siblings, 0 replies; 11+ messages in thread
From: David Lechner @ 2024-08-20 15:58 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc, David Lechner

Calibration support has been added to the ad4695 driver, so update the
documentation to reflect this.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 Documentation/iio/ad4695.rst | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/iio/ad4695.rst b/Documentation/iio/ad4695.rst
index 7612596bb6e9..33ed29b7c98a 100644
--- a/Documentation/iio/ad4695.rst
+++ b/Documentation/iio/ad4695.rst
@@ -143,13 +143,18 @@ present, then the external reference voltage is used and the internal buffer is
 disabled. If ``refin-supply`` is present, then the internal buffered reference
 voltage is used.
 
+Gain/offset calibration
+-----------------------
+
+System calibration is supported using the channel gain and offset registers via
+the ``calibscale`` and ``calibbias`` attributes respectively.
+
 Unimplemented features
 ----------------------
 
 - Additional wiring modes
 - Threshold events
 - Oversampling
-- Gain/offset calibration
 - GPIO support
 - CRC support
 

-- 
2.43.0


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

* [PATCH 4/4] iio: ABI: document ad4695 new attributes
  2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
                   ` (2 preceding siblings ...)
  2024-08-20 15:58 ` [PATCH 3/4] doc: iio: ad4695: update for " David Lechner
@ 2024-08-20 15:58 ` David Lechner
  2024-08-26 10:46 ` [PATCH 0/4] iio: adc: ad4695: implement calibration support Jonathan Cameron
  4 siblings, 0 replies; 11+ messages in thread
From: David Lechner @ 2024-08-20 15:58 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc, David Lechner

The ad4695 driver now supports calibration using the
in_voltageY_calib{scale,bias}[_available] attributes.

Only one of these was documented before. This adds rest.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 Documentation/ABI/testing/sysfs-bus-iio | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 345d58535dc9..89943c2d54e8 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -541,6 +541,7 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_temp_calibbias
+What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/out_currentY_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias
 KernelVersion:	2.6.35
@@ -556,6 +557,7 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
 What:		/sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
 What:		/sys/bus/iio/devices/iio:deviceX/in_temp_calibbias_available
 What:		/sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias_available
 What:		/sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias_available
 KernelVersion:  5.8
 Contact:        linux-iio@vger.kernel.org
@@ -603,6 +605,7 @@ Description:
 What:		/sys/bus/iio/devices/iio:deviceX/in_illuminanceY_calibscale_available
 What:		/sys/bus/iio/devices/iio:deviceX/in_intensityY_calibscale_available
 What:		/sys/bus/iio/devices/iio:deviceX/in_proximityY_calibscale_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale_available
 KernelVersion:	4.8
 Contact:	linux-iio@vger.kernel.org
 Description:

-- 
2.43.0


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

* Re: [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-20 15:58 ` [PATCH 2/4] iio: adc: ad4695: implement calibration support David Lechner
@ 2024-08-21  4:21   ` kernel test robot
  2024-08-26 10:57     ` Jonathan Cameron
  2024-08-21 13:16   ` Jonathan Cameron
  1 sibling, 1 reply; 11+ messages in thread
From: kernel test robot @ 2024-08-21  4:21 UTC (permalink / raw)
  To: David Lechner, Jonathan Cameron
  Cc: llvm, oe-kbuild-all, Michael Hennerich, Nuno Sá,
	Jonathan Corbet, linux-iio, linux-kernel, linux-doc,
	David Lechner

Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 0f718e10da81446df0909c9939dff2b77e3b4e95]

url:    https://github.com/intel-lab-lkp/linux/commits/David-Lechner/iio-adc-ad4695-add-2nd-regmap-for-16-bit-registers/20240821-000102
base:   0f718e10da81446df0909c9939dff2b77e3b4e95
patch link:    https://lore.kernel.org/r/20240820-ad4695-gain-offset-v1-2-c8f6e3b47551%40baylibre.com
patch subject: [PATCH 2/4] iio: adc: ad4695: implement calibration support
config: i386-buildonly-randconfig-002-20240821 (https://download.01.org/0day-ci/archive/20240821/202408211207.fmYTjQDK-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240821/202408211207.fmYTjQDK-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408211207.fmYTjQDK-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/iio/adc/ad4695.c:735:6: warning: unused variable 'ret' [-Wunused-variable]
     735 |         int ret;
         |             ^~~
   1 warning generated.


vim +/ret +735 drivers/iio/adc/ad4695.c

   728	
   729	static int ad4695_write_raw(struct iio_dev *indio_dev,
   730				    struct iio_chan_spec const *chan,
   731				    int val, int val2, long mask)
   732	{
   733		struct ad4695_state *st = iio_priv(indio_dev);
   734		unsigned int reg_val;
 > 735		int ret;
   736	
   737		iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
   738			switch (mask) {
   739			case IIO_CHAN_INFO_CALIBSCALE:
   740				switch (chan->type) {
   741				case IIO_VOLTAGE:
   742					if (val < 0 || val2 < 0)
   743						reg_val = 0;
   744					else if (val > 1)
   745						reg_val = U16_MAX;
   746					else
   747						reg_val = (val * (1 << 16) +
   748							   mul_u64_u32_div(val2, 1 << 16,
   749									   MICRO)) / 2;
   750	
   751					return regmap_write(st->regmap16,
   752						AD4695_REG_GAIN_IN(chan->scan_index),
   753						reg_val);
   754				default:
   755					return -EINVAL;
   756				}
   757			case IIO_CHAN_INFO_CALIBBIAS:
   758				switch (chan->type) {
   759				case IIO_VOLTAGE:
   760					if (val2 >= 0 && val > S16_MAX / 4)
   761						reg_val = S16_MAX;
   762					else if ((val2 < 0 ? -val : val) < S16_MIN / 4)
   763						reg_val = S16_MIN;
   764					else if (val2 < 0)
   765						reg_val = clamp_t(int,
   766							-(val * 4 + -val2 * 4 / MICRO),
   767							S16_MIN, S16_MAX);
   768					else if (val < 0)
   769						reg_val = clamp_t(int,
   770							val * 4 - val2 * 4 / MICRO,
   771							S16_MIN, S16_MAX);
   772					else
   773						reg_val = clamp_t(int,
   774							val * 4 + val2 * 4 / MICRO,
   775							S16_MIN, S16_MAX);
   776	
   777					return regmap_write(st->regmap16,
   778						AD4695_REG_OFFSET_IN(chan->scan_index),
   779						reg_val);
   780				default:
   781					return -EINVAL;
   782				}
   783			default:
   784				return -EINVAL;
   785			}
   786		}
   787		unreachable();
   788	}
   789	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-20 15:58 ` [PATCH 2/4] iio: adc: ad4695: implement calibration support David Lechner
  2024-08-21  4:21   ` kernel test robot
@ 2024-08-21 13:16   ` Jonathan Cameron
  2024-08-21 16:12     ` David Lechner
  1 sibling, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2024-08-21 13:16 UTC (permalink / raw)
  To: David Lechner
  Cc: Jonathan Cameron, Michael Hennerich, Nuno Sá,
	Jonathan Corbet, linux-iio, linux-kernel, linux-doc

On Tue, 20 Aug 2024 10:58:36 -0500
David Lechner <dlechner@baylibre.com> wrote:

> The AD4695 has a calibration feature that allows the user to compensate
> for variations in the analog front end. This implements this feature in
> the driver using the standard `calibgain` and `calibbias` attributes.
> 
> Signed-off-by: David Lechner <dlechner@baylibre.com>
Hi David,

Whilst some of the messy value manipulation is unavoidable
(oh for signed integer zero!), I wonder if we can at least
move one case into the core.

See below.

> +
> +static int ad4695_write_raw(struct iio_dev *indio_dev,
> +			    struct iio_chan_spec const *chan,
> +			    int val, int val2, long mask)
> +{
> +	struct ad4695_state *st = iio_priv(indio_dev);
> +	unsigned int reg_val;
> +	int ret;
> +
> +	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
> +		switch (mask) {
> +		case IIO_CHAN_INFO_CALIBSCALE:
> +			switch (chan->type) {
> +			case IIO_VOLTAGE:
> +				if (val < 0 || val2 < 0)
> +					reg_val = 0;
> +				else if (val > 1)
> +					reg_val = U16_MAX;
> +				else
> +					reg_val = (val * (1 << 16) +
> +						   mul_u64_u32_div(val2, 1 << 16,
> +								   MICRO)) / 2;
Maybe worth extending iio_write_channel_info() to handle
IIO_VAL_FRACTIONAL_LOG2()?
It'll look much like this and you'll need to provide write_raw_get_fmt()
so the core know what to do with the value formatting.

I don't really like the mixture here between the read path being able
to rely on the core code to deal with the /2^X and the write path not.
> +
> +				return regmap_write(st->regmap16,
> +					AD4695_REG_GAIN_IN(chan->scan_index),
> +					reg_val);
> +			default:
> +				return -EINVAL;




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

* Re: [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-21 13:16   ` Jonathan Cameron
@ 2024-08-21 16:12     ` David Lechner
  2024-08-21 16:33       ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: David Lechner @ 2024-08-21 16:12 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Jonathan Cameron, Michael Hennerich, Nuno Sá,
	Jonathan Corbet, linux-iio, linux-kernel, linux-doc

On 8/21/24 8:16 AM, Jonathan Cameron wrote:
> On Tue, 20 Aug 2024 10:58:36 -0500
> David Lechner <dlechner@baylibre.com> wrote:
> 
>> The AD4695 has a calibration feature that allows the user to compensate
>> for variations in the analog front end. This implements this feature in
>> the driver using the standard `calibgain` and `calibbias` attributes.
>>
>> Signed-off-by: David Lechner <dlechner@baylibre.com>
> Hi David,
> 
> Whilst some of the messy value manipulation is unavoidable
> (oh for signed integer zero!), I wonder if we can at least
> move one case into the core.
> 
> See below.
> 
>> +
>> +static int ad4695_write_raw(struct iio_dev *indio_dev,
>> +			    struct iio_chan_spec const *chan,
>> +			    int val, int val2, long mask)
>> +{
>> +	struct ad4695_state *st = iio_priv(indio_dev);
>> +	unsigned int reg_val;
>> +	int ret;
>> +
>> +	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
>> +		switch (mask) {
>> +		case IIO_CHAN_INFO_CALIBSCALE:
>> +			switch (chan->type) {
>> +			case IIO_VOLTAGE:
>> +				if (val < 0 || val2 < 0)
>> +					reg_val = 0;
>> +				else if (val > 1)
>> +					reg_val = U16_MAX;
>> +				else
>> +					reg_val = (val * (1 << 16) +
>> +						   mul_u64_u32_div(val2, 1 << 16,
>> +								   MICRO)) / 2;
> Maybe worth extending iio_write_channel_info() to handle
> IIO_VAL_FRACTIONAL_LOG2()?
> It'll look much like this and you'll need to provide write_raw_get_fmt()
> so the core know what to do with the value formatting.
> 
> I don't really like the mixture here between the read path being able
> to rely on the core code to deal with the /2^X and the write path not.

Sounds like a good idea to me.

It seems like we would need to add an extra out parameter to 
write_raw_get_fmt to say what we want the X in 2^X to be. For
example, we would want to make sure the val2 we get in write_raw
for this driver is 15.

>> +
>> +				return regmap_write(st->regmap16,
>> +					AD4695_REG_GAIN_IN(chan->scan_index),
>> +					reg_val);
>> +			default:
>> +				return -EINVAL;
> 
> 
> 


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

* Re: [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-21 16:12     ` David Lechner
@ 2024-08-21 16:33       ` Jonathan Cameron
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2024-08-21 16:33 UTC (permalink / raw)
  To: David Lechner
  Cc: Jonathan Cameron, Michael Hennerich, Nuno Sá,
	Jonathan Corbet, linux-iio, linux-kernel, linux-doc

On Wed, 21 Aug 2024 11:12:12 -0500
David Lechner <dlechner@baylibre.com> wrote:

> On 8/21/24 8:16 AM, Jonathan Cameron wrote:
> > On Tue, 20 Aug 2024 10:58:36 -0500
> > David Lechner <dlechner@baylibre.com> wrote:
> >   
> >> The AD4695 has a calibration feature that allows the user to compensate
> >> for variations in the analog front end. This implements this feature in
> >> the driver using the standard `calibgain` and `calibbias` attributes.
> >>
> >> Signed-off-by: David Lechner <dlechner@baylibre.com>  
> > Hi David,
> > 
> > Whilst some of the messy value manipulation is unavoidable
> > (oh for signed integer zero!), I wonder if we can at least
> > move one case into the core.
> > 
> > See below.
> >   
> >> +
> >> +static int ad4695_write_raw(struct iio_dev *indio_dev,
> >> +			    struct iio_chan_spec const *chan,
> >> +			    int val, int val2, long mask)
> >> +{
> >> +	struct ad4695_state *st = iio_priv(indio_dev);
> >> +	unsigned int reg_val;
> >> +	int ret;
> >> +
> >> +	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
> >> +		switch (mask) {
> >> +		case IIO_CHAN_INFO_CALIBSCALE:
> >> +			switch (chan->type) {
> >> +			case IIO_VOLTAGE:
> >> +				if (val < 0 || val2 < 0)
> >> +					reg_val = 0;
> >> +				else if (val > 1)
> >> +					reg_val = U16_MAX;
> >> +				else
> >> +					reg_val = (val * (1 << 16) +
> >> +						   mul_u64_u32_div(val2, 1 << 16,
> >> +								   MICRO)) / 2;  
> > Maybe worth extending iio_write_channel_info() to handle
> > IIO_VAL_FRACTIONAL_LOG2()?
> > It'll look much like this and you'll need to provide write_raw_get_fmt()
> > so the core know what to do with the value formatting.
> > 
> > I don't really like the mixture here between the read path being able
> > to rely on the core code to deal with the /2^X and the write path not.  
> 
> Sounds like a good idea to me.
> 
> It seems like we would need to add an extra out parameter to 
> write_raw_get_fmt to say what we want the X in 2^X to be. For
> example, we would want to make sure the val2 we get in write_raw
> for this driver is 15.
Yes.  (I tried to reply to say I'd neglected this but managed to
just email myself. oops.)

Maybe it's too complex to bother given that.  Definitely a job
for another day rather than something to block this series on.


Jonathan

> 
> >> +
> >> +				return regmap_write(st->regmap16,
> >> +					AD4695_REG_GAIN_IN(chan->scan_index),
> >> +					reg_val);
> >> +			default:
> >> +				return -EINVAL;  
> > 
> > 
> >   
> 


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

* Re: [PATCH 0/4] iio: adc: ad4695: implement calibration support
  2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
                   ` (3 preceding siblings ...)
  2024-08-20 15:58 ` [PATCH 4/4] iio: ABI: document ad4695 new attributes David Lechner
@ 2024-08-26 10:46 ` Jonathan Cameron
  4 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2024-08-26 10:46 UTC (permalink / raw)
  To: David Lechner
  Cc: Michael Hennerich, Nuno Sá, Jonathan Corbet, linux-iio,
	linux-kernel, linux-doc

On Tue, 20 Aug 2024 10:58:34 -0500
David Lechner <dlechner@baylibre.com> wrote:

> This series adds calibration support to the ad4695 driver.
> 
> This has the same "odd" gain and offset registers that are being used
> for calibration as discussed recently in the ad4030 series [1]. So if
> the ranges in the *_available attributes seem a bit big for calibration,
> that is why. The official datasheet explanation for this feature is,
> "The AD4695/AD4696 include offset and gain error correction
> functionality to correct for first-order nonidealities in a full
> [analog front end] signal chain."
> 
> [1]: https://lore.kernel.org/linux-iio/20240814193814.78fe45cc@jic23-huawei/
Series LGTM
Applied to the togreg branch of iio.git and pushed out as testing.
Note I'll be rebasing after the previous pull request (hopefully)
gets picked up by Greg.

Jonathan

> 
> ---
> David Lechner (4):
>       iio: adc: ad4695: add 2nd regmap for 16-bit registers
>       iio: adc: ad4695: implement calibration support
>       doc: iio: ad4695: update for calibration support
>       iio: ABI: document ad4695 new attributes
> 
>  Documentation/ABI/testing/sysfs-bus-iio |   3 +
>  Documentation/iio/ad4695.rst            |   7 +-
>  drivers/iio/adc/ad4695.c                | 242 +++++++++++++++++++++++++++++---
>  3 files changed, 234 insertions(+), 18 deletions(-)
> ---
> base-commit: 0f718e10da81446df0909c9939dff2b77e3b4e95
> change-id: 20240819-ad4695-gain-offset-c748d7addf27
> 
> Best regards,


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

* Re: [PATCH 2/4] iio: adc: ad4695: implement calibration support
  2024-08-21  4:21   ` kernel test robot
@ 2024-08-26 10:57     ` Jonathan Cameron
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2024-08-26 10:57 UTC (permalink / raw)
  To: kernel test robot
  Cc: David Lechner, llvm, oe-kbuild-all, Michael Hennerich,
	Nuno Sá, Jonathan Corbet, linux-iio, linux-kernel, linux-doc

On Wed, 21 Aug 2024 12:21:09 +0800
kernel test robot <lkp@intel.com> wrote:

> Hi David,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on 0f718e10da81446df0909c9939dff2b77e3b4e95]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/David-Lechner/iio-adc-ad4695-add-2nd-regmap-for-16-bit-registers/20240821-000102
> base:   0f718e10da81446df0909c9939dff2b77e3b4e95
> patch link:    https://lore.kernel.org/r/20240820-ad4695-gain-offset-v1-2-c8f6e3b47551%40baylibre.com
> patch subject: [PATCH 2/4] iio: adc: ad4695: implement calibration support
> config: i386-buildonly-randconfig-002-20240821 (https://download.01.org/0day-ci/archive/20240821/202408211207.fmYTjQDK-lkp@intel.com/config)
> compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240821/202408211207.fmYTjQDK-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202408211207.fmYTjQDK-lkp@intel.com/
> 
> All warnings (new ones prefixed by >>):
> 
> >> drivers/iio/adc/ad4695.c:735:6: warning: unused variable 'ret' [-Wunused-variable]  
>      735 |         int ret;
>          |             ^~~
>    1 warning generated.
I dropped this whilst applying.

> 
> 
> vim +/ret +735 drivers/iio/adc/ad4695.c
> 
>    728	
>    729	static int ad4695_write_raw(struct iio_dev *indio_dev,
>    730				    struct iio_chan_spec const *chan,
>    731				    int val, int val2, long mask)
>    732	{
>    733		struct ad4695_state *st = iio_priv(indio_dev);
>    734		unsigned int reg_val;
>  > 735		int ret;  
>    736	
>    737		iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
>    738			switch (mask) {
>    739			case IIO_CHAN_INFO_CALIBSCALE:
>    740				switch (chan->type) {
>    741				case IIO_VOLTAGE:
>    742					if (val < 0 || val2 < 0)
>    743						reg_val = 0;
>    744					else if (val > 1)
>    745						reg_val = U16_MAX;
>    746					else
>    747						reg_val = (val * (1 << 16) +
>    748							   mul_u64_u32_div(val2, 1 << 16,
>    749									   MICRO)) / 2;
>    750	
>    751					return regmap_write(st->regmap16,
>    752						AD4695_REG_GAIN_IN(chan->scan_index),
>    753						reg_val);
>    754				default:
>    755					return -EINVAL;
>    756				}
>    757			case IIO_CHAN_INFO_CALIBBIAS:
>    758				switch (chan->type) {
>    759				case IIO_VOLTAGE:
>    760					if (val2 >= 0 && val > S16_MAX / 4)
>    761						reg_val = S16_MAX;
>    762					else if ((val2 < 0 ? -val : val) < S16_MIN / 4)
>    763						reg_val = S16_MIN;
>    764					else if (val2 < 0)
>    765						reg_val = clamp_t(int,
>    766							-(val * 4 + -val2 * 4 / MICRO),
>    767							S16_MIN, S16_MAX);
>    768					else if (val < 0)
>    769						reg_val = clamp_t(int,
>    770							val * 4 - val2 * 4 / MICRO,
>    771							S16_MIN, S16_MAX);
>    772					else
>    773						reg_val = clamp_t(int,
>    774							val * 4 + val2 * 4 / MICRO,
>    775							S16_MIN, S16_MAX);
>    776	
>    777					return regmap_write(st->regmap16,
>    778						AD4695_REG_OFFSET_IN(chan->scan_index),
>    779						reg_val);
>    780				default:
>    781					return -EINVAL;
>    782				}
>    783			default:
>    784				return -EINVAL;
>    785			}
>    786		}
>    787		unreachable();
>    788	}
>    789	
> 


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

end of thread, other threads:[~2024-08-26 10:58 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-20 15:58 [PATCH 0/4] iio: adc: ad4695: implement calibration support David Lechner
2024-08-20 15:58 ` [PATCH 1/4] iio: adc: ad4695: add 2nd regmap for 16-bit registers David Lechner
2024-08-20 15:58 ` [PATCH 2/4] iio: adc: ad4695: implement calibration support David Lechner
2024-08-21  4:21   ` kernel test robot
2024-08-26 10:57     ` Jonathan Cameron
2024-08-21 13:16   ` Jonathan Cameron
2024-08-21 16:12     ` David Lechner
2024-08-21 16:33       ` Jonathan Cameron
2024-08-20 15:58 ` [PATCH 3/4] doc: iio: ad4695: update for " David Lechner
2024-08-20 15:58 ` [PATCH 4/4] iio: ABI: document ad4695 new attributes David Lechner
2024-08-26 10:46 ` [PATCH 0/4] iio: adc: ad4695: implement calibration support Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).