Devicetree
 help / color / mirror / Atom feed
* [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC
@ 2026-05-18 22:02 Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 01/11] dt-bindings: iio: adc: hx711: clean up existing binding text Piyush Patle
                   ` (10 more replies)
  0 siblings, 11 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

The HX710B is a 24-bit ADC from AVIA Semiconductor, related to the
HX711 already supported in this driver.  Unlike the HX711 (which has
selectable gain and two input channels), the HX710B has a fixed gain
of 128 and two operating modes selected by the trailing PD_SCK pulse
count after each conversion:

  25 pulses (1 trailing): differential input at 10 SPS
  26 pulses (2 trailing): DVDD-AVDD supply monitor at 40 SPS
  27 pulses (3 trailing): differential input at 40 SPS

This series first extends the existing HX711 binding and driver with
preparatory refactoring, then adds HX710B support on top.

The differential input is exposed as a single IIO channel with
IIO_CHAN_INFO_SAMP_FREQ, allowing userspace to select 10 or 40 SPS
without needing two separate channels for the same physical input.
The supply monitor is a second channel at fixed 40 SPS.

Patches 01/11, 02/11, 03/11, and 05/11 have already been applied to
the iio.git testing branch.  They are re-included here so the series
applies cleanly as a unit.

Changes from v8:
  - 04/11: Dropped a misleading sentence from the commit message that
    suggested HX711-only binding extensions live in earlier patches
    (they do not; the earlier patches extend the shared binding).
  - 06/11: No code change.  Added a note below the --- line clarifying
    that __counted_by_ptr() is available since 6.12 (this tree is
    6.17), so the annotation is well-defined.
  - 11/11: Redesigned HX710B channel layout per Jonathan's v8 review.
    Modes 1 and 3 both read the same physical differential input, so
    they are now a single IIO channel with IIO_CHAN_INFO_SAMP_FREQ
    instead of two separate channels.  Added hx710b_write_raw() and
    hx710b_read_avail() to let userspace control the sample rate.
    Introduced hx710b_trailing_pulses() helper so .address is no longer
    needed in the channel spec.  Fixed hx711_trigger() to check the
    return value of hx711_reset_read() and bail out on error.  Fixed
    channel_set update ordering in hx711_set_hx710b_channel() so the
    field is written immediately after hx711_read() commits the new
    hardware mode, before waiting for the chip to be ready.

Piyush Patle (11):
  dt-bindings: iio: adc: hx711: clean up existing binding text
  dt-bindings: iio: adc: hx711: add VSUP supply property
  dt-bindings: iio: adc: hx711: add RATE GPIO property
  dt-bindings: iio: adc: hx711: add HX710B support
  iio: adc: hx711: move scale computation to per-device storage
  iio: adc: hx711: introduce hx711_chip_info structure
  iio: adc: hx711: pass trailing pulse count into hx711_read
  iio: adc: hx711: split variable assignments in hx711_read and
    hx711_reset
  iio: adc: hx711: localize loop iterators in hx711_read
  iio: adc: hx711: pass iio_chan_spec to hx711_reset_read
  iio: adc: hx711: add support for HX710B

 .../bindings/iio/adc/avia-hx711.yaml          |  77 +++-
 drivers/iio/adc/Kconfig                       |   8 +-
 drivers/iio/adc/hx711.c                       | 362 ++++++++++++++----
 3 files changed, 362 insertions(+), 85 deletions(-)

-- 
2.43.0


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

* [PATCH v9 01/11] dt-bindings: iio: adc: hx711: clean up existing binding text
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 02/11] dt-bindings: iio: adc: hx711: add VSUP supply property Piyush Patle
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Rewrite the binding description and property text so it describes the
existing HX711 hardware behavior directly instead of documenting old
driver implementation details.

Also clarify that clock-frequency controls the SCK bit-bang timing.

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
No change from v8. Already applied to iio.git testing branch.
 .../bindings/iio/adc/avia-hx711.yaml          | 25 ++++++++-----------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index 9c57eb13f892..1ea60dff98d5 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -10,14 +10,9 @@ maintainers:
   - Andreas Klinger <ak@it-klinger.de>
 
 description: |
-  Bit-banging driver using two GPIOs:
-  - sck-gpio gives a clock to the sensor with 24 cycles for data retrieval
-    and up to 3 cycles for selection of the input channel and gain for the
-    next measurement
-  - dout-gpio is the sensor data the sensor responds to the clock
-
-  Specifications about the driver can be found at:
-  http://www.aviaic.com/ENProducts.aspx
+  The HX711 is a 24-bit ADC with selectable gain (32/64/128) and two
+  differential input channels. Channel A supports gain 64 and 128;
+  channel B supports gain 32.
 
 properties:
   compatible:
@@ -26,23 +21,23 @@ properties:
 
   sck-gpios:
     description:
-      Definition of the GPIO for the clock (output). In the datasheet it is
-      named PD_SCK
+      GPIO for the clock output (PD_SCK in the datasheet).
     maxItems: 1
 
   dout-gpios:
     description:
-      Definition of the GPIO for the data-out sent by the sensor in
-      response to the clock (input).
-      See Documentation/devicetree/bindings/gpio/gpio.txt for information
-      on how to specify a consumer gpio.
+      GPIO for the data output from the sensor (DOUT in the datasheet).
     maxItems: 1
 
   avdd-supply:
     description:
-      Definition of the regulator used as analog supply
+      Analog supply voltage (AVDD).
 
   clock-frequency:
+    description:
+      Controls the SCK bit-bang timing. The value is used to derive the
+      delay between SCK edges; keep the SCK high time below 60 us to
+      avoid triggering chip power-down mode.
     minimum: 20000
     maximum: 2500000
     default: 400000
-- 
2.43.0


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

* [PATCH v9 02/11] dt-bindings: iio: adc: hx711: add VSUP supply property
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 01/11] dt-bindings: iio: adc: hx711: clean up existing binding text Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 03/11] dt-bindings: iio: adc: hx711: add RATE GPIO property Piyush Patle
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Document the optional VSUP supply used by the HX711 on-chip regulator.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
No change from v8. Already applied to iio.git testing branch.
 Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index 1ea60dff98d5..a8eaa1f18de5 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -33,6 +33,10 @@ properties:
     description:
       Analog supply voltage (AVDD).
 
+  vsup-supply:
+    description:
+      Supply voltage for the on-chip regulator (VSUP).
+
   clock-frequency:
     description:
       Controls the SCK bit-bang timing. The value is used to derive the
-- 
2.43.0


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

* [PATCH v9 03/11] dt-bindings: iio: adc: hx711: add RATE GPIO property
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 01/11] dt-bindings: iio: adc: hx711: clean up existing binding text Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 02/11] dt-bindings: iio: adc: hx711: add VSUP supply property Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support Piyush Patle
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Document the optional RATE pin GPIO used to select the HX711 output
data rate.

Update the example to show the property in use.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
No change from v8. Already applied to iio.git testing branch.
 Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index a8eaa1f18de5..9134bbe41379 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -37,6 +37,13 @@ properties:
     description:
       Supply voltage for the on-chip regulator (VSUP).
 
+  rate-gpios:
+    description:
+      GPIO connected to the RATE pin. When driven low the output data
+      rate is 10 SPS; when driven high it is 80 SPS. If omitted the
+      RATE pin state is determined by the board wiring.
+    maxItems: 1
+
   clock-frequency:
     description:
       Controls the SCK bit-bang timing. The value is used to derive the
@@ -61,6 +68,7 @@ examples:
         compatible = "avia,hx711";
         sck-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
         dout-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+        rate-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
         avdd-supply = <&avdd>;
         clock-frequency = <100000>;
     };
-- 
2.43.0


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

* [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (2 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 03/11] dt-bindings: iio: adc: hx711: add RATE GPIO property Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:10   ` sashiko-bot
  2026-05-18 22:02 ` [PATCH v9 05/11] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Add the avia,hx710b compatible and document the HX710B-specific
DVDD and VREF supplies.

Add constraints that forbid HX711-only properties on HX710B nodes and
require vref-supply for HX710B, then add a separate HX710B example.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Changes from v8:
  - Dropped the trailing sentence "Keep the existing HX711-only binding
    extensions in earlier patches so this change is limited to the new
    variant." from the commit message.  The earlier patches in this
    series extend the shared top-level binding (VSUP, RATE GPIO, etc.)
    which are valid for both chips; there are no HX711-only binding
    extensions kept separate from this patch.

 .../bindings/iio/adc/avia-hx711.yaml          | 42 ++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index 9134bbe41379..b2b5c7bdf05e 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/iio/adc/avia-hx711.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: AVIA HX711 ADC chip for weight cells
+title: AVIA HX711 and HX710B ADCs
 
 maintainers:
   - Andreas Klinger <ak@it-klinger.de>
@@ -14,9 +14,14 @@ description: |
   differential input channels. Channel A supports gain 64 and 128;
   channel B supports gain 32.
 
+  The HX710B is a 24-bit ADC with fixed gain of 128. One input measures
+  the differential voltage between the two input pins; a second measures
+  the DVDD-AVDD supply voltage difference for battery level detection.
+
 properties:
   compatible:
     enum:
+      - avia,hx710b
       - avia,hx711
 
   sck-gpios:
@@ -44,6 +49,17 @@ properties:
       RATE pin state is determined by the board wiring.
     maxItems: 1
 
+  dvdd-supply:
+    description:
+      Digital supply voltage (DVDD). For the HX710B, DVDD must be
+      greater than or equal to AVDD. When DVDD is a battery rail and
+      AVDD is a regulated supply, one channel monitors the DVDD-AVDD
+      difference for battery level detection.
+
+  vref-supply:
+    description:
+      Reference voltage input (VREF).
+
   clock-frequency:
     description:
       Controls the SCK bit-bang timing. The value is used to derive the
@@ -53,6 +69,21 @@ properties:
     maximum: 2500000
     default: 400000
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          const: avia,hx710b
+    then:
+      properties:
+        vsup-supply: false
+        rate-gpios: false
+      required:
+        - vref-supply
+    else:
+      properties:
+        vref-supply: false
+
 required:
   - compatible
   - sck-gpios
@@ -72,3 +103,12 @@ examples:
         avdd-supply = <&avdd>;
         clock-frequency = <100000>;
     };
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    weight {
+        compatible = "avia,hx710b";
+        sck-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
+        dout-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+        avdd-supply = <&avdd>;
+        vref-supply = <&vref>;
+    };
-- 
2.43.0


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

* [PATCH v9 05/11] iio: adc: hx711: move scale computation to per-device storage
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (3 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure Piyush Patle
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

The gain-to-scale table is global today, so probe-time scale updates for
one device overwrite the values used by any earlier device instance.

Fix this by making the gain table const and storing the computed scale
values per device in hx711_data.

No functional change for single-sensor configurations.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No change from v8. Already applied to iio.git testing branch.
 drivers/iio/adc/hx711.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 1db8b68a8f64..86d2a70dd3de 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -28,22 +28,20 @@
 struct hx711_gain_to_scale {
 	int			gain;
 	int			gain_pulse;
-	int			scale;
 	int			channel;
 };
 
 /*
  * .scale depends on AVDD which in turn is known as soon as the regulator
- * is available
- * therefore we set .scale in hx711_probe()
+ * is available; it is stored per device in hx711_data.gain_scale[]
  *
  * channel A in documentation is channel 0 in source code
  * channel B in documentation is channel 1 in source code
  */
-static struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
-	{ 128, 1, 0, 0 },
-	{  32, 2, 0, 1 },
-	{  64, 3, 0, 0 }
+static const struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
+	{ 128, 1, 0 },
+	{  32, 2, 1 },
+	{  64, 3, 0 },
 };
 
 static int hx711_get_gain_to_pulse(int gain)
@@ -56,22 +54,22 @@ static int hx711_get_gain_to_pulse(int gain)
 	return 1;
 }
 
-static int hx711_get_gain_to_scale(int gain)
+static int hx711_get_gain_to_scale(const int *gain_scale, int gain)
 {
 	int i;
 
 	for (i = 0; i < HX711_GAIN_MAX; i++)
 		if (hx711_gain_to_scale[i].gain == gain)
-			return hx711_gain_to_scale[i].scale;
+			return gain_scale[i];
 	return 0;
 }
 
-static int hx711_get_scale_to_gain(int scale)
+static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
 {
 	int i;
 
 	for (i = 0; i < HX711_GAIN_MAX; i++)
-		if (hx711_gain_to_scale[i].scale == scale)
+		if (gain_scale[i] == scale)
 			return hx711_gain_to_scale[i].gain;
 	return -EINVAL;
 }
@@ -82,6 +80,7 @@ struct hx711_data {
 	struct gpio_desc	*gpiod_dout;
 	int			gain_set;	/* gain set on device */
 	int			gain_chan_a;	/* gain for channel A */
+	int			gain_scale[HX711_GAIN_MAX];
 	struct mutex		lock;
 	/*
 	 * triggered buffer
@@ -290,7 +289,8 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
 		*val = 0;
 		mutex_lock(&hx711_data->lock);
 
-		*val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
+		*val2 = hx711_get_gain_to_scale(hx711_data->gain_scale,
+						hx711_data->gain_set);
 
 		mutex_unlock(&hx711_data->lock);
 
@@ -321,7 +321,7 @@ static int hx711_write_raw(struct iio_dev *indio_dev,
 
 		mutex_lock(&hx711_data->lock);
 
-		gain = hx711_get_scale_to_gain(val2);
+		gain = hx711_get_scale_to_gain(hx711_data->gain_scale, val2);
 		if (gain < 0) {
 			mutex_unlock(&hx711_data->lock);
 			return gain;
@@ -386,6 +386,7 @@ static ssize_t hx711_scale_available_show(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
 {
+	struct hx711_data *hx711_data = iio_priv(dev_to_iio_dev(dev));
 	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
 	int channel = iio_attr->address;
 	int i, len = 0;
@@ -393,7 +394,7 @@ static ssize_t hx711_scale_available_show(struct device *dev,
 	for (i = 0; i < HX711_GAIN_MAX; i++)
 		if (hx711_gain_to_scale[i].channel == channel)
 			len += sprintf(buf + len, "0.%09d ",
-					hx711_gain_to_scale[i].scale);
+				       hx711_data->gain_scale[i]);
 
 	len += sprintf(buf + len, "\n");
 
@@ -511,7 +512,7 @@ static int hx711_probe(struct platform_device *pdev)
 	ret *= 100;
 
 	for (i = 0; i < HX711_GAIN_MAX; i++)
-		hx711_gain_to_scale[i].scale =
+		hx711_data->gain_scale[i] =
 			ret / hx711_gain_to_scale[i].gain / 1678;
 
 	hx711_data->gain_set = 128;
-- 
2.43.0


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

* [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (4 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 05/11] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:30   ` sashiko-bot
  2026-05-18 22:02 ` [PATCH v9 07/11] iio: adc: hx711: pass trailing pulse count into hx711_read Piyush Patle
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Add a per-variant static configuration structure and populate the IIO
device fields from it at probe time.

This is a preparatory change for adding support for more HX711-compatible
hardware variants without duplicating the probe-time setup.

No functional change for existing HX711 users.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No code change from v8.

Regarding the __counted_by_ptr() annotation on hx711_chip_info.channels:
this annotation was introduced in include/linux/compiler_types.h in
commit 4b8a2e8e09be ("compiler_types.h: Add __counted_by_ptr()") which
landed in 6.12-rc1.  This tree is 6.17, so the macro is
well-defined.  Jonathan Cameron requested this annotation in his v7
review; Sashiko's v8 bot flag was a false positive.

Regarding the legacy platform_device probe path: the concern that
probe could succeed without chip_info (returning a useless device) was
acknowledged.  Jonathan has indicated the current device_get_match_data()
guard is acceptable, so no change was made.

 drivers/iio/adc/hx711.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 86d2a70dd3de..10ccc69f209b 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -4,6 +4,8 @@
  *
  * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
  */
+#include <linux/array_size.h>
+#include <linux/dev_printk.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -74,6 +76,20 @@ static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
 	return -EINVAL;
 }
 
+/**
+ * struct hx711_chip_info - per-variant static configuration
+ * @name: IIO device name
+ * @channels: channel specification array
+ * @num_channels: number of entries in @channels
+ * @iio_info: IIO info ops for this variant
+ */
+struct hx711_chip_info {
+	const char			*name;
+	const struct iio_chan_spec	*channels __counted_by_ptr(num_channels);
+	unsigned int			num_channels;
+	const struct iio_info		*iio_info;
+};
+
 struct hx711_data {
 	struct device		*dev;
 	struct gpio_desc	*gpiod_pd_sck;
@@ -81,6 +97,7 @@ struct hx711_data {
 	int			gain_set;	/* gain set on device */
 	int			gain_chan_a;	/* gain for channel A */
 	int			gain_scale[HX711_GAIN_MAX];
+	const struct hx711_chip_info	*chip_info;
 	struct mutex		lock;
 	/*
 	 * triggered buffer
@@ -456,8 +473,16 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
+static const struct hx711_chip_info hx711_chip = {
+	.name		= "hx711",
+	.channels	= hx711_chan_spec,
+	.iio_info	= &hx711_iio_info,
+	.num_channels	= ARRAY_SIZE(hx711_chan_spec),
+};
+
 static int hx711_probe(struct platform_device *pdev)
 {
+	const struct hx711_chip_info *chip_info;
 	struct device *dev = &pdev->dev;
 	struct hx711_data *hx711_data;
 	struct iio_dev *indio_dev;
@@ -473,6 +498,12 @@ static int hx711_probe(struct platform_device *pdev)
 
 	mutex_init(&hx711_data->lock);
 
+	chip_info = device_get_match_data(dev);
+	if (!chip_info)
+		return dev_err_probe(dev, -ENODEV, "missing driver data\n");
+
+	hx711_data->chip_info = chip_info;
+
 	/*
 	 * PD_SCK stands for power down and serial clock input of HX711
 	 * in the driver it is an output
@@ -534,11 +565,11 @@ static int hx711_probe(struct platform_device *pdev)
 	hx711_data->data_ready_delay_ns =
 				1000000000 / hx711_data->clock_frequency;
 
-	indio_dev->name = "hx711";
-	indio_dev->info = &hx711_iio_info;
+	indio_dev->name = chip_info->name;
+	indio_dev->info = chip_info->iio_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = hx711_chan_spec;
-	indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
+	indio_dev->channels = chip_info->channels;
+	indio_dev->num_channels = chip_info->num_channels;
 
 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
 					      iio_pollfunc_store_time,
@@ -555,7 +586,7 @@ static int hx711_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id of_hx711_match[] = {
-	{ .compatible = "avia,hx711", },
+	{ .compatible = "avia,hx711", .data = &hx711_chip },
 	{ }
 };
 
-- 
2.43.0


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

* [PATCH v9 07/11] iio: adc: hx711: pass trailing pulse count into hx711_read
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (5 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 08/11] iio: adc: hx711: split variable assignments in hx711_read and hx711_reset Piyush Patle
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Move the trailing-pulse selection out of hx711_read() and into its
callers.

This is a preparatory change so later variant-specific code can pass the
per-channel pulse count without adding a separate read path.

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No change from v8.
 drivers/iio/adc/hx711.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 10ccc69f209b..30e1ce321747 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -155,7 +155,7 @@ static int hx711_cycle(struct hx711_data *hx711_data)
 	return gpiod_get_value(hx711_data->gpiod_dout);
 }
 
-static int hx711_read(struct hx711_data *hx711_data)
+static int hx711_read(struct hx711_data *hx711_data, int trailing_pulses)
 {
 	int i, ret;
 	int value = 0;
@@ -174,7 +174,7 @@ static int hx711_read(struct hx711_data *hx711_data)
 
 	value ^= 0x800000;
 
-	for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
+	for (i = 0; i < trailing_pulses; i++)
 		hx711_cycle(hx711_data);
 
 	return value;
@@ -237,7 +237,8 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
 		if (hx711_data->gain_set == 32) {
 			hx711_data->gain_set = hx711_data->gain_chan_a;
 
-			ret = hx711_read(hx711_data);
+			ret = hx711_read(hx711_data,
+					 hx711_get_gain_to_pulse(hx711_data->gain_set));
 			if (ret < 0)
 				return ret;
 
@@ -249,7 +250,8 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
 		if (hx711_data->gain_set != 32) {
 			hx711_data->gain_set = 32;
 
-			ret = hx711_read(hx711_data);
+			ret = hx711_read(hx711_data,
+					 hx711_get_gain_to_pulse(hx711_data->gain_set));
 			if (ret < 0)
 				return ret;
 
@@ -264,8 +266,8 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
 
 static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
 {
+	int trailing_pulses;
 	int ret;
-	int val;
 
 	/*
 	 * hx711_reset() must be called from here
@@ -280,9 +282,8 @@ static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
 	if (ret < 0)
 		return ret;
 
-	val = hx711_read(hx711_data);
-
-	return val;
+	trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
+	return hx711_read(hx711_data, trailing_pulses);
 }
 
 static int hx711_read_raw(struct iio_dev *indio_dev,
@@ -349,7 +350,8 @@ static int hx711_write_raw(struct iio_dev *indio_dev,
 			if (gain != 32)
 				hx711_data->gain_chan_a = gain;
 
-			ret = hx711_read(hx711_data);
+			ret = hx711_read(hx711_data,
+					 hx711_get_gain_to_pulse(hx711_data->gain_set));
 			if (ret < 0) {
 				mutex_unlock(&hx711_data->lock);
 				return ret;
-- 
2.43.0


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

* [PATCH v9 08/11] iio: adc: hx711: split variable assignments in hx711_read and hx711_reset
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (6 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 07/11] iio: adc: hx711: pass trailing pulse count into hx711_read Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 09/11] iio: adc: hx711: localize loop iterators in hx711_read Piyush Patle
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Separate the initial value assignments from the declarations in
hx711_read() and hx711_reset().

This is a small preparatory cleanup before the later loop-iterator and
variant-specific changes adjust the local variable layout in these
functions.

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No change from v8.
 drivers/iio/adc/hx711.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 30e1ce321747..9e5cafa1e307 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -159,9 +159,10 @@ static int hx711_read(struct hx711_data *hx711_data, int trailing_pulses)
 {
 	int i, ret;
 	int value = 0;
-	int val = gpiod_get_value(hx711_data->gpiod_dout);
+	int val;
 
 	/* we double check if it's really down */
+	val = gpiod_get_value(hx711_data->gpiod_dout);
 	if (val)
 		return -EIO;
 
@@ -204,7 +205,9 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data)
 
 static int hx711_reset(struct hx711_data *hx711_data)
 {
-	int val = hx711_wait_for_ready(hx711_data);
+	int val;
+
+	val = hx711_wait_for_ready(hx711_data);
 
 	if (val) {
 		/*
-- 
2.43.0


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

* [PATCH v9 09/11] iio: adc: hx711: localize loop iterators in hx711_read
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (7 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 08/11] iio: adc: hx711: split variable assignments in hx711_read and hx711_reset Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read Piyush Patle
  2026-05-18 22:02 ` [PATCH v9 11/11] iio: adc: hx711: add support for HX710B Piyush Patle
  10 siblings, 0 replies; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Tighten the scope of the loop variables in hx711_read() now that
