Convert to with_info API to simplify the code and make it easier to maintain. The conversion reduces code size by about 25%. No functional change intended. Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx> --- drivers/hwmon/g762.c | 473 ++++++++++++++++--------------------------- 1 file changed, 180 insertions(+), 293 deletions(-) diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index 5f8fd723a694..e513cd47fade 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -35,7 +35,6 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> @@ -154,11 +153,11 @@ static int do_set_clk_freq(struct device *dev, unsigned long val) } /* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */ -static int do_set_pwm_mode(struct device *dev, unsigned long val) +static int do_set_pwm_mode(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); - if (val && val != 1) + if (val < 0 || val > 1) return -EINVAL; return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1, @@ -167,11 +166,11 @@ static int do_set_pwm_mode(struct device *dev, unsigned long val) } /* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */ -static int do_set_fan_div(struct device *dev, unsigned long val) +static int do_set_fan_div(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); - if (hweight_long(val) != 1 || val > 8) + if (val < 0 || hweight_long(val) != 1 || val > 8) return -EINVAL; return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1, @@ -193,7 +192,7 @@ static int do_set_fan_gear_mode(struct device *dev, u32 val) } /* Set number of fan pulses per revolution. Accepts either 2 or 4. */ -static int do_set_fan_pulses(struct device *dev, unsigned long val) +static int do_set_fan_pulses(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); @@ -206,7 +205,7 @@ static int do_set_fan_pulses(struct device *dev, unsigned long val) } /* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */ -static int do_set_pwm_enable(struct device *dev, unsigned long val) +static int do_set_pwm_enable(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); struct regmap *regmap = data->regmap; @@ -255,11 +254,11 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val) * Set pwm value. Accepts values between 0 (stops the fan) and * 255 (full speed). This only makes sense in open-loop mode. */ -static int do_set_pwm(struct device *dev, unsigned long val) +static int do_set_pwm(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); - if (val > 255) + if (val < 0 || val > 255) return -EINVAL; return regmap_write(data->regmap, G762_REG_SET_OUT, val); @@ -269,7 +268,7 @@ static int do_set_pwm(struct device *dev, unsigned long val) * Set fan RPM value. Can be called both in closed and open-loop mode * but effect will only be seen after closed-loop mode is configured. */ -static int do_set_fan_target(struct device *dev, unsigned long val) +static int do_set_fan_target(struct device *dev, long val) { struct g762_data *data = dev_get_drvdata(dev); struct regmap *regmap = data->regmap; @@ -277,6 +276,9 @@ static int do_set_fan_target(struct device *dev, unsigned long val) u8 set_cnt; int ret; + if (val < 0) + return -EINVAL; + mutex_lock(&data->update_lock); ret = regmap_read(regmap, G762_REG_FAN_CMD1, &cmd1); @@ -346,317 +348,201 @@ static int get_fan_rpm(struct g762_data *data, int reg) return ret; } -/* - * Read function for fan1_input sysfs file. Return current fan RPM value, or - * 0 if fan is out of control. - */ -static ssize_t fan1_input_show(struct device *dev, - struct device_attribute *da, char *buf) +static int g762_fan_read(struct device *dev, u32 attr, long *val) { struct g762_data *data = dev_get_drvdata(dev); - u32 status; + u32 regval; int ret; - mutex_lock(&data->update_lock); - ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status); - /* reverse logic: fan out of control reporting is enabled low */ - if (ret || !(status & G762_REG_FAN_STA_OOC)) - goto unlock; - - ret = get_fan_rpm_locked(data, G762_REG_ACT_CNT); - if (ret < 0) - goto unlock; - - ret = sprintf(buf, "%u\n", ret); -unlock: - mutex_unlock(&data->update_lock); - return ret; + switch (attr) { + case hwmon_fan_target: + ret = get_fan_rpm(data, G762_REG_SET_CNT); + if (ret < 0) + return ret; + *val = ret; + break; + case hwmon_fan_div: + ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, ®val); + if (ret < 0) + return ret; + *val = G762_CLKDIV_FROM_REG(regval); + break; + case hwmon_fan_pulses: + ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, ®val); + if (ret < 0) + return ret; + *val = G762_PULSE_FROM_REG(regval); + break; + case hwmon_fan_input: + mutex_lock(&data->update_lock); + ret = regmap_read(data->regmap, G762_REG_FAN_STA, ®val); + if (ret || !(regval & G762_REG_FAN_STA_OOC)) { + mutex_unlock(&data->update_lock); + return ret ? : -ENODATA; + } + ret = get_fan_rpm_locked(data, G762_REG_ACT_CNT); + mutex_unlock(&data->update_lock); + if (ret < 0) + return ret; + *val = ret; + break; + case hwmon_fan_alarm: + ret = regmap_read(data->regmap, G762_REG_FAN_STA, ®val); + if (ret < 0) + return ret; + /* G762_REG_FAN_STA_OOC is active low */ + *val = !(regval & G762_REG_FAN_STA_OOC); + break; + case hwmon_fan_fault: + ret = regmap_read(data->regmap, G762_REG_FAN_STA, ®val); + if (ret < 0) + return ret; + *val = !!(regval & G762_REG_FAN_STA_FAIL); + break; + default: + return -EOPNOTSUPP; + } + return 0; } -/* - * Read and write functions for pwm1_mode sysfs file. Get and set fan speed - * control mode i.e. PWM (1) or DC (0). - */ -static ssize_t pwm1_mode_show(struct device *dev, struct device_attribute *da, - char *buf) +static int g762_pwm_read(struct device *dev, u32 attr, long *val) { struct g762_data *data = dev_get_drvdata(dev); - u32 cmd1; + u32 regval; int ret; - ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", !!(cmd1 & G762_REG_FAN_CMD1_OUT_MODE)); + switch (attr) { + case hwmon_pwm_input: + ret = regmap_read(data->regmap, G762_REG_SET_OUT, ®val); + if (ret < 0) + return ret; + *val = regval; + break; + case hwmon_pwm_mode: + ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, ®val); + if (ret < 0) + return ret; + *val = !!(regval & G762_REG_FAN_CMD1_OUT_MODE); + break; + case hwmon_pwm_enable: + ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, ®val); + if (ret < 0) + return ret; + *val = !!(regval & G762_REG_FAN_CMD1_FAN_MODE) + 1; + break; + default: + return -EOPNOTSUPP; + } + return 0; } -static ssize_t pwm1_mode_store(struct device *dev, - struct device_attribute *da, const char *buf, - size_t count) +static int g762_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) { - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_pwm_mode(dev, val); - if (ret < 0) - return ret; - - return count; + switch (type) { + case hwmon_fan: + return g762_fan_read(dev, attr, val); + case hwmon_pwm: + return g762_pwm_read(dev, attr, val); + default: + return -EOPNOTSUPP; + } } -/* - * Read and write functions for fan1_div sysfs file. Get and set fan - * controller prescaler value - */ -static ssize_t fan1_div_show(struct device *dev, struct device_attribute *da, - char *buf) +static int g762_fan_write(struct device *dev, u32 attr, long val) { - struct g762_data *data = dev_get_drvdata(dev); - u32 cmd1; - int ret; - - ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1); - if (ret < 0) - return ret; - - return sprintf(buf, "%ld\n", G762_CLKDIV_FROM_REG(cmd1)); + switch (attr) { + case hwmon_fan_target: + return do_set_fan_target(dev, val); + case hwmon_fan_div: + return do_set_fan_div(dev, val); + case hwmon_fan_pulses: + return do_set_fan_pulses(dev, val); + default: + return -EOPNOTSUPP; + } } -static ssize_t fan1_div_store(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) +static int g762_pwm_write(struct device *dev, u32 attr, long val) { - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_fan_div(dev, val); - if (ret < 0) - return ret; - - return count; + switch (attr) { + case hwmon_pwm_input: + return do_set_pwm(dev, val); + case hwmon_pwm_mode: + return do_set_pwm_mode(dev, val); + case hwmon_pwm_enable: + return do_set_pwm_enable(dev, val); + default: + return -EOPNOTSUPP; + } } -/* - * Read and write functions for fan1_pulses sysfs file. Get and set number - * of tachometer pulses per fan revolution. - */ -static ssize_t fan1_pulses_show(struct device *dev, - struct device_attribute *da, char *buf) +static int g762_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) { - struct g762_data *data = dev_get_drvdata(dev); - u32 cmd1; - int ret; - - ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1); - if (ret < 0) - return ret; - - return sprintf(buf, "%ld\n", G762_PULSE_FROM_REG(cmd1)); + switch (type) { + case hwmon_fan: + return g762_fan_write(dev, attr, val); + case hwmon_pwm: + return g762_pwm_write(dev, attr, val); + default: + return -EOPNOTSUPP; + } } -static ssize_t fan1_pulses_store(struct device *dev, - struct device_attribute *da, const char *buf, - size_t count) +static umode_t g762_is_visible(const void *_data, enum hwmon_sensor_types type, + u32 attr, int channel) { - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_fan_pulses(dev, val); - if (ret < 0) - return ret; - - return count; + switch (type) { + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + case hwmon_fan_alarm: + case hwmon_fan_fault: + return 0444; + case hwmon_fan_target: + case hwmon_fan_div: + case hwmon_fan_pulses: + return 0644; + default: + break; + } + break; + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_input: + case hwmon_pwm_mode: + case hwmon_pwm_enable: + return 0644; + default: + break; + } + break; + default: + break; + } + return 0; } -/* - * Read and write functions for pwm1_enable. Get and set fan speed control mode - * (i.e. closed or open-loop). - * - * Following documentation about hwmon's sysfs interface, a pwm1_enable node - * should accept the following: - * - * 0 : no fan speed control (i.e. fan at full speed) - * 1 : manual fan speed control enabled (use pwm[1-*]) (open-loop) - * 2+: automatic fan speed control enabled (use fan[1-*]_target) (closed-loop) - * - * but we do not accept 0 as this mode is not natively supported by the chip - * and it is not emulated by g762 driver. -EINVAL is returned in this case. - */ -static ssize_t pwm1_enable_show(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct g762_data *data = dev_get_drvdata(dev); - u32 cmd1; - int ret; - - ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", - !!(cmd1 & G762_REG_FAN_CMD1_FAN_MODE) + 1); -} - -static ssize_t pwm1_enable_store(struct device *dev, - struct device_attribute *da, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_pwm_enable(dev, val); - if (ret < 0) - return ret; - - return count; -} - -/* - * Read and write functions for pwm1 sysfs file. Get and set pwm value - * (which affects fan speed) in open-loop mode. 0 stops the fan and 255 - * makes it run at full speed. - */ -static ssize_t pwm1_show(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct g762_data *data = dev_get_drvdata(dev); - int ret; - u32 pwm; - - ret = regmap_read(data->regmap, G762_REG_SET_OUT, &pwm); - if (ret < 0) - return ret; - - return sprintf(buf, "%u\n", pwm); -} - -static ssize_t pwm1_store(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_pwm(dev, val); - if (ret < 0) - return ret; - - return count; -} - -/* - * Read and write function for fan1_target sysfs file. Get/set the fan speed in - * closed-loop mode. Speed is given as a RPM value; then the chip will regulate - * the fan speed using pulses from fan tachometer. - * - * Refer to rpm_from_cnt() implementation above to get info about count number - * calculation. - * - * Also note that due to rounding errors it is possible that you don't read - * back exactly the value you have set. - */ -static ssize_t fan1_target_show(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct g762_data *data = dev_get_drvdata(dev); - int rpm; - - rpm = get_fan_rpm(data, G762_REG_SET_CNT); - if (rpm < 0) - return rpm; - - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t fan1_target_store(struct device *dev, - struct device_attribute *da, const char *buf, - size_t count) -{ - unsigned long val; - int ret; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - ret = do_set_fan_target(dev, val); - if (ret < 0) - return ret; - - return count; -} - -/* read function for fan1_fault sysfs file. */ -static ssize_t fan1_fault_show(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct g762_data *data = dev_get_drvdata(dev); - u32 status; - int ret; - - ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status); - if (ret < 0) - return ret; - - return sprintf(buf, "%u\n", !!(status & G762_REG_FAN_STA_FAIL)); -} - -/* - * read function for fan1_alarm sysfs file. Note that OOC condition is - * enabled low - */ -static ssize_t fan1_alarm_show(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct g762_data *data = dev_get_drvdata(dev); - u32 status; - int ret; - - ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status); - if (ret < 0) - return ret; - - return sprintf(buf, "%u\n", !(status & G762_REG_FAN_STA_OOC)); -} - -static DEVICE_ATTR_RW(pwm1); -static DEVICE_ATTR_RW(pwm1_mode); -static DEVICE_ATTR_RW(pwm1_enable); -static DEVICE_ATTR_RO(fan1_input); -static DEVICE_ATTR_RO(fan1_alarm); -static DEVICE_ATTR_RO(fan1_fault); -static DEVICE_ATTR_RW(fan1_target); -static DEVICE_ATTR_RW(fan1_div); -static DEVICE_ATTR_RW(fan1_pulses); - -/* Driver data */ -static struct attribute *g762_attrs[] = { - &dev_attr_fan1_input.attr, - &dev_attr_fan1_alarm.attr, - &dev_attr_fan1_fault.attr, - &dev_attr_fan1_target.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan1_pulses.attr, - &dev_attr_pwm1.attr, - &dev_attr_pwm1_mode.attr, - &dev_attr_pwm1_enable.attr, +static const struct hwmon_channel_info * const g762_info[] = { + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT | + HWMON_F_TARGET | HWMON_F_DIV | HWMON_F_PULSES), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_MODE | HWMON_PWM_ENABLE), NULL }; -ATTRIBUTE_GROUPS(g762); +static const struct hwmon_ops g762_hwmon_ops = { + .is_visible = g762_is_visible, + .read = g762_read, + .write = g762_write, +}; + +static const struct hwmon_chip_info g762_chip_info = { + .ops = &g762_hwmon_ops, + .info = g762_info, +}; /* * Enable both fan failure detection and fan out of control protection. @@ -770,8 +656,9 @@ static int g762_probe(struct i2c_client *client) if (ret) return ret; - hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, - data, g762_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, + data, &g762_chip_info, + NULL); return PTR_ERR_OR_ZERO(hwmon_dev); } -- 2.39.2