]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hwmon: (adt7470) Use cached PWM frequency value
authorLuiz Angelo Daros de Luca <luizluca@gmail.com>
Tue, 28 Jul 2026 00:22:22 +0000 (21:22 -0300)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 28 Jul 2026 00:57:22 +0000 (17:57 -0700)
adt7470_pwm_read() currently ignores failures returned by
pwm1_freq_get(). If the register read fails, the negative error code is
returned through *val while the function itself reports success,
potentially exposing a negative PWM frequency through sysfs.

Fix this by using the cached PWM frequency maintained by the driver,
eliminating the register access from the read path.

Apart from the corrected error propagation and using the cached value,
no functional change is intended.

Fixes: ef67959c4253 ("hwmon: (adt7470) Convert to use regmap")
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Link: https://lore.kernel.org/r/20260727-adt7470_fixes-v2-6-598e38a46ba6@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/adt7470.c

index c6fc7d38d698ce1c6ef7625f040a87f8e06d9481..1fbca4869b7b6507bcf96a564d0d3cd6b93afb93 100644 (file)
@@ -182,6 +182,7 @@ struct adt7470_data {
        u8                      pwm_min[ADT7470_PWM_COUNT];
        s8                      pwm_tmin[ADT7470_PWM_COUNT];
        u8                      pwm_auto_temp[ADT7470_PWM_COUNT];
+       u32                     pwm_freq;
 
        struct task_struct      *auto_update;
        unsigned int            auto_update_interval;
@@ -756,7 +757,7 @@ static ssize_t force_pwm_max_store(struct device *dev,
 }
 
 /* These are the valid PWM frequencies to the nearest Hz */
-static const int adt7470_freq_map[] = {
+static const u32 adt7470_freq_map[] = {
        11, 15, 22, 29, 35, 44, 59, 88, 1400, 22500
 };
 
@@ -796,7 +797,7 @@ static int adt7470_pwm_read(struct device *dev, u32 attr, int channel, long *val
                *val = 1 + data->pwm_automatic[channel];
                break;
        case hwmon_pwm_freq:
-               *val = pwm1_freq_get(dev);
+               *val = data->pwm_freq;
                break;
        default:
                return -EOPNOTSUPP;
@@ -809,12 +810,14 @@ static int pwm1_freq_set(struct device *dev, long freq)
 {
        struct adt7470_data *data = dev_get_drvdata(dev);
        unsigned int low_freq = ADT7470_CFG_LF;
+       u32 closest_freq;
        int index;
        int err;
 
        /* Round the user value given to the closest available frequency */
        index = find_closest(freq, adt7470_freq_map,
                             ARRAY_SIZE(adt7470_freq_map));
+       closest_freq = adt7470_freq_map[index];
 
        if (index >= 8) {
                index -= 8;
@@ -832,6 +835,10 @@ static int pwm1_freq_set(struct device *dev, long freq)
        err = regmap_update_bits(data->regmap, ADT7470_REG_CFG_2,
                                 ADT7470_FREQ_MASK,
                                 index << ADT7470_FREQ_SHIFT);
+       if (err < 0)
+               goto out;
+
+       data->pwm_freq = closest_freq;
 out:
        mutex_unlock(&data->lock);
 
@@ -1285,6 +1292,7 @@ static int adt7470_probe(struct i2c_client *client)
        struct device *dev = &client->dev;
        struct adt7470_data *data;
        struct device *hwmon_dev;
+       int freq_val;
        int err;
 
        data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL);
@@ -1309,6 +1317,14 @@ static int adt7470_probe(struct i2c_client *client)
        if (err < 0)
                return err;
 
+       freq_val = pwm1_freq_get(dev);
+       if (freq_val <= 0) {
+               err = freq_val < 0 ? freq_val : -EINVAL;
+               return err;
+       }
+
+       data->pwm_freq = (u32)freq_val;
+
        /* Register sysfs hooks */
        hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
                                                         &adt7470_chip_info,