trailing-pulse selection is already handled by the callers.

Also replace the 24-bit loop bound with a named constant while touching
the same code.

Suggested-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No change from v8.
 drivers/iio/adc/hx711.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 9e5cafa1e307..0db2d2db9242 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -23,6 +23,8 @@
 #include <linux/gpio/consumer.h>
 #include <linux/regulator/consumer.h>
 
+#define HX711_DATA_BITS		24
+
 /* gain to pulse and scale conversion */
 #define HX711_GAIN_MAX		3
 #define HX711_RESET_GAIN	128
@@ -157,16 +159,16 @@ static int hx711_cycle(struct hx711_data *hx711_data)
 
 static int hx711_read(struct hx711_data *hx711_data, int trailing_pulses)
 {
-	int i, ret;
 	int value = 0;
 	int val;
+	int ret;
 
 	/* we double check if it's really down */
 	val = gpiod_get_value(hx711_data->gpiod_dout);
 	if (val)
 		return -EIO;
 
-	for (i = 0; i < 24; i++) {
+	for (int i = 0; i < HX711_DATA_BITS; i++) {
 		value <<= 1;
 		ret = hx711_cycle(hx711_data);
 		if (ret)
@@ -175,7 +177,7 @@ static int hx711_read(struct hx711_data *hx711_data, int trailing_pulses)
 
 	value ^= 0x800000;
 
-	for (i = 0; i < trailing_pulses; i++)
+	for (int i = 0; i < trailing_pulses; i++)
 		hx711_cycle(hx711_data);
 
 	return value;
-- 
2.43.0


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

* [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (8 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 09/11] iio: adc: hx711: localize loop iterators in hx711_read Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:41   ` sashiko-bot
  2026-05-18 22:02 ` [PATCH v9 11/11] iio: adc: hx711: add support for HX710B Piyush Patle
  10 siblings, 1 reply; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Change hx711_reset_read() to accept the channel descriptor directly and
update its callers accordingly.

Split the existing HX711 channel-selection work into a small helper so a
later variant-specific change can add a matching helper without growing
hx711_reset_read() further.

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
No change from v8.
 drivers/iio/adc/hx711.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 0db2d2db9242..183568196d52 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -269,7 +269,23 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
 	return 0;
 }
 
-static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
+static int hx711_set_hx711_channel(struct hx711_data *hx711_data,
+				   const struct iio_chan_spec *chan,
+				   int *trailing_pulses)
+{
+	int ret;
+
+	ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
+	if (ret < 0)
+		return ret;
+
+	*trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
+
+	return 0;
+}
+
+static int hx711_reset_read(struct hx711_data *hx711_data,
+			    const struct iio_chan_spec *chan)
 {
 	int trailing_pulses;
 	int ret;
@@ -283,11 +299,10 @@ static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
 		return -EIO;
 	}
 
-	ret = hx711_set_gain_for_channel(hx711_data, chan);
+	ret = hx711_set_hx711_channel(hx711_data, chan, &trailing_pulses);
 	if (ret < 0)
 		return ret;
 
-	trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
 	return hx711_read(hx711_data, trailing_pulses);
 }
 
@@ -301,7 +316,7 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&hx711_data->lock);
 
-		*val = hx711_reset_read(hx711_data, chan->channel);
+		*val = hx711_reset_read(hx711_data, chan);
 
 		mutex_unlock(&hx711_data->lock);
 
@@ -391,8 +406,8 @@ static irqreturn_t hx711_trigger(int irq, void *p)
 	memset(&hx711_data->buffer, 0, sizeof(hx711_data->buffer));
 
 	iio_for_each_active_channel(indio_dev, i) {
-		hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data,
-					indio_dev->channels[i].channel);
+		hx711_data->buffer.channel[j] =
+			hx711_reset_read(hx711_data, &indio_dev->channels[i]);
 		j++;
 	}
 
