* [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
2026-04-22 17:59 [PATCH v3 0/3] iio: adc: hx711: add HX710B support Piyush Patle
@ 2026-04-22 17:59 ` Piyush Patle
2026-04-23 8:05 ` Krzysztof Kozlowski
` (2 more replies)
2026-04-22 17:59 ` [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure Piyush Patle
2026-04-22 17:59 ` [PATCH v3 3/3] iio: adc: hx711: add support for HX710B Piyush Patle
2 siblings, 3 replies; 13+ messages in thread
From: Piyush Patle @ 2026-04-22 17:59 UTC (permalink / raw)
To: Jonathan Cameron, Andreas Klinger
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, 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) for the HX711, a rate-gpios property for the HX711 RATE
pin, and an allOf constraint that forbids HX711-only properties on
HX710B nodes. 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 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 | 50 +++++++++++++++----
1 file changed, 41 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
index 9c57eb13f892..0c7c5843b8d2 100644
--- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
@@ -4,24 +4,24 @@
$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. Channel 0 is the
+ differential input and channel 1 measures the DVDD-AVDD supply
+ voltage difference.
properties:
compatible:
enum:
+ - avia,hx710b
- avia,hx711
sck-gpios:
@@ -40,13 +40,44 @@ properties:
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). HX711 only.
+
+ vsup-supply:
+ description:
+ Supply voltage for the on-chip regulator (VSUP). HX711 only.
+
+ 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
+ dvdd-supply: false
+ rate-gpios: false
+
required:
- compatible
- sck-gpios
@@ -62,6 +93,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] 13+ messages in thread* Re: [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
2026-04-22 17:59 ` [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
@ 2026-04-23 8:05 ` Krzysztof Kozlowski
2026-04-24 12:00 ` Jonathan Cameron
2026-04-26 16:28 ` David Lechner
2 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-23 8:05 UTC (permalink / raw)
To: Piyush Patle
Cc: Jonathan Cameron, Andreas Klinger, David Lechner, Nuno Sá,
Andy Shevchenko, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-iio, devicetree,
linux-kernel
On Wed, Apr 22, 2026 at 11:29:08PM +0530, 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) for the HX711, a rate-gpios property for the HX711 RATE
> pin, and an allOf constraint that forbids HX711-only properties on
> HX710B nodes. 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 v3:
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
2026-04-22 17:59 ` [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
2026-04-23 8:05 ` Krzysztof Kozlowski
@ 2026-04-24 12:00 ` Jonathan Cameron
2026-04-26 16:28 ` David Lechner
2 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2026-04-24 12:00 UTC (permalink / raw)
To: Piyush Patle
Cc: Andreas Klinger, David Lechner, Nuno Sá, Andy Shevchenko,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, 22 Apr 2026 23:29:08 +0530
Piyush Patle <piyushpatle228@gmail.com> 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) for the HX711, a rate-gpios property for the HX711 RATE
> pin, and an allOf constraint that forbids HX711-only properties on
> HX710B nodes. Clarify the clock-frequency description to reflect its
> actual purpose: controlling the SCK bit-bang timing.
>
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Sashikio had some more comments...
https://sashiko.dev/#/patchset/20260422175910.1258579-1-piyushpatle228%40g
First one looks correct to me about the hx710b clearly having a DVDD supply
given we are measuring it.
> ---
> 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 | 50 +++++++++++++++----
> 1 file changed, 41 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> index 9c57eb13f892..0c7c5843b8d2 100644
> --- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
> @@ -4,24 +4,24 @@
> $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. Channel 0 is the
> + differential input and channel 1 measures the DVDD-AVDD supply
> + voltage difference.
How can it be measuring something including DVDD if that supply isn't
allowed for the part?
>
> properties:
> compatible:
> enum:
> + - avia,hx710b
> - avia,hx711
>
> sck-gpios:
> @@ -40,13 +40,44 @@ properties:
>
> 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). HX711 only.
This is the confusing description.
> +
> + vsup-supply:
> + description:
> + Supply voltage for the on-chip regulator (VSUP). HX711 only.
> +
> + 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
I'm fairly sure the sashiko comment on this is wrong given this
looks like standard way of doing this.
> + then:
> + properties:
> + vsup-supply: false
> + dvdd-supply: false
> + rate-gpios: false
> +
> required:
> - compatible
> - sck-gpios
> @@ -62,6 +93,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>;
> };
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
2026-04-22 17:59 ` [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
2026-04-23 8:05 ` Krzysztof Kozlowski
2026-04-24 12:00 ` Jonathan Cameron
@ 2026-04-26 16:28 ` David Lechner
2026-04-26 16:43 ` Piyush Patle
2 siblings, 1 reply; 13+ messages in thread
From: David Lechner @ 2026-04-26 16:28 UTC (permalink / raw)
To: Piyush Patle, Jonathan Cameron, Andreas Klinger
Cc: Nuno Sá, Andy Shevchenko, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-iio, devicetree,
linux-kernel
On 4/22/26 12:59 PM, 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) for the HX711, a rate-gpios property for the HX711 RATE
> pin, and an allOf constraint that forbids HX711-only properties on
> HX710B nodes. 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 v3:
> - Drop the vref-supply mention from avdd-supply; no such binding
> property exists.
Why is there no vref-supply?
HX710B has a VREF pin for a reference voltage input.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible
2026-04-26 16:28 ` David Lechner
@ 2026-04-26 16:43 ` Piyush Patle
0 siblings, 0 replies; 13+ messages in thread
From: Piyush Patle @ 2026-04-26 16:43 UTC (permalink / raw)
To: David Lechner
Cc: Jonathan Cameron, Andreas Klinger, Nuno Sá, Andy Shevchenko,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Sun, Apr 26, 2026 at 9:58 PM David Lechner <dlechner@baylibre.com> wrote:
>
> On 4/22/26 12:59 PM, 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) for the HX711, a rate-gpios property for the HX711 RATE
> > pin, and an allOf constraint that forbids HX711-only properties on
> > HX710B nodes. 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 v3:
> > - Drop the vref-supply mention from avdd-supply; no such binding
> > property exists.
>
> Why is there no vref-supply?
>
> HX710B has a VREF pin for a reference voltage input.
>
In v4 I will add vref-supply as an HX710B property and update the
allOf block accordingly.
Regards,
Piyush Patle
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure
2026-04-22 17:59 [PATCH v3 0/3] iio: adc: hx711: add HX710B support Piyush Patle
2026-04-22 17:59 ` [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
@ 2026-04-22 17:59 ` Piyush Patle
2026-04-22 20:16 ` Andy Shevchenko
` (2 more replies)
2026-04-22 17:59 ` [PATCH v3 3/3] iio: adc: hx711: add support for HX710B Piyush Patle
2 siblings, 3 replies; 13+ messages in thread
From: Piyush Patle @ 2026-04-22 17:59 UTC (permalink / raw)
To: Jonathan Cameron, Andreas Klinger
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
devicetree, linux-kernel
Introduce hx711_chip_info to hold per-variant static configuration:
device name, IIO channel spec, channel count, and iio_info pointer.
Store a chip_info pointer in hx711_data and populate indio_dev fields
from it at probe instead of hardcoding them.
Pass trailing pulse count directly to hx711_read() instead of
computing it inside the function, and change hx711_reset_read() to
take a const struct iio_chan_spec * instead of an integer channel
index so callers can pass the full channel descriptor.
Use device_get_match_data() to look up the chip_info from the
of_device_id table. No functional change for existing HX711 users.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
Changes in v3:
- New patch split out from the HX710B support patch.
- Keep this as a standalone refactor for the existing HX711 path.
- Use unsigned int for the channel count and trailing pulse count.
- Use a loop-local unsigned int for the trailing pulse loop.
- Add direct includes for ARRAY_SIZE and basic types.
- Align Kconfig, file header, and module description wording with the
"HX711 and compatible ADCs" phrasing.
Changes in v2:
- N/A; this standalone refactor patch is new in v3.
drivers/iio/adc/Kconfig | 7 ++--
drivers/iio/adc/hx711.c | 92 +++++++++++++++++++++++++++--------------
2 files changed, 65 insertions(+), 34 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 1db8b68a8f64..a444a2872257 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>
@@ -76,12 +78,27 @@ static int hx711_get_scale_to_gain(int scale)
return -EINVAL;
}
+/**
+ * struct hx711_chip_info - per-variant static configuration
+ * @name: IIO device name
+ * @channels: channel specification
+ * @num_channels: number of channels
+ * @iio_info: IIO info ops for this variant
+ */
+struct hx711_chip_info {
+ const char *name;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ const struct iio_info *iio_info;
+};
+
struct hx711_data {
struct device *dev;
struct gpio_desc *gpiod_pd_sck;
struct gpio_desc *gpiod_dout;
int gain_set; /* gain set on device */
int gain_chan_a; /* gain for channel A */
+ const struct hx711_chip_info *chip_info;
struct mutex lock;
/*
* triggered buffer
@@ -92,10 +109,7 @@ struct hx711_data {
aligned_s64 timestamp;
} buffer;
/*
- * delay after a rising edge on SCK until the data is ready DOUT
- * this is dependent on the hx711 where the datasheet tells a
- * maximum value of 100 ns
- * but also on potential parasitic capacities on the wiring
+ * Delay after SCK rising edge before sampling DOUT.
*/
u32 data_ready_delay_ns;
u32 clock_frequency;
@@ -139,9 +153,13 @@ 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)
+/*
+ * Clock out 24 data bits and then send trailing pulses to select the
+ * next channel/gain state.
+ */
+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);
@@ -149,7 +167,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)
@@ -158,7 +176,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;
@@ -213,6 +231,7 @@ static int hx711_reset(struct hx711_data *hx711_data)
return val;
}
+/* Select HX711 channel/gain for the next conversion. */
static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
{
int ret;
@@ -221,7 +240,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;
@@ -233,7 +253,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;
@@ -246,27 +267,24 @@ 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;
- int val;
- /*
- * hx711_reset() must be called from here
- * because it could be calling hx711_read() by itself
- */
+ /* Reset first so the read starts from a known chip state. */
if (hx711_reset(hx711_data)) {
dev_err(hx711_data->dev, "reset failed!");
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;
- 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,
@@ -279,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);
@@ -332,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;
@@ -368,7 +387,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++;
}
@@ -455,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,
+ .num_channels = ARRAY_SIZE(hx711_chan_spec),
+ .iio_info = &hx711_iio_info,
+};
+
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;
@@ -472,6 +499,9 @@ static int hx711_probe(struct platform_device *pdev)
mutex_init(&hx711_data->lock);
+ chip_info = device_get_match_data(dev);
+ 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
@@ -517,6 +547,8 @@ static int hx711_probe(struct platform_device *pdev)
hx711_data->gain_set = 128;
hx711_data->gain_chan_a = 128;
+ indio_dev->info = chip_info->iio_info;
+
hx711_data->clock_frequency = 400000;
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
&hx711_data->clock_frequency);
@@ -533,11 +565,10 @@ 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->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,
@@ -554,7 +585,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 },
{ }
};
@@ -571,7 +602,6 @@ 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] 13+ messages in thread* Re: [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure
2026-04-22 17:59 ` [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure Piyush Patle
@ 2026-04-22 20:16 ` Andy Shevchenko
2026-04-24 11:53 ` Jonathan Cameron
2026-04-24 12:14 ` Jonathan Cameron
2 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-04-22 20:16 UTC (permalink / raw)
To: Piyush Patle
Cc: Jonathan Cameron, Andreas Klinger, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, Apr 22, 2026 at 11:29:09PM +0530, Piyush Patle wrote:
...
> 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
This along with top comment and other text doesn't belong to the change, please
split into separate patch.
> +/**
> + * struct hx711_chip_info - per-variant static configuration
> + * @name: IIO device name
> + * @channels: channel specification
> + * @num_channels: number of channels
> + * @iio_info: IIO info ops for this variant
> + */
> +struct hx711_chip_info {
> + const char *name;
> + const struct iio_chan_spec *channels;
> + unsigned int num_channels;
> + const struct iio_info *iio_info;
> +};
...
> /*
> - * delay after a rising edge on SCK until the data is ready DOUT
> - * this is dependent on the hx711 where the datasheet tells a
> - * maximum value of 100 ns
> - * but also on potential parasitic capacities on the wiring
> + * Delay after SCK rising edge before sampling DOUT.
> */
Doesn't seem like a part of this change.
...
> - for (i = 0; i < 24; i++) {
> + for (int i = 0; i < 24; i++) {
Be consistent. Why here is 'i' signed?
In any case doesn't belong to this change.
...
> - ret = hx711_read(hx711_data);
> + ret = hx711_read(hx711_data,
> + hx711_get_gain_to_pulse(hx711_data->gain_set));
This sounds like a separate change to me.
...
> -MODULE_DESCRIPTION("HX711 bitbanging driver - ADC for weight cells");
> +MODULE_DESCRIPTION("HX711 and compatible bitbanging ADC driver");
Doesn't belong to this change.
...
This needs to be split to 3 or even more patches!
- text in the MODULE_*(), top comments, and Kconfig
- chip_info initial change
- modifying the existing code to prepare for new HW support
(the above ^^^ might be done in a couple of patches)
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure
2026-04-22 17:59 ` [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure Piyush Patle
2026-04-22 20:16 ` Andy Shevchenko
@ 2026-04-24 11:53 ` Jonathan Cameron
2026-04-24 12:14 ` Jonathan Cameron
2 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2026-04-24 11:53 UTC (permalink / raw)
To: Piyush Patle
Cc: Andreas Klinger, David Lechner, Nuno Sá, Andy Shevchenko,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, 22 Apr 2026 23:29:09 +0530
Piyush Patle <piyushpatle228@gmail.com> wrote:
> Introduce hx711_chip_info to hold per-variant static configuration:
> device name, IIO channel spec, channel count, and iio_info pointer.
> Store a chip_info pointer in hx711_data and populate indio_dev fields
> from it at probe instead of hardcoding them.
>
> Pass trailing pulse count directly to hx711_read() instead of
> computing it inside the function, and change hx711_reset_read() to
> take a const struct iio_chan_spec * instead of an integer channel
> index so callers can pass the full channel descriptor.
>
> Use device_get_match_data() to look up the chip_info from the
> of_device_id table. No functional change for existing HX711 users.
>
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
One trivial additional thing from me. The white space tweak at the
end is correct but not in a patch doing anything else.
Maybe that would be ok in the one Andy is suggesting that includes
the update to the text just above it (though mention it in the commit
message as a 'whilst here'). Or just check for other whitespace
cleanup and do a patch just for those.
> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> index 1db8b68a8f64..a444a2872257 100644
> --- a/drivers/iio/adc/hx711.c
> +++ b/drivers/iio/adc/hx711.c
> @@ -571,7 +602,6 @@ 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");
> -
Stray change. Check patches after you generate them for stuff like this.
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure
2026-04-22 17:59 ` [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure Piyush Patle
2026-04-22 20:16 ` Andy Shevchenko
2026-04-24 11:53 ` Jonathan Cameron
@ 2026-04-24 12:14 ` Jonathan Cameron
2 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2026-04-24 12:14 UTC (permalink / raw)
To: Piyush Patle
Cc: Andreas Klinger, David Lechner, Nuno Sá, Andy Shevchenko,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, 22 Apr 2026 23:29:09 +0530
Piyush Patle <piyushpatle228@gmail.com> wrote:
> Introduce hx711_chip_info to hold per-variant static configuration:
> device name, IIO channel spec, channel count, and iio_info pointer.
> Store a chip_info pointer in hx711_data and populate indio_dev fields
> from it at probe instead of hardcoding them.
>
> Pass trailing pulse count directly to hx711_read() instead of
> computing it inside the function, and change hx711_reset_read() to
> take a const struct iio_chan_spec * instead of an integer channel
> index so callers can pass the full channel descriptor.
>
> Use device_get_match_data() to look up the chip_info from the
> of_device_id table. No functional change for existing HX711 users.
>
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Couple of things sashiko raised on this...
One about hx711_gain_to_scale() is an existing driver bug.
Need to take a per instance copy of that so as to support
more than one sensor. Ideally fix that whilst you are touching the
driver (as a precursor patch - maybe we'll backport it) but if you
want to leave it for another day then just say that in the cover letter.
The other one about matching via non DT routes is an interesting corner
that i suspect applies to other drivers. The module alias in this
driver is also rather odd.
>
> @@ -571,7 +602,6 @@ 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");
So Sashiko thinks (and it's plausible) that this module alias is a problem
as if the driver match is against it might be possible to probe the
driver without the match data getting set. I think it's referring to
the final driver match fallback path
https://elixir.bootlin.com/linux/v7.0/source/drivers/base/platform.c#L1370
Whilst unlikely anyone would get to this, I guess the fix is to ensure
we get a match by having a platform_device_id table for legacy matching
and making sure that covers such a match and provides data.
We don't (I think) currently have an equivalent of the catch all matching
functions that exist for i2c and spi.
Bit ugly for platform data as I think you need to get it via
platform_get_device_id()
Maybe we just check if device_get_match_data() returns NULL and fail instead.
> -
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 3/3] iio: adc: hx711: add support for HX710B
2026-04-22 17:59 [PATCH v3 0/3] iio: adc: hx711: add HX710B support Piyush Patle
2026-04-22 17:59 ` [PATCH v3 1/3] dt-bindings: iio: adc: avia-hx711: add avia,hx710b compatible Piyush Patle
2026-04-22 17:59 ` [PATCH v3 2/3] iio: adc: hx711: refactor to per-chip hx711_chip_info structure Piyush Patle
@ 2026-04-22 17:59 ` Piyush Patle
2026-04-22 20:20 ` Andy Shevchenko
2026-04-24 12:19 ` Jonathan Cameron
2 siblings, 2 replies; 13+ messages in thread
From: Piyush Patle @ 2026-04-22 17:59 UTC (permalink / raw)
To: Jonathan Cameron, Andreas Klinger
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, 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 between the differential input and the DVDD-AVDD supply
monitor.
Model the HX710B with its own channel specification and iio_info.
Store the HX710B trailing pulse counts in chan->address and add
fixed-gain handling so the HX711 selectable-gain path remains
separate from the HX710B fixed-gain path.
The HX710B datasheet documents a single fixed PGA gain of 128 and
does not provide configurable gain selection like the HX711.
Order hx711_chip_info as pointers first, then unsigned int fields, then
bool. pahole then reports no internal holes in the structure; the
remaining padding is tail padding from 8-byte alignment.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
---
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 | 134 +++++++++++++++++++++++++++++++++++-----
2 files changed, 120 insertions(+), 15 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 a444a2872257..d7050bec53b4 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -82,14 +82,18 @@ static int hx711_get_scale_to_gain(int scale)
* struct hx711_chip_info - per-variant static configuration
* @name: IIO device name
* @channels: channel specification
- * @num_channels: number of channels
* @iio_info: IIO info ops for this variant
+ * @num_channels: number of channels
+ * @fixed_gain: true if the variant has a fixed ADC gain (e.g. HX710B)
+ * @fixed_gain_val: the fixed gain value used to compute scale (when fixed_gain)
*/
struct hx711_chip_info {
const char *name;
const struct iio_chan_spec *channels;
- unsigned int num_channels;
const struct iio_info *iio_info;
+ unsigned int num_channels;
+ unsigned int fixed_gain_val;
+ bool fixed_gain;
};
struct hx711_data {
@@ -98,6 +102,8 @@ struct hx711_data {
struct gpio_desc *gpiod_dout;
int gain_set; /* gain set on device */
int gain_chan_a; /* gain for channel A */
+ unsigned int channel_set; /* HX710B current channel */
+ unsigned int scale; /* HX710B fixed scale */
const struct hx711_chip_info *chip_info;
struct mutex lock;
/*
@@ -206,6 +212,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) {
@@ -224,8 +231,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;
+ /* Restore variant default after reset. */
+ if (info->fixed_gain)
+ hx711_data->channel_set = 0;
+ else
+ hx711_data->gain_set = HX711_RESET_GAIN;
}
return val;
@@ -267,9 +277,32 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
return 0;
}
+/* Select HX710B channel for the next conversion. */
+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 +312,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 +332,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,7 +349,10 @@ 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);
+ if (info->fixed_gain)
+ *val2 = hx711_data->scale;
+ else
+ *val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
mutex_unlock(&hx711_data->lock);
@@ -442,6 +486,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,
@@ -474,6 +522,48 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
IIO_CHAN_SOFT_TIMESTAMP(2),
};
+/*
+ * HX710B channels.
+ * Channel 0: differential input (IN+ vs IN-), 10 SPS, 1 trailing pulse.
+ * Channel 1: DVDD-AVDD supply monitor, 40 SPS, 2 trailing pulses.
+ * .address holds the trailing pulse count used by hx710b_set_channel().
+ */
+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 = 1,
+ .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,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
static const struct hx711_chip_info hx711_chip = {
.name = "hx711",
.channels = hx711_chan_spec,
@@ -481,6 +571,15 @@ static const struct hx711_chip_info hx711_chip = {
.iio_info = &hx711_iio_info,
};
+static const struct hx711_chip_info hx710b_chip = {
+ .name = "hx710b",
+ .channels = hx710b_chan_spec,
+ .num_channels = ARRAY_SIZE(hx710b_chan_spec),
+ .iio_info = &hx710b_iio_info,
+ .fixed_gain = true,
+ .fixed_gain_val = 128,
+};
+
static int hx711_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -540,12 +639,16 @@ static int hx711_probe(struct platform_device *pdev)
/* we need 10^-9 mV */
ret *= 100;
- for (i = 0; i < HX711_GAIN_MAX; i++)
- hx711_gain_to_scale[i].scale =
- 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_gain_to_scale[i].scale =
+ 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;
+ }
indio_dev->info = chip_info->iio_info;
@@ -585,7 +688,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] 13+ messages in thread* Re: [PATCH v3 3/3] iio: adc: hx711: add support for HX710B
2026-04-22 17:59 ` [PATCH v3 3/3] iio: adc: hx711: add support for HX710B Piyush Patle
@ 2026-04-22 20:20 ` Andy Shevchenko
2026-04-24 12:19 ` Jonathan Cameron
1 sibling, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2026-04-22 20:20 UTC (permalink / raw)
To: Piyush Patle
Cc: Jonathan Cameron, Andreas Klinger, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, Apr 22, 2026 at 11:29:10PM +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 between the differential input and the DVDD-AVDD supply
> monitor.
>
> Model the HX710B with its own channel specification and iio_info.
> Store the HX710B trailing pulse counts in chan->address and add
> fixed-gain handling so the HX711 selectable-gain path remains
> separate from the HX710B fixed-gain path.
>
> The HX710B datasheet documents a single fixed PGA gain of 128 and
> does not provide configurable gain selection like the HX711.
>
> Order hx711_chip_info as pointers first, then unsigned int fields, then
> bool. pahole then reports no internal holes in the structure; the
> remaining padding is tail padding from 8-byte alignment.
>
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
> ---
> 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.
...
> * struct hx711_chip_info - per-variant static configuration
> * @name: IIO device name
> * @channels: channel specification
> - * @num_channels: number of channels
> * @iio_info: IIO info ops for this variant
> + * @num_channels: number of channels
> struct hx711_chip_info {
> - unsigned int num_channels;
> const struct iio_info *iio_info;
> + unsigned int num_channels;
> };
No ping-pong patches, please. If you know the result, place the field in the
structure and kernel-doc in the place where it will stay during the entire
chain of changes in the same series. I.o.w. ideally you must have no '-' lines
_at all_ in this patch.
...
Also, split to a couple more preparatory patches. Altogether I expect this
series to be ~7 patches or more.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v3 3/3] iio: adc: hx711: add support for HX710B
2026-04-22 17:59 ` [PATCH v3 3/3] iio: adc: hx711: add support for HX710B Piyush Patle
2026-04-22 20:20 ` Andy Shevchenko
@ 2026-04-24 12:19 ` Jonathan Cameron
1 sibling, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2026-04-24 12:19 UTC (permalink / raw)
To: Piyush Patle
Cc: Andreas Klinger, David Lechner, Nuno Sá, Andy Shevchenko,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-iio, devicetree, linux-kernel
On Wed, 22 Apr 2026 23:29:10 +0530
Piyush Patle <piyushpatle228@gmail.com> 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 between the differential input and the DVDD-AVDD supply
> monitor.
>
> Model the HX710B with its own channel specification and iio_info.
> Store the HX710B trailing pulse counts in chan->address and add
> fixed-gain handling so the HX711 selectable-gain path remains
> separate from the HX710B fixed-gain path.
>
> The HX710B datasheet documents a single fixed PGA gain of 128 and
> does not provide configurable gain selection like the HX711.
>
> Order hx711_chip_info as pointers first, then unsigned int fields, then
> bool. pahole then reports no internal holes in the structure; the
> remaining padding is tail padding from 8-byte alignment.
>
> Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
> ---
> 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.
Just to confirm - you verified this? It does seem very odd as that
might well take a large value.
> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> index a444a2872257..d7050bec53b4 100644
> --- a/drivers/iio/adc/hx711.c
> +++ b/drivers/iio/adc/hx711.c
> +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,
> @@ -474,6 +522,48 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
> IIO_CHAN_SOFT_TIMESTAMP(2),
> };
>
> +/*
> + * HX710B channels.
> + * Channel 0: differential input (IN+ vs IN-), 10 SPS, 1 trailing pulse.
> + * Channel 1: DVDD-AVDD supply monitor, 40 SPS, 2 trailing pulses.
> + * .address holds the trailing pulse count used by hx710b_set_channel().
> + */
> +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 = 1,
Sashiko is winning today. See it's comment on the indexing wich is
spot on.
https://sashiko.dev/#/patchset/20260422175910.1258579-1-piyushpatle228%40gmail.com
This should be channel = 2 or given it's actually a differential measurement, maybe
invent channels 2 and 3 so you can represent it as that. If useful label
can be used to provide info on this magic channel to userspace.
> + .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,
> + },
> + },
> + IIO_CHAN_SOFT_TIMESTAMP(2),
> +};
...
> +
> static int hx711_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -540,12 +639,16 @@ static int hx711_probe(struct platform_device *pdev)
> /* we need 10^-9 mV */
> ret *= 100;
>
> - for (i = 0; i < HX711_GAIN_MAX; i++)
> - hx711_gain_to_scale[i].scale =
> - 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_gain_to_scale[i].scale =
> + ret / hx711_gain_to_scale[i].gain / 1678;
Just to point it out, this is the update of the global variable I mentioned
Sashiko spotting as broken in my reply to previous patch.
>
^ permalink raw reply [flat|nested] 13+ messages in thread