Re: [PATCH v3] hwmon: (ads7828) Fix external VREF regulator handling
Guenter Roeck <[email protected]> Tue, 4 Aug 2026 22:32:07 -0700
| Newsgroups | org.kernel.vger.linux-hwmon,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 8/4/26 21:21, Qingshuang Fu wrote: > From: Qingshuang Fu <[email protected]> > > The driver currently has two issues with the external VREF regulator > handling in ads7828_probe(): > > 1. All errors from devm_regulator_get_optional() are ignored, causing the > driver to incorrectly fall back to internal VREF even for transient > errors like -EPROBE_DEFER or genuine failures like -ENOMEM. > > 2. The external regulator is never enabled. The driver calls > regulator_get_voltage() without first calling regulator_enable(), > so the VREF pin may remain unpowered if the regulator is not > configured as always-on. > > Fix both issues by switching to devm_regulator_get_enable_read_voltage(), > which handles regulator get, enable, and voltage read in one call. > Only -ENODEV (no regulator specified in device tree) should trigger the > fallback to internal VREF. All other errors are propagated to the caller. > > Fixes: a8ddfea09566 ("hwmon: (ads7828) Accept optional parameters from device tree") > Signed-off-by: Qingshuang Fu <[email protected]> > --- > Changes in v3: > - Switch to devm_regulator_get_enable_read_voltage() to also enable the > external regulator, as suggested by Guenter Roeck. > Changes in v2: > - Broaden the error check to handle all errors except -ENODEV, instead of > only checking for -EPROBE_DEFER. This addresses the Sashiko AI review > concern about masking genuine errors like -ENOMEM and -EINVAL. > > drivers/hwmon/ads7828.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c > index 149cfcec78dc..172da6f6549d 100644 > --- a/drivers/hwmon/ads7828.c > +++ b/drivers/hwmon/ads7828.c > @@ -106,12 +106,11 @@ static int ads7828_probe(struct i2c_client *client) > struct ads7828_data *data; > struct device *hwmon_dev; > unsigned int vref_mv = ADS7828_INT_VREF_MV; > - unsigned int vref_uv; > + int vref_uv; > bool diff_input = false; > bool ext_vref = false; > unsigned int regval; > enum ads7828_chips chip; > - struct regulator *reg; > > data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); > if (!data) > @@ -125,14 +124,15 @@ static int ads7828_probe(struct i2c_client *client) > } else if (dev->of_node) { > diff_input = of_property_read_bool(dev->of_node, > "ti,differential-input"); > - reg = devm_regulator_get_optional(dev, "vref"); > - if (!IS_ERR(reg)) { > - vref_uv = regulator_get_voltage(reg); > + vref_uv = devm_regulator_get_enable_read_voltage(dev, "vref"); > + if (vref_uv >= 0) { Please use if (IS_ERR(vref_uv)) { if (vref_uv != -ENODEV) return vref_uv; } else { ... Thanks, Guenter > vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000); > if (vref_mv < ADS7828_EXT_VREF_MV_MIN || > vref_mv > ADS7828_EXT_VREF_MV_MAX) > return -EINVAL; > ext_vref = true; > + } else if (vref_uv != -ENODEV) { > + return vref_uv; > } > } >