-- 
2.43.0


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

* [PATCH v9 11/11] iio: adc: hx711: add support for HX710B
  2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
                   ` (9 preceding siblings ...)
  2026-05-18 22:02 ` [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read Piyush Patle
@ 2026-05-18 22:02 ` Piyush Patle
  2026-05-18 22:39   ` sashiko-bot
  10 siblings, 1 reply; 17+ messages in thread
From: Piyush Patle @ 2026-05-18 22:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, devicetree, linux-kernel, Andreas Klinger,
	Andy Shevchenko, Conor Dooley, Krzysztof Kozlowski, Rob Herring

Add support for the AVIA HX710B ADC, which shares the HX711 GPIO
interface but uses trailing PD_SCK pulses to select the active mode.

Model the HX710B with variant-specific channel tables and IIO info,
track the active channel across conversions, and use the fixed gain
value when computing scale.

Also update the adjacent Kconfig text, file header, and module
description so the driver text matches the newly supported variant.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
Changes from v8:

Channel layout redesign (Jonathan Cameron):
  HX710B modes 1 and 3 both read the same physical differential input
  (only the sample rate differs: 10 vs 40 SPS).  Exposing them as two
  separate IIO channels was incorrect.  They are now collapsed into a
  single channel (in_voltage0-voltage1) with IIO_CHAN_INFO_SAMP_FREQ;
  userspace reads/writes sampling_frequency to select 10 or 40 SPS.
  The hx710b_write_raw() and hx710b_read_avail() callbacks are added
  to hx710b_iio_info to support this.

  The channel spec no longer uses .address to carry the trailing pulse
  count.  A new hx710b_trailing_pulses() helper derives the count from
  hx711_data.samp_freq (1 for 10 SPS, 3 for 40 SPS) and the channel
  type (2 for the supply monitor, which is always 40 SPS).

  The IIO_DECLARE_BUFFER_WITH_TS() slot count is reduced from 3 to 2
  to reflect that both HX711 and HX710B now have at most 2 physical
  channels.

channel_set ordering fix (Sashiko Suzuki):
  hx711_set_hx710b_channel() previously updated channel_set after
  hx711_wait_for_ready(), meaning a timeout would leave the field out
  of sync with the hardware.  The hardware mode is committed once
  hx711_read() sends the trailing pulses, so channel_set is now
  updated immediately after hx711_read() returns successfully, before
  the ready-wait.

Trigger error handling (Jonathan Cameron):
  hx711_trigger() was silently casting negative error codes from
  hx711_reset_read() to u32 and pushing them to the buffer.  The
  handler now checks the return value, logs the error with
  dev_err_ratelimited(), and skips the push via goto out_unlock.

 drivers/iio/adc/Kconfig |   8 +-
 drivers/iio/adc/hx711.c | 240 ++++++++++++++++++++++++++++++++++------
 2 files changed, 212 insertions(+), 36 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a9dedbb8eb46..38ba8cae13f1 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -791,13 +791,15 @@ config HI8435
 	  called hi8435.
 
 config HX711
-	tristate "AVIA HX711 ADC for weight cells"
+	tristate "AVIA HX711 and compatible ADCs"
 	depends on GPIOLIB
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
-	  If you say yes here you get support for AVIA HX711 ADC which is used
-	  for weigh cells
+	  If you say Y here you get support for the following AVIA ADCs:
+	    - HX710B
+	    - HX711
+	  which are used for bridge sensors such as weigh cells.
 
 	  This driver uses two GPIOs, one acts as the clock and controls the
 	  channel selection and gain, the other one is used for the measurement
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 183568196d52..d5c977b4669b 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * HX711: analog to digital converter for weight sensor module
+ * HX711 and compatible ADCs driver for weigh sensor modules
  *
  * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
  */
@@ -15,6 +15,8 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/types.h>
+
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
@@ -84,12 +86,16 @@ static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
  * @channels: channel specification array
  * @num_channels: number of entries in @channels
  * @iio_info: IIO info ops for this variant
+ * @fixed_gain_val: fixed PGA gain (used when @has_fixed_gain is true)
+ * @has_fixed_gain: true if the variant has a fixed ADC gain
  */
 struct hx711_chip_info {
 	const char			*name;
 	const struct iio_chan_spec	*channels __counted_by_ptr(num_channels);
 	unsigned int			num_channels;
 	const struct iio_info		*iio_info;
+	unsigned int			fixed_gain_val;
+	bool				has_fixed_gain;
 };
 
 struct hx711_data {
@@ -99,16 +105,12 @@ struct hx711_data {
 	int			gain_set;	/* gain set on device */
 	int			gain_chan_a;	/* gain for channel A */
 	int			gain_scale[HX711_GAIN_MAX];
+	int			channel_set;	/* HX710B active channel */
+	unsigned int		samp_freq;	/* HX710B differential channel sample rate */
 	const struct hx711_chip_info	*chip_info;
 	struct mutex		lock;
-	/*
-	 * triggered buffer
-	 * 2x32-bit channel + 64-bit naturally aligned timestamp
-	 */
-	struct {
-		u32 channel[2];
-		aligned_s64 timestamp;
-	} buffer;
+	/* 2x32-bit channels + 64-bit naturally aligned timestamp */
+	IIO_DECLARE_BUFFER_WITH_TS(u32, buffer, 2);
 	/*
 	 * delay after a rising edge on SCK until the data is ready DOUT
 	 * this is dependent on the hx711 where the datasheet tells a
@@ -207,6 +209,7 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data)
 
 static int hx711_reset(struct hx711_data *hx711_data)
 {
+	const struct hx711_chip_info *info = hx711_data->chip_info;
 	int val;
 
 	val = hx711_wait_for_ready(hx711_data);
@@ -227,8 +230,11 @@ static int hx711_reset(struct hx711_data *hx711_data)
 
 		val = hx711_wait_for_ready(hx711_data);
 
-		/* after a reset the gain is 128 */
-		hx711_data->gain_set = HX711_RESET_GAIN;
+		if (info->has_fixed_gain)
+			hx711_data->channel_set = 0;
+		else
+			/* after a reset the gain is 128 */
+			hx711_data->gain_set = HX711_RESET_GAIN;
 	}
 
 	return val;
@@ -284,9 +290,51 @@ static int hx711_set_hx711_channel(struct hx711_data *hx711_data,
 	return 0;
 }
 
+/*
+ * Return the trailing pulse count for an HX710B channel (Table 3 in
+ * the datasheet).  The supply-monitor channel always uses 2 trailing
+ * pulses; the differential channel uses 1 (10 SPS) or 3 (40 SPS).
+ */
+static int hx710b_trailing_pulses(const struct hx711_data *hx711_data,
+				  const struct iio_chan_spec *chan)
+{
+	if (!chan->differential)
+		return 2;
+	return hx711_data->samp_freq == 10 ? 1 : 3;
+}
+
+/*
+ * Switch the HX710B to the requested channel for the next conversion.
+ * channel_set tracks the trailing pulse count that was last sent to the
+ * chip; it is updated immediately after hx711_read() commits the new
+ * mode in hardware, before waiting for the chip to be ready again.
+ */
+static int hx711_set_hx710b_channel(struct hx711_data *hx711_data,
+				    const struct iio_chan_spec *chan)
+{
+	int trailing_pulses = hx710b_trailing_pulses(hx711_data, chan);
+	int ret;
+
+	if (hx711_data->channel_set == trailing_pulses)
+		return 0;
+
+	ret = hx711_read(hx711_data, trailing_pulses);
+	if (ret < 0)
+		return ret;
+
+	hx711_data->channel_set = trailing_pulses;
+
+	ret = hx711_wait_for_ready(hx711_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int hx711_reset_read(struct hx711_data *hx711_data,
 			    const struct iio_chan_spec *chan)
 {
+	const struct hx711_chip_info *info = hx711_data->chip_info;
 	int trailing_pulses;
 	int ret;
 
@@ -299,9 +347,16 @@ static int hx711_reset_read(struct hx711_data *hx711_data,
 		return -EIO;
 	}
 
-	ret = hx711_set_hx711_channel(hx711_data, chan, &trailing_pulses);
-	if (ret < 0)
-		return ret;
+	if (info->has_fixed_gain) {
+		ret = hx711_set_hx710b_channel(hx711_data, chan);
+		if (ret < 0)
+			return ret;
+		trailing_pulses = hx710b_trailing_pulses(hx711_data, chan);
+	} else {
+		ret = hx711_set_hx711_channel(hx711_data, chan, &trailing_pulses);
+		if (ret < 0)
+			return ret;
+	}
 
 	return hx711_read(hx711_data, trailing_pulses);
 }
@@ -323,6 +378,9 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
 		if (*val < 0)
 			return *val;
 		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = hx711_data->samp_freq;
+		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		*val = 0;
 		mutex_lock(&hx711_data->lock);
@@ -400,20 +458,26 @@ static irqreturn_t hx711_trigger(int irq, void *p)
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct hx711_data *hx711_data = iio_priv(indio_dev);
 	int i, j = 0;
+	int ret;
 
 	mutex_lock(&hx711_data->lock);
 
-	memset(&hx711_data->buffer, 0, sizeof(hx711_data->buffer));
+	memset(hx711_data->buffer, 0, sizeof(hx711_data->buffer));
 
 	iio_for_each_active_channel(indio_dev, i) {
-		hx711_data->buffer.channel[j] =
-			hx711_reset_read(hx711_data, &indio_dev->channels[i]);
-		j++;
+		ret = hx711_reset_read(hx711_data, &indio_dev->channels[i]);
+		if (ret < 0) {
+			dev_err_ratelimited(hx711_data->dev,
+					    "read failed: %d\n", ret);
+			goto out_unlock;
+		}
+		hx711_data->buffer[j++] = ret;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, &hx711_data->buffer,
-							pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, hx711_data->buffer,
+					   pf->timestamp);
 
+out_unlock:
 	mutex_unlock(&hx711_data->lock);
 
 	iio_trigger_notify_done(indio_dev->trig);
@@ -463,6 +527,50 @@ static const struct iio_info hx711_iio_info = {
 	.attrs			= &hx711_attribute_group,
 };
 
+static const int hx710b_samp_freq_avail[] = { 10, 40 };
+
+static int hx710b_read_avail(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     const int **vals, int *type, int *length,
+			     long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*vals = hx710b_samp_freq_avail;
+		*type = IIO_VAL_INT;
+		*length = ARRAY_SIZE(hx710b_samp_freq_avail);
+		return IIO_AVAIL_LIST;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hx710b_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct hx711_data *hx711_data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val != 10 && val != 40)
+			return -EINVAL;
+		mutex_lock(&hx711_data->lock);
+		hx711_data->samp_freq = val;
+		hx711_data->channel_set = 0;
+		mutex_unlock(&hx711_data->lock);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info hx710b_iio_info = {
+	.read_raw		= hx711_read_raw,
+	.write_raw		= hx710b_write_raw,
+	.read_avail		= hx710b_read_avail,
+};
+
 static const struct iio_chan_spec hx711_chan_spec[] = {
 	{
 		.type = IIO_VOLTAGE,
@@ -495,6 +603,51 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
+/*
+ * HX710B channels (Table 3 in datasheet).
+ * 25 pulses (1 trailing): differential input, 10 SPS
+ * 26 pulses (2 trailing): DVDD-AVDD supply monitor, 40 SPS
+ * 27 pulses (3 trailing): differential input, 40 SPS
+ * Channel 0 exposes both differential rates via IIO_CHAN_INFO_SAMP_FREQ.
+ * Channel 2 is used for the supply monitor to avoid aliasing the
+ * channel2 terminal of the differential pair.
+ */
+static const struct iio_chan_spec hx710b_chan_spec[] = {
+	{
+		.type = IIO_VOLTAGE,
+		.differential = 1,
+		.channel = 0,
+		.channel2 = 1,
+		.indexed = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.storagebits = 32,
+			.endianness = IIO_CPU,
+		},
+	},
+	{
+		.type = IIO_VOLTAGE,
+		.channel = 2,
+		.indexed = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.storagebits = 32,
+			.endianness = IIO_CPU,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
 static const struct hx711_chip_info hx711_chip = {
 	.name		= "hx711",
 	.channels	= hx711_chan_spec,
@@ -502,6 +655,15 @@ static const struct hx711_chip_info hx711_chip = {
 	.num_channels	= ARRAY_SIZE(hx711_chan_spec),
 };
 
+static const struct hx711_chip_info hx710b_chip = {
+	.name		= "hx710b",
+	.channels	= hx710b_chan_spec,
+	.iio_info	= &hx710b_iio_info,
+	.num_channels	= ARRAY_SIZE(hx710b_chan_spec),
+	.fixed_gain_val	= 128,
+	.has_fixed_gain	= true,
+};
+
 static int hx711_probe(struct platform_device *pdev)
 {
 	const struct hx711_chip_info *chip_info;
@@ -544,32 +706,43 @@ static int hx711_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(hx711_data->gpiod_dout),
 				     "failed to get dout-gpiod\n");
 
-	ret = devm_regulator_get_enable_read_voltage(dev, "avdd");
+	if (chip_info->has_fixed_gain)
+		ret = devm_regulator_get_enable_read_voltage(dev, "vref");
+	else
+		ret = devm_regulator_get_enable_read_voltage(dev, "avdd");
 	if (ret < 0)
 		return ret;
 
 	/*
-	 * with
-	 * full scale differential input range: AVDD / GAIN
+	 * With
+	 * full scale differential input range: reference / GAIN
 	 * full scale output data: 2^24
 	 * we can say:
-	 *     AVDD / GAIN = 2^24
+	 *     reference / GAIN = 2^24
 	 * therefore:
-	 *     1 LSB = AVDD / GAIN / 2^24
-	 * AVDD is in uV, but we need 10^-9 mV
+	 *     1 LSB = reference / GAIN / 2^24
+	 * reference is in uV, but we need 10^-9 mV
 	 * approximately to fit into a 32 bit number:
-	 * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
+	 * 1 LSB = (reference * 100) / GAIN / 1678 [10^-9 mV]
 	 */
 
 	/* we need 10^-9 mV */
 	ret *= 100;
 
-	for (i = 0; i < HX711_GAIN_MAX; i++)
-		hx711_data->gain_scale[i] =
-			ret / hx711_gain_to_scale[i].gain / 1678;
+	if (chip_info->has_fixed_gain) {
+		for (i = 0; i < HX711_GAIN_MAX; i++)
+			hx711_data->gain_scale[i] =
+				ret / chip_info->fixed_gain_val / 1678;
+		hx711_data->gain_set = chip_info->fixed_gain_val;
+		hx711_data->samp_freq = 10;
+	} else {
+		for (i = 0; i < HX711_GAIN_MAX; i++)
+			hx711_data->gain_scale[i] =
+				ret / hx711_gain_to_scale[i].gain / 1678;
 
-	hx711_data->gain_set = 128;
-	hx711_data->gain_chan_a = 128;
+		hx711_data->gain_set = 128;
+		hx711_data->gain_chan_a = 128;
+	}
 
 	hx711_data->clock_frequency = 400000;
 	ret = device_property_read_u32(&pdev->dev, "clock-frequency",
@@ -608,6 +781,7 @@ static int hx711_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id of_hx711_match[] = {
+	{ .compatible = "avia,hx710b", .data = &hx710b_chip },
 	{ .compatible = "avia,hx711", .data = &hx711_chip },
 	{ }
 };
@@ -625,7 +799,7 @@ static struct platform_driver hx711_driver = {
 module_platform_driver(hx711_driver);
 
 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
-MODULE_DESCRIPTION("HX711 bitbanging driver - ADC for weight cells");
+MODULE_DESCRIPTION("HX711 and compatible bitbanging ADC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:hx711-gpio");
 
-- 
2.43.0


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

* Re: [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support
  2026-05-18 22:02 ` [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support Piyush Patle
@ 2026-05-18 22:10   ` sashiko-bot
  2026-05-19 17:21     ` Conor Dooley
  0 siblings, 1 reply; 17+ messages in thread
From: sashiko-bot @ 2026-05-18 22:10 UTC (permalink / raw)
  To: Piyush Patle; +Cc: robh, devicetree, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The newly added `dvdd-supply` property is described as HX710B-specific but is not forbidden on HX711 nodes in the schema.
--

commit e277e4c3f21226be9f52ecf29adbdc5f6f73f38d
Author: Piyush Patle <piyushpatle228@gmail.com>

dt-bindings: iio: adc: hx711: add HX710B support

This commit adds support for the HX710B ADC chip. It adds the avia,hx710b
compatible string, documents the HX710B-specific dvdd-supply and vref-supply
properties, and updates the schema constraints.

> diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> index 9134bbe413796..b2b5c7bdf05e6 100644
> --- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml

[ ... ]

> @@ -53,6 +69,21 @@ properties:
>      maximum: 2500000
>      default: 400000
>  
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          const: avia,hx710b
> +    then:
> +      properties:
> +        vsup-supply: false
> +        rate-gpios: false
> +      required:
> +        - vref-supply
> +    else:
> +      properties:
> +        vref-supply: false

The commit message mentions documenting the HX710B-specific DVDD and VREF
supplies. While vref-supply is explicitly forbidden on HX711 nodes in this
else branch, dvdd-supply is not.

Does this schema unintentionally allow the dvdd-supply property on avia,hx711
nodes? Should dvdd-supply: false also be added to this else branch?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260518220228.63322-1-piyushpatle228@gmail.com?part=4

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

* Re: [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure
  2026-05-18 22:02 ` [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure Piyush Patle
@ 2026-05-18 22:30   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-18 22:30 UTC (permalink / raw)
  To: Piyush Patle; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Driver probe unconditionally fails for legacy non-DT platform devices.
- [Low] Use of undeclared macro `__counted_by_ptr` causes a build failure.
--

commit e7a943897aef3be5de1d3c4561e37e20e131b7c5
Author: Piyush Patle <piyushpatle228@gmail.com>

iio: adc: hx711: introduce hx711_chip_info structure

Add a per-variant static configuration structure and populate the IIO
device fields from it at probe time.

> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> index 823fd74f9cf95..062d6860da7d6 100644
> --- a/drivers/iio/adc/hx711.c
> +++ b/drivers/iio/adc/hx711.c
[ ... ]
> @@ -74,6 +76,20 @@ static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
>  	return -EINVAL;
>  }
>  
> +/**
> + * struct hx711_chip_info - per-variant static configuration
> + * @name: IIO device name
> + * @channels: channel specification array
> + * @num_channels: number of entries in @channels
> + * @iio_info: IIO info ops for this variant
> + */
> +struct hx711_chip_info {
> +	const char			*name;
> +	const struct iio_chan_spec	*channels __counted_by_ptr(num_channels);

Does this cause a build failure? The __counted_by_ptr macro does not appear 
to be defined in the kernel headers, which will result in a syntax error 
during compilation.

> +	unsigned int			num_channels;
> +	const struct iio_info		*iio_info;
> +};
> +
[ ... ]
> @@ -473,6 +498,12 @@ static int hx711_probe(struct platform_device *pdev)
>  
>  	mutex_init(&hx711_data->lock);
>  
> +	chip_info = device_get_match_data(dev);
> +	if (!chip_info)
> +		return dev_err_probe(dev, -ENODEV, "missing driver data\n");

Does this cause a regression for legacy non-DT platform devices?

The device_get_match_data function relies on a firmware node being present. 
If a platform device is registered by name without a device tree or ACPI 
node, this will return NULL.

Since there is no fallback behavior or id_table provided for name-based 
matching, this now unconditionally fails the probe with -ENODEV, whereas 
previously the driver fell back to the default configuration.

> +
> +	hx711_data->chip_info = chip_info;
> +

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260518220228.63322-1-piyushpatle228@gmail.com?part=6

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

* Re: [PATCH v9 11/11] iio: adc: hx711: add support for HX710B
  2026-05-18 22:02 ` [PATCH v9 11/11] iio: adc: hx711: add support for HX710B Piyush Patle
@ 2026-05-18 22:39   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-18 22:39 UTC (permalink / raw)
  To: Piyush Patle; +Cc: conor+dt, devicetree, robh

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The trigger handler incorrectly performs physical ADC reads for the software timestamp channel.
- [Medium] Missing `iio_device_claim_direct_mode()` protection in the newly added `hx710b_write_raw()`.
- [Low] Data race on `samp_freq` when handling `IIO_CHAN_INFO_SAMP_FREQ` reads.
--

commit 63c1473f6788341d410e6d9c03f632bdcaeaf6df
Author: Piyush Patle <piyushpatle228@gmail.com>

iio: adc: hx711: add support for HX710B

This commit adds support for the AVIA HX710B ADC to the existing hx711
driver. It handles the different trailing pulse requirements and fixed
gain scaling, while exposing both 10 and 40 SPS sample rates.

> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> index 8ec4dee1f451e..20ea667af7254 100644
> --- a/drivers/iio/adc/hx711.c
> +++ b/drivers/iio/adc/hx711.c
[ ... ]
> @@ -323,6 +378,9 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
>  		if (*val < 0)
>  			return *val;
>  		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		*val = hx711_data->samp_freq;
> +		return IIO_VAL_INT;

Is there a potential data race here? 

In hx710b_write_raw(), hx711_data->samp_freq is updated while holding
hx711_data->lock. Should this read also be protected by the same mutex to
ensure state consistency?

[ ... ]
> @@ -400,20 +458,26 @@ static irqreturn_t hx711_trigger(int irq, void *p)
>  	struct iio_dev *indio_dev = pf->indio_dev;
>  	struct hx711_data *hx711_data = iio_priv(indio_dev);
>  	int i, j = 0;
> +	int ret;
>  
>  	mutex_lock(&hx711_data->lock);
>  
> -	memset(&hx711_data->buffer, 0, sizeof(hx711_data->buffer));
> +	memset(hx711_data->buffer, 0, sizeof(hx711_data->buffer));
>  
>  	iio_for_each_active_channel(indio_dev, i) {
> -		hx711_data->buffer.channel[j] =
> -			hx711_reset_read(hx711_data, &indio_dev->channels[i]);
> -		j++;
> +		ret = hx711_reset_read(hx711_data, &indio_dev->channels[i]);

Does this loop incorrectly perform a physical ADC read for the software
timestamp channel when userspace enables it?

When the timestamp channel is enabled, its bit is set in active_scan_mask.
The iio_for_each_active_channel() macro will iterate over it, causing
hx711_reset_read() to execute for the timestamp channel.

For the HX710B variant, chan->differential evaluates to 0 for the timestamp
channel, which causes hx710b_trailing_pulses() to return 2 trailing pulses,
performing an unintentional read over the supply monitor channel.

For the HX711 variant, the timestamp channel sets chan->channel = -1. 
hx711_set_gain_for_channel() then falls into the else branch (since -1 != 0),
changing the hardware to channel B and performing a dummy physical read.

In both cases, this forces the driver to wait for the ADC to settle on every
trigger event, which can severely impact the sampling rate. Should this loop
skip the timestamp channel (for example, by checking if the channel type is
IIO_TIMESTAMP)?

[ ... ]
> +static int hx710b_write_raw(struct iio_dev *indio_dev,
> +			    struct iio_chan_spec const *chan,
> +			    int val, int val2, long mask)
> +{
> +	struct hx711_data *hx711_data = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		if (val != 10 && val != 40)
> +			return -EINVAL;
> +		mutex_lock(&hx711_data->lock);
> +		hx711_data->samp_freq = val;
> +		hx711_data->channel_set = 0;
> +		mutex_unlock(&hx711_data->lock);
> +		return 0;

Does this implementation need to use iio_device_claim_direct_mode() to
prevent concurrent hardware changes while a buffered capture is active?

If userspace modifies the sampling frequency during an active IIO triggered
buffer capture, it resets channel_set to 0. This could alter the hardware
configuration (changing the trailing pulses) out from under the IIO capture
thread, which violates IIO concurrency semantics.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260518220228.63322-1-piyushpatle228@gmail.com?part=11

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

* Re: [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read
  2026-05-18 22:02 ` [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read Piyush Patle
@ 2026-05-18 22:41   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-18 22:41 UTC (permalink / raw)
  To: Piyush Patle; +Cc: robh, devicetree, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Triggering the buffer with the soft timestamp channel enabled causes a bogus physical hardware read, leading to severe latency spikes and sample rate degradation.
--

commit ca51c74e19ecc54987d0605c8007f8dcdc337783
Author: Piyush Patle <piyushpatle228@gmail.com>

iio: adc: hx711: pass iio_chan_spec to hx711_reset_read

Change hx711_reset_read() to accept the channel descriptor directly and
update its callers accordingly.

> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> index d7987c70beec2..8ec4dee1f451e 100644
> --- a/drivers/iio/adc/hx711.c
> +++ b/drivers/iio/adc/hx711.c
[ ... ]
> @@ -391,8 +406,8 @@ static irqreturn_t hx711_trigger(int irq, void *p)
>  	memset(&hx711_data->buffer, 0, sizeof(hx711_data->buffer));
>  
>  	iio_for_each_active_channel(indio_dev, i) {
> -		hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data,
> -					indio_dev->channels[i].channel);
> +		hx711_data->buffer.channel[j] =
> +			hx711_reset_read(hx711_data, &indio_dev->channels[i]);
>  		j++;
>  	}

Does this loop cause a bogus physical hardware read when the soft timestamp
channel is enabled?

Because iio_for_each_active_channel() iterates over all bits set in the
active_scan_mask, it includes the soft timestamp channel, passing it
directly into hx711_reset_read().

For the timestamp channel, chan->channel is -1. When passed down to
hx711_set_gain_for_channel(), any non-zero channel is treated as the
secondary physical channel (Channel B), forcing a hardware channel switch.

Since switching channels on the HX711 requires a dummy read and up to a 400ms
settling time handled in hx711_wait_for_ready(), toggling between Channel A
and the Timestamp channel on every trigger could introduce an ~800ms
blocking delay per sample.

Is it necessary to explicitly skip the timestamp channel during the hardware
read loop here, perhaps by checking chan->type != IIO_TIMESTAMP?

A related concern originally flagged an out-of-bounds array write to
buffer.channel[2] here, leading to a UBSAN panic. While that specific memory
safety issue is fixed later in the series by commit "iio: adc: hx711: add
support for HX710B" which safely bounds the buffer using
IIO_DECLARE_BUFFER_WITH_TS(), the underlying logic error of triggering a bogus
hardware read for the timestamp channel appears to remain unfixed.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260518220228.63322-1-piyushpatle228@gmail.com?part=10

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

* Re: [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support
  2026-05-18 22:10   ` sashiko-bot
@ 2026-05-19 17:21     ` Conor Dooley
  0 siblings, 0 replies; 17+ messages in thread
From: Conor Dooley @ 2026-05-19 17:21 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: Piyush Patle, robh, devicetree, conor+dt

[-- Attachment #1: Type: text/plain, Size: 1893 bytes --]

On Mon, May 18, 2026 at 10:10:54PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Low] The newly added `dvdd-supply` property is described as HX710B-specific but is not forbidden on HX711 nodes in the schema.
> --
> 
> commit e277e4c3f21226be9f52ecf29adbdc5f6f73f38d
> Author: Piyush Patle <piyushpatle228@gmail.com>
> 
> dt-bindings: iio: adc: hx711: add HX710B support
> 
> This commit adds support for the HX710B ADC chip. It adds the avia,hx710b
> compatible string, documents the HX710B-specific dvdd-supply and vref-supply
> properties, and updates the schema constraints.
> 
> > diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> > index 9134bbe413796..b2b5c7bdf05e6 100644
> > --- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> > +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> 
> [ ... ]
> 
> > @@ -53,6 +69,21 @@ properties:
> >      maximum: 2500000
> >      default: 400000
> >  
> > +allOf:
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          const: avia,hx710b
> > +    then:
> > +      properties:
> > +        vsup-supply: false
> > +        rate-gpios: false
> > +      required:
> > +        - vref-supply
> > +    else:
> > +      properties:
> > +        vref-supply: false
> 
> The commit message mentions documenting the HX710B-specific DVDD and VREF
> supplies. While vref-supply is explicitly forbidden on HX711 nodes in this
> else branch, dvdd-supply is not.
> 
> Does this schema unintentionally allow the dvdd-supply property on avia,hx711
> nodes? Should dvdd-supply: false also be added to this else branch?

No.

https://lore.kernel.org/all/20260512-frantic-finch-2b268bed4e15@spud/


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2026-05-19 17:21 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 22:02 [PATCH v9 00/11] iio: adc: Add support for AVIA HX710B ADC Piyush Patle
2026-05-18 22:02 ` [PATCH v9 01/11] dt-bindings: iio: adc: hx711: clean up existing binding text Piyush Patle
2026-05-18 22:02 ` [PATCH v9 02/11] dt-bindings: iio: adc: hx711: add VSUP supply property Piyush Patle
2026-05-18 22:02 ` [PATCH v9 03/11] dt-bindings: iio: adc: hx711: add RATE GPIO property Piyush Patle
2026-05-18 22:02 ` [PATCH v9 04/11] dt-bindings: iio: adc: hx711: add HX710B support Piyush Patle
2026-05-18 22:10   ` sashiko-bot
2026-05-19 17:21     ` Conor Dooley
2026-05-18 22:02 ` [PATCH v9 05/11] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
2026-05-18 22:02 ` [PATCH v9 06/11] iio: adc: hx711: introduce hx711_chip_info structure Piyush Patle
2026-05-18 22:30   ` sashiko-bot
2026-05-18 22:02 ` [PATCH v9 07/11] iio: adc: hx711: pass trailing pulse count into hx711_read Piyush Patle
2026-05-18 22:02 ` [PATCH v9 08/11] iio: adc: hx711: split variable assignments in hx711_read and hx711_reset Piyush Patle
2026-05-18 22:02 ` [PATCH v9 09/11] iio: adc: hx711: localize loop iterators in hx711_read Piyush Patle
2026-05-18 22:02 ` [PATCH v9 10/11] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read Piyush Patle
2026-05-18 22:41   ` sashiko-bot
2026-05-18 22:02 ` [PATCH v9 11/11] iio: adc: hx711: add support for HX710B Piyush Patle
2026-05-18 22:39   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox