]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iio: dac: mcp47feb02: Fix Vref validation [1-999] case
authorAriana Lazar <ariana.lazar@microchip.com>
Tue, 10 Mar 2026 11:56:44 +0000 (13:56 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sun, 15 Mar 2026 12:27:41 +0000 (12:27 +0000)
Store reference voltages in uV instead of mV to avoid invalid error code
in dev_err_probe() call. Vref variables store the actual value returned by
devm_regulator_get_enable_read_voltage() function instead of the results of
dividing it by MILLI. The corner case [1-999] divided by MILLI of the
voltage reference variable value would become 0 is covered too.

Fixes: bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02")
Link: https://lore.kernel.org/all/aYXvP5FLA5BvkoVX@stanley.mountain/
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/dac/mcp47feb02.c

index 08fb85359697695c310de481d087871b5e8e0510..faccb804a5ed548088aaf83266b16ed45a92916c 100644 (file)
@@ -65,7 +65,7 @@
 #define MCP47FEB02_MAX_SCALES_CH                       3
 #define MCP47FEB02_DAC_WIPER_UNLOCKED                  0
 #define MCP47FEB02_NORMAL_OPERATION                    0
-#define MCP47FEB02_INTERNAL_BAND_GAP_mV                        2440
+#define MCP47FEB02_INTERNAL_BAND_GAP_uV                        2440000
 #define NV_DAC_ADDR_OFFSET                             0x10
 
 enum mcp47feb02_vref_mode {
@@ -697,44 +697,40 @@ static const struct iio_chan_spec mcp47febxx_ch_template = {
 };
 
 static void mcp47feb02_init_scale(struct mcp47feb02_data *data, enum mcp47feb02_scale scale,
-                                 int vref_mV, int scale_avail[])
+                                 int vref_uV, int scale_avail[])
 {
        u32 value_micro, value_int;
        u64 tmp;
 
-       /* vref_mV should not be negative */
-       tmp = (u64)vref_mV * MICRO >> data->chip_features->resolution;
+       /* vref_uV should not be negative */
+       tmp = (u64)vref_uV * MILLI >> data->chip_features->resolution;
        value_int = div_u64_rem(tmp, MICRO, &value_micro);
        scale_avail[scale * 2] = value_int;
        scale_avail[scale * 2 + 1] = value_micro;
 }
 
-static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
-                                       int vref_mV, int vref1_mV)
+static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_uV,
+                                       int vref_uV, int vref1_uV)
 {
-       struct device *dev = regmap_get_device(data->regmap);
        int tmp_vref;
 
-       mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
+       mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_uV, data->scale);
 
        if (data->use_vref)
-               tmp_vref = vref_mV;
+               tmp_vref = vref_uV;
        else
-               tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
+               tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_uV;
 
        mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
        mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
 
        if (data->phys_channels >= 4) {
-               mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
-
-               if (data->use_vref1 && vref1_mV <= 0)
-                       return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
+               mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_uV, data->scale_1);
 
                if (data->use_vref1)
-                       tmp_vref = vref1_mV;
+                       tmp_vref = vref1_uV;
                else
-                       tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
+                       tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_uV;
 
                mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1,
                                      tmp_vref, data->scale_1);
@@ -1078,8 +1074,8 @@ static int mcp47feb02_init_ctrl_regs(struct mcp47feb02_data *data)
        return 0;
 }
 
-static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_mV,
-                                    int vref_mV, int vref1_mV)
+static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_uV,
+                                    int vref_uV, int vref1_uV)
 {
        unsigned int i;
 
@@ -1087,7 +1083,7 @@ static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_mV,
                struct device *dev = regmap_get_device(data->regmap);
                int ret;
 
-               ret = mcp47feb02_init_scales_avail(data, vdd_mV, vref_mV, vref1_mV);
+               ret = mcp47feb02_init_scales_avail(data, vdd_uV, vref_uV, vref1_uV);
                if (ret)
                        return dev_err_probe(dev, ret, "failed to init scales for ch %u\n", i);
        }
@@ -1101,10 +1097,7 @@ static int mcp47feb02_probe(struct i2c_client *client)
        struct device *dev = &client->dev;
        struct mcp47feb02_data *data;
        struct iio_dev *indio_dev;
-       int vref1_mV = 0;
-       int vref_mV = 0;
-       int vdd_mV;
-       int ret;
+       int vref1_uV, vref_uV, vdd_uV, ret;
 
        indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
        if (!indio_dev)
@@ -1141,13 +1134,14 @@ static int mcp47feb02_probe(struct i2c_client *client)
        if (ret < 0)
                return ret;
 
-       vdd_mV = ret / MILLI;
+       vdd_uV = ret;
 
        ret = devm_regulator_get_enable_read_voltage(dev, "vref");
        if (ret > 0) {
-               vref_mV = ret / MILLI;
+               vref_uV = ret;
                data->use_vref = true;
        } else {
+               vref_uV = 0;
                dev_dbg(dev, "using internal band gap as voltage reference.\n");
                dev_dbg(dev, "Vref is unavailable.\n");
        }
@@ -1155,9 +1149,10 @@ static int mcp47feb02_probe(struct i2c_client *client)
        if (chip_features->have_ext_vref1) {
                ret = devm_regulator_get_enable_read_voltage(dev, "vref1");
                if (ret > 0) {
-                       vref1_mV = ret / MILLI;
+                       vref1_uV = ret;
                        data->use_vref1 = true;
                } else {
+                       vref1_uV = 0;
                        dev_dbg(dev, "using internal band gap as voltage reference 1.\n");
                        dev_dbg(dev, "Vref1 is unavailable.\n");
                }
@@ -1167,7 +1162,7 @@ static int mcp47feb02_probe(struct i2c_client *client)
        if (ret)
                return dev_err_probe(dev, ret, "Error initialising vref register\n");
 
-       ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV);
+       ret = mcp47feb02_init_ch_scales(data, vdd_uV, vref_uV, vref1_uV);
        if (ret)
                return ret;