diff options
Diffstat (limited to 'drivers/hwmon/emc2103.c')
| -rw-r--r-- | drivers/hwmon/emc2103.c | 126 |
1 files changed, 58 insertions, 68 deletions
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index af914ad93ec..78002de46cb 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -1,21 +1,21 @@ /* - emc2103.c - Support for SMSC EMC2103 - Copyright (c) 2010 SMSC - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ + * emc2103.c - Support for SMSC EMC2103 + * Copyright (c) 2010 SMSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ #include <linux/module.h> #include <linux/init.h> @@ -48,14 +48,16 @@ static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 }; /* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ #define FAN_RPM_FACTOR 3932160 -/* 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes +/* + * 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes * in anti-parallel mode, and in this configuration both can be read * independently (so we have 4 temperature inputs). The device can't * detect if it's connected in this mode, so we have to manually enable * it. Default is to leave the device in the state it's already in (-1). - * This parameter allows APD mode to be optionally forced on or off */ + * This parameter allows APD mode to be optionally forced on or off + */ static int apd = -1; -module_param(apd, bool, 0); +module_param(apd, bint, 0); MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); struct temperature { @@ -244,13 +246,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, struct emc2103_data *data = i2c_get_clientdata(client); long val; - int result = strict_strtol(buf, 10, &val); + int result = kstrtol(buf, 10, &val); if (result < 0) - return -EINVAL; + return result; - val = DIV_ROUND_CLOSEST(val, 1000); - if ((val < -63) || (val > 127)) - return -EINVAL; + val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127); mutex_lock(&data->update_lock); data->temp_min[nr] = val; @@ -268,13 +268,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, struct emc2103_data *data = i2c_get_clientdata(client); long val; - int result = strict_strtol(buf, 10, &val); + int result = kstrtol(buf, 10, &val); if (result < 0) - return -EINVAL; + return result; - val = DIV_ROUND_CLOSEST(val, 1000); - if ((val < -63) || (val > 127)) - return -EINVAL; + val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127); mutex_lock(&data->update_lock); data->temp_max[nr] = val; @@ -302,10 +300,12 @@ show_fan_div(struct device *dev, struct device_attribute *da, char *buf) return sprintf(buf, "%d\n", fan_div); } -/* Note: we also update the fan target here, because its value is - determined in part by the fan clock divider. This follows the principle - of least surprise; the user doesn't expect the fan target to change just - because the divider changed. */ +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { @@ -314,9 +314,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, int new_range_bits, old_div = 8 / data->fan_multiplier; long new_div; - int status = strict_strtol(buf, 10, &new_div); + int status = kstrtol(buf, 10, &new_div); if (status < 0) - return -EINVAL; + return status; if (new_div == old_div) /* No change */ return count; @@ -345,7 +345,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_FAN_CONF1, status); mutex_unlock(&data->update_lock); - return -EIO; + return status; } status &= 0x9F; status |= (new_range_bits << 5); @@ -386,22 +386,21 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, { struct emc2103_data *data = emc2103_update_device(dev); struct i2c_client *client = to_i2c_client(dev); - long rpm_target; + unsigned long rpm_target; - int result = strict_strtol(buf, 10, &rpm_target); + int result = kstrtoul(buf, 10, &rpm_target); if (result < 0) - return -EINVAL; + return result; /* Datasheet states 16384 as maximum RPM target (table 3.2) */ - if ((rpm_target < 0) || (rpm_target > 16384)) - return -EINVAL; + rpm_target = clamp_val(rpm_target, 0, 16384); mutex_lock(&data->update_lock); if (rpm_target == 0) data->fan_target = 0x1fff; else - data->fan_target = SENSORS_LIMIT( + data->fan_target = clamp_val( (FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target, 0, 0x1fff); @@ -434,9 +433,9 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, long new_value; u8 conf_reg; - int result = strict_strtol(buf, 10, &new_value); + int result = kstrtol(buf, 10, &new_value); if (result < 0) - return -EINVAL; + return result; mutex_lock(&data->update_lock); switch (new_value) { @@ -447,11 +446,15 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, data->fan_rpm_control = true; break; default: - mutex_unlock(&data->update_lock); - return -EINVAL; + count = -EINVAL; + goto err; } - read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); + result = read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); + if (result) { + count = result; + goto err; + } if (data->fan_rpm_control) conf_reg |= 0x80; @@ -459,7 +462,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, conf_reg &= ~0x80; i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); - +err: mutex_unlock(&data->update_lock); return count; } @@ -582,7 +585,8 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct emc2103_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -600,7 +604,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) if (status < 0) { dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, status); - goto exit_free; + return status; } /* detect current state of hardware */ @@ -623,7 +627,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Register sysfs hooks */ status = sysfs_create_group(&client->dev.kobj, &emc2103_group); if (status) - goto exit_free; + return status; if (data->temp_count >= 3) { status = sysfs_create_group(&client->dev.kobj, @@ -658,8 +662,6 @@ exit_remove_temp3: sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); exit_remove: sysfs_remove_group(&client->dev.kobj, &emc2103_group); -exit_free: - kfree(data); return status; } @@ -677,7 +679,6 @@ static int emc2103_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &emc2103_group); - kfree(data); return 0; } @@ -722,19 +723,8 @@ static struct i2c_driver emc2103_driver = { .address_list = normal_i2c, }; -static int __init sensors_emc2103_init(void) -{ - return i2c_add_driver(&emc2103_driver); -} - -static void __exit sensors_emc2103_exit(void) -{ - i2c_del_driver(&emc2103_driver); -} +module_i2c_driver(emc2103_driver); -MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); +MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>"); MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); MODULE_LICENSE("GPL"); - -module_init(sensors_emc2103_init); -module_exit(sensors_emc2103_exit); |
