public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] iio: adc: hx711: add HX710B support
@ 2026-04-27 10:09 Piyush Patle
  2026-04-27 10:09 ` [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
                   ` (6 more replies)
  0 siblings, 7 replies; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Add support for the HX710B ADC, a variant of the HX711 with the same
GPIO interface but a different channel and gain model.

The first patch updates the devicetree binding to add the
`avia,hx710b` compatible, document the variant-specific hardware
behaviour, and add chip-specific supply properties (avdd-supply,
dvdd-supply, vsup-supply, vref-supply), the RATE pin for the HX711, and
allOf constraints forbidding HX711-only properties on HX710B nodes and
vice versa.

The second patch fixes a pre-existing bug: hx711_gain_to_scale[].scale
is a global array overwritten on each probe call, which breaks multiple
sensor instances that have different AVDD supplies. This is fixed by
moving the scale into a per-device array.

Patches 3-6 split the v3 refactor into smaller independent steps as
requested by Andy Shevchenko: text cleanup (Kconfig, header,
MODULE_DESCRIPTION), chip_info introduction, trailing-pulse
parametrisation of hx711_read(), and iio_chan_spec * signature for
hx711_reset_read().

The final patch adds HX710B support using that infrastructure. Trailing
pulse counts from Table 3 of the HX710B datasheet are stored in
chan->address. Three channels are exposed: two differential inputs
(10 SPS and 40 SPS) and a DVDD-AVDD supply monitor (40 SPS). The driver
probes vref-supply first for the ADC reference and falls back to
avdd-supply when the VREF pin is tied to AVDD on the board.

Tested on PocketBeagle2 with an HX710B breakout module. The device
probed successfully, all three channels returned stable raw readings, and
alternating reads confirmed channel switching between the differential
input and the DVDD-AVDD supply monitor path.

Build-tested with:
- make -s W=1 drivers/iio/adc/hx711.o
- pahole -C hx711_chip_info drivers/iio/adc/hx711.o

pahole reports hx711_chip_info as 40 bytes with no internal holes. The
remaining 7 bytes are tail padding from 8-byte pointer alignment.

Changes in v4:
- Fix pre-existing global scale mutation bug (new patch 2).
- Split the v3 refactor patch into four independent patches (patches
  3-6) as requested by Andy Shevchenko.
- Keep hx711_chip_info fields in their final order from introduction;
  the HX710B patch only appends new fields without reordering.
- Add vref-supply binding and probe path for HX710B VREF pin.
- Add a third HX710B channel (27 pulses, differential 40 SPS) from
  Table 3 of the datasheet.
- Use .channel = 2 for the supply monitor to avoid indexing clash with
  .channel2 = 1 of the differential pair.
- Remove dvdd-supply from the HX710B forbidden list in the binding; the
  HX710B has a DVDD supply and the DVDD-AVDD channel relies on it.
- Add NULL guard on device_get_match_data() return value.
- Fix checkpatch alignment in multi-line hx711_read() calls.

Changes in v3:
- See individual patch changelogs for full details.
- dt-bindings: remove vref-supply wording; drop repeated
  clock-frequency default text; restore example node name; remove the
  extra HX710B example
- driver: split the hx711_chip_info refactor from the HX710B support
  patch; fix signedness; update channel_set only after successful
  channel switching; keep HX710B scale based on the documented fixed
  gain of 128; add direct ARRAY_SIZE/types includes; use pahole to
  verify and improve hx711_chip_info field ordering
- Reworked Kconfig text to use "HX711 and compatible ADCs" and list
  supported AVIA ADCs one per line.
- Restored/updated driver header and module description wording while
  keeping the bitbanging context.

Changes in v2:
- See individual patch changelogs for full details.
- dt-bindings: add dvdd-supply, vsup-supply, rate-gpios; allOf if/then
  for HX710B; fix clock-frequency description; remove dead vendor URL;
  clarify AVDD as voltage reference on both chips
- driver: fix pulse count bug ({25,26}->{1,2}); move counts to
  chan->address; add fixed_gain flag; add .differential/.channel2;
  remove NULL check; drop reset_channel; pass iio_chan_spec * directly

Piyush Patle (7):
  dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
  iio: adc: hx711: move scale computation to per-device storage
  iio: adc: hx711: update Kconfig, module description and file header
  iio: adc: hx711: introduce hx711_chip_info per-variant structure
  iio: adc: hx711: pass trailing pulse count into 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          |  82 +++++-
 drivers/iio/adc/Kconfig                       |   8 +-
 drivers/iio/adc/hx711.c                       | 278 ++++++++++++++----
 3 files changed, 297 insertions(+), 71 deletions(-)

-- 
2.43.0


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

* [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 15:29   ` David Lechner
  2026-04-27 10:09 ` [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

The HX710B shares the same two-wire interface as the HX711 but differs
in its channel and gain model: gain is fixed at 128 and the number of
trailing PD_SCK pulses selects the input channel rather than the gain.

Add avia,hx710b to the compatible enum. Document the chip differences
in the description and add chip-specific supply properties (dvdd-supply,
vsup-supply, vref-supply) and a rate-gpios property for the HX711 RATE
pin. Add allOf constraints that forbid HX711-only properties on HX710B
nodes and vice versa. Clarify the clock-frequency description to
reflect its actual purpose: controlling the SCK bit-bang timing.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- Add vref-supply for the HX710B VREF reference voltage pin.
- Remove dvdd-supply from the HX710B forbidden properties list; the
  HX710B has a DVDD supply and the DVDD-AVDD channel relies on it.
- Add allOf block forbidding vref-supply on HX711 nodes.
- Add an HX710B example showing vref-supply.
- Update description: avoid specific channel-number references in
  hardware text.

Changes in v3:
- Drop the vref-supply mention from avdd-supply; no such binding
  property exists.
- Drop the clock-frequency sentence that repeated the schema default.
- Restore the example node name to weight.
- Remove the separate HX710B example.

Changes in v2:
- Remove driver implementation details from the description and describe
  hardware behaviour only.
- Drop unrelated punctuation cleanup.
- Add dvdd-supply and vsup-supply optional properties for HX711.
- Add rate-gpios optional property for the HX711 RATE pin and forbid it
  on HX710B.
- Add the allOf if/then block forbidding HX711-only properties on
  HX710B nodes.
- Clarify clock-frequency as SCK bit-bang timing, not a crystal or
  external clock input.
- Sort compatible enum alphabetically.
- Remove redundant example comments.
- Update the HX711 example to exercise rate-gpios.
---
 .../bindings/iio/adc/avia-hx711.yaml          | 82 +++++++++++++++----
 1 file changed, 67 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..fddd296bfaca 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -4,49 +4,91 @@
 $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>
 
 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
+  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.
 
-  Specifications about the driver can be found at:
-  http://www.aviaic.com/ENProducts.aspx
+  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:
     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). Also serves as the voltage reference on
+      both chips.
+
+  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.
+
+  vsup-supply:
+    description:
+      Supply voltage for the on-chip regulator (VSUP). HX711 only.
+
+  vref-supply:
+    description:
+      Reference voltage input (VREF). HX710B only. When omitted, the driver
+      assumes VREF is tied to AVDD on the board.
+
+  rate-gpios:
+    description:
+      GPIO connected to the RATE pin (HX711 only). 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
+      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
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          const: avia,hx710b
+    then:
+      properties:
+        vsup-supply: false
+        rate-gpios: false
+
+  - if:
+      properties:
+        compatible:
+          const: avia,hx711
+    then:
+      properties:
+        vref-supply: false
+
 required:
   - compatible
   - sck-gpios
@@ -62,6 +104,16 @@ 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>;
     };
