diff -Naur old/Documentation/i2c/chips/w83792d b/Documentation/i2c/chips/w83792d --- old/Documentation/i2c/chips/w83792d 1970-01-01 01:00:00.000000000 +0100 +++ b/Documentation/i2c/chips/w83792d 2005-06-21 09:48:28.760798720 +0200 @@ -0,0 +1,172 @@ +Kernel driver w83792d +===================== + +Supported chips: + * Winbond W83792D + Prefix: 'w83792d' + Addresses scanned: I2C 0x2c - 0x2f + Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035 + +Author: Chunhao Huang @ Winbond + + +Module Parameters +----------------- + +* init int + (default 1) + Use 'init=0' to bypass initializing the chip. + Try this if your computer crashes when you load the module. + +* force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b' + to force the subclients of chip 0x2f on bus 0 to i2c addresses + 0x4a and 0x4b. + + +Description +----------- + +This driver implements support for the Winbond W83792AD/D. + +Detection of the chip can sometimes be foiled because it can be in an +internal state that allows no clean access (Bank with ID register is not +currently selected). If you know the address of the chip, use a 'force' +parameter; this will put it into a more well-behaved state first. + +The driver implements three temperature sensors, seven fan rotation speed +sensors, nine voltage sensors, and two the automatic fan regulation +strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II. +Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run +synchronized with selected fan (fan1-fan3). This functionality and manual PWM +control for fan4-fan7 is not yet implemented. + +Temperatures are measured in degrees Celsius and measurement resolution is 1 +degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when +the temperature gets higher than the Overtemperature Shutdown value; it stays +on until the temperature falls below the Hysteresis value. + +Fan rotation speeds are reported in RPM (rotations per minute). An alarm is +triggered if the rotation speed has dropped below a programmable limit. Fan +readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or +128) to give the readings more range or accuracy. + +Voltage sensors (also known as IN sensors) report their values in millivolts. +An alarm is triggered if the voltage has crossed a programmable minimum +or maximum limit. + +Alarms are provided as output from "realtime status register". Following bits +are defined: + +bit - alarm on: +0 - in0 +1 - in1 +2 - temp1 +3 - temp2 +4 - temp3 +5 - fan1 +6 - fan2 +7 - fan3 +8 - in2 +9 - in3 +10 - in4 +11 - in5 +12 - in6 +13 - VID change +14 - chassis +15 - fan7 +16 - tart1 +17 - tart2 +18 - tart3 +19 - in7 +20 - in8 +21 - fan4 +22 - fan5 +23 - fan6 + +Tart will be asserted while target temperature cannot be achieved after 3 minutes +of full speed rotation of corresponding fan. + +In addition to the alarms described above, there is a CHAS alarm on the +chips which triggers if your computer case is open. (This one is latched +as opposite of realtime alarms) + +The chips only update values each 3 seconds; reading them more often will +do no harm, but will return 'old' values. + + +W83792D PROBLEMS +---------------- +Known problems: + - 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]. + - The function of vid and vrm has not been finished, because I'm NOT + very familiar with them. Adding support is welcomed. + - The function of chassis open detection needs more tests. + +Fan control +----------- + +Manual mode +----------- + +Works as expected. You just need to specify desired PWM/DC value (fan speed) +in appropriate pwm# file. + +Thermal cruise +-------------- + +At this mode, W83792D provides the Smart Fan system to automatically control +fan speed to keep the temperatures of CPU and the system within specific +range. At first a wanted temperature and interval must be set. This is done +via thermal_cruise# file. The tolerance# file serves to create T +- tolerance +interval. The fan speed will be lowered as long as the current temperature +remains below the thermal_cruise# +- tolerance# value. Once the temperature +exceeds the high limit (T+tolerance), the fan will be turned on with a +specific speed set by pwm# and automatically controlled its PWM duty cycle +with the temperature varying. Three conditions may occur: + +(1) If the temperature still exceeds the high limit, PWM duty +cycle will increase slowly. + +(2) If the temperature goes below the high limit, but still above the low +limit (T-tolerance), the fan speed will be fixed at the current speed because +the temperature is in the target range. + +(3) If the temperature goes below the low limit, PWM duty cycle will decrease +slowly to 0 or a preset stop value until the temperature exceeds the low +limit. (The preset stop value handling is not yet implemented in driver) + +Smart Fan II +------------ + +W83792D also provides a special mode for fan. Four temperature points are +available. When related temperature sensors detects the temperature in preset +temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run +on programmed value from sf2_level@_fan#. You need to set four temperatures +for each fan. + + +/sys files +---------- + +# denotes number any number from 1 to 3 +@ denotes number any number from 1 to 4 + +pwm# - this file stores PWM duty cycle or DC value (fan speed) in range: + 0 (stop) to 255 (full) +pwm#_enable - this file controls mode of fan/temperature control: + * 1 Manual mode + * 2 Smart Fan II + * 3 Thermal Cruise +pwm#_mode - Select PWM of DC mode + * 0 DC + * 1 PWM +thermal_cruise# - Selects the desired temperature for cruise (degC) +tolerance# - Value in degrees of Celsius (degC) for +- T +sf2_point@_fan# - four temperature points for each fan for Smart Fan II +sf2_level#_fan# - three PWM/DC levels for each fan for Smart Fan II diff -Naur old/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig --- old/drivers/i2c/chips/Kconfig 2005-06-21 08:52:53.000000000 +0200 +++ b/drivers/i2c/chips/Kconfig 2005-06-21 09:21:41.953070624 +0200 @@ -363,6 +363,16 @@ This driver can also be built as a module. If so, the module will be called w83781d. +config SENSORS_W83792D + tristate "Winbond W83792D" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for the Winbond W83792D chip. + + This driver can also be built as a module. If so, the module + will be called w83792d. + config SENSORS_W83L785TS tristate "Winbond W83L785TS-S" depends on I2C && EXPERIMENTAL diff -Naur old/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile --- old/drivers/i2c/chips/Makefile 2005-06-21 08:52:54.000000000 +0200 +++ b/drivers/i2c/chips/Makefile 2005-06-21 09:21:41.954070472 +0200 @@ -45,6 +45,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o +obj-$(CONFIG_SENSORS_W83792D) += w83792d.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o diff -Naur old/drivers/i2c/chips/w83792d.c b/drivers/i2c/chips/w83792d.c --- old/drivers/i2c/chips/w83792d.c 2005-06-21 09:13:03.736851464 +0200 +++ b/drivers/i2c/chips/w83792d.c 2005-06-21 09:46:06.926360832 +0200 @@ -4,6 +4,8 @@ Copyright (C) 2004, 2005 Winbond Electronics Corp. Chunhao Huang + Converted to new sysfs style by Rudolf Marek + 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 @@ -41,6 +43,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2f, I2C_CLIENT_END }; @@ -356,15 +359,21 @@ } /* following are the sysfs callback functions */ -static ssize_t show_in(struct device *dev, char *buf, int nr) +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) { + 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)))); } #define show_in_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ +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); \ + 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))); \ } @@ -373,8 +382,11 @@ show_in_reg(in_max); #define store_in_reg(REG, reg) \ -static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ +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); \ + int nr = sensor_attr->index; \ struct i2c_client *client = to_i2c_client(dev); \ struct w83792d_data *data = i2c_get_clientdata(client); \ u32 val; \ @@ -388,60 +400,51 @@ store_in_reg(MIN, min); store_in_reg(MAX, max); -#define sysfs_in_offset(offset) \ -static ssize_t \ -show_regs_in_##offset (struct device *dev, char *buf) \ -{ \ - return show_in(dev, buf, offset); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); - -#define sysfs_in_reg_offset(reg, offset) \ -static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ -{ \ - return show_in_##reg (dev, buf, offset); \ -} \ -static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \ -{ \ - return store_in_##reg (dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset); - -#define sysfs_in_offsets(offset) \ -sysfs_in_offset(offset); \ -sysfs_in_reg_offset(min, offset); \ -sysfs_in_reg_offset(max, offset); - -sysfs_in_offsets(0); -sysfs_in_offsets(1); -sysfs_in_offsets(2); -sysfs_in_offsets(3); -sysfs_in_offsets(4); -sysfs_in_offsets(5); -sysfs_in_offsets(6); -sysfs_in_offsets(7); -sysfs_in_offsets(8); +#define sysfs_in_reg(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ +NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ +show_in_min, store_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ +show_in_max, store_in_max, offset); + +sysfs_in_reg(0); +sysfs_in_reg(1); +sysfs_in_reg(2); +sysfs_in_reg(3); +sysfs_in_reg(4); +sysfs_in_reg(5); +sysfs_in_reg(6); +sysfs_in_reg(7); +sysfs_in_reg(8); #define device_create_file_in(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_in##offset##_input); \ -device_create_file(&client->dev, &dev_attr_in##offset##_min); \ -device_create_file(&client->dev, &dev_attr_in##offset##_max); \ +device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \ } while (0) #define show_fan_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ +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); \ + int nr = sensor_attr->index; \ struct w83792d_data *data = w83792d_update_device(dev); \ return sprintf(buf,"%ld\n", \ FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ } + show_fan_reg(fan); show_fan_reg(fan_min); static ssize_t -store_fan_min(struct device *dev, const char *buf, size_t count, int nr) +store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -455,182 +458,181 @@ return count; } -#define sysfs_fan_offset(offset) \ -static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ -{ \ - return show_fan(dev, buf, offset); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + 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) DIV_FROM_REG(data->fan_div[nr - 1])); +} -#define sysfs_fan_min_offset(offset) \ -static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset); \ -} \ -static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \ -{ \ - return store_fan_min(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset); - -sysfs_fan_offset(1); -sysfs_fan_min_offset(1); -sysfs_fan_offset(2); -sysfs_fan_min_offset(2); -sysfs_fan_offset(3); -sysfs_fan_min_offset(3); -sysfs_fan_offset(4); -sysfs_fan_min_offset(4); -sysfs_fan_offset(5); -sysfs_fan_min_offset(5); -sysfs_fan_offset(6); -sysfs_fan_min_offset(6); -sysfs_fan_offset(7); -sysfs_fan_min_offset(7); +/* 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 suprise; 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) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index - 1; + struct i2c_client *client = to_i2c_client(dev); + struct w83792d_data *data = i2c_get_clientdata(client); + unsigned long min; + /*u8 reg;*/ + u8 fan_div_reg = 0; + u8 tmp_fan_div; + + /* Save fan_min */ + 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)); + + fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); + fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8; + tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70) + : ((data->fan_div[nr]) & 0x07); + w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], + fan_div_reg | tmp_fan_div); + + /* Restore fan_min */ + data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); + + return count; +} + +#define sysfs_fan(offset) \ +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ +offset); \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ +show_fan_div, store_fan_div, offset); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ +show_fan_min, store_fan_min, offset); + +sysfs_fan(1); +sysfs_fan(2); +sysfs_fan(3); +sysfs_fan(4); +sysfs_fan(5); +sysfs_fan(6); +sysfs_fan(7); #define device_create_file_fan(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ -device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ +device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ } while (0) /* read/write the temperature1, includes measured value and limits */ -#define show_temp1_reg(reg, index) \ -static ssize_t show_##reg (struct device *dev, char *buf) \ -{ \ - struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf,"%ld\n", (long)TEMP1_FROM_REG(data->temp1[index])); \ -} -show_temp1_reg(temp1, 0); -show_temp1_reg(temp1_max, 1); -show_temp1_reg(temp1_max_hyst, 2); - -#define store_temp1_reg(reg, index) \ -static ssize_t store_##reg (struct device *dev, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83792d_data *data = i2c_get_clientdata(client); \ - s32 val; \ - \ - val = simple_strtol(buf, NULL, 10); \ - \ - data->temp1[index] = TEMP1_TO_REG(val); \ - w83792d_write_value(client, W83792D_REG_TEMP1[index], \ - data->temp1[index]); \ - \ - return count; \ +static ssize_t show_temp1(struct device *dev, struct device_attribute *attr, + char *buf) +{ + 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)TEMP1_FROM_REG(data->temp1[nr])); } -store_temp1_reg(temp1_max, 1); -store_temp1_reg(temp1_max_hyst, 2); -static ssize_t show_regs_temp1(struct device *dev, char *buf) +static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - return show_temp1(dev, buf); + 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); + s32 val; + + val = simple_strtol(buf, NULL, 10); + + data->temp1[nr] = TEMP1_TO_REG(val); + w83792d_write_value(client, W83792D_REG_TEMP1[nr], + data->temp1[nr]); + + return count; } -static DEVICE_ATTR(temp1_input, S_IRUGO, show_regs_temp1, NULL); - -#define sysfs_temp_offsets(reg) \ -static ssize_t show_regs_##reg(struct device *dev, char *buf) \ -{ \ - return show_##reg(dev, buf); \ -} \ -static ssize_t store_regs_##reg(struct device *dev, const char *buf, size_t count) \ -{ \ - return store_##reg(dev, buf, count); \ -} \ -static DEVICE_ATTR(reg, S_IRUGO|S_IWUSR, show_regs_##reg, store_regs_##reg); -sysfs_temp_offsets(temp1_max); -sysfs_temp_offsets(temp1_max_hyst); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1, + store_temp1, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, + store_temp1, 2); #define device_create_file_temp1(client) \ do { \ -device_create_file(&client->dev, &dev_attr_temp1_input); \ -device_create_file(&client->dev, &dev_attr_temp1_max); \ -device_create_file(&client->dev, &dev_attr_temp1_max_hyst); \ +device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \ } while (0) + /* read/write the temperature2-3, includes measured value and limits */ -#define show_temp_add_reg(reg, offset, index) \ -static ssize_t show_##reg (struct device *dev, char *buf) \ -{ \ - struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf,"%ld\n", \ - (long)TEMP_ADD_FROM_REG(data->temp_add[offset][index], \ - data->temp_add[offset][index+1])); \ + +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); + int nr = sensor_attr->nr; + int index = sensor_attr->index; + struct w83792d_data *data = w83792d_update_device(dev); + return sprintf(buf,"%ld\n", + (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index], + data->temp_add[nr][index+1])); } -show_temp_add_reg(temp2, 0, 0); -show_temp_add_reg(temp2_max, 0, 2); -show_temp_add_reg(temp2_max_hyst, 0, 4); -show_temp_add_reg(temp3, 1, 0); -show_temp_add_reg(temp3_max, 1, 2); -show_temp_add_reg(temp3_max_hyst, 1, 4); +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); + 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; -#define store_temp_add_reg(reg, offset, index) \ -static ssize_t store_##reg (struct device *dev, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83792d_data *data = i2c_get_clientdata(client); \ - s32 val; \ - \ - val = simple_strtol(buf, NULL, 10); \ - \ - data->temp_add[offset][index] = TEMP_ADD_TO_REG_HIGH(val); \ - data->temp_add[offset][index+1] = TEMP_ADD_TO_REG_LOW(val); \ - w83792d_write_value(client, W83792D_REG_TEMP_ADD[offset][index], \ - data->temp_add[offset][index]); \ - w83792d_write_value(client, W83792D_REG_TEMP_ADD[offset][index+1], \ - data->temp_add[offset][index+1]); \ - \ - return count; \ -} + val = simple_strtol(buf, NULL, 10); -store_temp_add_reg(temp2_max, 0, 2); -store_temp_add_reg(temp2_max_hyst, 0, 4); -store_temp_add_reg(temp3_max, 1, 2); -store_temp_add_reg(temp3_max_hyst, 1, 4); + data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); + data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); + w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], + data->temp_add[nr][index]); + w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], + data->temp_add[nr][index+1]); -#define show_regs_temp_add(reg) \ -static ssize_t show_regs_##reg(struct device *dev, char *buf) \ -{ \ - return show_##reg(dev, buf); \ -} \ -static DEVICE_ATTR(reg##_input, S_IRUGO, show_regs_##reg, NULL); + return count; +} -show_regs_temp_add(temp2); -show_regs_temp_add(temp3); +#define sysfs_temp23(name,idx) \ +static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ +idx, 0); \ +static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ +show_temp23, store_temp23, idx, 2); \ +static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \ +show_temp23, store_temp23, idx, 4); -#define sysfs_temp_add_offsets(reg) \ -static ssize_t show_regs_##reg(struct device *dev, char *buf) \ -{ \ - return show_##reg(dev, buf); \ -} \ -static ssize_t store_regs_##reg(struct device *dev, const char *buf, size_t count) \ -{ \ - return store_##reg(dev, buf, count); \ -} \ -static DEVICE_ATTR(reg, S_IRUGO|S_IWUSR, show_regs_##reg, store_regs_##reg); - -sysfs_temp_add_offsets(temp2_max); -sysfs_temp_add_offsets(temp2_max_hyst); -sysfs_temp_add_offsets(temp3_max); -sysfs_temp_add_offsets(temp3_max_hyst); +sysfs_temp23(temp2,0) +sysfs_temp23(temp3,1) #define device_create_file_temp_add(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ -device_create_file(&client->dev, &dev_attr_temp##offset##_max); \ -device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \ +device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \ +device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \ +device_create_file(&client->dev, \ +&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \ } while (0) /* get reatime status of all sensors items: voltage, temp, fan */ static ssize_t -show_alarms_reg(struct device *dev, char *buf) +show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); return sprintf(buf, "%d\n", data->alarms); @@ -642,82 +644,23 @@ device_create_file(&client->dev, &dev_attr_alarms); -static ssize_t -show_fan_div_reg(struct device *dev, char *buf, int nr) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", - (long) 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 suprise; the user doesn't expect the fan minimum to change just - because the divisor changed. */ static ssize_t -store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long min; - /*u8 reg;*/ - u8 fan_div_reg = 0; - u8 tmp_fan_div; - - /* Save fan_min */ - 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)); - - fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); - fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8; - tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70) - : ((data->fan_div[nr]) & 0x07); - w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], - fan_div_reg | tmp_fan_div); - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); - - return count; -} - -#define sysfs_fan_div(offset) \ -static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \ -{ \ - return show_fan_div_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \ -{ \ - return store_fan_div_reg(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset); - -sysfs_fan_div(1); -sysfs_fan_div(2); -sysfs_fan_div(3); -sysfs_fan_div(4); -sysfs_fan_div(5); -sysfs_fan_div(6); -sysfs_fan_div(7); - -#define device_create_file_fan_div(client, offset) \ -do { \ -device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ -} while (0) - -static ssize_t -show_pwm_reg(struct device *dev, char *buf, int nr) +show_pwm(struct device *dev, struct device_attribute *attr, + char *buf) { + 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) PWM_FROM_REG(data->pwm[nr-1])); } static ssize_t -show_pwmenable_reg(struct device *dev, char *buf, int nr) +show_pwmenable(struct device *dev, struct device_attribute *attr, + char *buf) { + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); long pwm_enable_tmp = 1; if (data->pwmenable[nr-1] == 0) { @@ -731,8 +674,11 @@ } static ssize_t -store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) +store_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -746,8 +692,11 @@ } static ssize_t -store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) +store_pwmenable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -779,59 +728,43 @@ } #define sysfs_pwm(offset) \ -static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \ -{ \ - return show_pwm_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_pwm_##offset (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_pwm_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_regs_pwm_##offset, store_regs_pwm_##offset); - -#define sysfs_pwmenable(offset) \ -static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \ -{ \ - return show_pwmenable_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_pwmenable_##offset (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_pwmenable_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); +static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ +show_pwm, store_pwm, offset); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ +show_pwmenable, store_pwmenable, offset); \ sysfs_pwm(1); sysfs_pwm(2); sysfs_pwm(3); -sysfs_pwmenable(1); -sysfs_pwmenable(2); -sysfs_pwmenable(3); + #define device_create_file_pwm(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_pwm##offset); \ +device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \ } while (0) #define device_create_file_pwmenable(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_pwm##offset##_enable); \ +device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \ } while (0) static ssize_t -show_pwm_mode_reg(struct device *dev, char *buf, int nr) +show_pwm_mode(struct device *dev, struct device_attribute *attr, + char *buf) { + 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)data->pwm_mode[nr-1]); } static ssize_t -store_pwm_mode_reg(struct device *dev, const char *buf, size_t count, int nr) +store_pwm_mode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -848,17 +781,8 @@ } #define sysfs_pwm_mode(offset) \ -static ssize_t show_regs_pwm_mode_##offset (struct device *dev, char *buf) \ -{ \ - return show_pwm_mode_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_pwm_mode_##offset (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_pwm_mode_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ - show_regs_pwm_mode_##offset, store_regs_pwm_mode_##offset); +static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ +show_pwm_mode, store_pwm_mode, offset); sysfs_pwm_mode(1); sysfs_pwm_mode(2); @@ -866,22 +790,18 @@ #define device_create_file_pwm_mode(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_pwm##offset##_mode); \ +device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \ } while (0) -static ssize_t -show_chassis_reg(struct device *dev, char *buf) +static ssize_t +show_regs_chassis(struct device *dev, struct device_attribute *attr, + char *buf) { struct w83792d_data *data = w83792d_update_device(dev); return sprintf(buf, "%ld\n", (long)data->chassis); } -static ssize_t show_regs_chassis (struct device *dev, char *buf) -{ - return show_chassis_reg(dev, buf); -} - static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); #define device_create_file_chassis(client) \ @@ -891,14 +811,15 @@ static ssize_t -show_chassis_clear_reg(struct device *dev, char *buf) +show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); return sprintf(buf, "%ld\n", (long)data->chassis_clear); } static ssize_t -store_chassis_clear_reg(struct device *dev, const char *buf, size_t count) +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); @@ -916,19 +837,8 @@ return count; } -static ssize_t show_regs_chassis_clear (struct device *dev, char *buf) -{ - return show_chassis_clear_reg(dev, buf); -} - -static ssize_t store_regs_chassis_clear (struct device *dev, - const char *buf, size_t count) -{ - return store_chassis_clear_reg(dev, buf, count); -} - static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, - show_regs_chassis_clear, store_regs_chassis_clear); + show_chassis_clear, store_chassis_clear); #define device_create_file_chassis_clear(client) \ do { \ @@ -939,15 +849,21 @@ /* For Smart Fan I / Thermal Cruise */ static ssize_t -show_thermal_cruise_reg(struct device *dev, char *buf, int nr) +show_thermal_cruise(struct device *dev, struct device_attribute *attr, + char *buf) { + 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)data->thermal_cruise[nr-1]); } static ssize_t -store_thermal_cruise_reg(struct device *dev, const char *buf, size_t count, int nr) +store_thermal_cruise(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -966,17 +882,8 @@ } #define sysfs_thermal_cruise(offset) \ -static ssize_t show_regs_thermal_cruise##offset (struct device *dev, char *buf) \ -{ \ - return show_thermal_cruise_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_thermal_cruise##offset (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_thermal_cruise_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ - show_regs_thermal_cruise##offset, store_regs_thermal_cruise##offset); +static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ +show_thermal_cruise, store_thermal_cruise, offset); sysfs_thermal_cruise(1); sysfs_thermal_cruise(2); @@ -984,21 +891,27 @@ #define device_create_file_thermal_cruise(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_thermal_cruise##offset); \ +device_create_file(&client->dev, &sensor_dev_attr_thermal_cruise##offset.dev_attr); \ } while (0) /* For Smart Fan I/Thermal Cruise and Smart Fan II */ static ssize_t -show_tolerance_reg(struct device *dev, char *buf, int nr) +show_tolerance(struct device *dev, struct device_attribute *attr, + char *buf) { + 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)data->tolerance[nr-1]); } static ssize_t -store_tolerance_reg(struct device *dev, const char *buf, size_t count, int nr) +store_tolerance(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + 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; @@ -1021,17 +934,8 @@ } #define sysfs_tolerance(offset) \ -static ssize_t show_regs_tolerance##offset (struct device *dev, char *buf) \ -{ \ - return show_tolerance_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_tolerance##offset (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_tolerance_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ - show_regs_tolerance##offset, store_regs_tolerance##offset); +static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ +show_tolerance, store_tolerance, offset); sysfs_tolerance(1); sysfs_tolerance(2); @@ -1039,21 +943,29 @@ #define device_create_file_tolerance(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_tolerance##offset); \ +device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \ } while (0) /* For Smart Fan II */ static ssize_t -show_sf2_point_reg(struct device *dev, char *buf, int nr, int index) +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); + int nr = sensor_attr->nr; + int index = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]); } static ssize_t -store_sf2_point_reg(struct device *dev, const char *buf, size_t count, int nr, int index) +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); + 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); u32 val; @@ -1071,18 +983,8 @@ } #define sysfs_sf2_point(offset, index) \ -static ssize_t show_regs_sf2_point##offset##_fan##index (struct device *dev, char *buf) \ -{ \ - return show_sf2_point_reg(dev, buf, offset, index); \ -} \ -static ssize_t store_regs_sf2_point##offset##_fan##index (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_sf2_point_reg(dev, buf, count, offset, index); \ -} \ -static DEVICE_ATTR(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_regs_sf2_point##offset##_fan##index, \ - store_regs_sf2_point##offset##_fan##index); +static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ +show_sf2_point, store_sf2_point, offset, index); sysfs_sf2_point(1, 1); /* Fan1 */ sysfs_sf2_point(2, 1); /* Fan1 */ @@ -1099,21 +1001,30 @@ #define device_create_file_sf2_point(client, offset, index) \ do { \ -device_create_file(&client->dev, &dev_attr_sf2_point##offset##_fan##index); \ +device_create_file(&client->dev, \ +&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ } while (0) static ssize_t -show_sf2_level_reg(struct device *dev, char *buf, int nr, int index) +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); + int nr = sensor_attr->nr; + int index = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); return sprintf(buf, "%d\n", (((data->sf2_levels[index-1][nr]) * 100) / 15)); } static ssize_t -store_sf2_level_reg(struct device *dev, const char *buf, size_t count, int nr, int index) +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); + 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); u32 val; @@ -1136,19 +1047,8 @@ } #define sysfs_sf2_level(offset, index) \ -static ssize_t show_regs_sf2_level##offset##_fan##index (struct device *dev, char *buf) \ -{ \ - return show_sf2_level_reg(dev, buf, offset, index); \ -} \ -static ssize_t store_regs_sf2_level##offset##_fan##index (struct device *dev, \ - const char *buf, size_t count) \ -{ \ - return store_sf2_level_reg(dev, buf, count, offset, index); \ -} \ -static DEVICE_ATTR(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_regs_sf2_level##offset##_fan##index, \ - store_regs_sf2_level##offset##_fan##index); - +static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ +show_sf2_level, store_sf2_level, offset, index); sysfs_sf2_level(1, 1); /* Fan1 */ sysfs_sf2_level(2, 1); /* Fan1 */ @@ -1162,7 +1062,8 @@ #define device_create_file_sf2_level(client, offset, index) \ do { \ -device_create_file(&client->dev, &dev_attr_sf2_level##offset##_fan##index); \ +device_create_file(&client->dev, \ +&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \ } while (0) @@ -1411,14 +1312,6 @@ device_create_file_alarms(new_client); - device_create_file_fan_div(new_client, 1); - device_create_file_fan_div(new_client, 2); - device_create_file_fan_div(new_client, 3); - device_create_file_fan_div(new_client, 4); - device_create_file_fan_div(new_client, 5); - device_create_file_fan_div(new_client, 6); - device_create_file_fan_div(new_client, 7); - device_create_file_pwm(new_client, 1); device_create_file_pwm(new_client, 2); device_create_file_pwm(new_client, 3); diff -Naur old/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h --- old/include/linux/hwmon-sysfs.h 2005-06-21 08:53:23.000000000 +0200 +++ b/include/linux/hwmon-sysfs.h 2005-06-21 09:47:27.313140184 +0200 @@ -33,4 +33,19 @@ .index = _index, \ } +struct sensor_device_attribute_2 { + struct device_attribute dev_attr; + u8 index; + u8 nr; +}; +#define to_sensor_dev_attr_2(_dev_attr) \ + container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) + +#define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ +struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ + .dev_attr = __ATTR(_name,_mode,_show,_store), \ + .index = _index, \ + .nr = _nr, \ +} + #endif /* _LINUX_HWMON_SYSFS_H */