diff -uprN linux-2.6.18-rc2/drivers/hwmon/Kconfig linux-2.6.18-rc2-patched/drivers/hwmon/Kconfig --- linux-2.6.18-rc2/drivers/hwmon/Kconfig 2006-08-24 17:45:20.593382000 +0200 +++ linux-2.6.18-rc2-patched/drivers/hwmon/Kconfig 2006-08-24 17:46:07.996344500 +0200 @@ -461,6 +461,15 @@ config SENSORS_W83792D This driver can also be built as a module. If so, the module will be called w83792d. +config SENSORS_W83793 + tristate "Winbond W83793" + depends on HWMON && I2C && EXPERIMENTAL + help + If you say yes here you get support for the Winbond W83793 chip. + + This driver can also be built as a module. If so, the module + will be called w83793. + config SENSORS_W83L785TS tristate "Winbond W83L785TS-S" depends on HWMON && I2C && EXPERIMENTAL diff -uprN linux-2.6.18-rc2/drivers/hwmon/Makefile linux-2.6.18-rc2-patched/drivers/hwmon/Makefile --- linux-2.6.18-rc2/drivers/hwmon/Makefile 2006-08-24 17:45:20.601382500 +0200 +++ linux-2.6.18-rc2-patched/drivers/hwmon/Makefile 2006-08-24 17:46:55.527315000 +0200 @@ -9,6 +9,7 @@ obj-$(CONFIG_HWMON_VID) += hwmon-vid.o obj-$(CONFIG_SENSORS_ASB100) += asb100.o obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o obj-$(CONFIG_SENSORS_W83792D) += w83792d.o +obj-$(CONFIG_SENSORS_W83793) += w83793.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o diff -uprN linux-2.6.18-rc2/drivers/hwmon/w83793.c linux-2.6.18-rc2-patched/drivers/hwmon/w83793.c --- linux-2.6.18-rc2/drivers/hwmon/w83793.c 2006-08-23 18:49:30.000000000 +0200 +++ linux-2.6.18-rc2-patched/drivers/hwmon/w83793.c 2006-08-24 19:32:56.000000000 +0200 @@ -1,7 +1,6 @@ /* - w83793.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2006 Winbond Electronics Corp. + w83793.c - Linux kernel modules for hardware monitoring + Copyright (C) 2006 Winbond Electronics Corp. Yuan Mu This program is free software; you can redistribute it and/or modify @@ -16,7 +15,8 @@ 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. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. */ /* @@ -102,7 +102,7 @@ static u16 W83793_REG_TEMP[][5] = { #define IN_MAX 1 #define IN_LOW 2 static const u16 W83793_REG_IN[][3] = { - /*Read, High, Low */ + /* Read, High, Low */ {0x10, 0x60, 0x61}, /* Vcore A */ {0x11, 0x62, 0x63}, /* Vcore B */ {0x12, 0x64, 0x65}, /* Vtt */ @@ -144,7 +144,7 @@ static u8 scale_in[] = { 2, 2, 2, 16, 16 #define WRITE_TO_REG(REG, val, stored_val) \ do { \ - if (0 != w83793_write_value(client, REG, val)) \ + if (w83793_write_value(client, REG, val) >= 0) \ stored_val = val; \ } while(0) @@ -171,7 +171,7 @@ struct w83793_data { enum chips type; struct mutex lock; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_nonvolatile; /* In jiffies, last time we update the nonvolatile registers */ @@ -254,7 +254,7 @@ store_vrm(struct device *dev, struct dev struct i2c_client *client = to_i2c_client(dev); struct w83793_data *data = i2c_get_clientdata(client); - data->vrm = simple_strtol(buf, NULL, 10); + data->vrm = simple_strtoul(buf, NULL, 10); return count; } @@ -293,7 +293,7 @@ store_beep(struct device *dev, struct de u8 beep_bit = 1 << shift; u8 val; - val = simple_strtol(buf, NULL, 10); + val = simple_strtoul(buf, NULL, 10); if (val != 0 && val != 1) return -EINVAL; @@ -320,7 +320,7 @@ store_beep_enable(struct device *dev, st { struct i2c_client *client = to_i2c_client(dev); struct w83793_data *data = i2c_get_clientdata(client); - u8 val = simple_strtol(buf, NULL, 10); + u8 val = simple_strtoul(buf, NULL, 10); if (val != 0 && val != 1) return -EINVAL; @@ -382,7 +382,7 @@ store_fan_min(struct device *dev, struct int index = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83793_data *data = i2c_get_clientdata(client); - u16 val = FAN_TO_REG(simple_strtol(buf, NULL, 10)); + u16 val = FAN_TO_REG(simple_strtoul(buf, NULL, 10)); mutex_lock(&data->update_lock); data->fan_min[index] = val; @@ -404,7 +404,7 @@ show_pwm(struct device *dev, struct devi struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); struct w83793_data *data = w83793_update_device(dev); - u8 val; + u16 val; int nr = sensor_attr->nr; int index = sensor_attr->index; @@ -430,11 +430,11 @@ store_pwm(struct device *dev, struct dev mutex_lock(&data->update_lock); if (PWM_STOP_TIME == nr) { - val = TIME_TO_REG(simple_strtol(buf, NULL, 10)); + val = TIME_TO_REG(simple_strtoul(buf, NULL, 10)); WRITE_TO_REG(W83793_REG_PWM_STOP_TIME(index), val, data->pwm_stop_time[index]); } else { - val = SENSORS_LIMIT(simple_strtol(buf, NULL, 10), 0, 0xff) >> 2; + val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2; data->pwm[index][nr] = w83793_read_value(client, W83793_REG_PWM(index, nr)); val |= data->pwm[index][nr] & 0xc0; @@ -521,7 +521,7 @@ store_temp_mode(struct device *dev, stru int index = sensor_attr->index; u8 mask = (index < 4) ? 0x03 : 0x01; u8 shift = (index < 4) ? (2 * index) : (index - 4); - int val = simple_strtol(buf, NULL, 10); + int val = simple_strtoul(buf, NULL, 10); if (val < 0 || val > mask) return -EINVAL; @@ -549,7 +549,7 @@ show_sf_setup(struct device *dev, struct to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; struct w83793_data *data = w83793_update_device(dev); - u8 val = 0; + u16 val = 0; if (SETUP_PWM_DEFAULT == nr) { val = (data->pwm_default & 0x3f) << 2; @@ -558,7 +558,7 @@ show_sf_setup(struct device *dev, struct } else if (SETUP_PWM_DOWNTIME == nr) { val = TIME_FROM_REG(data->pwm_downtime); } else if (SETUP_TEMP_CRITICAL == nr) { - val = data->temp_critical & 0x7f; + val = TEMP_FROM_REG(data->temp_critical & 0x7f); } return sprintf(buf, "%d\n", val); @@ -579,21 +579,21 @@ store_sf_setup(struct device *dev, struc if (SETUP_PWM_DEFAULT == nr) { data->pwm_default = w83793_read_value(client, W83793_REG_PWM_DEFAULT); - val = SENSORS_LIMIT(simple_strtol(buf, NULL, 10), 0, 0xff) >> 2; + val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2; val |= data->pwm_default & 0xc0; WRITE_TO_REG(W83793_REG_PWM_DEFAULT, val, data->pwm_default); } else if (SETUP_PWM_UPTIME == nr) { - val = TIME_TO_REG(simple_strtol(buf, NULL, 10)); + val = TIME_TO_REG(simple_strtoul(buf, NULL, 10)); val += val == 0 ? 1 : 0; WRITE_TO_REG(W83793_REG_PWM_UPTIME, val, data->pwm_uptime); } else if (SETUP_PWM_DOWNTIME == nr) { - val = TIME_TO_REG(simple_strtol(buf, NULL, 10)); + val = TIME_TO_REG(simple_strtoul(buf, NULL, 10)); val += val == 0 ? 1 : 0; WRITE_TO_REG(W83793_REG_PWM_DOWNTIME, val, data->pwm_downtime); } else { /* SETUP_TEMP_CRITICAL */ data->temp_critical = w83793_read_value(client, W83793_REG_TEMP_CRITICAL); - val = SENSORS_LIMIT(simple_strtol(buf, NULL, 10), 0, 0x7f); + val = SENSORS_LIMIT(TEMP_TO_REG(simple_strtol(buf, NULL, 10)), 0, 0x7f); val |= data->temp_critical & 0x80; WRITE_TO_REG(W83793_REG_TEMP_CRITICAL, val, data->temp_critical); @@ -736,7 +736,7 @@ store_sf2_pwm(struct device *dev, struct to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; - u8 val = SENSORS_LIMIT(simple_strtol(buf, NULL, 10), 0, 0xff) >> 2; + u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2; mutex_lock(&data->update_lock); data->sf2_pwm[index][nr] = @@ -821,11 +821,13 @@ store_in(struct device *dev, struct devi if (index > 2) { val = SENSORS_LIMIT(val, 0, 255); } else { - u8 low_bits = (val & 0x03) << (2 * index); + u8 low_bits; + val = SENSORS_LIMIT(val, 0, 0x3FF); + low_bits = (val & 0x03) << (2 * index); data->in_low_bits[nr] = w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]); low_bits &= data->in_low_bits[nr] & (~(0x03 << (2 * index))); - val = (val >> 2) & 0xff; + val >>= 2; WRITE_TO_REG(W83793_REG_IN_LOW_BITS[nr], low_bits, data->in_low_bits[nr]); } @@ -1014,12 +1016,22 @@ static int w83793_attach_adapter(struct static int w83793_detach_client(struct i2c_client *client) { struct w83793_data *data = i2c_get_clientdata(client); - int err; + struct device *dev = &client->dev; + int err, i; /* main client */ if (data) hwmon_device_unregister(data->class_dev); + for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) + device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) + device_remove_file(dev, &sda_single_files[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) + device_remove_file(dev, &w83793_left_fan[i].dev_attr); + if ((err = i2c_detach_client(client))) return err; @@ -1113,12 +1125,12 @@ w83793_detect_subclients(struct i2c_adap /* Undo inits in case of errors */ - ERROR_SC_1: +ERROR_SC_1: if (data->lm75[0] != NULL) { i2c_detach_client(data->lm75[0]); kfree(data->lm75[0]); } - ERROR_SC_0: +ERROR_SC_0: return err; } @@ -1127,14 +1139,14 @@ static int w83793_detect(struct i2c_adap int i; u8 tmp, val; struct i2c_client *client; - struct device *dev; struct w83793_data *data; + struct device *dev; int err = 0; const char *client_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { err = -EINVAL; - goto ERROR0; + goto exit; } /* OK. For now, we presume we have a valid client. We now create the @@ -1143,7 +1155,7 @@ static int w83793_detect(struct i2c_adap if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) { err = -ENOMEM; - goto ERROR0; + goto exit; } client = &data->client; @@ -1162,7 +1174,7 @@ static int w83793_detect(struct i2c_adap if (w83793_read_value(client, W83793_REG_CONFIG) & 0x80) { dev_dbg(dev, "Detection failed at step 1\n"); err = -ENODEV; - goto ERROR1; + goto free_mem; } data->bank = w83793_read_value(client, W83793_REG_BANKSEL); @@ -1171,7 +1183,7 @@ static int w83793_detect(struct i2c_adap if (tmp != w83793_read_value(client, W83793_REG_VENDORID)) { dev_dbg(dev, "Detection failed at check vendor id\n"); err = -ENODEV; - goto ERROR1; + goto free_mem; } /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR @@ -1180,7 +1192,7 @@ static int w83793_detect(struct i2c_adap (address << 1)) { dev_dbg(dev, "Detection failed at check i2c addr\n"); err = -ENODEV; - goto ERROR1; + goto free_mem; } } @@ -1201,14 +1213,14 @@ static int w83793_detect(struct i2c_adap " 0x%02x\n", i2c_adapter_id(adapter), address); err = -ENODEV; - goto ERROR1; + goto free_mem; } } if (kind != w83793) { dev_err(dev, "w83793: Internal error: unknown kind %d\n", kind); err = -ENODEV; - goto ERROR1; + goto free_mem; } /* Fill in the remaining client fields and put into the global list */ @@ -1220,10 +1232,10 @@ static int w83793_detect(struct i2c_adap /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(client))) - goto ERROR1; + goto free_mem; if ((err = w83793_detect_subclients(adapter, address, kind, client))) - goto ERROR2; + goto detach_client; /* Initialize the chip */ w83793_init_client(client); @@ -1274,17 +1286,18 @@ static int w83793_detect(struct i2c_adap } /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); - goto ERROR3; + for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) { + err = device_create_file(dev, &w83793_sensor_attr_2[i].dev_attr); + if (err) + goto exit_remove; } - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) - device_create_file(dev, &w83793_sensor_attr_2[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { + err = device_create_file(dev, &sda_single_files[i].dev_attr); + if (err) + goto exit_remove; - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) - device_create_file(dev, &sda_single_files[i].dev_attr); + } for (i = 5; i < 12; i++) { int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; @@ -1292,26 +1305,46 @@ static int w83793_detect(struct i2c_adap int j; if (!(data->has_fan & (1 << i))) continue; - for (j = 0; j < files_fan; j++) - device_create_file(dev, - &w83793_left_fan[(i - - 5) * - files_fan + - j].dev_attr); + for (j = 0; j < files_fan; j++) { + err = device_create_file(dev, + &w83793_left_fan[(i - 5) * files_fan + + j].dev_attr); + if (err) + goto exit_remove; + } if (i >= 8 || !(data->has_pwm & (1 << i))) continue; - for (j = 0; j < files_pwm; j++) - device_create_file(dev, - &w83793_left_fan[(i - - 3) * - files_pwm + - j].dev_attr); + for (j = 0; j < files_pwm; j++) { + err = device_create_file(dev, + &w83793_left_fan[(i - 3) * files_pwm + + j].dev_attr); + if (err) + goto exit_remove; + } } + + data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_remove; + } + return 0; - ERROR3: + /* Unregister sysfs hooks */ + +exit_remove: + for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) + device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) + device_remove_file(dev, &sda_single_files[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) + device_remove_file(dev, &w83793_left_fan[i].dev_attr); + if (data->lm75[0] != NULL) { i2c_detach_client(data->lm75[0]); kfree(data->lm75[0]); @@ -1320,11 +1353,11 @@ static int w83793_detect(struct i2c_adap i2c_detach_client(data->lm75[1]); kfree(data->lm75[1]); } - ERROR2: +detach_client: i2c_detach_client(client); - ERROR1: +free_mem: kfree(data); - ERROR0: +exit: return err; } @@ -1468,7 +1501,7 @@ static struct w83793_data *w83793_update data->last_updated = jiffies; data->valid = 1; - END: +END: mutex_unlock(&data->update_lock); return data; } @@ -1487,14 +1520,16 @@ static u8 w83793_read_value(struct i2c_c (client, W83793_REG_BANKSEL, new_bank) >= 0) data->bank = new_bank; else { - dev_err(&client->dev, "set bank to %d failed, fall back" - " to bank %d, read reg 0x%x error\n", new_bank, - data->bank, reg); + dev_err(&client->dev, + "set bank to %d failed, fall back" + " to bank %d, read reg 0x%x error\n", + new_bank, data->bank, reg); goto END; } } res = i2c_smbus_read_byte_data(client, reg & 0xff); - END: +END: + res = 0x0; /* read 0x0 from the chip */ mutex_unlock(&data->lock); return res; } @@ -1508,15 +1543,20 @@ static int w83793_write_value(struct i2c mutex_lock(&data->lock); new_bank |= data->bank & 0xfc; if (data->bank != new_bank) { - res = - i2c_smbus_write_byte_data(client, W83793_REG_BANKSEL, - new_bank); - if (res < 0) + if ((res = i2c_smbus_write_byte_data + (client, W83793_REG_BANKSEL, new_bank)) >= 0) + data->bank = new_bank; + else { + dev_err(&client->dev, + "set bank to %d failed, fall back" + " to bank %d, write reg 0x%x error\n", + new_bank, data->bank, reg); goto END; - data->bank = new_bank; + } } + res = i2c_smbus_write_byte_data(client, reg & 0xff, value); - END: +END: mutex_unlock(&data->lock); return res; }