+  - |
+    #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] 20+ messages in thread

* [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
  2026-04-27 10:09 ` [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 14:02   ` Andy Shevchenko
  2026-04-27 10:09 ` [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header Piyush Patle
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

The gain-to-scale table hx711_gain_to_scale[] is a global array whose
.scale fields are overwritten in hx711_probe() using the AVDD voltage
read at probe time. When two HX711 sensors are connected to supplies at
different voltages, the second probe call overwrites the scale values
computed for the first sensor, silently corrupting its readings.

Fix this by removing the .scale field from the global table, making the
table const, and adding a per-instance gain_scale[] array to hx711_data.
Populate gain_scale[] in hx711_probe() using the device's own AVDD
regulator voltage. Update hx711_get_gain_to_scale() and
hx711_get_scale_to_gain() to take the per-instance array as a parameter,
and update hx711_scale_available_show() to retrieve it via iio_priv().

No functional change for single-sensor configurations.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- New patch. Fixes a pre-existing bug reported during v3 review: the
  global hx711_gain_to_scale[].scale is overwritten on each probe call,
  breaking multiple sensor instances with different AVDD supplies.
---
 drivers/iio/adc/hx711.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 1db8b68a8f64..0776a23bf59b 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;
@@ -388,12 +388,14 @@ static ssize_t hx711_scale_available_show(struct device *dev,
 {
 	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
 	int channel = iio_attr->address;
+	struct hx711_data *hx711_data =
+				iio_priv(dev_to_iio_dev(dev));
 	int i, len = 0;
 
 	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 +513,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] 20+ messages in thread

* [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
  2026-04-27 10:09 ` [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
  2026-04-27 10:09 ` [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 10:26   ` Joshua Crofts
  2026-04-27 13:58   ` Andy Shevchenko
  2026-04-27 10:09 ` [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure Piyush Patle
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Update the Kconfig entry to "AVIA HX711 and compatible ADCs" and list
supported chips one per line to make it easy to extend when new variants
are added. Change the module description and file header to match.

Add direct includes for linux/array_size.h and linux/types.h rather than
relying on transitive includes pulled in by other headers.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- New patch. Split out from the v3 refactor patch as requested by
  Andy Shevchenko so that text/description changes are separate from
  code refactoring.
- Add direct linux/array_size.h and linux/types.h includes.
---
 drivers/iio/adc/Kconfig | 7 ++++---
 drivers/iio/adc/hx711.c | 6 ++++--
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 60038ae8dfc4..f18692aea795 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -784,13 +784,14 @@ 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:
+	    - 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 0776a23bf59b..32362771cfc8 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -1,12 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * HX711: analog to digital converter for weight sensor module
+ * HX711 and compatible ADCs driver for weight sensor modules
  *
  * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
  */
+#include <linux/array_size.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/types.h>
 #include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
@@ -573,7 +575,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] 20+ messages in thread

* [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
                   ` (2 preceding siblings ...)
  2026-04-27 10:09 ` [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 14:08   ` Andy Shevchenko
  2026-04-27 10:09 ` [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read() Piyush Patle
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Add struct hx711_chip_info to hold per-variant static configuration:
device name, IIO channel spec array, IIO info ops pointer, and channel
count. Store a chip_info pointer in hx711_data and populate indio_dev
fields from it at probe time instead of hardcoding them.

Use device_get_match_data() to look up the chip_info pointer from the
of_device_id table. Guard against a NULL return so that the driver
fails cleanly if probed via the platform name match path without
associated match data.

No functional change for existing HX711 users.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- New patch. Split out from the v3 refactor patch as requested by
  Andy Shevchenko.
- Place hx711_chip_info fields in their final order from the start so
  that the HX710B support patch (which adds fixed_gain/fixed_gain_val)
  appends new fields without reordering existing ones.
- Add NULL guard on device_get_match_data() return value to handle the
  platform alias match path that can bind without match data.
---
 drivers/iio/adc/hx711.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 32362771cfc8..2a6e9645f54d 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -76,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
+ * @iio_info:     IIO info ops for this variant
+ * @num_channels: number of entries in @channels
+ */
+struct hx711_chip_info {
+	const char			*name;
+	const struct iio_chan_spec	*channels;
+	const struct iio_info		*iio_info;
+	unsigned int			num_channels;
+};
+
 struct hx711_data {
 	struct device		*dev;
 	struct gpio_desc	*gpiod_pd_sck;
@@ -83,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
@@ -459,10 +474,18 @@ 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)
 {
 	struct device *dev = &pdev->dev;
 	struct hx711_data *hx711_data;
+	const struct hx711_chip_info *chip_info;
 	struct iio_dev *indio_dev;
 	int ret;
 	int i;
@@ -476,6 +499,11 @@ 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 match 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
@@ -537,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,
@@ -558,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] 20+ messages in thread

* [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read()
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
                   ` (3 preceding siblings ...)
  2026-04-27 10:09 ` [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 14:12   ` Andy Shevchenko
  2026-04-27 10:09 ` [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read() Piyush Patle
  2026-04-27 10:09 ` [PATCH v4 7/7] iio: adc: hx711: add support for HX710B Piyush Patle
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Move the trailing-pulse computation out of hx711_read() and into the
callers. hx711_read() now takes an explicit 'trailing_pulses' parameter
so the HX710B support patch can pass the per-channel count stored in
chan->address without adding a separate code path in hx711_read().

Use scoped loop variables (for (int i = ...) / for (unsigned int i = ...))
to tighten the scope of the loop counters.

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- New patch. Split out from the v3 refactor patch as requested by
  Andy Shevchenko.
---
 drivers/iio/adc/hx711.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 2a6e9645f54d..8e77978f062b 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -155,9 +155,9 @@ 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, unsigned int trailing_pulses)
 {
-	int i, ret;
+	int ret;
 	int value = 0;
 	int val = gpiod_get_value(hx711_data->gpiod_dout);
 
@@ -165,7 +165,7 @@ static int hx711_read(struct hx711_data *hx711_data)
 	if (val)
 		return -EIO;
 
-	for (i = 0; i < 24; i++) {
+	for (int i = 0; i < 24; i++) {
 		value <<= 1;
 		ret = hx711_cycle(hx711_data);
 		if (ret)
@@ -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 (unsigned int 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)
 {
+	unsigned 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] 20+ messages in thread

* [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read()
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
                   ` (4 preceding siblings ...)
  2026-04-27 10:09 ` [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read() Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 14:16   ` Andy Shevchenko
  2026-04-27 10:09 ` [PATCH v4 7/7] iio: adc: hx711: add support for HX710B Piyush Patle
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Change hx711_reset_read() to accept a const struct iio_chan_spec *
instead of a plain integer channel index. This lets the HX710B support
patch pass the full channel descriptor (including chan->address for the
trailing pulse count) without adding a wrapper or a separate code path
for each call site.

Update the two callers: hx711_read_raw() already has the iio_chan_spec *
from its own parameter, and hx711_trigger() passes &indio_dev->channels[i].

No functional change.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- New patch. Split out from the v3 refactor patch as requested by
  Andy Shevchenko.
---
 drivers/iio/adc/hx711.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index 8e77978f062b..dc6703ead8a0 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -264,7 +264,8 @@ 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_reset_read(struct hx711_data *hx711_data,
+			    const struct iio_chan_spec *chan)
 {
 	unsigned int trailing_pulses;
 	int ret;
@@ -278,7 +279,7 @@ 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_gain_for_channel(hx711_data, chan->channel);
 	if (ret < 0)
 		return ret;
 
@@ -296,7 +297,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);
 
@@ -387,7 +388,7 @@ static irqreturn_t hx711_trigger(int irq, void *p)
 
 	iio_for_each_active_channel(indio_dev, i) {
 		hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data,
-					indio_dev->channels[i].channel);
+						&indio_dev->channels[i]);
 		j++;
 	}
 
-- 
2.43.0


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

* [PATCH v4 7/7] iio: adc: hx711: add support for HX710B
  2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
                   ` (5 preceding siblings ...)
  2026-04-27 10:09 ` [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read() Piyush Patle
@ 2026-04-27 10:09 ` Piyush Patle
  2026-04-27 14:34   ` Andy Shevchenko
  6 siblings, 1 reply; 20+ messages in thread
From: Piyush Patle @ 2026-04-27 10:09 UTC (permalink / raw)
  To: ak, jic23
  Cc: dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio,
	devicetree, linux-kernel

Add support for the AVIA HX710B ADC, which shares the HX711 GPIO
interface but has a fixed gain of 128 and uses trailing PD_SCK pulses
to select the active channel rather than the gain.

The HX710B has three operating modes controlled by the trailing pulse
count after the 24 data bits (Table 3 in the HX710B datasheet):
  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

Model the HX710B with its own hx710b_chan_spec[] and hx710b_iio_info.
Store the trailing pulse count in chan->address so hx710b_set_channel()
can switch channels without a separate lookup table. The supply monitor
uses .channel = 2 to avoid aliasing the channel2 terminal (index 1) of
the differential pair.

The HX710B has a dedicated VREF pin for the ADC reference voltage. The
driver tries vref-supply first; if absent it falls back to avdd-supply
(for boards where VREF is tied to AVDD). The HX711 uses AVDD as its
reference and is unaffected.

Add fixed_gain and fixed_gain_val fields to hx711_chip_info to carry the
gain into the scale calculation. Store a per-instance scale in
hx711_data for HX710B and use it in hx711_read_raw() when fixed_gain is
set. Update hx711_reset() to reset channel_set on HX710B after a
power-down cycle.

Enlarge the trigger buffer from 2 to 3 channels plus a pad word to keep
the timestamp naturally aligned; HX711 continues to use only the first
two slots.

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v4:
- Add a third HX710B channel (27 pulses, differential 40 SPS) based on
  Table 3 of the HX710B datasheet.
- Use .channel = 2 for the supply monitor channel to avoid aliasing the
  .channel2 = 1 terminal of the first differential pair.
- Add vref-supply probe path for the HX710B VREF reference pin; fall
  back to avdd-supply when vref-supply is absent.
- Add NULL guard on device_get_match_data() in the chip_info
  introduction patch; kept here as documentation that the guard exists.
- Keep hx711_chip_info fields in the final order introduced by the
  chip_info patch; this patch appends fixed_gain_val and fixed_gain
  without reordering existing fields.
- Move channel_set and scale fields to hx711_data (per-instance).
- Update channel_set only after both hx711_read() and
  hx711_wait_for_ready() succeed.
- Keep a single HX710B scale derived from the fixed gain of 128.

Changes in v3:
- Add HX710B support on top of the separate hx711_chip_info refactor.
- Update channel_set only after hx711_read() and hx711_wait_for_ready()
  both succeed.
- Keep a single HX710B fixed-gain scale based on the datasheet's fixed
  PGA gain of 128; do not apply the HX711 channel-B gain of 32 to the
  HX710B supply monitor path.
- Use unsigned int for channel state and fixed-gain scale storage.
- Keep HX710B trailing pulse counts in chan->address.
- Describe HX710B channel 0 as a differential IIO channel.
- Reorder hx711_chip_info fields based on pahole output so the
  structure has no internal holes.

Changes in v2:
- Fix pulse count bug: HX710B values were {25, 26} total SCK cycles;
  corrected to {1, 2} trailing pulses because hx711_read() already
  clocks the 24 data bits.
- Add .differential = 1 and .channel2 = 1 to HX710B channel 0.
- Move trailing pulse counts from a separate array to chan->address.
- Replace chan_pulse_count tests with a dedicated fixed_gain flag.
- Add fixed_gain_val to hx711_chip_info.
- Add the iio_info pointer to hx711_chip_info and assign
  indio_dev->info from chip_info.
- Remove the NULL check after device_get_match_data().
- Remove reset_channel from hx711_chip_info.
- Change hx711_reset_read() and hx710b_set_channel() to take
  const struct iio_chan_spec *.
- Revert unrelated hx711_data struct member alignment noise.
- Sort of_device_id entries alphabetically.
- Expand the commit message to explain HX711 versus HX710B trailing
  pulse behaviour.
- Restore the file header to mention weight sensor modules.
---
 drivers/iio/adc/Kconfig |   1 +
 drivers/iio/adc/hx711.c | 189 ++++++++++++++++++++++++++++++++++------
 2 files changed, 164 insertions(+), 26 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index f18692aea795..09a1b29fbd9c 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -790,6 +790,7 @@ config HX711
 	select IIO_TRIGGERED_BUFFER
 	help
 	  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.
 
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index dc6703ead8a0..41b9beb6d787 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -78,16 +78,20 @@ static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
 
 /**
  * struct hx711_chip_info - per-variant static configuration
- * @name:         IIO device name
- * @channels:     channel specification array
- * @iio_info:     IIO info ops for this variant
- * @num_channels: number of entries in @channels
+ * @name:          IIO device name
+ * @channels:      channel specification array
+ * @iio_info:      IIO info ops for this variant
+ * @num_channels:  number of entries in @channels
+ * @fixed_gain_val: fixed PGA gain (used when @fixed_gain is true)
+ * @fixed_gain:    true if the variant has a fixed ADC gain (e.g. HX710B)
  */
 struct hx711_chip_info {
 	const char			*name;
 	const struct iio_chan_spec	*channels;
 	const struct iio_info		*iio_info;
 	unsigned int			num_channels;
+	unsigned int			fixed_gain_val;
+	bool				fixed_gain;
 };
 
 struct hx711_data {
@@ -97,14 +101,17 @@ struct hx711_data {
 	int			gain_set;	/* gain set on device */
 	int			gain_chan_a;	/* gain for channel A */
 	int			gain_scale[HX711_GAIN_MAX];
+	unsigned int		channel_set;	/* HX710B active channel */
 	const struct hx711_chip_info	*chip_info;
+	unsigned int		scale;		/* HX710B fixed-gain scale */
 	struct mutex		lock;
 	/*
 	 * triggered buffer
-	 * 2x32-bit channel + 64-bit naturally aligned timestamp
+	 * up to 3x32-bit channels + pad + 64-bit naturally aligned timestamp
 	 */
 	struct {
-		u32 channel[2];
+		u32 channel[3];
+		u32 pad;
 		aligned_s64 timestamp;
 	} buffer;
 	/*
@@ -204,6 +211,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 = hx711_wait_for_ready(hx711_data);
 
 	if (val) {
@@ -222,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->fixed_gain)
+			hx711_data->channel_set = 0;
+		else
+			/* after a reset the gain is 128 */
+			hx711_data->gain_set = HX711_RESET_GAIN;
 	}
 
 	return val;
@@ -264,9 +275,36 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
 	return 0;
 }
 
+/*
+ * Switch the HX710B to the requested channel for the next conversion.
+ * chan->address holds the trailing pulse count (Table 3 in datasheet).
+ * channel_set is updated only after both reads succeed.
+ */
+static int hx710b_set_channel(struct hx711_data *hx711_data,
+			      const struct iio_chan_spec *chan)
+{
+	int ret;
+
+	if (hx711_data->channel_set == (unsigned int)chan->channel)
+		return 0;
+
+	ret = hx711_read(hx711_data, chan->address);
+	if (ret < 0)
+		return ret;
+
+	ret = hx711_wait_for_ready(hx711_data);
+	if (ret)
+		return ret;
+
+	hx711_data->channel_set = chan->channel;
+
+	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;
 	unsigned int trailing_pulses;
 	int ret;
 
@@ -279,11 +317,18 @@ static int hx711_reset_read(struct hx711_data *hx711_data,
 		return -EIO;
 	}
 
-	ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
-	if (ret < 0)
-		return ret;
+	if (info->fixed_gain) {
+		ret = hx710b_set_channel(hx711_data, chan);
+		if (ret < 0)
+			return ret;
+		trailing_pulses = chan->address;
+	} else {
+		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);
+	}
 
-	trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
 	return hx711_read(hx711_data, trailing_pulses);
 }
 
@@ -292,6 +337,7 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
 				int *val, int *val2, long mask)
 {
 	struct hx711_data *hx711_data = iio_priv(indio_dev);
+	const struct hx711_chip_info *info = hx711_data->chip_info;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -308,8 +354,11 @@ 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_scale,
-						hx711_data->gain_set);
+		if (info->fixed_gain)
+			*val2 = hx711_data->scale;
+		else
+			*val2 = hx711_get_gain_to_scale(hx711_data->gain_scale,
+							hx711_data->gain_set);
 
 		mutex_unlock(&hx711_data->lock);
 
@@ -445,6 +494,10 @@ static const struct iio_info hx711_iio_info = {
 	.attrs			= &hx711_attribute_group,
 };
 
+static const struct iio_info hx710b_iio_info = {
+	.read_raw		= hx711_read_raw,
+};
+
 static const struct iio_chan_spec hx711_chan_spec[] = {
 	{
 		.type = IIO_VOLTAGE,
@@ -477,6 +530,68 @@ 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  -> channel 0
+ * 26 pulses (2 trailing): DVDD-AVDD supply monitor, 40 SPS -> channel 2
+ * 27 pulses (3 trailing): differential input, 40 SPS  -> channel 3
+ * .address stores the trailing pulse count for hx710b_set_channel().
+ * Channel 2 is used for the supply monitor to avoid aliasing the
+ * channel2 terminal (index 1) of the differential pair.
+ */
+static const struct iio_chan_spec hx710b_chan_spec[] = {
+	{
+		.type = IIO_VOLTAGE,
+		.differential = 1,
+		.channel = 0,
+		.channel2 = 1,
+		.indexed = 1,
+		.address = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.storagebits = 32,
+			.endianness = IIO_CPU,
+		},
+	},
+	{
+		.type = IIO_VOLTAGE,
+		.channel = 2,
+		.indexed = 1,
+		.address = 2,
+		.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,
+		},
+	},
+	{
+		.type = IIO_VOLTAGE,
+		.differential = 1,
+		.channel = 3,
+		.channel2 = 4,
+		.indexed = 1,
+		.address = 3,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 2,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.storagebits = 32,
+			.endianness = IIO_CPU,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
 static const struct hx711_chip_info hx711_chip = {
 	.name		= "hx711",
 	.channels	= hx711_chan_spec,
@@ -484,6 +599,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	= true,
+	.fixed_gain_val	= 128,
+};
+
 static int hx711_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -525,32 +649,44 @@ 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");
+	/*
+	 * The HX710B uses the VREF pin as the ADC reference; try vref-supply
+	 * first and fall back to avdd-supply when VREF is tied to AVDD on the
+	 * board.  The HX711 uses AVDD as its reference.
+	 */
+	if (chip_info->fixed_gain)
+		ret = devm_regulator_get_enable_read_voltage(dev, "vref");
+	if (!chip_info->fixed_gain || ret == -ENODEV)
+		ret = devm_regulator_get_enable_read_voltage(dev, "avdd");
 	if (ret < 0)
 		return ret;
 
 	/*
 	 * with
-	 * full scale differential input range: AVDD / GAIN
+	 * full scale differential input range: VREF / GAIN
 	 * full scale output data: 2^24
 	 * we can say:
-	 *     AVDD / GAIN = 2^24
+	 *     VREF / GAIN = 2^24
 	 * therefore:
-	 *     1 LSB = AVDD / GAIN / 2^24
-	 * AVDD is in uV, but we need 10^-9 mV
+	 *     1 LSB = VREF / GAIN / 2^24
+	 * VREF 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 = (VREF * 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->fixed_gain) {
+		hx711_data->scale = ret / chip_info->fixed_gain_val / 1678;
+	} 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",
@@ -589,7 +725,8 @@ static int hx711_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id of_hx711_match[] = {
-	{ .compatible = "avia,hx711", .data = &hx711_chip },
+	{ .compatible = "avia,hx710b", .data = &hx710b_chip },
+	{ .compatible = "avia,hx711",  .data = &hx711_chip  },
 	{ }
 };
 
-- 
2.43.0


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

* Re: [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 10:09 ` [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header Piyush Patle
@ 2026-04-27 10:26   ` Joshua Crofts
  2026-04-27 13:46     ` Andy Shevchenko
  2026-04-27 13:58   ` Andy Shevchenko
  1 sibling, 1 reply; 20+ messages in thread
From: Joshua Crofts @ 2026-04-27 10:26 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, 27 Apr 2026 at 12:23, Piyush Patle <piyushpatle228@gmail.com> wrote:
> +         which are used for bridge sensors such as weigh cells.

Typo here.

-- 
Kind regards

CJD

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

* Re: [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 10:26   ` Joshua Crofts
@ 2026-04-27 13:46     ` Andy Shevchenko
  2026-04-27 13:49       ` Joshua Crofts
  0 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 13:46 UTC (permalink / raw)
  To: Joshua Crofts
  Cc: Piyush Patle, ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt, linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 12:26:53PM +0200, Joshua Crofts wrote:
> On Mon, 27 Apr 2026 at 12:23, Piyush Patle <piyushpatle228@gmail.com> wrote:

...

> > +         which are used for bridge sensors such as weigh cells.
> 
> Typo here.

It's better if you point exactly what the typo is.
I think you meant "weigh" that should be "weight"?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 13:46     ` Andy Shevchenko
@ 2026-04-27 13:49       ` Joshua Crofts
  0 siblings, 0 replies; 20+ messages in thread
From: Joshua Crofts @ 2026-04-27 13:49 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Piyush Patle, ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt, linux-iio, devicetree, linux-kernel

On Mon, 27 Apr 2026 at 15:46, Andy Shevchenko
<andriy.shevchenko@intel.com> wrote:
>
> On Mon, Apr 27, 2026 at 12:26:53PM +0200, Joshua Crofts wrote:
> > On Mon, 27 Apr 2026 at 12:23, Piyush Patle <piyushpatle228@gmail.com> wrote:
>
> ...
>
> > > +         which are used for bridge sensors such as weigh cells.
> >
> > Typo here.
>
> It's better if you point exactly what the typo is.
> I think you meant "weigh" that should be "weight"?

Yep, that's it, my mistake.

-- 
Kind regards

CJD

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

* Re: [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 10:09 ` [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header Piyush Patle
  2026-04-27 10:26   ` Joshua Crofts
@ 2026-04-27 13:58   ` Andy Shevchenko
  2026-04-27 14:19     ` Andy Shevchenko
  1 sibling, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 13:58 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:34PM +0530, Piyush Patle wrote:
> Update the Kconfig entry to "AVIA HX711 and compatible ADCs" and list
> supported chips one per line to make it easy to extend when new variants
> are added. Change the module description and file header to match.
> 
> Add direct includes for linux/array_size.h and linux/types.h rather than
> relying on transitive includes pulled in by other headers.

Obviously something went wrong. First of all, I have told that MODULE_*()
changes doesn't belong to the refactoring patch. Second, I meant that the
Kconfig help text to go to a separate patch.

Header inclusions should be taken care when it's required. It doesn't belong
here.

Looking at this again, most of it probably should be folded into the new HW
support patch where you add a new chip_info.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage
  2026-04-27 10:09 ` [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
@ 2026-04-27 14:02   ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:02 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:33PM +0530, Piyush Patle wrote:
> The gain-to-scale table hx711_gain_to_scale[] is a global array whose
> .scale fields are overwritten in hx711_probe() using the AVDD voltage
> read at probe time. When two HX711 sensors are connected to supplies at
> different voltages, the second probe call overwrites the scale values
> computed for the first sensor, silently corrupting its readings.
> 
> Fix this by removing the .scale field from the global table, making the
> table const, and adding a per-instance gain_scale[] array to hx711_data.
> Populate gain_scale[] in hx711_probe() using the device's own AVDD
> regulator voltage. Update hx711_get_gain_to_scale() and
> hx711_get_scale_to_gain() to take the per-instance array as a parameter,
> and update hx711_scale_available_show() to retrieve it via iio_priv().
> 
> No functional change for single-sensor configurations.

...

>  /*
>   * .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 }

I would leave trailing comma, as it is semantically is not the terminator entry.

>  };

...

>  {
>  	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
>  	int channel = iio_attr->address;
> +	struct hx711_data *hx711_data =
> +				iio_priv(dev_to_iio_dev(dev));

First of all, please preserve the reversed xmas tree order.
Second, it's more than enough room to have it a single line.

	struct hx711_data *hx711_data = iio_priv(dev_to_iio_dev(dev));

>  	int i, len = 0;

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure
  2026-04-27 10:09 ` [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure Piyush Patle
@ 2026-04-27 14:08   ` Andy Shevchenko
  2026-04-27 14:14     ` Andy Shevchenko
  0 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:08 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:35PM +0530, Piyush Patle wrote:
> Add struct hx711_chip_info to hold per-variant static configuration:
> device name, IIO channel spec array, IIO info ops pointer, and channel
> count. Store a chip_info pointer in hx711_data and populate indio_dev
> fields from it at probe time instead of hardcoding them.
> 
> Use device_get_match_data() to look up the chip_info pointer from the
> of_device_id table. Guard against a NULL return so that the driver
> fails cleanly if probed via the platform name match path without
> associated match data.
> 
> No functional change for existing HX711 users.

All the above is fine, but I missed the answer to the question "why?"
You need to add that this is preparatory change to add more HW support
or something alike along these words.

...

> +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),

The array_size.h inclusion should go with this patch.

> +};

...

>  	struct device *dev = &pdev->dev;
>  	struct hx711_data *hx711_data;
> +	const struct hx711_chip_info *chip_info;

Preserve reversed xmas tree order.

>  	struct iio_dev *indio_dev;
>  	int ret;
>  	int i;

...

> +	chip_info = device_get_match_data(dev);
> +	if (!chip_info)
> +		return dev_err_probe(dev, -ENODEV, "missing match data\n");

Since we are here, it's not match data, it's driver data. "missing driver data".

> +	hx711_data->chip_info = chip_info;

+ Blank line.

>  	/*

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read()
  2026-04-27 10:09 ` [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read() Piyush Patle
@ 2026-04-27 14:12   ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:12 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:36PM +0530, Piyush Patle wrote:
> Move the trailing-pulse computation out of hx711_read() and into the
> callers. hx711_read() now takes an explicit 'trailing_pulses' parameter
> so the HX710B support patch can pass the per-channel count stored in
> chan->address without adding a separate code path in hx711_read().
> 
> Use scoped loop variables (for (int i = ...) / for (unsigned int i = ...))
> to tighten the scope of the loop counters.
> 
> No functional change.

...

> -static int hx711_read(struct hx711_data *hx711_data)
> +static int hx711_read(struct hx711_data *hx711_data, unsigned int trailing_pulses)
>  {
> -	int i, ret;
> +	int ret;
>  	int value = 0;
>  	int val = gpiod_get_value(hx711_data->gpiod_dout);

Try to follow the reversed xmas tree order.

> -	for (i = 0; i < 24; i++) {
> +	for (int i = 0; i < 24; i++) {

Why is 'i' signed?

> -	for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
> +	for (unsigned int i = 0; i < trailing_pulses; i++)
>  		hx711_cycle(hx711_data);

With the above the both seems like a candidate to a separate change (after this
trailing_pulses patch).

>  	return value;

...

So, split this to two:
- trailing_pulses (without touching 'i')
- localising loop iterators

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure
  2026-04-27 14:08   ` Andy Shevchenko
@ 2026-04-27 14:14     ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:14 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 05:08:17PM +0300, Andy Shevchenko wrote:
> On Mon, Apr 27, 2026 at 03:39:35PM +0530, Piyush Patle wrote:

...

> > +	chip_info = device_get_match_data(dev);
> > +	if (!chip_info)
> > +		return dev_err_probe(dev, -ENODEV, "missing match data\n");
> 
> Since we are here, it's not match data, it's driver data. "missing driver data".

And does it need property.h to be included?

Also check if dev_printk.h and errno.h are there (it may be that driver already
uses device.h and err.h that cover these two).

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read()
  2026-04-27 10:09 ` [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read() Piyush Patle
@ 2026-04-27 14:16   ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:16 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:37PM +0530, Piyush Patle wrote:
> Change hx711_reset_read() to accept a const struct iio_chan_spec *
> instead of a plain integer channel index. This lets the HX710B support
> patch pass the full channel descriptor (including chan->address for the

s/patch/change in the future/

> trailing pulse count) without adding a wrapper or a separate code path
> for each call site.
> 
> Update the two callers: hx711_read_raw() already has the iio_chan_spec *
> from its own parameter, and hx711_trigger() passes &indio_dev->channels[i].
> 
> No functional change.

...

>  	iio_for_each_active_channel(indio_dev, i) {
>  		hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data,
> -					indio_dev->channels[i].channel);
> +						&indio_dev->channels[i]);

Re-indent this to be

		hx711_data->buffer.channel[j] =
			hx711_reset_read(hx711_data, &indio_dev->channels[i]);

>  		j++;
>  	}

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header
  2026-04-27 13:58   ` Andy Shevchenko
@ 2026-04-27 14:19     ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:19 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 04:58:03PM +0300, Andy Shevchenko wrote:
> On Mon, Apr 27, 2026 at 03:39:34PM +0530, Piyush Patle wrote:
> > Update the Kconfig entry to "AVIA HX711 and compatible ADCs" and list
> > supported chips one per line to make it easy to extend when new variants
> > are added. Change the module description and file header to match.
> > 
> > Add direct includes for linux/array_size.h and linux/types.h rather than
> > relying on transitive includes pulled in by other headers.
> 
> Obviously something went wrong. First of all, I have told that MODULE_*()
> changes doesn't belong to the refactoring patch. Second, I meant that the
> Kconfig help text to go to a separate patch.
> 
> Header inclusions should be taken care when it's required. It doesn't belong
> here.
> 
> Looking at this again, most of it probably should be folded into the new HW
> support patch where you add a new chip_info.

I checked again after browsing through the whole series. This patch basically
should be either folded to the patch 7, or immediately prepend that (without
being any between them).

- Kconfig + MODULE_*() + respective comments update
  // no patches in between!
- new HW support

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 7/7] iio: adc: hx711: add support for HX710B
  2026-04-27 10:09 ` [PATCH v4 7/7] iio: adc: hx711: add support for HX710B Piyush Patle
@ 2026-04-27 14:34   ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-04-27 14:34 UTC (permalink / raw)
  To: Piyush Patle
  Cc: ak, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	linux-iio, devicetree, linux-kernel

On Mon, Apr 27, 2026 at 03:39:38PM +0530, Piyush Patle wrote:
> Add support for the AVIA HX710B ADC, which shares the HX711 GPIO
> interface but has a fixed gain of 128 and uses trailing PD_SCK pulses
> to select the active channel rather than the gain.
> 
> The HX710B has three operating modes controlled by the trailing pulse
> count after the 24 data bits (Table 3 in the HX710B datasheet):
>   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
> 
> Model the HX710B with its own hx710b_chan_spec[] and hx710b_iio_info.
> Store the trailing pulse count in chan->address so hx710b_set_channel()
> can switch channels without a separate lookup table. The supply monitor
> uses .channel = 2 to avoid aliasing the channel2 terminal (index 1) of
> the differential pair.
> 
> The HX710B has a dedicated VREF pin for the ADC reference voltage. The
> driver tries vref-supply first; if absent it falls back to avdd-supply
> (for boards where VREF is tied to AVDD). The HX711 uses AVDD as its
> reference and is unaffected.
> 
> Add fixed_gain and fixed_gain_val fields to hx711_chip_info to carry the
> gain into the scale calculation. Store a per-instance scale in
> hx711_data for HX710B and use it in hx711_read_raw() when fixed_gain is
> set. Update hx711_reset() to reset channel_set on HX710B after a
> power-down cycle.
> 
> Enlarge the trigger buffer from 2 to 3 channels plus a pad word to keep
> the timestamp naturally aligned; HX711 continues to use only the first
> two slots.

So, missed types.h should be in this patch.

...

>  /**
>   * struct hx711_chip_info - per-variant static configuration
> - * @name:         IIO device name
> - * @channels:     channel specification array
> - * @iio_info:     IIO info ops for this variant
> - * @num_channels: number of entries in @channels
> + * @name:          IIO device name
> + * @channels:      channel specification array
> + * @iio_info:      IIO info ops for this variant
> + * @num_channels:  number of entries in @channels
> + * @fixed_gain_val: fixed PGA gain (used when @fixed_gain is true)
> + * @fixed_gain:    true if the variant has a fixed ADC gain (e.g. HX710B)

No, make sure there will be no '-' lines here.

>   */

...

>  struct hx711_data {

>  	int			gain_set;	/* gain set on device */
>  	int			gain_chan_a;	/* gain for channel A */
>  	int			gain_scale[HX711_GAIN_MAX];

> +	unsigned int		channel_set;	/* HX710B active channel */
>  	const struct hx711_chip_info	*chip_info;
> +	unsigned int		scale;		/* HX710B fixed-gain scale */

Semantically the scale is closer to the above gain_* ones AFAICS.

>  	struct mutex		lock;
>  	/*
>  	 * triggered buffer
> -	 * 2x32-bit channel + 64-bit naturally aligned timestamp
> +	 * up to 3x32-bit channels + pad + 64-bit naturally aligned timestamp
>  	 */
>  	struct {
> -		u32 channel[2];
> +		u32 channel[3];
> +		u32 pad;
>  		aligned_s64 timestamp;
>  	} buffer;
>  	/*

...

>  static int hx711_reset(struct hx711_data *hx711_data)
>  {
> +	const struct hx711_chip_info *info = hx711_data->chip_info;
>  	int val = hx711_wait_for_ready(hx711_data);
>  
>  	if (val) {

The rule of thumb is to split definition and assignment for the variables that
are going to be validated.

Here I expect to see

	int val;

	val = hx711_wait_for_ready(hx711_data);
	if (val) {

But since it's not related directly to this change, make a preparatory patch.
Because now with two variables this looks worse and adds more potential to be
mistaken in the future.


> +static int hx710b_set_channel(struct hx711_data *hx711_data,
> +			      const struct iio_chan_spec *chan)
> +{
> +	int ret;
> +
> +	if (hx711_data->channel_set == (unsigned int)chan->channel)
> +		return 0;
> +
> +	ret = hx711_read(hx711_data, chan->address);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = hx711_wait_for_ready(hx711_data);
> +	if (ret)
> +		return ret;
> +
> +	hx711_data->channel_set = chan->channel;
> +
> +	return 0;
> +}

...

> -	ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
> -	if (ret < 0)
> -		return 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);
> +	}
>  
> -	trailing_pulses = hx711_get_gain_to_pulse(hx711_data->gain_set);
>  	return hx711_read(hx711_data, trailing_pulses);

Instead of the above, first split these lines to a helper

static int hx711_set_hx711_channel(..., *tp)
{
	int ret;

	ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
	if (ret < 0)
		return ret;

	*tp = hx711_get_gain_to_pulse(hx711_data->gain_set);
	return 0;
}

And name your new function something like

hx711_set_hx710b_channel()

...

> +	/*
> +	 * The HX710B uses the VREF pin as the ADC reference; try vref-supply
> +	 * first and fall back to avdd-supply when VREF is tied to AVDD on the
> +	 * board.  The HX711 uses AVDD as its reference.

I think we use a single space in the comment, but double check that.
The rule of thumb is to keep the original driver style and change it
separately if required.

> +	 */

...

>  	/*
>  	 * with

While at it, with --> With.

> -	 * full scale differential input range: AVDD / GAIN
> +	 * full scale differential input range: VREF / GAIN
>  	 * full scale output data: 2^24
>  	 * we can say:
> -	 *     AVDD / GAIN = 2^24
> +	 *     VREF / GAIN = 2^24
>  	 * therefore:
> -	 *     1 LSB = AVDD / GAIN / 2^24
> -	 * AVDD is in uV, but we need 10^-9 mV
> +	 *     1 LSB = VREF / GAIN / 2^24
> +	 * VREF 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 = (VREF * 100) / GAIN / 1678 [10^-9 mV]
>  	 */

...

> -	for (i = 0; i < HX711_GAIN_MAX; i++)
> -		hx711_data->gain_scale[i] =
> -			ret / hx711_gain_to_scale[i].gain / 1678;
> +	if (chip_info->fixed_gain) {
> +		hx711_data->scale = ret / chip_info->fixed_gain_val / 1678;
> +	} 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;
> +	}

Looking at this I'm wondering wouldn't be easier just to have the array, but
feel it with the same data.

...

> -	{ .compatible = "avia,hx711", .data = &hx711_chip },

> +	{ .compatible = "avia,hx711",  .data = &hx711_chip  },

Why?! This is stray change.


-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
  2026-04-27 10:09 ` [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
@ 2026-04-27 15:29   ` David Lechner
  0 siblings, 0 replies; 20+ messages in thread
From: David Lechner @ 2026-04-27 15:29 UTC (permalink / raw)
  To: Piyush Patle, ak, jic23
  Cc: nuno.sa, andy, robh, krzk+dt, conor+dt, linux-iio, devicetree,
	linux-kernel

On 4/27/26 5:09 AM, Piyush Patle wrote:
> The HX710B shares the same two-wire interface as the HX711 but differs
> in its channel and gain model: gain is fixed at 128 and the number of
> trailing PD_SCK pulses selects the input channel rather than the gain.
> 
> Add avia,hx710b to the compatible enum. Document the chip differences
> in the description and add chip-specific supply properties (dvdd-supply,
> vsup-supply, vref-supply) and a rate-gpios property for the HX711 RATE
> pin. Add allOf constraints that forbid HX711-only properties on HX710B
> nodes and vice versa. Clarify the clock-frequency description to
> reflect its actual purpose: controlling the SCK bit-bang timing.

Krzysztof gave a Reviewed-by on the last revision [1], so you need to
include that here or explain why you didn't pick it up. If you just make
a trivial change, you can still pick it up. In this case though, I think
that enough changes were made that it is worth having a DT maintainer have
another look.

https://lore.kernel.org/linux-iio/20260423-famous-tody-of-opposition-73c8af@quoll/

> 
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
> ---
> Changes in v4:
> - Add vref-supply for the HX710B VREF reference voltage pin.
> - Remove dvdd-supply from the HX710B forbidden properties list; the
>   HX710B has a DVDD supply and the DVDD-AVDD channel relies on it.
> - Add allOf block forbidding vref-supply on HX711 nodes.
> - Add an HX710B example showing vref-supply.
> - Update description: avoid specific channel-number references in
>   hardware text.
> 
> Changes in v3:
> - Drop the vref-supply mention from avdd-supply; no such binding
>   property exists.
> - Drop the clock-frequency sentence that repeated the schema default.
> - Restore the example node name to weight.
> - Remove the separate HX710B example.
> 
> Changes in v2:
> - Remove driver implementation details from the description and describe
>   hardware behaviour only.
> - Drop unrelated punctuation cleanup.
> - Add dvdd-supply and vsup-supply optional properties for HX711.
> - Add rate-gpios optional property for the HX711 RATE pin and forbid it
>   on HX710B.
> - Add the allOf if/then block forbidding HX711-only properties on
>   HX710B nodes.
> - Clarify clock-frequency as SCK bit-bang timing, not a crystal or
>   external clock input.
> - Sort compatible enum alphabetically.
> - Remove redundant example comments.
> - Update the HX711 example to exercise rate-gpios.
> ---
>  .../bindings/iio/adc/avia-hx711.yaml          | 82 +++++++++++++++----
>  1 file changed, 67 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..fddd296bfaca 100644
> --- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> @@ -4,49 +4,91 @@
>  $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>
>  
>  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
> +  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.
>  
> -  Specifications about the driver can be found at:
> -  http://www.aviaic.com/ENProducts.aspx
> +  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:
>      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). Also serves as the voltage reference on
> +      both chips.
> +
> +  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.
> +
> +  vsup-supply:
> +    description:
> +      Supply voltage for the on-chip regulator (VSUP). HX711 only.
> +
> +  vref-supply:
> +    description:
> +      Reference voltage input (VREF). HX710B only. When omitted, the driver
> +      assumes VREF is tied to AVDD on the board.
> +
> +  rate-gpios:
> +    description:
> +      GPIO connected to the RATE pin (HX711 only). 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
> +      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
>  
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          const: avia,hx710b
> +    then:
> +      properties:
> +        vsup-supply: false
> +        rate-gpios: false
> +
> +  - if:

Could just be else:

Probably OK either way though.

> +      properties:
> +        compatible:
> +          const: avia,hx711
> +    then:
> +      properties:
> +        vref-supply: false
> +
>  required:
>    - compatible
>    - sck-gpios
> @@ -62,6 +104,16 @@ 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>;
>      };
> +  - |
> +    #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>;
> +    };


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

end of thread, other threads:[~2026-04-27 15:29 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-27 10:09 [PATCH v4 0/7] iio: adc: hx711: add HX710B support Piyush Patle
2026-04-27 10:09 ` [PATCH v4 1/7] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
2026-04-27 15:29   ` David Lechner
2026-04-27 10:09 ` [PATCH v4 2/7] iio: adc: hx711: move scale computation to per-device storage Piyush Patle
2026-04-27 14:02   ` Andy Shevchenko
2026-04-27 10:09 ` [PATCH v4 3/7] iio: adc: hx711: update Kconfig, module description and file header Piyush Patle
2026-04-27 10:26   ` Joshua Crofts
2026-04-27 13:46     ` Andy Shevchenko
2026-04-27 13:49       ` Joshua Crofts
2026-04-27 13:58   ` Andy Shevchenko
2026-04-27 14:19     ` Andy Shevchenko
2026-04-27 10:09 ` [PATCH v4 4/7] iio: adc: hx711: introduce hx711_chip_info per-variant structure Piyush Patle
2026-04-27 14:08   ` Andy Shevchenko
2026-04-27 14:14     ` Andy Shevchenko
2026-04-27 10:09 ` [PATCH v4 5/7] iio: adc: hx711: pass trailing pulse count into hx711_read() Piyush Patle
2026-04-27 14:12   ` Andy Shevchenko
2026-04-27 10:09 ` [PATCH v4 6/7] iio: adc: hx711: pass iio_chan_spec to hx711_reset_read() Piyush Patle
2026-04-27 14:16   ` Andy Shevchenko
2026-04-27 10:09 ` [PATCH v4 7/7] iio: adc: hx711: add support for HX710B Piyush Patle
2026-04-27 14:34   ` Andy Shevchenko

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