rewrote from scratch to implement new hwmon registration API. Signed-off-by: Il Han <corone.il.han@xxxxxxxxx> --- Documentation/hwmon/ctf2304.rst | 9 +- Documentation/hwmon/index.rst | 1 + drivers/hwmon/Kconfig | 5 +- drivers/hwmon/ctf2304.c | 598 +++++++++++++++----------------- 4 files changed, 285 insertions(+), 328 deletions(-) diff --git a/Documentation/hwmon/ctf2304.rst b/Documentation/hwmon/ctf2304.rst index d0e9ef9ea52e..46f4b1671795 100644 --- a/Documentation/hwmon/ctf2304.rst +++ b/Documentation/hwmon/ctf2304.rst @@ -21,8 +21,9 @@ Description This driver implements support for the Sensylink CTF2304 chip. -The CTF2304 controls the speeds of up to four fans using four independent -PWM outputs with local and remote temperature and remote voltage sensing. +The CTF2304 is a system level thermal management solution chip, including +1-channel local temperature, 8-channels remote temperature or voltage monitor +and 4-channels fan speed monitor and driver with I2C/SMBus digital interface. Sysfs entries @@ -31,11 +32,11 @@ Sysfs entries ================== === ======================================================= fan[1-4]_input RO fan tachometer speed in RPM fan[1-4]_target RW desired fan speed in RPM -fan[1-4]_div RW sets the RPM range of the fan. +fan[1-4]_div RW sets the RPM range of the fan pwm[1-4]_enable RW regulator mode, 0=auto temperature mode, 1=manual mode, 2=rpm mode pwm[1-4] RW read: current pwm duty cycle, write: target pwm duty cycle (0-255) -in[1-8]_input RO measured output voltage +in[0-7]_input RO measured output voltage temp[1-9]_input RO measured temperature ================== === ======================================================= diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index f1fe75f596a5..a74cd43a3916 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -54,6 +54,7 @@ Hardware Monitoring Kernel Drivers coretemp corsair-cpro corsair-psu + ctf2304 da9052 da9055 dell-smm-hwmon diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index da9fbb0f8af3..df30a5a921de 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -478,8 +478,9 @@ config SENSORS_CTF2304 tristate "Sensylink CTF2304 sensor chip" depends on I2C help - If you say yes here you get support for PWM and Fan Controller - with temperature and voltage sensing. + If you say yes here you get support for 1-channel local temperature, + 8-channels remote temperature or voltage monitor and 4-channels fan + speed monitor and driver. This driver can also be built as a module. If so, the module will be called ctf2304. diff --git a/drivers/hwmon/ctf2304.c b/drivers/hwmon/ctf2304.c index 5788740a57e5..42939e39babf 100644 --- a/drivers/hwmon/ctf2304.c +++ b/drivers/hwmon/ctf2304.c @@ -8,7 +8,6 @@ #include <linux/err.h> #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/jiffies.h> @@ -47,9 +46,12 @@ #define FAN_RPM_MIN 480 #define FAN_RPM_MAX 1966080 -#define FAN_COUNT_REG_MAX 0xFFF +#define FAN_COUNT_REG_MAX 0xFFF0 -#define TEMP_FROM_REG(reg) (((reg) * 1000) >> 8) +#define TEMP_FROM_REG(reg, tr) ((tr) ? \ + (((((reg) & 0x7FF0) * 1000) >> 8) \ + + ((reg) >> 15) ? -64000 : 0) : \ + (((reg) * 1000) >> 8)) #define VOLT_FROM_REG(reg, fs) ((((reg) >> 4) * (fs)) >> 12) #define DIV_FROM_REG(reg) (1 << (reg)) #define DIV_TO_REG(div) ((div == 8) ? 0x3 : \ @@ -71,7 +73,7 @@ struct ctf2304_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* register values */ @@ -89,6 +91,7 @@ static struct ctf2304_data *ctf2304_update_device(struct device *dev) { struct ctf2304_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; + struct ctf2304_data *ret = data; int i; int rv; @@ -97,427 +100,377 @@ static struct ctf2304_data *ctf2304_update_device(struct device *dev) if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_LOCAL_TEMP); - if (rv >= 0) - data->local_temp = rv; + if (rv < 0) + goto abort; + data->local_temp = rv; for (i = 0; i < NR_CHANNEL; i++) { rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_REMOTE_CHANNEL(i)); - if (rv >= 0) - data->remote_channel[i] = rv; + if (rv < 0) + goto abort; + data->remote_channel[i] = rv; } rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_FAN_CONFIG1); - if (rv >= 0) - data->fan_config1 = rv; + if (rv < 0) + goto abort; + data->fan_config1 = rv; rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_FAN_CONFIG2); - if (rv >= 0) - data->fan_config2 = rv; + if (rv < 0) + goto abort; + data->fan_config2 = rv; rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_FAN_RPM_CTRL); - if (rv >= 0) - data->fan_rpm_ctrl = rv; + if (rv < 0) + goto abort; + data->fan_rpm_ctrl = rv; for (i = 0; i < NR_FAN_CHANNEL; i++) { rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_TACH_COUNT(i)); - if (rv >= 0) - data->tach[i] = rv; + if (rv < 0) + goto abort; + data->tach[i] = rv; rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_PWMOUT(i)); - if (rv >= 0) - data->pwm[i] = rv; + if (rv < 0) + goto abort; + data->pwm[i] = rv; rv = i2c_smbus_read_word_swapped(client, CTF2304_REG_TARGET_COUNT(i)); - if (rv >= 0) - data->target_count[i] = rv; + if (rv < 0) + goto abort; + data->target_count[i] = rv; } data->last_updated = jiffies; data->valid = true; } + goto done; +abort: + data->valid = false; + ret = ERR_PTR(rv); + +done: mutex_unlock(&data->update_lock); return data; } -static int register_to_temp(u16 reg, u16 config) -{ - if (config & CTF2304_FAN_CFG1_TRANGE) - return TEMP_FROM_REG(reg & 0x7FF0) + ((reg >> 15) ? -64000:0); - else - return TEMP_FROM_REG(reg); -} - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) +static int ctf2304_read_temp(struct device *dev, u32 attr, int channel, + long *val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = ctf2304_update_device(dev); u16 reg; - if (attr->index == 0) - reg = data->local_temp; - else - reg = data->remote_channel[attr->index-1]; - - return sprintf(buf, "%d\n", register_to_temp(reg, data->fan_config1)); + switch (attr) { + case hwmon_temp_input: + if (channel == 0) + reg = data->local_temp; + else + reg = data->remote_channel[channel-1]; + *val = TEMP_FROM_REG(reg, (data->fan_config1 + & CTF2304_FAN_CFG1_TRANGE)); + return 0; + default: + return -EOPNOTSUPP; + } } +static const int full_scale[8] = { 2560, CTF2304_VCC, 4096, 2048, 1024, 512, 256, 256 }; + static int get_full_scale(u16 config) { - int full_scale; u8 bits; bits = (config >> CTF2304_FAN_CFG1_MODE_SHIFT) & CTF2304_FAN_CFG1_MODE_MASK; - if (bits == 0x0) - full_scale = 2560; - else if (bits == 0x1) - full_scale = CTF2304_VCC; - else if (bits == 0x2) - full_scale = 4096; - else if (bits == 0x3) - full_scale = 2048; - else if (bits == 0x4) - full_scale = 1024; - else if (bits == 0x5) - full_scale = 512; - else - full_scale = 256; - - return full_scale; + return full_scale[bits]; } -static int register_to_volt(u16 reg, u16 config) +static int ctf2304_read_in(struct device *dev, u32 attr, int channel, + long *val) { - int full_scale; - - full_scale = get_full_scale(config); - - return VOLT_FROM_REG(reg, full_scale); -} - -static ssize_t show_voltage(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ctf2304_data *data = ctf2304_update_device(dev); - int voltage; - - voltage = register_to_volt(data->remote_channel[attr->index], - data->fan_config1); - - return sprintf(buf, "%d\n", voltage); -} - -static ssize_t get_fan(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = ctf2304_update_device(dev); - int rpm; - rpm = RPM_FROM_REG(data->tach[attr->index]); - - return sprintf(buf, "%d\n", rpm); + switch (attr) { + case hwmon_temp_input: + *val = VOLT_FROM_REG(data->remote_channel[channel], + get_full_scale(data->fan_config1)); + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t get_fan_target(struct device *dev, - struct device_attribute *devattr, char *buf) +static int ctf2304_read_fan(struct device *dev, u32 attr, int channel, + long *val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = ctf2304_update_device(dev); - int rpm; - - rpm = RPM_FROM_REG(data->target_count[attr->index]); + u8 bits; - return sprintf(buf, "%d\n", rpm); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (attr) { + case hwmon_fan_input: + if (data->tach[channel] == FAN_COUNT_REG_MAX) + *val = 0; + else + *val = RPM_FROM_REG(data->tach[channel]); + return 0; + case hwmon_fan_target: + *val = RPM_FROM_REG(data->target_count[channel]); + return 0; + case hwmon_fan_div: + bits = (data->fan_rpm_ctrl & CTF2304_FAN_DIV_MASK(channel)) + >> CTF2304_FAN_DIV_SHIFT(channel); + *val = DIV_FROM_REG(bits); + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t set_fan_target(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static int ctf2304_write_fan(struct device *dev, u32 attr, int channel, + long val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - unsigned long rpm; int target_count; - int err; - - err = kstrtoul(buf, 10, &rpm); - if (err) - return err; - - rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX); - target_count = RPM_TO_REG(rpm); - target_count = clamp_val(target_count, 0x1, 0xFFF); + int err = 0; mutex_lock(&data->update_lock); - data->target_count[attr->index] = target_count << 4; - i2c_smbus_write_word_swapped(client, - CTF2304_REG_TARGET_COUNT(attr->index), - data->target_count[attr->index]); + switch (attr) { + case hwmon_fan_target: + val = clamp_val(val, FAN_RPM_MIN, FAN_RPM_MAX); + target_count = RPM_TO_REG(val); + target_count = clamp_val(target_count, 0x1, 0xFFF); + data->target_count[channel] = target_count << 4; + err = i2c_smbus_write_word_swapped(client, + CTF2304_REG_TARGET_COUNT(channel), + data->target_count[channel]); + break; + case hwmon_fan_div: + data->fan_rpm_ctrl = (data->fan_rpm_ctrl + & ~CTF2304_FAN_DIV_MASK(channel)) + | (DIV_TO_REG(val) + << CTF2304_FAN_DIV_SHIFT(channel)); + err = i2c_smbus_write_word_swapped(client, + CTF2304_REG_FAN_RPM_CTRL, + data->fan_rpm_ctrl); + break; + default: + err = -EOPNOTSUPP; + break; + } mutex_unlock(&data->update_lock); - return count; + return err; } -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *devattr, char *buf) +static int ctf2304_read_pwm(struct device *dev, u32 attr, int channel, + long *val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = ctf2304_update_device(dev); u8 bits; - bits = (data->fan_rpm_ctrl & CTF2304_FAN_DIV_MASK(attr->index)) - >> CTF2304_FAN_DIV_SHIFT(attr->index); - - return sprintf(buf, "%d\n", DIV_FROM_REG(bits)); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (attr) { + case hwmon_pwm_input: + *val = data->pwm[channel] >> 8; + return 0; + case hwmon_pwm_enable: + bits = (data->fan_config2 + & CTF2304_FAN_CFG2_MODE_MASK(channel)) + >> CTF2304_FAN_CFG2_MODE_SHIFT(channel); + if (bits == CTF2304_FAN_CFG2_RPM_MODE) + *val = 2; + else if (bits == CTF2304_FAN_CFG2_DCY_MODE) + *val = 1; + else + *val = 0; + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t set_fan_div(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static int ctf2304_write_pwm(struct device *dev, u32 attr, int channel, + long val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct ctf2304_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - unsigned long div; - int err; - - err = kstrtoul(buf, 10, &div); - if (err) - return err; + int err = 0; mutex_lock(&data->update_lock); - data->fan_rpm_ctrl = (data->fan_rpm_ctrl - & ~CTF2304_FAN_DIV_MASK(attr->index)) - | (DIV_TO_REG(div) - << CTF2304_FAN_DIV_SHIFT(attr->index)); - - i2c_smbus_write_word_swapped(client, - CTF2304_REG_FAN_RPM_CTRL, data->fan_rpm_ctrl); + switch (attr) { + case hwmon_pwm_input: + if (val < 0 || val > 255) { + err = -EINVAL; + break; + } + data->pwm[channel] = (data->pwm[channel] & 0xFF) | (val << 8); + err = i2c_smbus_write_word_swapped(client, + CTF2304_REG_PWMOUT(channel), + data->pwm[channel]); + break; + case hwmon_pwm_enable: + if (val == 0) { + data->fan_config2 = (data->fan_config2 + & ~CTF2304_FAN_CFG2_MODE_MASK(channel)) + | (CTF2304_FAN_CFG2_TEMP_MODE + << CTF2304_FAN_CFG2_MODE_SHIFT(channel)); + } else if (val == 1) { + data->fan_config2 = (data->fan_config2 + & ~CTF2304_FAN_CFG2_MODE_MASK(channel)) + | (CTF2304_FAN_CFG2_DCY_MODE + << CTF2304_FAN_CFG2_MODE_SHIFT(channel)); + } else if (val == 2) { + data->fan_config2 = (data->fan_config2 + & ~CTF2304_FAN_CFG2_MODE_MASK(channel)) + | (CTF2304_FAN_CFG2_RPM_MODE + << CTF2304_FAN_CFG2_MODE_SHIFT(channel)); + } else { + err = -EINVAL; + break; + } + err = i2c_smbus_write_word_swapped(client, + CTF2304_REG_FAN_CONFIG2, + data->fan_config2); + break; + default: + err = -EOPNOTSUPP; + break; + } mutex_unlock(&data->update_lock); - return count; + return err; } -static ssize_t get_pwm(struct device *dev, - struct device_attribute *devattr, char *buf) +static int ctf2304_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ctf2304_data *data = ctf2304_update_device(dev); - int pwm; - - pwm = data->pwm[attr->index] >> 8; - - return sprintf(buf, "%d\n", pwm); -} - -static ssize_t set_pwm(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ctf2304_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - unsigned long pwm; - int err; - - err = kstrtoul(buf, 10, &pwm); - if (err) - return err; - - pwm = clamp_val(pwm, 0, 255); - - mutex_lock(&data->update_lock); - - data->pwm[attr->index] = (data->pwm[attr->index] & 0xFF) | (pwm << 8); - i2c_smbus_write_word_swapped(client, - CTF2304_REG_PWMOUT(attr->index), - data->pwm[attr->index]); - - mutex_unlock(&data->update_lock); - - return count; + switch (type) { + case hwmon_temp: + return ctf2304_read_temp(dev, attr, channel, val); + case hwmon_in: + return ctf2304_read_in(dev, attr, channel, val); + case hwmon_fan: + return ctf2304_read_fan(dev, attr, channel, val); + case hwmon_pwm: + return ctf2304_read_pwm(dev, attr, channel, val); + default: + return -EOPNOTSUPP; + } } -static ssize_t get_pwm_enable(struct device *dev, - struct device_attribute *devattr, char *buf) +static int ctf2304_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ctf2304_data *data = ctf2304_update_device(dev); - int config; - int mode; - - config = (data->fan_config2 & CTF2304_FAN_CFG2_MODE_MASK(attr->index)) - >> CTF2304_FAN_CFG2_MODE_SHIFT(attr->index); - if (config == CTF2304_FAN_CFG2_RPM_MODE) - mode = 2; - else if (config == CTF2304_FAN_CFG2_DCY_MODE) - mode = 1; - else - mode = 0; - - return sprintf(buf, "%d\n", mode); + switch (type) { + case hwmon_fan: + return ctf2304_write_fan(dev, attr, channel, val); + case hwmon_pwm: + return ctf2304_write_pwm(dev, attr, channel, val); + default: + return -EOPNOTSUPP; + } } -static ssize_t set_pwm_enable(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static umode_t ctf2304_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ctf2304_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - unsigned long mode; - int err; - - err = kstrtoul(buf, 10, &mode); - if (err) - return err; - - mutex_lock(&data->update_lock); - - switch (mode) { - case 0: - data->fan_config2 = - (data->fan_config2 - & ~CTF2304_FAN_CFG2_MODE_MASK(attr->index)) - | (CTF2304_FAN_CFG2_TEMP_MODE - << CTF2304_FAN_CFG2_MODE_SHIFT(attr->index)); - break; - case 1: - data->fan_config2 = - (data->fan_config2 - & ~CTF2304_FAN_CFG2_MODE_MASK(attr->index)) - | (CTF2304_FAN_CFG2_DCY_MODE - << CTF2304_FAN_CFG2_MODE_SHIFT(attr->index)); - break; - case 2: - data->fan_config2 = - (data->fan_config2 - & ~CTF2304_FAN_CFG2_MODE_MASK(attr->index)) - | (CTF2304_FAN_CFG2_RPM_MODE - << CTF2304_FAN_CFG2_MODE_SHIFT(attr->index)); + switch (type) { + case hwmon_temp: + case hwmon_in: + return 0444; + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + return 0444; + case hwmon_fan_target: + case hwmon_fan_div: + return 0644; + default: + break; + } break; + case hwmon_pwm: + return 0644; default: - return -EINVAL; + break; } - i2c_smbus_write_word_swapped(client, - CTF2304_REG_FAN_CONFIG2, data->fan_config2); - - mutex_unlock(&data->update_lock); - - return count; + return 0; } -static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, 0444, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, 0444, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, 0444, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, 0444, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, 0444, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_input, 0444, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_input, 0444, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp9_input, 0444, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(in1_input, 0444, show_voltage, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, 0444, show_voltage, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, 0444, show_voltage, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, 0444, show_voltage, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_input, 0444, show_voltage, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_input, 0444, show_voltage, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_input, 0444, show_voltage, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_input, 0444, show_voltage, NULL, 7); -static SENSOR_DEVICE_ATTR(fan1_input, 0444, get_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, 0444, get_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, 0444, get_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, 0444, get_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_target, 0644, - get_fan_target, set_fan_target, 0); -static SENSOR_DEVICE_ATTR(fan2_target, 0644, - get_fan_target, set_fan_target, 1); -static SENSOR_DEVICE_ATTR(fan3_target, 0644, - get_fan_target, set_fan_target, 2); -static SENSOR_DEVICE_ATTR(fan4_target, 0644, - get_fan_target, set_fan_target, 3); -static SENSOR_DEVICE_ATTR(fan1_div, 0644, show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, 0644, show_fan_div, set_fan_div, 1); -static SENSOR_DEVICE_ATTR(fan3_div, 0644, show_fan_div, set_fan_div, 2); -static SENSOR_DEVICE_ATTR(fan4_div, 0644, show_fan_div, set_fan_div, 3); -static SENSOR_DEVICE_ATTR(pwm1, 0644, get_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, 0644, get_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, 0644, get_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, 0644, get_pwm, set_pwm, 3); -static SENSOR_DEVICE_ATTR(pwm1_enable, 0644, - get_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, 0644, - get_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, 0644, - get_pwm_enable, set_pwm_enable, 2); -static SENSOR_DEVICE_ATTR(pwm4_enable, 0644, - get_pwm_enable, set_pwm_enable, 3); - -static struct attribute *ctf2304_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp7_input.dev_attr.attr, - &sensor_dev_attr_temp8_input.dev_attr.attr, - &sensor_dev_attr_temp9_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan1_target.dev_attr.attr, - &sensor_dev_attr_fan2_target.dev_attr.attr, - &sensor_dev_attr_fan3_target.dev_attr.attr, - &sensor_dev_attr_fan4_target.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan4_div.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm4.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm4_enable.dev_attr.attr, +static const struct hwmon_channel_info *ctf2304_info[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT, + HWMON_I_INPUT), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV, + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV, + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV, + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), NULL }; -ATTRIBUTE_GROUPS(ctf2304); +static const struct hwmon_ops ctf2304_hwmon_ops = { + .is_visible = ctf2304_is_visible, + .read = ctf2304_read, + .write = ctf2304_write, +}; -static int ctf2304_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct hwmon_chip_info ctf2304_chip_info = { + .ops = &ctf2304_hwmon_ops, + .info = ctf2304_info, +}; + +static int ctf2304_probe(struct i2c_client *client) { + struct i2c_adapter *adapter = client->adapter; struct device *dev = &client->dev; struct ctf2304_data *data; struct device *hwmon_dev; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + data = devm_kzalloc(dev, sizeof(struct ctf2304_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -525,9 +478,10 @@ static int ctf2304_probe(struct i2c_client *client, data->client = client; mutex_init(&data->update_lock); - hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, - data, - ctf2304_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, + data, + &ctf2304_chip_info, + NULL); return PTR_ERR_OR_ZERO(hwmon_dev); } @@ -540,10 +494,10 @@ MODULE_DEVICE_TABLE(i2c, ctf2304_id); static struct i2c_driver ctf2304_driver = { .class = I2C_CLASS_HWMON, - .probe = ctf2304_probe, .driver = { .name = "ctf2304", }, + .probe_new = ctf2304_probe, .id_table = ctf2304_id, }; -- 2.26.3