diff options
Diffstat (limited to 'drivers/hwmon/w83792d.c')
| -rw-r--r-- | drivers/hwmon/w83792d.c | 483 |
1 files changed, 264 insertions, 219 deletions
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 679718e6b01..4068db4d958 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -1,39 +1,39 @@ /* - w83792d.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (C) 2004, 2005 Winbond Electronics Corp. - Chunhao Huang <DZShen@Winbond.com.tw>, - Rudolf Marek <r.marek@assembler.cz> - - 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. - - Note: - 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver. - 2. This driver is only for Winbond W83792D C version device, there - are also some motherboards with B version W83792D device. The - calculation method to in6-in7(measured value, limits) is a little - different between C and B version. C or B version can be identified - by CR[0x49h]. -*/ + * w83792d.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * Copyright (C) 2004, 2005 Winbond Electronics Corp. + * Shane Huang, + * Rudolf Marek <r.marek@assembler.cz> + * + * 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. + * + * Note: + * 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver. + * 2. This driver is only for Winbond W83792D C version device, there + * are also some motherboards with B version W83792D device. The + * calculation method to in6-in7(measured value, limits) is a little + * different between C and B version. C or B version can be identified + * by CR[0x49h]. + */ /* - Supports following chips: - - Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - w83792d 9 7 7 3 0x7a 0x5ca3 yes no -*/ + * Supports following chips: + * + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * w83792d 9 7 7 3 0x7a 0x5ca3 yes no + */ #include <linux/module.h> #include <linux/init.h> @@ -44,6 +44,7 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/sysfs.h> +#include <linux/jiffies.h> /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, @@ -53,10 +54,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, static unsigned short force_subclients[4]; module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); +MODULE_PARM_DESC(force_subclients, + "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}"); -static int init; +static bool init; module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to one to force chip initialization"); @@ -218,39 +219,40 @@ static const u8 W83792D_REG_LEVELS[3][4] = { #define W83792D_REG_VBAT 0x5D #define W83792D_REG_I2C_ADDR 0x48 -/* Conversions. Rounding and limit checking is only done on the TO_REG - variants. Note that you should be a bit careful with which arguments - these macros are called: arguments may be evaluated more than once. - Fixing this is just not worth it. */ -#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \ - ((((nr)==6)||((nr)==7))?(val*6):(val*4))) -#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \ - ((((nr)==6)||((nr)==7))?(val/6):(val/4))) +/* + * Conversions. Rounding and limit checking is only done on the TO_REG + * variants. Note that you should be a bit careful with which arguments + * these macros are called: arguments may be evaluated more than once. + * Fixing this is just not worth it. + */ +#define IN_FROM_REG(nr, val) (((nr) <= 1) ? ((val) * 2) : \ + ((((nr) == 6) || ((nr) == 7)) ? ((val) * 6) : ((val) * 4))) +#define IN_TO_REG(nr, val) (((nr) <= 1) ? ((val) / 2) : \ + ((((nr) == 6) || ((nr) == 7)) ? ((val) / 6) : ((val) / 4))) static inline u8 FAN_TO_REG(long rpm, int div) { if (rpm == 0) return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); + rpm = clamp_val(rpm, 1, 1000000); + return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254); } -#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ +#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ ((val) == 255 ? 0 : \ 1350000 / ((val) * (div)))) /* for temp1 */ -#define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ - : (val)) / 1000, 0, 0xff)) +#define TEMP1_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \ + : (val)) / 1000, 0, 0xff)) #define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) -/* for temp2 and temp3, because they need addtional resolution */ +/* for temp2 and temp3, because they need additional resolution */ #define TEMP_ADD_FROM_REG(val1, val2) \ ((((val1) & 0x80 ? (val1)-0x100 \ : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0)) #define TEMP_ADD_TO_REG_HIGH(val) \ - (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ - : (val)) / 1000, 0, 0xff)) + (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 : (val)) / 1000, 0, 0xff)) #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) #define DIV_FROM_REG(val) (1 << (val)) @@ -259,13 +261,13 @@ static inline u8 DIV_TO_REG(long val) { int i; - val = SENSORS_LIMIT(val, 1, 128) >> 1; + val = clamp_val(val, 1, 128) >> 1; for (i = 0; i < 7; i++) { if (val == 0) break; val >>= 1; } - return ((u8) i); + return (u8)i; } struct w83792d_data { @@ -287,12 +289,13 @@ struct w83792d_data { u8 temp1[3]; /* current, over, thyst */ u8 temp_add[2][6]; /* Register value */ u8 fan_div[7]; /* Register encoding, shifted right */ - u8 pwm[7]; /* We only consider the first 3 set of pwm, - although 792 chip has 7 set of pwm. */ + u8 pwm[7]; /* + * We only consider the first 3 set of pwm, + * although 792 chip has 7 set of pwm. + */ u8 pwmenable[3]; u32 alarms; /* realtime status register encoding,combined */ u8 chassis; /* Chassis status */ - u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */ u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */ u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */ @@ -333,12 +336,14 @@ static struct i2c_driver w83792d_driver = { static inline long in_count_from_reg(int nr, struct w83792d_data *data) { /* in7 and in8 do not have low bits, but the formula still works */ - return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03)); + return (data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03); } -/* The SMBus locks itself. The Winbond W83792D chip has a bank register, - but the driver only accesses registers in bank 0, so we don't have - to switch banks and lock access between switches. */ +/* + * The SMBus locks itself. The Winbond W83792D chip has a bank register, + * but the driver only accesses registers in bank 0, so we don't have + * to switch banks and lock access between switches. + */ static inline int w83792d_read_value(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); @@ -357,37 +362,43 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data)))); + return sprintf(buf, "%ld\n", + IN_FROM_REG(nr, in_count_from_reg(nr, data))); } #define show_in_reg(reg) \ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + struct sensor_device_attribute *sensor_attr \ + = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \ + return sprintf(buf, "%ld\n", \ + (long)(IN_FROM_REG(nr, data->reg[nr]) * 4)); \ } show_in_reg(in_min); show_in_reg(in_max); #define store_in_reg(REG, reg) \ -static ssize_t store_in_##reg (struct device *dev, \ +static ssize_t store_in_##reg(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + struct sensor_device_attribute *sensor_attr \ + = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ struct i2c_client *client = to_i2c_client(dev); \ struct w83792d_data *data = i2c_get_clientdata(client); \ - u32 val; \ - \ - val = simple_strtoul(buf, NULL, 10); \ + unsigned long val; \ + int err = kstrtoul(buf, 10, &val); \ + if (err) \ + return err; \ mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \ - w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + data->in_##reg[nr] = clamp_val(IN_TO_REG(nr, val) / 4, 0, 255); \ + w83792d_write_value(client, W83792D_REG_IN_##REG[nr], \ + data->in_##reg[nr]); \ mutex_unlock(&data->update_lock); \ \ return count; \ @@ -396,13 +407,14 @@ store_in_reg(MIN, min); store_in_reg(MAX, max); #define show_fan_reg(reg) \ -static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + struct sensor_device_attribute *sensor_attr \ + = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index - 1; \ struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf,"%d\n", \ + return sprintf(buf, "%d\n", \ FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ } @@ -417,9 +429,13 @@ store_fan_min(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], @@ -439,10 +455,12 @@ show_fan_div(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1])); } -/* Note: we save and restore the fan minimum here, because its value is - determined in part by the fan divisor. This follows the principle of - least surprise; the user doesn't expect the fan minimum to change just - because the divisor changed. */ +/* + * Note: we save and restore the fan minimum here, because its value is + * determined in part by the fan divisor. This follows the principle of + * least surprise; the user doesn't expect the fan minimum to change just + * because the divisor changed. + */ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -455,13 +473,19 @@ store_fan_div(struct device *dev, struct device_attribute *attr, /*u8 reg;*/ u8 fan_div_reg = 0; u8 tmp_fan_div; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; /* Save fan_min */ mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10)); + data->fan_div[nr] = DIV_TO_REG(val); fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8; @@ -496,9 +520,13 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - s32 val; + long val; + int err; + + err = kstrtol(buf, 10, &val); + if (err) + return err; - val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp1[nr] = TEMP1_TO_REG(val); w83792d_write_value(client, W83792D_REG_TEMP1[nr], @@ -513,11 +541,12 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf,"%ld\n", + return sprintf(buf, "%ld\n", (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index], data->temp_add[nr][index+1])); } @@ -525,14 +554,19 @@ static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - s32 val; + long val; + int err; + + err = kstrtol(buf, 10, &val); + if (err) + return err; - val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); @@ -545,7 +579,7 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, return count; } -/* get reatime status of all sensors items: voltage, temp, fan */ +/* get realtime status of all sensors items: voltage, temp, fan */ static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -604,7 +638,13 @@ store_pwm(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; + val = clamp_val(val, 0, 255) >> 4; mutex_lock(&data->update_lock); val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; @@ -623,10 +663,14 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); if (val < 1 || val > 3) return -EINVAL; @@ -645,7 +689,7 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, cfg1_tmp = data->pwmenable[0]; cfg2_tmp = (data->pwmenable[1]) << 2; cfg3_tmp = (data->pwmenable[2]) << 4; - cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0; + cfg4_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG) & 0xc0; fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); mutex_unlock(&data->update_lock); @@ -671,10 +715,13 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; + unsigned long val; + int err; - val = simple_strtoul(buf, NULL, 10); - if (val != 0 && val != 1) + err = kstrtoul(buf, 10, &val); + if (err) + return err; + if (val > 1) return -EINVAL; mutex_lock(&data->update_lock); @@ -691,7 +738,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, } static ssize_t -show_regs_chassis(struct device *dev, struct device_attribute *attr, +show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); @@ -699,28 +746,21 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, } static ssize_t -show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->chassis_clear); -} - -static ssize_t store_chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; - u8 temp1 = 0, temp2 = 0; + unsigned long val; + u8 reg; + + if (kstrtoul(buf, 10, &val) || val != 0) + return -EINVAL; - val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); - temp1 = ((data->chassis_clear) << 7) & 0x80; - temp2 = w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) & 0x7f; - w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); + reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); + w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); + data->valid = 0; /* Force cache refresh */ mutex_unlock(&data->update_lock); return count; @@ -745,15 +785,20 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; - u8 target_tmp=0, target_mask=0; + u8 target_tmp = 0, target_mask = 0; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); target_tmp = val; target_tmp = target_tmp & 0x7f; mutex_lock(&data->update_lock); - target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80; - data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); + target_mask = w83792d_read_value(client, + W83792D_REG_THERMAL[nr]) & 0x80; + data->thermal_cruise[nr] = clamp_val(target_tmp, 0, 255); w83792d_write_value(client, W83792D_REG_THERMAL[nr], (data->thermal_cruise[nr]) | target_mask); mutex_unlock(&data->update_lock); @@ -780,19 +825,22 @@ store_tolerance(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; u8 tol_tmp, tol_mask; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); tol_mask = w83792d_read_value(client, W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); - tol_tmp = SENSORS_LIMIT(val, 0, 15); + tol_tmp = clamp_val(val, 0, 15); tol_tmp &= 0x0f; data->tolerance[nr] = tol_tmp; - if (nr == 1) { + if (nr == 1) tol_tmp <<= 4; - } w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], tol_mask | tol_tmp); mutex_unlock(&data->update_lock); @@ -805,7 +853,8 @@ static ssize_t show_sf2_point(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); @@ -816,17 +865,22 @@ static ssize_t store_sf2_point(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr - 1; int index = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; u8 mask_tmp = 0; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); + data->sf2_points[index][nr] = clamp_val(val, 0, 127); mask_tmp = w83792d_read_value(client, W83792D_REG_POINTS[index][nr]) & 0x80; w83792d_write_value(client, W83792D_REG_POINTS[index][nr], @@ -840,7 +894,8 @@ static ssize_t show_sf2_level(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); @@ -852,25 +907,30 @@ static ssize_t store_sf2_level(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); + struct sensor_device_attribute_2 *sensor_attr + = to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index - 1; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; - u8 mask_tmp=0, level_tmp=0; + u8 mask_tmp = 0, level_tmp = 0; + unsigned long val; + int err; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; - val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); + data->sf2_levels[index][nr] = clamp_val((val * 15) / 100, 0, 15); mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) - & ((nr==3) ? 0xf0 : 0x0f); - if (nr==3) { + & ((nr == 3) ? 0xf0 : 0x0f); + if (nr == 3) level_tmp = data->sf2_levels[index][nr]; - } else { + else level_tmp = data->sf2_levels[index][nr] << 4; - } - w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp); + w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], + level_tmp | mask_tmp); mutex_unlock(&data->update_lock); return count; @@ -891,8 +951,8 @@ w83792d_detect_subclients(struct i2c_client *new_client) for (i = 2; i <= 3; i++) { if (force_subclients[i] < 0x48 || force_subclients[i] > 0x4f) { - dev_err(&new_client->dev, "invalid subclient " - "address %d; must be 0x48-0x4f\n", + dev_err(&new_client->dev, + "invalid subclient address %d; must be 0x48-0x4f\n", force_subclients[i]); err = -ENODEV; goto ERROR_SC_0; @@ -904,14 +964,14 @@ w83792d_detect_subclients(struct i2c_client *new_client) } val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); - if (!(val & 0x08)) { + if (!(val & 0x08)) data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); - } if (!(val & 0x80)) { if ((data->lm75[0] != NULL) && ((val & 0x7) == ((val >> 4) & 0x7))) { - dev_err(&new_client->dev, "duplicate addresses 0x%x, " - "use force_subclient\n", data->lm75[0]->addr); + dev_err(&new_client->dev, + "duplicate addresses 0x%x, use force_subclient\n", + data->lm75[0]->addr); err = -ENODEV; goto ERROR_SC_1; } @@ -1010,8 +1070,7 @@ static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20); static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21); static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); -static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_chassis_clear, store_chassis_clear); static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); @@ -1212,8 +1271,7 @@ static struct attribute *w83792d_attributes[] = { &sensor_dev_attr_pwm3_mode.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &dev_attr_alarms.attr, - &dev_attr_chassis.attr, - &dev_attr_chassis_clear.attr, + &dev_attr_intrusion0_alarm.attr, &sensor_dev_attr_tolerance1.dev_attr.attr, &sensor_dev_attr_thermal_cruise1.dev_attr.attr, &sensor_dev_attr_tolerance2.dev_attr.attr, @@ -1268,9 +1326,8 @@ w83792d_detect(struct i2c_client *client, struct i2c_board_info *info) int val1, val2; unsigned short address = client->addr; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - } if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) return -ENODEV; @@ -1280,11 +1337,13 @@ w83792d_detect(struct i2c_client *client, struct i2c_board_info *info) /* Check for Winbond ID if in bank 0 */ if (!(val1 & 0x07)) { /* is Bank0 */ if ((!(val1 & 0x80) && val2 != 0xa3) || - ( (val1 & 0x80) && val2 != 0x5c)) + ((val1 & 0x80) && val2 != 0x5c)) return -ENODEV; } - /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR - should match */ + /* + * If Winbond chip, address of chip and W83792D_REG_I2C_ADDR + * should match + */ if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) return -ENODEV; @@ -1312,19 +1371,16 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) struct device *dev = &client->dev; int i, val1, err; - data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR0; - } + data = devm_kzalloc(dev, sizeof(struct w83792d_data), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); - data->valid = 0; mutex_init(&data->update_lock); err = w83792d_detect_subclients(client); if (err) - goto ERROR1; + return err; /* Initialize the chip */ w83792d_init_client(client); @@ -1336,33 +1392,40 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* Register sysfs hooks */ - if ((err = sysfs_create_group(&dev->kobj, &w83792d_group))) - goto ERROR3; + err = sysfs_create_group(&dev->kobj, &w83792d_group); + if (err) + goto exit_i2c_unregister; - /* Read GPIO enable register to check if pins for fan 4,5 are used as - GPIO */ + /* + * Read GPIO enable register to check if pins for fan 4,5 are used as + * GPIO + */ val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); - if (!(val1 & 0x40)) - if ((err = sysfs_create_group(&dev->kobj, - &w83792d_group_fan[0]))) + if (!(val1 & 0x40)) { + err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[0]); + if (err) goto exit_remove_files; + } - if (!(val1 & 0x20)) - if ((err = sysfs_create_group(&dev->kobj, - &w83792d_group_fan[1]))) + if (!(val1 & 0x20)) { + err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[1]); + if (err) goto exit_remove_files; + } val1 = w83792d_read_value(client, W83792D_REG_PIN); - if (val1 & 0x40) - if ((err = sysfs_create_group(&dev->kobj, - &w83792d_group_fan[2]))) + if (val1 & 0x40) { + err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[2]); + if (err) goto exit_remove_files; + } - if (val1 & 0x04) - if ((err = sysfs_create_group(&dev->kobj, - &w83792d_group_fan[3]))) + if (val1 & 0x04) { + err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[3]); + if (err) goto exit_remove_files; + } data->hwmon_dev = hwmon_device_register(dev); if (IS_ERR(data->hwmon_dev)) { @@ -1376,14 +1439,11 @@ exit_remove_files: sysfs_remove_group(&dev->kobj, &w83792d_group); for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); -ERROR3: +exit_i2c_unregister: if (data->lm75[0] != NULL) i2c_unregister_device(data->lm75[0]); if (data->lm75[1] != NULL) i2c_unregister_device(data->lm75[1]); -ERROR1: - kfree(data); -ERROR0: return err; } @@ -1404,7 +1464,6 @@ w83792d_remove(struct i2c_client *client) if (data->lm75[1] != NULL) i2c_unregister_device(data->lm75[1]); - kfree(data); return 0; } @@ -1413,14 +1472,16 @@ w83792d_init_client(struct i2c_client *client) { u8 temp2_cfg, temp3_cfg, vid_in_b; - if (init) { + if (init) w83792d_write_value(client, W83792D_REG_CONFIG, 0x80); - } - /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0): - W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of - vin0/vin1 can be modified by user; - W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of - vin0/vin1 auto-updated, can NOT be modified by user. */ + + /* + * Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0): + * W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of + * vin0/vin1 can be modified by user; + * W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of + * vin0/vin1 auto-updated, can NOT be modified by user. + */ vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B); w83792d_write_value(client, W83792D_REG_VID_IN_B, vid_in_b & 0xbf); @@ -1489,7 +1550,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) for (i = 0; i < 2; i++) { for (j = 0; j < 6; j++) { data->temp_add[i][j] = w83792d_read_value( - client,W83792D_REG_TEMP_ADD[i][j]); + client, W83792D_REG_TEMP_ADD[i][j]); } } @@ -1514,8 +1575,6 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) /* Update CaseOpen status and it's CLR_CHS. */ data->chassis = (w83792d_read_value(client, W83792D_REG_CHASSIS) >> 5) & 0x01; - data->chassis_clear = (w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) >> 7) & 0x01; /* Update Thermal Cruise/Smart Fan I target value */ for (i = 0; i < 3; i++) { @@ -1534,8 +1593,9 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) /* Update Smart Fan II temperature points */ for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { - data->sf2_points[i][j] = w83792d_read_value( - client,W83792D_REG_POINTS[i][j]) & 0x7f; + data->sf2_points[i][j] + = w83792d_read_value(client, + W83792D_REG_POINTS[i][j]) & 0x7f; } } @@ -1567,10 +1627,10 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) #ifdef DEBUG static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) { - int i=0, j=0; + int i = 0, j = 0; dev_dbg(dev, "==========The following is the debug message...========\n"); dev_dbg(dev, "9 set of Voltages: =====>\n"); - for (i=0; i<9; i++) { + for (i = 0; i < 9; i++) { dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]); dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]); dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]); @@ -1578,47 +1638,32 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff); dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8); dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n"); - for (i=0; i<7; i++) { + for (i = 0; i < 7; i++) { dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); } dev_dbg(dev, "3 set of Temperatures: =====>\n"); - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]); - } - for (i=0; i<2; i++) { - for (j=0; j<6; j++) { + for (i = 0; i < 2; i++) { + for (j = 0; j < 6; j++) { dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j, data->temp_add[i][j]); } } - for (i=0; i<7; i++) { + for (i = 0; i < 7; i++) dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]); - } - dev_dbg(dev, "==========End of the debug message...==================\n"); + + dev_dbg(dev, "==========End of the debug message...================\n"); dev_dbg(dev, "\n"); } #endif -static int __init -sensors_w83792d_init(void) -{ - return i2c_add_driver(&w83792d_driver); -} +module_i2c_driver(w83792d_driver); -static void __exit -sensors_w83792d_exit(void) -{ - i2c_del_driver(&w83792d_driver); -} - -MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>"); +MODULE_AUTHOR("Shane Huang (Winbond)"); MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6"); MODULE_LICENSE("GPL"); - -module_init(sensors_w83792d_init); -module_exit(sensors_w83792d_exit); - |
