From bc37ae71207ca899efb93be1fe6b000366debc3a Mon Sep 17 00:00:00 2001 From: Mark van Doesburg Date: Wed, 7 Jan 2009 16:37:27 +0100 Subject: hwmon: (f71882fg) Use sensor_device_attribute_2 Convert f71882fg driver from SENSOR_ATTR to SENSOR_ATTR2 use, this is a preparation patch for adding pwm support, which is broken out to make what changes really in the pwm support patch clear. Signed-off-by: Hans de Goede Cc: Mark van Doesburg Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 187 ++++++++++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 92 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 67067e9a323e..e2f3c5a82153 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -188,79 +188,82 @@ static struct device_attribute f71882fg_dev_attr[] = __ATTR( name, S_IRUGO, show_name, NULL ), }; -static struct sensor_device_attribute f71882fg_in_temp_attr[] = -{ - SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), - SENSOR_ATTR(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 1), - SENSOR_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, 1), - SENSOR_ATTR(in1_alarm, S_IRUGO, show_in_alarm, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), - SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), - SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), - SENSOR_ATTR(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0), - SENSOR_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0), - SENSOR_ATTR(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0), - SENSOR_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0), - SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), - SENSOR_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0), - SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0), - SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), - SENSOR_ATTR(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 1), - SENSOR_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 1), - SENSOR_ATTR(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 1), - SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1), - SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), - SENSOR_ATTR(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 1), - SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1), - SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), - SENSOR_ATTR(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 2), - SENSOR_ATTR(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 2), - SENSOR_ATTR(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 2), - SENSOR_ATTR(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 2), - SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), - SENSOR_ATTR(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 2), - SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2), - SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2) +static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, + 0, 1), + SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, + 0, 1), + SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), + SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 0), + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0, 0), + SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 0), + SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, + 0, 0), + SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 0), + SENSOR_ATTR_2(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 0), + SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0), + SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 1), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0, 1), + SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 1), + SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, + 0, 1), + SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1), + SENSOR_ATTR_2(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 1), + SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), + SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), + SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 2), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0, 2), + SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 2), + SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, + 0, 2), + SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 2), + SENSOR_ATTR_2(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 2), + SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), + SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -static struct sensor_device_attribute f71882fg_fan_attr[] = -{ - SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), - SENSOR_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0), - SENSOR_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0), - SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), - SENSOR_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 1), - SENSOR_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1), - SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), - SENSOR_ATTR(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 2), - SENSOR_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2), - SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), - SENSOR_ATTR(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 3), - SENSOR_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3) +static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { + SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), + SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 0), + SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), + SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), + SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 1), + SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), + SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), + SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 2), + SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), + SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), + SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 3), + SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), }; @@ -417,7 +420,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int speed = fan_from_reg(data->fan[nr]); if (speed == FAN_MIN_DETECT) @@ -430,7 +433,7 @@ static ssize_t show_fan_beep(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->fan_beep & (1 << nr)) return sprintf(buf, "1\n"); @@ -442,7 +445,7 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -461,7 +464,7 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->fan_status & (1 << nr)) return sprintf(buf, "1\n"); @@ -473,7 +476,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", data->in[nr] * 8); } @@ -507,7 +510,7 @@ static ssize_t show_in_beep(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->in_beep & (1 << nr)) return sprintf(buf, "1\n"); @@ -519,7 +522,7 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -538,7 +541,7 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->in_status & (1 << nr)) return sprintf(buf, "1\n"); @@ -550,7 +553,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", data->temp[nr] * 1000); } @@ -559,7 +562,7 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", data->temp_high[nr] * 1000); } @@ -568,7 +571,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10) / 1000; if (val > 255) @@ -586,7 +589,7 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", (data->temp_high[nr] - data->temp_hyst[nr]) * 1000); @@ -596,7 +599,7 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10) / 1000; ssize_t ret = count; @@ -636,7 +639,7 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000); } @@ -645,7 +648,7 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10) / 1000; if (val > 255) @@ -663,7 +666,7 @@ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000); @@ -673,7 +676,7 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; return sprintf(buf, "%d\n", data->temp_type[nr]); } @@ -682,7 +685,7 @@ static ssize_t show_temp_beep(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->temp_beep & (1 << (nr + 1))) return sprintf(buf, "1\n"); @@ -694,7 +697,7 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; int val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -713,7 +716,7 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->temp_status & (1 << (nr + 1))) return sprintf(buf, "1\n"); @@ -725,7 +728,7 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute *devattr, char *buf) { struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->index; if (data->temp_diode_open & (1 << (nr + 1))) return sprintf(buf, "1\n"); -- cgit v1.2.3 From 77a4a3e2a36aea5896f86653f6b77168d578c962 Mon Sep 17 00:00:00 2001 From: Mark van Doesburg Date: Wed, 7 Jan 2009 16:37:27 +0100 Subject: hwmon: (f71882fg) Misc cleanups A few cleanups that were originally part of a larger patch but are better submitted separately. Signed-off-by: Hans de Goede Cc: Mark van Doesburg Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index e2f3c5a82153..c6fa8578bdeb 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -27,11 +27,11 @@ #include #include #include -#include +#include #define DRVNAME "f71882fg" -#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device*/ +#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ @@ -78,7 +78,7 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -static struct platform_device *f71882fg_pdev = NULL; +static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); @@ -114,7 +114,7 @@ struct f71882fg_data { u8 temp_diode_open; }; -/* Sysfs in*/ +/* Sysfs in */ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf); static ssize_t show_in_max(struct device *dev, struct device_attribute @@ -335,7 +335,7 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) outb(val, data->addr + DATA_REG_OFFSET); } -static struct f71882fg_data *f71882fg_update_device(struct device * dev) +static struct f71882fg_data *f71882fg_update_device(struct device *dev) { struct f71882fg_data *data = dev_get_drvdata(dev); int nr, reg, reg2; -- cgit v1.2.3 From 9ab796ebe185257013f0ac505ecbe7abf068a608 Mon Sep 17 00:00:00 2001 From: Mark van Doesburg Date: Wed, 7 Jan 2009 16:37:27 +0100 Subject: hwmon: (f71882fg) Add PWM support Add PWM (fan speed control) support to the f71882fg driver. Both manual control and automatic (temperature-based) modes are supported. Additionally, each mode has a PWM-based and an RPM-based variant. By default we use the mode set by the BIOS. Signed-off-by: Hans de Goede Cc: Mark van Doesburg Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 656 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 655 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index c6fa8578bdeb..c04108735f3f 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -57,6 +57,8 @@ #define F71882FG_REG_IN1_HIGH 0x32 #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) +#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) +#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr))) #define F71882FG_REG_FAN_STATUS 0x92 #define F71882FG_REG_FAN_BEEP 0x93 @@ -70,6 +72,17 @@ #define F71882FG_REG_TEMP_TYPE 0x6B #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F +#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr))) +#define F71882FG_REG_PWM_TYPE 0x94 +#define F71882FG_REG_PWM_ENABLE 0x96 + +#define F71882FG_REG_FAN_HYST0 0x98 +#define F71882FG_REG_FAN_HYST1 0x99 + +#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm))) +#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm))) +#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr)) + #define F71882FG_REG_START 0x01 #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ @@ -78,6 +91,12 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); +static int fan_mode[4] = { 0, 0, 0, 0 }; +module_param_array(fan_mode, int, NULL, 0644); +MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) " + "(0=don't change, 1=pwm, 2=rpm)\n" + "Note: this needs a write to pwm#_enable to take effect"); + static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ @@ -102,6 +121,8 @@ struct f71882fg_data { u8 in_status; u8 in_beep; u16 fan[4]; + u16 fan_target[4]; + u16 fan_full_speed[4]; u8 fan_status; u8 fan_beep; u8 temp[3]; @@ -112,6 +133,12 @@ struct f71882fg_data { u8 temp_status; u8 temp_beep; u8 temp_diode_open; + u8 pwm[4]; + u8 pwm_enable; + u8 pwm_auto_point_hyst[2]; + u8 pwm_auto_point_mapping[4]; + u8 pwm_auto_point_pwm[4][5]; + u8 pwm_auto_point_temp[4][4]; }; /* Sysfs in */ @@ -130,6 +157,10 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute /* Sysfs Fan */ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf); +static ssize_t show_fan_full_speed(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_fan_full_speed(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); static ssize_t show_fan_beep(struct device *dev, struct device_attribute *devattr, char *buf); static ssize_t store_fan_beep(struct device *dev, struct device_attribute @@ -163,6 +194,35 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute *devattr, char *buf); static ssize_t show_temp_fault(struct device *dev, struct device_attribute *devattr, char *buf); +/* PWM and Auto point control */ +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_enable(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_pwm_interpolate(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_interpolate(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_pwm_auto_point_channel(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_auto_point_channel(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_pwm_auto_point_pwm(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_auto_point_pwm(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t store_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); /* Sysfs misc */ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf); @@ -249,21 +309,217 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), + SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, + show_fan_full_speed, + store_fan_full_speed, 0, 0), SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, store_fan_beep, 0, 0), SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), + SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, + show_fan_full_speed, + store_fan_full_speed, 0, 1), SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, store_fan_beep, 0, 1), SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), + SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, + show_fan_full_speed, + store_fan_full_speed, 0, 2), SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, store_fan_beep, 0, 2), SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), + SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, + show_fan_full_speed, + store_fan_full_speed, 0, 3), SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, store_fan_beep, 0, 3), SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), + + SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), + SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 0), + SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 0), + SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 0), + SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 0), + SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 0), + SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 0), + SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 0), + SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 0), + SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 0), + SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 0), + SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 0), + SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 0), + SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 0), + SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 0), + SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 0), + SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 0), + + SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), + SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 1), + SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 1), + SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 1), + SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 1), + SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 1), + SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 1), + SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 1), + SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 1), + SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 1), + SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 1), + SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 1), + SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 1), + SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 1), + SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 1), + SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 1), + SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 1), + + SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), + SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 2), + SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 2), + SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 2), + SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 2), + SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 2), + SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 2), + SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 2), + SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 2), + SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 2), + SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 2), + SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 2), + SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 2), + SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 2), + SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 2), + SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 2), + SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 2), + + SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3), + SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 3), + SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 3), + SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 3), + SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 3), + SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 3), + SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 3), + SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 3), + SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 3), + SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 3), + SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 3), + SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 3), + SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 3), + SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 3), + SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 3), + SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 3), + SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 3), }; @@ -307,6 +563,11 @@ static inline u16 fan_from_reg(u16 reg) return reg ? (1500000 / reg) : 0; } +static inline u16 fan_to_reg(u16 fan) +{ + return fan ? (1500000 / fan) : 0; +} + static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) { u8 val; @@ -335,6 +596,14 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) outb(val, data->addr + DATA_REG_OFFSET); } +static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) +{ + outb(reg++, data->addr + ADDR_REG_OFFSET); + outb(val >> 8, data->addr + DATA_REG_OFFSET); + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val & 255, data->addr + DATA_REG_OFFSET); +} + static struct f71882fg_data *f71882fg_update_device(struct device *dev) { struct f71882fg_data *data = dev_get_drvdata(dev); @@ -381,6 +650,32 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); + data->pwm_enable = f71882fg_read8(data, + F71882FG_REG_PWM_ENABLE); + data->pwm_auto_point_hyst[0] = f71882fg_read8(data, + F71882FG_REG_FAN_HYST0); + data->pwm_auto_point_hyst[1] = f71882fg_read8(data, + F71882FG_REG_FAN_HYST1); + for (nr = 0; nr < 4; nr++) { + int point; + + data->pwm_auto_point_mapping[nr] = + f71882fg_read8(data, + F71882FG_REG_POINT_MAPPING(nr)); + + for (point = 0; point < 5; point++) { + data->pwm_auto_point_pwm[nr][point] = + f71882fg_read8(data, + F71882FG_REG_POINT_PWM + (nr, point)); + } + for (point = 0; point < 4; point++) { + data->pwm_auto_point_temp[nr][point] = + f71882fg_read8(data, + F71882FG_REG_POINT_TEMP + (nr, point)); + } + } data->last_limits = jiffies; } @@ -396,9 +691,17 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->fan_status = f71882fg_read8(data, F71882FG_REG_FAN_STATUS); - for (nr = 0; nr < 4; nr++) + for (nr = 0; nr < 4; nr++) { data->fan[nr] = f71882fg_read16(data, F71882FG_REG_FAN(nr)); + data->fan_target[nr] = + f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr)); + data->fan_full_speed[nr] = + f71882fg_read16(data, + F71882FG_REG_FAN_FULL_SPEED(nr)); + data->pwm[nr] = + f71882fg_read8(data, F71882FG_REG_PWM(nr)); + } data->in_status = f71882fg_read8(data, F71882FG_REG_IN_STATUS); @@ -429,6 +732,40 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", speed); } +static ssize_t show_fan_full_speed(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + int speed = fan_from_reg(data->fan_full_speed[nr]); + return sprintf(buf, "%d\n", speed); +} + +static ssize_t store_fan_full_speed(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + long val = simple_strtol(buf, NULL, 10); + + val = SENSORS_LIMIT(val, 23, 1500000); + val = fan_to_reg(val); + + mutex_lock(&data->update_lock); + if (data->pwm_enable & (1 << (2 * nr))) + /* PWM mode */ + count = -EINVAL; + else { + /* RPM mode */ + f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); + data->fan_full_speed[nr] = val; + } + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t show_fan_beep(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -736,6 +1073,323 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute return sprintf(buf, "0\n"); } +static ssize_t show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int val, nr = to_sensor_dev_attr_2(devattr)->index; + if (data->pwm_enable & (1 << (2 * nr))) + /* PWM mode */ + val = data->pwm[nr]; + else { + /* RPM mode */ + mutex_lock(&data->update_lock); + val = 255 * fan_from_reg(data->fan_target[nr]) + / fan_from_reg(data->fan_full_speed[nr]); + mutex_unlock(&data->update_lock); + } + return sprintf(buf, "%d\n", val); +} + +static ssize_t store_pwm(struct device *dev, + struct device_attribute *devattr, const char *buf, + size_t count) +{ + /* struct f71882fg_data *data = dev_get_drvdata(dev); */ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + long val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(val, 0, 255); + + mutex_lock(&data->update_lock); + if (data->pwm_enable & (1 << (2 * nr))) { + /* PWM mode */ + f71882fg_write8(data, F71882FG_REG_PWM(nr), val); + data->pwm[nr] = val; + } else { + /* RPM mode */ + int target = val * fan_from_reg(data->fan_full_speed[nr]) / 255; + f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), + fan_to_reg(target)); + data->fan_target[nr] = fan_to_reg(target); + } + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int result; + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + + if (data->pwm_enable & (2 << (2 * nr))) + result = 1; + else + result = 2; + + return sprintf(buf, "%d\n", result); +} + +static ssize_t store_pwm_enable(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + long val = simple_strtol(buf, NULL, 10); + if (val < 1 || val > 2) + return -EINVAL; + + mutex_lock(&data->update_lock); + switch (val) { + case 1: + data->pwm_enable |= 2 << (2 * nr); + break; /* Manual */ + case 2: + data->pwm_enable &= ~(2 << (2 * nr)); + break; /* Temperature ctrl */ + } + switch (fan_mode[nr]) { + case 1: + data->pwm_enable |= 1 << (2 * nr); + break; /* Duty cycle mode */ + case 2: + data->pwm_enable &= ~(1 << (2 * nr)); + break; /* RPM mode */ + } + f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_auto_point_pwm(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int result; + struct f71882fg_data *data = f71882fg_update_device(dev); + int pwm = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + + if (data->pwm_enable & (1 << (2 * pwm))) { + /* PWM mode */ + result = data->pwm_auto_point_pwm[pwm][point]; + } else { + /* RPM mode */ + result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]); + } + + return sprintf(buf, "%d\n", result); +} + +static ssize_t store_pwm_auto_point_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + /* struct f71882fg_data *data = dev_get_drvdata(dev); */ + struct f71882fg_data *data = f71882fg_update_device(dev); + int pwm = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + int val = simple_strtoul(buf, NULL, 10); + val = SENSORS_LIMIT(val, 0, 255); + + mutex_lock(&data->update_lock); + if (data->pwm_enable & (1 << (2 * pwm))) { + /* PWM mode */ + } else { + /* RPM mode */ + if (val < 29) /* Prevent negative numbers */ + val = 255; + else + val = (255 - val) * 32 / val; + } + f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val); + data->pwm_auto_point_pwm[pwm][point] = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int result = 0; + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + + mutex_lock(&data->update_lock); + switch (nr) { + case 0: + result = data->pwm_auto_point_hyst[0] & 0x0f; + break; + case 1: + result = data->pwm_auto_point_hyst[0] >> 4; + break; + case 2: + result = data->pwm_auto_point_hyst[1] & 0x0f; + break; + case 3: + result = data->pwm_auto_point_hyst[1] >> 4; + break; + } + result = 1000 * (data->pwm_auto_point_temp[nr][point] - result); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", result); +} + +static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + long val = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->update_lock); + val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15, + data->pwm_auto_point_temp[nr][point]); + val = data->pwm_auto_point_temp[nr][point] - val; + + switch (nr) { + case 0: + val = (data->pwm_auto_point_hyst[0] & 0xf0) | val; + break; + case 1: + val = (data->pwm_auto_point_hyst[0] & 0x0f) | (val << 4); + break; + case 2: + val = (data->pwm_auto_point_hyst[1] & 0xf0) | val; + break; + case 3: + val = (data->pwm_auto_point_hyst[1] & 0x0f) | (val << 4); + break; + } + if (nr == 0 || nr == 1) { + f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val); + data->pwm_auto_point_hyst[0] = val; + } else { + f71882fg_write8(data, F71882FG_REG_FAN_HYST1, val); + data->pwm_auto_point_hyst[1] = val; + } + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_interpolate(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int result; + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + + result = (data->pwm_auto_point_mapping[nr] >> 4) & 1; + + return sprintf(buf, "%d\n", result); +} + +static ssize_t store_pwm_interpolate(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + /* struct f71882fg_data *data = dev_get_drvdata(dev); */ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + int val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); + if (val) + val = data->pwm_auto_point_mapping[nr] | (1 << 4); + else + val = data->pwm_auto_point_mapping[nr] & (~(1 << 4)); + f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); + data->pwm_auto_point_mapping[nr] = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_auto_point_channel(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int result; + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + + result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1); + + return sprintf(buf, "%d\n", result); +} + +static ssize_t store_pwm_auto_point_channel(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + /* struct f71882fg_data *data = dev_get_drvdata(dev); */ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr_2(devattr)->index; + long val = simple_strtol(buf, NULL, 10); + switch (val) { + case 1: + val = 1; + break; + case 2: + val = 2; + break; + case 4: + val = 3; + break; + default: + return -EINVAL; + } + mutex_lock(&data->update_lock); + val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val; + f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); + data->pwm_auto_point_mapping[nr] = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int result; + struct f71882fg_data *data = f71882fg_update_device(dev); + int pwm = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + + result = data->pwm_auto_point_temp[pwm][point]; + return sprintf(buf, "%d\n", 1000 * result); +} + +static ssize_t store_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + /* struct f71882fg_data *data = dev_get_drvdata(dev); */ + struct f71882fg_data *data = f71882fg_update_device(dev); + int pwm = to_sensor_dev_attr_2(devattr)->index; + int point = to_sensor_dev_attr_2(devattr)->nr; + long val = simple_strtol(buf, NULL, 10) / 1000; + val = SENSORS_LIMIT(val, 0, 255); + + mutex_lock(&data->update_lock); + f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); + data->pwm_auto_point_temp[pwm][point] = val; + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { -- cgit v1.2.3 From c13548c531ff40501aee1c1dd6f474c3c6adfcd5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:27 +0100 Subject: hwmon: (f71882fg) Style cleanups and put some repeating code into functions Various small cleanups as preparation for adding f71862fg support to the f71882fg driver. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 89 ++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 48 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index c04108735f3f..593ed2a0555c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2006 by Hans Edgington * - * Copyright (C) 2007 by Hans de Goede * + * Copyright (C) 2007,2008 by Hans de Goede * * * * 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 * @@ -228,11 +228,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf); static int __devinit f71882fg_probe(struct platform_device * pdev); -static int __devexit f71882fg_remove(struct platform_device *pdev); -static int __init f71882fg_init(void); -static int __init f71882fg_find(int sioaddr, unsigned short *address); -static int __init f71882fg_device_add(unsigned short address); -static void __exit f71882fg_exit(void); +static int f71882fg_remove(struct platform_device *pdev); static struct platform_driver f71882fg_driver = { .driver = { @@ -243,10 +239,7 @@ static struct platform_driver f71882fg_driver = { .remove = __devexit_p(f71882fg_remove), }; -static struct device_attribute f71882fg_dev_attr[] = -{ - __ATTR( name, S_IRUGO, show_name, NULL ), -}; +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), @@ -1396,14 +1389,27 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr, return sprintf(buf, DRVNAME "\n"); } +static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, + struct sensor_device_attribute_2 *attr, int count) +{ + int err, i; + + for (i = 0; i < count; i++) { + err = device_create_file(&pdev->dev, &attr[i].dev_attr); + if (err) + return err; + } + return 0; +} -static int __devinit f71882fg_probe(struct platform_device * pdev) +static int __devinit f71882fg_probe(struct platform_device *pdev) { struct f71882fg_data *data; - int err, i; + int err; u8 start_reg; - if (!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL))) + data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL); + if (!data) return -ENOMEM; data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; @@ -1411,65 +1417,50 @@ static int __devinit f71882fg_probe(struct platform_device * pdev) platform_set_drvdata(pdev, data); /* Register sysfs interface files */ - for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) { - err = device_create_file(&pdev->dev, &f71882fg_dev_attr[i]); - if (err) - goto exit_unregister_sysfs; - } + err = device_create_file(&pdev->dev, &dev_attr_name); + if (err) + goto exit_unregister_sysfs; start_reg = f71882fg_read8(data, F71882FG_REG_START); if (start_reg & 0x01) { - for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) { - err = device_create_file(&pdev->dev, - &f71882fg_in_temp_attr[i].dev_attr); - if (err) - goto exit_unregister_sysfs; - } + err = f71882fg_create_sysfs_files(pdev, f71882fg_in_temp_attr, + ARRAY_SIZE(f71882fg_in_temp_attr)); + if (err) + goto exit_unregister_sysfs; } if (start_reg & 0x02) { - for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) { - err = device_create_file(&pdev->dev, - &f71882fg_fan_attr[i].dev_attr); - if (err) - goto exit_unregister_sysfs; - } + err = f71882fg_create_sysfs_files(pdev, f71882fg_fan_attr, + ARRAY_SIZE(f71882fg_fan_attr)); + if (err) + goto exit_unregister_sysfs; } data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); + data->hwmon_dev = NULL; goto exit_unregister_sysfs; } return 0; exit_unregister_sysfs: - for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) - device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); - - for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) - device_remove_file(&pdev->dev, - &f71882fg_in_temp_attr[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) - device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); - - kfree(data); + f71882fg_remove(pdev); /* Will unregister the sysfs files for us */ return err; } -static int __devexit f71882fg_remove(struct platform_device *pdev) +static int f71882fg_remove(struct platform_device *pdev) { int i; struct f71882fg_data *data = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); - hwmon_device_unregister(data->hwmon_dev); + if (data->hwmon_dev) + hwmon_device_unregister(data->hwmon_dev); - for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) - device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); + device_remove_file(&pdev->dev, &dev_attr_name); for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) device_remove_file(&pdev->dev, @@ -1577,10 +1568,12 @@ static int __init f71882fg_init(void) if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address)) goto exit; - if ((err = platform_driver_register(&f71882fg_driver))) + err = platform_driver_register(&f71882fg_driver); + if (err) goto exit; - if ((err = f71882fg_device_add(address))) + err = f71882fg_device_add(address); + if (err) goto exit_driver; return 0; @@ -1598,7 +1591,7 @@ static void __exit f71882fg_exit(void) } MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans Edgington (hans@edgington.nl)"); +MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)"); MODULE_LICENSE("GPL"); module_init(f71882fg_init); -- cgit v1.2.3 From 498be96834bf88a44db2f4a3115688c882e6f3e3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:28 +0100 Subject: hwmon: (f71882fg) Add support for the F71862FG superio sensors This patch adds support for the Fintek f71862fg superio monitoring functions to the f71882fg driver. This support has been tested without problems on a Jetway J9F2 by Tony McConnell. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 296 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 224 insertions(+), 72 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 593ed2a0555c..cdd16d4966c3 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -43,6 +43,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ #define REGION_LENGTH 8 @@ -51,10 +52,10 @@ #define F71882FG_REG_PECI 0x0A -#define F71882FG_REG_IN_STATUS 0x12 -#define F71882FG_REG_IN_BEEP 0x13 +#define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */ +#define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */ #define F71882FG_REG_IN(nr) (0x20 + (nr)) -#define F71882FG_REG_IN1_HIGH 0x32 +#define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */ #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) #define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) @@ -97,6 +98,13 @@ MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) " "(0=don't change, 1=pwm, 2=rpm)\n" "Note: this needs a write to pwm#_enable to take effect"); +enum chips { f71862fg, f71882fg }; + +static const char *f71882fg_names[] = { + "f71862fg", + "f71882fg", +}; + static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ @@ -106,8 +114,13 @@ static inline void superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); +struct f71882fg_sio_data { + enum chips type; +}; + struct f71882fg_data { unsigned short addr; + enum chips type; struct device *hwmon_dev; struct mutex update_lock; @@ -241,14 +254,9 @@ static struct platform_driver f71882fg_driver = { static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { +static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), - SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, - 0, 1), - SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, - 0, 1), - SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), @@ -300,7 +308,15 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { +static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { + SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, + 0, 1), + SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, + 0, 1), + SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), +}; + +static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed, @@ -322,13 +338,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, store_fan_beep, 0, 2), SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), - SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), - SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, - show_fan_full_speed, - store_fan_full_speed, 0, 3), - SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 3), - SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, @@ -338,6 +347,75 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, show_pwm_auto_point_channel, store_pwm_auto_point_channel, 0, 0), + + SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), + SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 1), + SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 1), + SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 1), + + SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), + SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 2), + SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, + show_pwm_interpolate, store_pwm_interpolate, 0, 2), + SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_channel, + store_pwm_auto_point_channel, 0, 2), +}; + +static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { + SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 0), + SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 0), + SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 0), + SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 0), + SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 0), + SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 0), + + SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 1), + SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 1), + SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 1), + SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 1), + SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 1), + SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 1), +}; + +static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { + SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), + SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, + show_fan_full_speed, + store_fan_full_speed, 0, 3), + SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 3), + SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), + SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 0, 0), @@ -376,14 +454,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, show_pwm_auto_point_temp_hyst, NULL, 3, 0), - SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), - SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 1), - SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 1), - SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 1), SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 0, 1), @@ -422,14 +492,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, show_pwm_auto_point_temp_hyst, NULL, 3, 1), - SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), - SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 2), - SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 2), - SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 2), SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 0, 2), @@ -601,14 +663,19 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) { struct f71882fg_data *data = dev_get_drvdata(dev); int nr, reg, reg2; + int nr_fans = (data->type == f71862fg) ? 3 : 4; mutex_lock(&data->update_lock); /* Update once every 60 seconds */ if ( time_after(jiffies, data->last_limits + 60 * HZ ) || !data->valid) { - data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH); - data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); + if (data->type == f71882fg) { + data->in1_max = + f71882fg_read8(data, F71882FG_REG_IN1_HIGH); + data->in_beep = + f71882fg_read8(data, F71882FG_REG_IN_BEEP); + } /* Get High & boundary temps*/ for (nr = 0; nr < 3; nr++) { @@ -649,24 +716,42 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) F71882FG_REG_FAN_HYST0); data->pwm_auto_point_hyst[1] = f71882fg_read8(data, F71882FG_REG_FAN_HYST1); - for (nr = 0; nr < 4; nr++) { - int point; - + for (nr = 0; nr < nr_fans; nr++) { data->pwm_auto_point_mapping[nr] = f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); - for (point = 0; point < 5; point++) { - data->pwm_auto_point_pwm[nr][point] = - f71882fg_read8(data, - F71882FG_REG_POINT_PWM - (nr, point)); - } - for (point = 0; point < 4; point++) { - data->pwm_auto_point_temp[nr][point] = - f71882fg_read8(data, - F71882FG_REG_POINT_TEMP - (nr, point)); + if (data->type == f71882fg) { + int point; + for (point = 0; point < 5; point++) { + data->pwm_auto_point_pwm[nr][point] = + f71882fg_read8(data, + F71882FG_REG_POINT_PWM + (nr, point)); + } + for (point = 0; point < 4; point++) { + data->pwm_auto_point_temp[nr][point] = + f71882fg_read8(data, + F71882FG_REG_POINT_TEMP + (nr, point)); + } + } else { + data->pwm_auto_point_pwm[nr][1] = + f71882fg_read8(data, + F71882FG_REG_POINT_PWM + (nr, 1)); + data->pwm_auto_point_pwm[nr][4] = + f71882fg_read8(data, + F71882FG_REG_POINT_PWM + (nr, 4)); + data->pwm_auto_point_temp[nr][0] = + f71882fg_read8(data, + F71882FG_REG_POINT_TEMP + (nr, 0)); + data->pwm_auto_point_temp[nr][3] = + f71882fg_read8(data, + F71882FG_REG_POINT_TEMP + (nr, 3)); } } data->last_limits = jiffies; @@ -684,7 +769,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->fan_status = f71882fg_read8(data, F71882FG_REG_FAN_STATUS); - for (nr = 0; nr < 4; nr++) { + for (nr = 0; nr < nr_fans; nr++) { data->fan[nr] = f71882fg_read16(data, F71882FG_REG_FAN(nr)); data->fan_target[nr] = @@ -696,7 +781,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) f71882fg_read8(data, F71882FG_REG_PWM(nr)); } - data->in_status = f71882fg_read8(data, + if (data->type == f71882fg) + data->in_status = f71882fg_read8(data, F71882FG_REG_IN_STATUS); for (nr = 0; nr < 9; nr++) data->in[nr] = f71882fg_read8(data, @@ -1144,13 +1230,15 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute data->pwm_enable &= ~(2 << (2 * nr)); break; /* Temperature ctrl */ } - switch (fan_mode[nr]) { - case 1: - data->pwm_enable |= 1 << (2 * nr); - break; /* Duty cycle mode */ - case 2: - data->pwm_enable &= ~(1 << (2 * nr)); - break; /* RPM mode */ + if (data->type == f71882fg) { + switch (fan_mode[nr]) { + case 1: + data->pwm_enable |= 1 << (2 * nr); + break; /* Duty cycle mode */ + case 2: + data->pwm_enable &= ~(1 << (2 * nr)); + break; /* RPM mode */ + } } f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); mutex_unlock(&data->update_lock); @@ -1386,7 +1474,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { - return sprintf(buf, DRVNAME "\n"); + struct f71882fg_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", f71882fg_names[data->type]); } static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, @@ -1405,6 +1494,7 @@ static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, static int __devinit f71882fg_probe(struct platform_device *pdev) { struct f71882fg_data *data; + struct f71882fg_sio_data *sio_data = pdev->dev.platform_data; int err; u8 start_reg; @@ -1413,6 +1503,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) return -ENOMEM; data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; + data->type = sio_data->type; mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); @@ -1423,15 +1514,35 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) start_reg = f71882fg_read8(data, F71882FG_REG_START); if (start_reg & 0x01) { - err = f71882fg_create_sysfs_files(pdev, f71882fg_in_temp_attr, - ARRAY_SIZE(f71882fg_in_temp_attr)); + err = f71882fg_create_sysfs_files(pdev, f718x2fg_in_temp_attr, + ARRAY_SIZE(f718x2fg_in_temp_attr)); if (err) goto exit_unregister_sysfs; + + if (data->type == f71882fg) { + err = f71882fg_create_sysfs_files(pdev, + f71882fg_in_temp_attr, + ARRAY_SIZE(f71882fg_in_temp_attr)); + if (err) + goto exit_unregister_sysfs; + } } if (start_reg & 0x02) { - err = f71882fg_create_sysfs_files(pdev, f71882fg_fan_attr, + err = f71882fg_create_sysfs_files(pdev, f718x2fg_fan_attr, + ARRAY_SIZE(f718x2fg_fan_attr)); + if (err) + goto exit_unregister_sysfs; + + if (data->type == f71862fg) { + err = f71882fg_create_sysfs_files(pdev, + f71862fg_fan_attr, + ARRAY_SIZE(f71862fg_fan_attr)); + } else { + err = f71882fg_create_sysfs_files(pdev, + f71882fg_fan_attr, ARRAY_SIZE(f71882fg_fan_attr)); + } if (err) goto exit_unregister_sysfs; } @@ -1462,10 +1573,20 @@ static int f71882fg_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_name); + for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++) + device_remove_file(&pdev->dev, + &f718x2fg_in_temp_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) device_remove_file(&pdev->dev, &f71882fg_in_temp_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(f718x2fg_fan_attr); i++) + device_remove_file(&pdev->dev, &f718x2fg_fan_attr[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(f71862fg_fan_attr); i++) + device_remove_file(&pdev->dev, &f71862fg_fan_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); @@ -1474,11 +1595,12 @@ static int f71882fg_remove(struct platform_device *pdev) return 0; } -static int __init f71882fg_find(int sioaddr, unsigned short *address) +static int __init f71882fg_find(int sioaddr, unsigned short *address, + struct f71882fg_sio_data *sio_data) { int err = -ENODEV; u16 devid; - u8 start_reg; + u8 reg; struct f71882fg_data data; superio_enter(sioaddr); @@ -1490,7 +1612,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) } devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); - if (devid != SIO_F71882_ID) { + switch (devid) { + case SIO_F71862_ID: + sio_data->type = f71862fg; + break; + case SIO_F71882_ID: + sio_data->type = f71882fg; + break; + default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); goto exit; } @@ -1510,23 +1639,35 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ data.addr = *address; - start_reg = f71882fg_read8(&data, F71882FG_REG_START); - if (!(start_reg & 0x03)) { + reg = f71882fg_read8(&data, F71882FG_REG_START); + if (!(reg & 0x03)) { printk(KERN_WARNING DRVNAME ": Hardware monitoring not activated\n"); goto exit; } + /* If it is a 71862 and the fan / pwm part is enabled sanity check + the pwm settings */ + if (sio_data->type == f71862fg && (reg & 0x02)) { + reg = f71882fg_read8(&data, F71882FG_REG_PWM_ENABLE); + if ((reg & 0x15) != 0x15) { + printk(KERN_ERR DRVNAME + ": Invalid (reserved) pwm settings: 0x%02x\n", + (unsigned int)reg); + goto exit; + } + } err = 0; - printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n", - (unsigned int)*address, + printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", + f71882fg_names[sio_data->type], (unsigned int)*address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); return err; } -static int __init f71882fg_device_add(unsigned short address) +static int __init f71882fg_device_add(unsigned short address, + const struct f71882fg_sio_data *sio_data) { struct resource res = { .start = address, @@ -1546,6 +1687,13 @@ static int __init f71882fg_device_add(unsigned short address) goto exit_device_put; } + err = platform_device_add_data(f71882fg_pdev, sio_data, + sizeof(struct f71882fg_sio_data)); + if (err) { + printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + goto exit_device_put; + } + err = platform_device_add(f71882fg_pdev); if (err) { printk(KERN_ERR DRVNAME ": Device addition failed\n"); @@ -1564,15 +1712,19 @@ static int __init f71882fg_init(void) { int err = -ENODEV; unsigned short address; + struct f71882fg_sio_data sio_data; + + memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address)) + if (f71882fg_find(0x2e, &address, &sio_data) && + f71882fg_find(0x4e, &address, &sio_data)) goto exit; err = platform_driver_register(&f71882fg_driver); if (err) goto exit; - err = f71882fg_device_add(address); + err = f71882fg_device_add(address, &sio_data); if (err) goto exit_driver; -- cgit v1.2.3 From 3cc74758a667c5ad46fa5d6810ce701095370d35 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:28 +0100 Subject: hwmon: (f71882fg) Move some io access from the detect to the probe function The f71882fg driver did some io to ioports it hadn't reserved yet in its find (detect) function, this patches moves this io to the probe function where these ports are reserved and this io belongs. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index cdd16d4966c3..1cfd2231677a 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1507,12 +1507,31 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); + start_reg = f71882fg_read8(data, F71882FG_REG_START); + if (!(start_reg & 0x03)) { + dev_warn(&pdev->dev, "Hardware monitoring not activated\n"); + err = -ENODEV; + goto exit_free; + } + + /* If it is a 71862 and the fan / pwm part is enabled sanity check + the pwm settings */ + if (data->type == f71862fg && (start_reg & 0x02)) { + u8 reg = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); + if ((reg & 0x15) != 0x15) { + dev_err(&pdev->dev, + "Invalid (reserved) pwm settings: 0x%02x\n", + (unsigned int)reg); + err = -ENODEV; + goto exit_free; + } + } + /* Register sysfs interface files */ err = device_create_file(&pdev->dev, &dev_attr_name); if (err) goto exit_unregister_sysfs; - start_reg = f71882fg_read8(data, F71882FG_REG_START); if (start_reg & 0x01) { err = f71882fg_create_sysfs_files(pdev, f718x2fg_in_temp_attr, ARRAY_SIZE(f718x2fg_in_temp_attr)); @@ -1558,7 +1577,9 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) exit_unregister_sysfs: f71882fg_remove(pdev); /* Will unregister the sysfs files for us */ - + return err; /* f71882fg_remove() also frees our data */ +exit_free: + kfree(data); return err; } @@ -1600,8 +1621,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, { int err = -ENODEV; u16 devid; - u8 reg; - struct f71882fg_data data; superio_enter(sioaddr); @@ -1638,25 +1657,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - data.addr = *address; - reg = f71882fg_read8(&data, F71882FG_REG_START); - if (!(reg & 0x03)) { - printk(KERN_WARNING DRVNAME - ": Hardware monitoring not activated\n"); - goto exit; - } - - /* If it is a 71862 and the fan / pwm part is enabled sanity check - the pwm settings */ - if (sio_data->type == f71862fg && (reg & 0x02)) { - reg = f71882fg_read8(&data, F71882FG_REG_PWM_ENABLE); - if ((reg & 0x15) != 0x15) { - printk(KERN_ERR DRVNAME - ": Invalid (reserved) pwm settings: 0x%02x\n", - (unsigned int)reg); - goto exit; - } - } err = 0; printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", f71882fg_names[sio_data->type], (unsigned int)*address, -- cgit v1.2.3 From 7567a0435520fe61420ff2cdc4cec1b5399a5134 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:28 +0100 Subject: hwmon: (f71882fg) Prepare for adding F8000 support This patch is a preparation patch for adding F8000 support to the f71882fg driver. If you look at the register addresses and esp, the bits used for the temperature channels, then you will notice that it appears that they start at 1 in a system meant to start at 0. As the F8000 actually uses the 0 addresses and bits, this patch changes the f71882fg driver to take 4 temperatures numbered 0-3 in to account, using 1-3 in this new scheme for the temperatures actually present in the F718x2FG. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 117 ++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 57 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 1cfd2231677a..2604c6d7ea58 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -63,9 +63,9 @@ #define F71882FG_REG_FAN_STATUS 0x92 #define F71882FG_REG_FAN_BEEP 0x93 -#define F71882FG_REG_TEMP(nr) (0x72 + 2 * (nr)) -#define F71882FG_REG_TEMP_OVT(nr) (0x82 + 2 * (nr)) -#define F71882FG_REG_TEMP_HIGH(nr) (0x83 + 2 * (nr)) +#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr)) +#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr)) +#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr)) #define F71882FG_REG_TEMP_STATUS 0x62 #define F71882FG_REG_TEMP_BEEP 0x63 #define F71882FG_REG_TEMP_HYST1 0x6C @@ -138,11 +138,14 @@ struct f71882fg_data { u16 fan_full_speed[4]; u8 fan_status; u8 fan_beep; - u8 temp[3]; - u8 temp_ovt[3]; - u8 temp_high[3]; - u8 temp_hyst[3]; - u8 temp_type[3]; + /* Note: all models have only 3 temperature channels, but on some + they are addressed as 0-2 and on others as 1-3, so for coding + convenience we reserve space for 4 channels */ + u8 temp[4]; + u8 temp_ovt[4]; + u8 temp_high[4]; + u8 temp_hyst[4]; + u8 temp_type[4]; u8 temp_status; u8 temp_beep; u8 temp_diode_open; @@ -264,48 +267,48 @@ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), - SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 0), + store_temp_max, 0, 1), SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 0), + store_temp_max_hyst, 0, 1), SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 0), + store_temp_crit, 0, 1), SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 0), - SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 0), + 0, 1), + SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1), SENSOR_ATTR_2(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 0), - SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0), - SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0), - SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), + store_temp_beep, 0, 1), + SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), + SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2), SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 1), + store_temp_max, 0, 2), SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 1), + store_temp_max_hyst, 0, 2), SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 1), + store_temp_crit, 0, 2), SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 1), - SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1), + 0, 2), + SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 1), - SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), - SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), - SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), + store_temp_beep, 0, 2), + SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), + SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 2), + store_temp_max, 0, 3), SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 2), + store_temp_max_hyst, 0, 3), SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 2), + store_temp_crit, 0, 3), SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 2), - SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 2), + 0, 3), + SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3), SENSOR_ATTR_2(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 2), - SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), - SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), + store_temp_beep, 0, 3), + SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3), + SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), }; static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { @@ -678,7 +681,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) } /* Get High & boundary temps*/ - for (nr = 0; nr < 3; nr++) { + for (nr = 1; nr < 4; nr++) { data->temp_ovt[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_OVT(nr)); data->temp_high[nr] = f71882fg_read8(data, @@ -686,25 +689,25 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) } /* Have to hardcode hyst*/ - data->temp_hyst[0] = f71882fg_read8(data, + data->temp_hyst[1] = f71882fg_read8(data, F71882FG_REG_TEMP_HYST1) >> 4; /* Hyst temps 2 & 3 stored in same register */ reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); - data->temp_hyst[1] = reg & 0x0F; - data->temp_hyst[2] = reg >> 4; + data->temp_hyst[2] = reg & 0x0F; + data->temp_hyst[3] = reg >> 4; /* Have to hardcode type, because temp1 is special */ reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) - data->temp_type[0] = 6 /* PECI */; + data->temp_type[1] = 6 /* PECI */; else if ((reg2 & 0x03) == 0x02) - data->temp_type[0] = 5 /* AMDSI */; + data->temp_type[1] = 5 /* AMDSI */; else - data->temp_type[0] = (reg & 0x02) ? 2 : 4; + data->temp_type[1] = (reg & 0x02) ? 2 : 4; - data->temp_type[1] = (reg & 0x04) ? 2 : 4; - data->temp_type[2] = (reg & 0x08) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + data->temp_type[3] = (reg & 0x08) ? 2 : 4; data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); @@ -763,7 +766,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) F71882FG_REG_TEMP_STATUS); data->temp_diode_open = f71882fg_read8(data, F71882FG_REG_TEMP_DIODE_OPEN); - for (nr = 0; nr < 3; nr++) + for (nr = 1; nr < 4; nr++) data->temp[nr] = f71882fg_read8(data, F71882FG_REG_TEMP(nr)); @@ -1032,19 +1035,19 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute /* convert value to register contents */ switch (nr) { - case 0: - val = val << 4; - break; case 1: - val = val | (data->temp_hyst[2] << 4); + val = val << 4; break; case 2: - val = data->temp_hyst[1] | (val << 4); + val = val | (data->temp_hyst[3] << 4); + break; + case 3: + val = data->temp_hyst[2] | (val << 4); break; } - f71882fg_write8(data, nr ? F71882FG_REG_TEMP_HYST23 : - F71882FG_REG_TEMP_HYST1, val); + f71882fg_write8(data, (nr <= 1) ? F71882FG_REG_TEMP_HYST1 : + F71882FG_REG_TEMP_HYST23, val); store_temp_max_hyst_exit: mutex_unlock(&data->update_lock); @@ -1103,7 +1106,7 @@ static ssize_t show_temp_beep(struct device *dev, struct device_attribute struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - if (data->temp_beep & (1 << (nr + 1))) + if (data->temp_beep & (1 << nr)) return sprintf(buf, "1\n"); else return sprintf(buf, "0\n"); @@ -1118,9 +1121,9 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute mutex_lock(&data->update_lock); if (val) - data->temp_beep |= 1 << (nr + 1); + data->temp_beep |= 1 << nr; else - data->temp_beep &= ~(1 << (nr + 1)); + data->temp_beep &= ~(1 << nr); f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep); mutex_unlock(&data->update_lock); @@ -1134,7 +1137,7 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - if (data->temp_status & (1 << (nr + 1))) + if (data->temp_status & (1 << nr)) return sprintf(buf, "1\n"); else return sprintf(buf, "0\n"); @@ -1146,7 +1149,7 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - if (data->temp_diode_open & (1 << (nr + 1))) + if (data->temp_diode_open & (1 << nr)) return sprintf(buf, "1\n"); else return sprintf(buf, "0\n"); -- cgit v1.2.3 From ce0bfa5ee25ddbe4072b16054e809f552bf72320 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:28 +0100 Subject: hwmon: (f71882fg) Fix various sysfs callback function issues While working on adding F8000 support I noticed that various of the store sysfs functions (and a few of the show also) had issues. This patch fixes the following issues in these functions: * store: storing the result of strto[u]l in an int, resulting in a possible overflow before boundary checking * store: use of f71882fg_update_device(), we don't want to read the whole device in store functions, just the registers we need * store: use of cached register values instead of reading the needed regs in the store function, including cases where f71882fg_update_device() was not used, this could cause real isues * show: shown value is a calculation of 2 or more cached register reads, without locking the data struct. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 122 ++++++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 49 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 2604c6d7ea58..345f465aa288 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -835,6 +835,7 @@ static ssize_t store_fan_full_speed(struct device *dev, val = fan_to_reg(val); mutex_lock(&data->update_lock); + data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); if (data->pwm_enable & (1 << (2 * nr))) /* PWM mode */ count = -EINVAL; @@ -865,9 +866,10 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10); + unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); + data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); if (val) data->fan_beep |= 1 << nr; else @@ -912,10 +914,8 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct f71882fg_data *data = dev_get_drvdata(dev); - int val = simple_strtoul(buf, NULL, 10) / 8; - - if (val > 255) - val = 255; + long val = simple_strtol(buf, NULL, 10) / 8; + val = SENSORS_LIMIT(val, 0, 255); mutex_lock(&data->update_lock); f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val); @@ -942,9 +942,10 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10); + unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); + data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); if (val) data->in_beep |= 1 << nr; else @@ -991,10 +992,8 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10) / 1000; - - if (val > 255) - val = 255; + long val = simple_strtol(buf, NULL, 10) / 1000; + val = SENSORS_LIMIT(val, 0, 255); mutex_lock(&data->update_lock); f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val); @@ -1009,9 +1008,13 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute { struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; + int temp_max_hyst; - return sprintf(buf, "%d\n", - (data->temp_high[nr] - data->temp_hyst[nr]) * 1000); + mutex_lock(&data->update_lock); + temp_max_hyst = (data->temp_high[nr] - data->temp_hyst[nr]) * 1000; + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp_max_hyst); } static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute @@ -1019,37 +1022,38 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10) / 1000; + long val = simple_strtol(buf, NULL, 10) / 1000; ssize_t ret = count; + u8 reg; mutex_lock(&data->update_lock); /* convert abs to relative and check */ + data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr)); + val = SENSORS_LIMIT(val, data->temp_high[nr] - 15, + data->temp_high[nr]); val = data->temp_high[nr] - val; - if (val < 0 || val > 15) { - ret = -EINVAL; - goto store_temp_max_hyst_exit; - } - data->temp_hyst[nr] = val; /* convert value to register contents */ switch (nr) { case 1: - val = val << 4; + reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST1); + reg = (reg & 0x0f) | (val << 4); break; case 2: - val = val | (data->temp_hyst[3] << 4); + reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); + reg = (reg & 0xf0) | val; break; case 3: - val = data->temp_hyst[2] | (val << 4); + reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); + reg = (reg & 0x0f) | (val << 4); break; } f71882fg_write8(data, (nr <= 1) ? F71882FG_REG_TEMP_HYST1 : - F71882FG_REG_TEMP_HYST23, val); + F71882FG_REG_TEMP_HYST23, reg); -store_temp_max_hyst_exit: mutex_unlock(&data->update_lock); return ret; } @@ -1068,10 +1072,8 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10) / 1000; - - if (val > 255) - val = 255; + long val = simple_strtol(buf, NULL, 10) / 1000; + val = SENSORS_LIMIT(val, 0, 255); mutex_lock(&data->update_lock); f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val); @@ -1086,9 +1088,13 @@ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute { struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; + int temp_crit_hyst; - return sprintf(buf, "%d\n", - (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000); + mutex_lock(&data->update_lock); + temp_crit_hyst = (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000; + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp_crit_hyst); } static ssize_t show_temp_type(struct device *dev, struct device_attribute @@ -1117,9 +1123,10 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10); + unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); + data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); if (val) data->temp_beep |= 1 << nr; else @@ -1160,16 +1167,16 @@ static ssize_t show_pwm(struct device *dev, { struct f71882fg_data *data = f71882fg_update_device(dev); int val, nr = to_sensor_dev_attr_2(devattr)->index; + mutex_lock(&data->update_lock); if (data->pwm_enable & (1 << (2 * nr))) /* PWM mode */ val = data->pwm[nr]; else { /* RPM mode */ - mutex_lock(&data->update_lock); val = 255 * fan_from_reg(data->fan_target[nr]) / fan_from_reg(data->fan_full_speed[nr]); - mutex_unlock(&data->update_lock); } + mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", val); } @@ -1177,23 +1184,26 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - /* struct f71882fg_data *data = dev_get_drvdata(dev); */ - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; long val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, 0, 255); mutex_lock(&data->update_lock); + data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); if (data->pwm_enable & (1 << (2 * nr))) { /* PWM mode */ f71882fg_write8(data, F71882FG_REG_PWM(nr), val); data->pwm[nr] = val; } else { /* RPM mode */ - int target = val * fan_from_reg(data->fan_full_speed[nr]) / 255; - f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), - fan_to_reg(target)); - data->fan_target[nr] = fan_to_reg(target); + int target, full_speed; + full_speed = f71882fg_read16(data, + F71882FG_REG_FAN_FULL_SPEED(nr)); + target = fan_to_reg(val * fan_from_reg(full_speed) / 255); + f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target); + data->fan_target[nr] = target; + data->fan_full_speed[nr] = full_speed; } mutex_unlock(&data->update_lock); @@ -1225,6 +1235,7 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute return -EINVAL; mutex_lock(&data->update_lock); + data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); switch (val) { case 1: data->pwm_enable |= 2 << (2 * nr); @@ -1258,6 +1269,7 @@ static ssize_t show_pwm_auto_point_pwm(struct device *dev, int pwm = to_sensor_dev_attr_2(devattr)->index; int point = to_sensor_dev_attr_2(devattr)->nr; + mutex_lock(&data->update_lock); if (data->pwm_enable & (1 << (2 * pwm))) { /* PWM mode */ result = data->pwm_auto_point_pwm[pwm][point]; @@ -1265,6 +1277,7 @@ static ssize_t show_pwm_auto_point_pwm(struct device *dev, /* RPM mode */ result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]); } + mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", result); } @@ -1273,14 +1286,14 @@ static ssize_t store_pwm_auto_point_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - /* struct f71882fg_data *data = dev_get_drvdata(dev); */ - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int pwm = to_sensor_dev_attr_2(devattr)->index; int point = to_sensor_dev_attr_2(devattr)->nr; - int val = simple_strtoul(buf, NULL, 10); + long val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, 0, 255); mutex_lock(&data->update_lock); + data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); if (data->pwm_enable & (1 << (2 * pwm))) { /* PWM mode */ } else { @@ -1331,16 +1344,25 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; int point = to_sensor_dev_attr_2(devattr)->nr; long val = simple_strtol(buf, NULL, 10) / 1000; mutex_lock(&data->update_lock); + data->pwm_auto_point_temp[nr][point] = + f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point)); val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15, data->pwm_auto_point_temp[nr][point]); val = data->pwm_auto_point_temp[nr][point] - val; + if (nr == 0 || nr == 1) { + data->pwm_auto_point_hyst[0] = + f71882fg_read8(data, F71882FG_REG_FAN_HYST0); + } else { + data->pwm_auto_point_hyst[1] = + f71882fg_read8(data, F71882FG_REG_FAN_HYST1); + } switch (nr) { case 0: val = (data->pwm_auto_point_hyst[0] & 0xf0) | val; @@ -1383,11 +1405,13 @@ static ssize_t store_pwm_interpolate(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - /* struct f71882fg_data *data = dev_get_drvdata(dev); */ - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - int val = simple_strtoul(buf, NULL, 10); + unsigned long val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); + data->pwm_auto_point_mapping[nr] = + f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); if (val) val = data->pwm_auto_point_mapping[nr] | (1 << 4); else @@ -1416,8 +1440,7 @@ static ssize_t store_pwm_auto_point_channel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - /* struct f71882fg_data *data = dev_get_drvdata(dev); */ - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; long val = simple_strtol(buf, NULL, 10); switch (val) { @@ -1434,6 +1457,8 @@ static ssize_t store_pwm_auto_point_channel(struct device *dev, return -EINVAL; } mutex_lock(&data->update_lock); + data->pwm_auto_point_mapping[nr] = + f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val; f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); data->pwm_auto_point_mapping[nr] = val; @@ -1459,8 +1484,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - /* struct f71882fg_data *data = dev_get_drvdata(dev); */ - struct f71882fg_data *data = f71882fg_update_device(dev); + struct f71882fg_data *data = dev_get_drvdata(dev); int pwm = to_sensor_dev_attr_2(devattr)->index; int point = to_sensor_dev_attr_2(devattr)->nr; long val = simple_strtol(buf, NULL, 10) / 1000; -- cgit v1.2.3 From bc27490f9164281b9e1768a5df8e0951541f90a1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:29 +0100 Subject: hwmon: (f71882fg) Cleanup fan and temp hyst functions Simplify fan and temp hyst. handling by treating the registers as an array of nibbles instead of using switch cases. Also unify the way hysts are handled between temp and fans, the temp code was storing the actual per temp hyst values in 4 u8's, where as the fan code was storing actual register values. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 121 +++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 78 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 345f465aa288..de559923454c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -68,8 +68,7 @@ #define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr)) #define F71882FG_REG_TEMP_STATUS 0x62 #define F71882FG_REG_TEMP_BEEP 0x63 -#define F71882FG_REG_TEMP_HYST1 0x6C -#define F71882FG_REG_TEMP_HYST23 0x6D +#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr)) #define F71882FG_REG_TEMP_TYPE 0x6B #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F @@ -77,8 +76,7 @@ #define F71882FG_REG_PWM_TYPE 0x94 #define F71882FG_REG_PWM_ENABLE 0x96 -#define F71882FG_REG_FAN_HYST0 0x98 -#define F71882FG_REG_FAN_HYST1 0x99 +#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr)) #define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm))) #define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm))) @@ -144,7 +142,7 @@ struct f71882fg_data { u8 temp[4]; u8 temp_ovt[4]; u8 temp_high[4]; - u8 temp_hyst[4]; + u8 temp_hyst[2]; /* 2 hysts stored per reg */ u8 temp_type[4]; u8 temp_status; u8 temp_beep; @@ -688,13 +686,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) F71882FG_REG_TEMP_HIGH(nr)); } - /* Have to hardcode hyst*/ - data->temp_hyst[1] = f71882fg_read8(data, - F71882FG_REG_TEMP_HYST1) >> 4; - /* Hyst temps 2 & 3 stored in same register */ - reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); - data->temp_hyst[2] = reg & 0x0F; - data->temp_hyst[3] = reg >> 4; + /* hyst */ + data->temp_hyst[0] = + f71882fg_read8(data, F71882FG_REG_TEMP_HYST(0)); + data->temp_hyst[1] = + f71882fg_read8(data, F71882FG_REG_TEMP_HYST(1)); /* Have to hardcode type, because temp1 is special */ reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); @@ -715,10 +711,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - data->pwm_auto_point_hyst[0] = f71882fg_read8(data, - F71882FG_REG_FAN_HYST0); - data->pwm_auto_point_hyst[1] = f71882fg_read8(data, - F71882FG_REG_FAN_HYST1); + data->pwm_auto_point_hyst[0] = + f71882fg_read8(data, F71882FG_REG_FAN_HYST(0)); + data->pwm_auto_point_hyst[1] = + f71882fg_read8(data, F71882FG_REG_FAN_HYST(1)); + for (nr = 0; nr < nr_fans; nr++) { data->pwm_auto_point_mapping[nr] = f71882fg_read8(data, @@ -1011,7 +1008,11 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute int temp_max_hyst; mutex_lock(&data->update_lock); - temp_max_hyst = (data->temp_high[nr] - data->temp_hyst[nr]) * 1000; + if (nr & 1) + temp_max_hyst = data->temp_hyst[nr / 2] >> 4; + else + temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f; + temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000; mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", temp_max_hyst); @@ -1033,26 +1034,15 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute val = SENSORS_LIMIT(val, data->temp_high[nr] - 15, data->temp_high[nr]); val = data->temp_high[nr] - val; - data->temp_hyst[nr] = val; /* convert value to register contents */ - switch (nr) { - case 1: - reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST1); - reg = (reg & 0x0f) | (val << 4); - break; - case 2: - reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); - reg = (reg & 0xf0) | val; - break; - case 3: - reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); - reg = (reg & 0x0f) | (val << 4); - break; - } - - f71882fg_write8(data, (nr <= 1) ? F71882FG_REG_TEMP_HYST1 : - F71882FG_REG_TEMP_HYST23, reg); + reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2)); + if (nr & 1) + reg = (reg & 0x0f) | (val << 4); + else + reg = (reg & 0xf0) | val; + f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg); + data->temp_hyst[nr / 2] = reg; mutex_unlock(&data->update_lock); return ret; @@ -1091,7 +1081,11 @@ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute int temp_crit_hyst; mutex_lock(&data->update_lock); - temp_crit_hyst = (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000; + if (nr & 1) + temp_crit_hyst = data->temp_hyst[nr / 2] >> 4; + else + temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f; + temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000; mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", temp_crit_hyst); @@ -1320,20 +1314,10 @@ static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, int point = to_sensor_dev_attr_2(devattr)->nr; mutex_lock(&data->update_lock); - switch (nr) { - case 0: - result = data->pwm_auto_point_hyst[0] & 0x0f; - break; - case 1: - result = data->pwm_auto_point_hyst[0] >> 4; - break; - case 2: - result = data->pwm_auto_point_hyst[1] & 0x0f; - break; - case 3: - result = data->pwm_auto_point_hyst[1] >> 4; - break; - } + if (nr & 1) + result = data->pwm_auto_point_hyst[nr / 2] >> 4; + else + result = data->pwm_auto_point_hyst[nr / 2] & 0x0f; result = 1000 * (data->pwm_auto_point_temp[nr][point] - result); mutex_unlock(&data->update_lock); @@ -1348,6 +1332,7 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, int nr = to_sensor_dev_attr_2(devattr)->index; int point = to_sensor_dev_attr_2(devattr)->nr; long val = simple_strtol(buf, NULL, 10) / 1000; + u8 reg; mutex_lock(&data->update_lock); data->pwm_auto_point_temp[nr][point] = @@ -1356,34 +1341,14 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, data->pwm_auto_point_temp[nr][point]); val = data->pwm_auto_point_temp[nr][point] - val; - if (nr == 0 || nr == 1) { - data->pwm_auto_point_hyst[0] = - f71882fg_read8(data, F71882FG_REG_FAN_HYST0); - } else { - data->pwm_auto_point_hyst[1] = - f71882fg_read8(data, F71882FG_REG_FAN_HYST1); - } - switch (nr) { - case 0: - val = (data->pwm_auto_point_hyst[0] & 0xf0) | val; - break; - case 1: - val = (data->pwm_auto_point_hyst[0] & 0x0f) | (val << 4); - break; - case 2: - val = (data->pwm_auto_point_hyst[1] & 0xf0) | val; - break; - case 3: - val = (data->pwm_auto_point_hyst[1] & 0x0f) | (val << 4); - break; - } - if (nr == 0 || nr == 1) { - f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val); - data->pwm_auto_point_hyst[0] = val; - } else { - f71882fg_write8(data, F71882FG_REG_FAN_HYST1, val); - data->pwm_auto_point_hyst[1] = val; - } + reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2)); + if (nr & 1) + reg = (reg & 0x0f) | (val << 4); + else + reg = (reg & 0xf0) | val; + + f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg); + data->pwm_auto_point_hyst[nr / 2] = reg; mutex_unlock(&data->update_lock); return count; -- cgit v1.2.3 From 12d66e840b605265d6adf4b800cc3fc5fb410903 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:29 +0100 Subject: hwmon: (f71882fg) Check for hwmon powerdown state More F8000 prep work. Take over the checking if the hwmon part is not powered down from the standalone f8000 driver. This check is valid for all supported models. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index de559923454c..03a4f84b4e5c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1500,6 +1500,11 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); start_reg = f71882fg_read8(data, F71882FG_REG_START); + if (start_reg & 0x04) { + dev_warn(&pdev->dev, "Hardware monitor is powered down\n"); + err = -ENODEV; + goto exit_free; + } if (!(start_reg & 0x03)) { dev_warn(&pdev->dev, "Hardware monitoring not activated\n"); err = -ENODEV; -- cgit v1.2.3 From 754a5907b01687089382e362753dcceaca58ee66 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:29 +0100 Subject: hwmon: (f71882fg) Separate max and crit alarm and beep While studying the datasheets for adding F8000 support, I noticed that the F718x2 has separate alarms (and beep control) for its max and crit limits. We keep the temp#_alarm attributes as they are, even though it would be more logical to rename them to temp#_max_alarm. Because lm_sensors v2 depends on them. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 03a4f84b4e5c..95a279f70264 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -270,42 +270,56 @@ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { store_temp_max, 0, 1), SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, store_temp_max_hyst, 0, 1), + /* Should really be temp1_max_alarm, but older versions did not handle + the max and crit alarms separately and lm_sensors v2 depends on the + presence of temp#_alarm files. The same goes for temp2/3 _alarm. */ + SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), + SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 1), SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, store_temp_crit, 0, 1), SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0, 1), + SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), + SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 5), SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1), - SENSOR_ATTR_2(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 1), - SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2), SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 2), SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, store_temp_max_hyst, 0, 2), + /* Should be temp2_max_alarm, see temp1_alarm note */ + SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), + SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 2), SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, store_temp_crit, 0, 2), SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0, 2), + SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), + SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), - SENSOR_ATTR_2(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 2), - SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, store_temp_max_hyst, 0, 3), + /* Should be temp3_max_alarm, see temp1_alarm note */ + SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3), + SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 3), SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, store_temp_crit, 0, 3), SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0, 3), + SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7), + SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0, 7), SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3), - SENSOR_ATTR_2(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 3), - SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3), SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), }; -- cgit v1.2.3 From 4c82c38ae29a01338b5104b0111cecefaf3a1025 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:30 +0100 Subject: hwmon: (f71882fg) Remove the fan_mode module option Remove the fan_mode module option it was a monstrosity to begin with, and when adding support for the F8000 it becomes a real pain! Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 95a279f70264..842592fe5aa9 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -90,12 +90,6 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -static int fan_mode[4] = { 0, 0, 0, 0 }; -module_param_array(fan_mode, int, NULL, 0644); -MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) " - "(0=don't change, 1=pwm, 2=rpm)\n" - "Note: this needs a write to pwm#_enable to take effect"); - enum chips { f71862fg, f71882fg }; static const char *f71882fg_names[] = { @@ -846,15 +840,8 @@ static ssize_t store_fan_full_speed(struct device *dev, val = fan_to_reg(val); mutex_lock(&data->update_lock); - data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - if (data->pwm_enable & (1 << (2 * nr))) - /* PWM mode */ - count = -EINVAL; - else { - /* RPM mode */ - f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); - data->fan_full_speed[nr] = val; - } + f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); + data->fan_full_speed[nr] = val; mutex_unlock(&data->update_lock); return count; @@ -1252,16 +1239,6 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute data->pwm_enable &= ~(2 << (2 * nr)); break; /* Temperature ctrl */ } - if (data->type == f71882fg) { - switch (fan_mode[nr]) { - case 1: - data->pwm_enable |= 1 << (2 * nr); - break; /* Duty cycle mode */ - case 2: - data->pwm_enable &= ~(1 << (2 * nr)); - break; /* RPM mode */ - } - } f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); mutex_unlock(&data->update_lock); -- cgit v1.2.3 From ed4f7c20b346294959a16d35443def922e5e1e59 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:30 +0100 Subject: hwmon: (f71882fg) Add F8000 support And (finally) the patch actually adding f8000 support. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 353 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 291 insertions(+), 62 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 842592fe5aa9..a833797e96d3 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F8000_ID 0x0581 /* Chipset ID */ #define REGION_LENGTH 8 #define ADDR_REG_OFFSET 5 @@ -90,11 +91,12 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71862fg, f71882fg }; +enum chips { f71862fg, f71882fg, f8000 }; static const char *f71882fg_names[] = { "f71862fg", "f71882fg", + "f8000", }; static struct platform_device *f71882fg_pdev; @@ -249,6 +251,7 @@ static struct platform_driver f71882fg_driver = { static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +/* Temp and in attr common to both the f71862fg and f71882fg */ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), @@ -317,6 +320,7 @@ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), }; +/* Temp and in attr found only on the f71882fg */ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 0, 1), @@ -325,27 +329,51 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), }; -static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { +/* Temp and in attr for the f8000 + Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max) + is used as hysteresis value to clear alarms + */ +static struct sensor_device_attribute_2 f8000_in_temp_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), + SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 0), + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 0), + SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 1), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 1), + SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), + SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), + SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0, 2), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0, 2), + SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), +}; + +/* Fan / PWM attr common to all models */ +static struct sensor_device_attribute_2 fxxxx_fan_attr[] = { SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed, store_fan_full_speed, 0, 0), - SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 0), SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed, store_fan_full_speed, 0, 1), - SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 1), SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed, store_fan_full_speed, 0, 2), - SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 2), SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), @@ -366,9 +394,6 @@ static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { show_pwm_auto_point_channel, store_pwm_auto_point_channel, 0, 1), - SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), - SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 2), SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, show_pwm_interpolate, store_pwm_interpolate, 0, 2), SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, @@ -376,7 +401,16 @@ static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { store_pwm_auto_point_channel, 0, 2), }; +/* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the + f71882fg */ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { + SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 0), + SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 1), + SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 2), + SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 1, 0), @@ -416,7 +450,14 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { show_pwm_auto_point_temp_hyst, NULL, 3, 1), }; +/* Fan / PWM attr for the f71882fg */ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { + SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 0), + SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 1), + SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0, 2), SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed, @@ -501,6 +542,9 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, show_pwm_auto_point_temp_hyst, NULL, 3, 1), + SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), + SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 2), SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 0, 2), @@ -586,6 +630,128 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { show_pwm_auto_point_temp_hyst, NULL, 3, 3), }; +/* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm! + Also the register block at offset A0 maps to TEMP1 (so our temp2, as the + F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */ +static struct sensor_device_attribute_2 f8000_fan_attr[] = { + SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), + + SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2), + + SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 2), + SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 2), + SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 2), + SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 2), + SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 2), + SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 2), + SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 2), + SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 2), + SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 2), + SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 2), + SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 2), + SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 2), + SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 2), + + SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 0), + SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 0), + SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 0), + SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 0), + SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 0), + SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 0), + SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 0), + SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 0), + SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 0), + SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 0), + SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 0), + SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 0), + SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 0), + + SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 0, 1), + SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 1), + SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 2, 1), + SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 3, 1), + SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 1), + SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 1), + SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 1, 1), + SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 2, 1), + SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 1), + SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 1), + SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 1, 1), + SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 2, 1), + SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 1), +}; /* Super I/O functions */ static inline int superio_inb(int base, int reg) @@ -671,8 +837,10 @@ static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) static struct f71882fg_data *f71882fg_update_device(struct device *dev) { struct f71882fg_data *data = dev_get_drvdata(dev); - int nr, reg, reg2; - int nr_fans = (data->type == f71862fg) ? 3 : 4; + int nr, reg = 0, reg2; + int nr_fans = (data->type == f71882fg) ? 4 : 3; + int nr_ins = (data->type == f8000) ? 3 : 9; + int temp_start = (data->type == f8000) ? 0 : 1; mutex_lock(&data->update_lock); @@ -687,35 +855,36 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) } /* Get High & boundary temps*/ - for (nr = 1; nr < 4; nr++) { + for (nr = temp_start; nr < 3 + temp_start; nr++) { data->temp_ovt[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_OVT(nr)); data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr)); } - /* hyst */ - data->temp_hyst[0] = - f71882fg_read8(data, F71882FG_REG_TEMP_HYST(0)); - data->temp_hyst[1] = - f71882fg_read8(data, F71882FG_REG_TEMP_HYST(1)); - - /* Have to hardcode type, because temp1 is special */ - reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + if (data->type != f8000) { + data->fan_beep = f71882fg_read8(data, + F71882FG_REG_FAN_BEEP); + data->temp_beep = f71882fg_read8(data, + F71882FG_REG_TEMP_BEEP); + data->temp_hyst[0] = f71882fg_read8(data, + F71882FG_REG_TEMP_HYST(0)); + data->temp_hyst[1] = f71882fg_read8(data, + F71882FG_REG_TEMP_HYST(1)); + /* Have to hardcode type, because temp1 is special */ + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + data->temp_type[3] = (reg & 0x08) ? 2 : 4; + } reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) data->temp_type[1] = 6 /* PECI */; else if ((reg2 & 0x03) == 0x02) data->temp_type[1] = 5 /* AMDSI */; - else + else if (data->type != f8000) data->temp_type[1] = (reg & 0x02) ? 2 : 4; - - data->temp_type[2] = (reg & 0x04) ? 2 : 4; - data->temp_type[3] = (reg & 0x08) ? 2 : 4; - - data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); - - data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); + else + data->temp_type[1] = 2; /* F8000 only supports BJT */ data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); @@ -729,7 +898,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); - if (data->type == f71882fg) { + if (data->type != f71862fg) { int point; for (point = 0; point < 5; point++) { data->pwm_auto_point_pwm[nr][point] = @@ -771,7 +940,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) F71882FG_REG_TEMP_STATUS); data->temp_diode_open = f71882fg_read8(data, F71882FG_REG_TEMP_DIODE_OPEN); - for (nr = 1; nr < 4; nr++) + for (nr = temp_start; nr < 3 + temp_start; nr++) data->temp[nr] = f71882fg_read8(data, F71882FG_REG_TEMP(nr)); @@ -789,10 +958,14 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) f71882fg_read8(data, F71882FG_REG_PWM(nr)); } + /* The f8000 can monitor 1 more fan, but has no pwm for it */ + if (data->type == f8000) + data->fan[3] = f71882fg_read16(data, + F71882FG_REG_FAN(3)); if (data->type == f71882fg) data->in_status = f71882fg_read8(data, F71882FG_REG_IN_STATUS); - for (nr = 0; nr < 9; nr++) + for (nr = 0; nr < nr_ins; nr++) data->in[nr] = f71882fg_read8(data, F71882FG_REG_IN(nr)); @@ -1186,6 +1359,11 @@ static ssize_t store_pwm(struct device *dev, mutex_lock(&data->update_lock); data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); + if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) || + (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) { + count = -EROFS; + goto leave; + } if (data->pwm_enable & (1 << (2 * nr))) { /* PWM mode */ f71882fg_write8(data, F71882FG_REG_PWM(nr), val); @@ -1200,6 +1378,7 @@ static ssize_t store_pwm(struct device *dev, data->fan_target[nr] = target; data->fan_full_speed[nr] = full_speed; } +leave: mutex_unlock(&data->update_lock); return count; @@ -1208,14 +1387,25 @@ static ssize_t store_pwm(struct device *dev, static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf) { - int result; + int result = 0; struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; - if (data->pwm_enable & (2 << (2 * nr))) - result = 1; - else - result = 2; + switch ((data->pwm_enable >> 2 * nr) & 3) { + case 0: + case 1: + result = 2; /* Normal auto mode */ + break; + case 2: + result = 1; /* Manual mode */ + break; + case 3: + if (data->type == f8000) + result = 3; /* Thermostat mode */ + else + result = 1; /* Manual mode */ + break; + } return sprintf(buf, "%d\n", result); } @@ -1226,20 +1416,37 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; long val = simple_strtol(buf, NULL, 10); - if (val < 1 || val > 2) - return -EINVAL; mutex_lock(&data->update_lock); data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - switch (val) { - case 1: - data->pwm_enable |= 2 << (2 * nr); - break; /* Manual */ - case 2: - data->pwm_enable &= ~(2 << (2 * nr)); - break; /* Temperature ctrl */ + /* Special case for F8000 auto PWM mode / Thermostat mode */ + if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) { + switch (val) { + case 2: + data->pwm_enable &= ~(2 << (2 * nr)); + break; /* Normal auto mode */ + case 3: + data->pwm_enable |= 2 << (2 * nr); + break; /* Thermostat mode */ + default: + count = -EINVAL; + goto leave; + } + } else { + switch (val) { + case 1: + data->pwm_enable |= 2 << (2 * nr); + break; /* Manual */ + case 2: + data->pwm_enable &= ~(2 << (2 * nr)); + break; /* Normal auto mode */ + default: + count = -EINVAL; + goto leave; + } } f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); +leave: mutex_unlock(&data->update_lock); return count; @@ -1521,34 +1728,51 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) goto exit_unregister_sysfs; if (start_reg & 0x01) { - err = f71882fg_create_sysfs_files(pdev, f718x2fg_in_temp_attr, - ARRAY_SIZE(f718x2fg_in_temp_attr)); - if (err) - goto exit_unregister_sysfs; - - if (data->type == f71882fg) { + switch (data->type) { + case f71882fg: err = f71882fg_create_sysfs_files(pdev, f71882fg_in_temp_attr, ARRAY_SIZE(f71882fg_in_temp_attr)); if (err) goto exit_unregister_sysfs; + /* fall through! */ + case f71862fg: + err = f71882fg_create_sysfs_files(pdev, + f718x2fg_in_temp_attr, + ARRAY_SIZE(f718x2fg_in_temp_attr)); + break; + case f8000: + err = f71882fg_create_sysfs_files(pdev, + f8000_in_temp_attr, + ARRAY_SIZE(f8000_in_temp_attr)); + break; } + if (err) + goto exit_unregister_sysfs; } if (start_reg & 0x02) { - err = f71882fg_create_sysfs_files(pdev, f718x2fg_fan_attr, - ARRAY_SIZE(f718x2fg_fan_attr)); + err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr, + ARRAY_SIZE(fxxxx_fan_attr)); if (err) goto exit_unregister_sysfs; - if (data->type == f71862fg) { + switch (data->type) { + case f71862fg: err = f71882fg_create_sysfs_files(pdev, f71862fg_fan_attr, ARRAY_SIZE(f71862fg_fan_attr)); - } else { + break; + case f71882fg: err = f71882fg_create_sysfs_files(pdev, f71882fg_fan_attr, ARRAY_SIZE(f71882fg_fan_attr)); + break; + case f8000: + err = f71882fg_create_sysfs_files(pdev, + f8000_fan_attr, + ARRAY_SIZE(f8000_fan_attr)); + break; } if (err) goto exit_unregister_sysfs; @@ -1580,6 +1804,8 @@ static int f71882fg_remove(struct platform_device *pdev) if (data->hwmon_dev) hwmon_device_unregister(data->hwmon_dev); + /* Note we are not looping over all attr arrays we have as the ones + below are supersets of the ones skipped. */ device_remove_file(&pdev->dev, &dev_attr_name); for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++) @@ -1590,15 +1816,15 @@ static int f71882fg_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &f71882fg_in_temp_attr[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(f718x2fg_fan_attr); i++) - device_remove_file(&pdev->dev, &f718x2fg_fan_attr[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(f71862fg_fan_attr); i++) - device_remove_file(&pdev->dev, &f71862fg_fan_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++) + device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr); for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++) + device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr); + kfree(data); return 0; @@ -1626,6 +1852,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, case SIO_F71882_ID: sio_data->type = f71882fg; break; + case SIO_F8000_ID: + sio_data->type = f8000; + break; default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); goto exit; -- cgit v1.2.3 From 4901062f78401f09ef0296466172905c93575ddd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:30 +0100 Subject: hwmon: (f71882fg) Add missing pwm3 attr for f71862fg For some reason the fan_attr array for the f71862fg was missing the attr for the 3th pwm output. This patch fixes this. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index a833797e96d3..f4998bf82ca5 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -448,6 +448,28 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { 0, 1), SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, show_pwm_auto_point_temp_hyst, NULL, 3, 1), + + SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), + SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, + store_pwm_enable, 0, 2), + SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 1, 2), + SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, + show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, + 4, 2), + SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 0, 2), + SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp, store_pwm_auto_point_temp, + 3, 2), + SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, + show_pwm_auto_point_temp_hyst, + store_pwm_auto_point_temp_hyst, + 0, 2), + SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, + show_pwm_auto_point_temp_hyst, NULL, 3, 2), }; /* Fan / PWM attr for the f71882fg */ -- cgit v1.2.3 From 30453018655a3acd5f59e793da55a2f969ed9c32 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:30 +0100 Subject: hwmon: (f71882fg) Fix auto_channels_temp temp numbering with f8000 Adjust auto_channels_temp show and store functions for different numbering of temps between f8000 and other supported models. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index f4998bf82ca5..0ef7265336ba 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1615,8 +1615,9 @@ static ssize_t show_pwm_auto_point_channel(struct device *dev, int result; struct f71882fg_data *data = f71882fg_update_device(dev); int nr = to_sensor_dev_attr_2(devattr)->index; + int temp_start = (data->type == f8000) ? 0 : 1; - result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1); + result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - temp_start); return sprintf(buf, "%d\n", result); } @@ -1627,20 +1628,23 @@ static ssize_t store_pwm_auto_point_channel(struct device *dev, { struct f71882fg_data *data = dev_get_drvdata(dev); int nr = to_sensor_dev_attr_2(devattr)->index; + int temp_start = (data->type == f8000) ? 0 : 1; long val = simple_strtol(buf, NULL, 10); + switch (val) { case 1: - val = 1; + val = 0; break; case 2: - val = 2; + val = 1; break; case 4: - val = 3; + val = 2; break; default: return -EINVAL; } + val += temp_start; mutex_lock(&data->update_lock); data->pwm_auto_point_mapping[nr] = f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); -- cgit v1.2.3 From 28ba858798d5c70513cd8b9742841fd1bd49a074 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:31 +0100 Subject: hwmon: (f71882fg) Printout fan modes Print the mode (duty-cycle or RPM) of each fan on driver load. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 0ef7265336ba..a6dc3c7787f7 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1711,7 +1711,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) { struct f71882fg_data *data; struct f71882fg_sio_data *sio_data = pdev->dev.platform_data; - int err; + int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3; u8 start_reg; data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL); @@ -1735,14 +1735,14 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) goto exit_free; } + data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); /* If it is a 71862 and the fan / pwm part is enabled sanity check the pwm settings */ if (data->type == f71862fg && (start_reg & 0x02)) { - u8 reg = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - if ((reg & 0x15) != 0x15) { + if ((data->pwm_enable & 0x15) != 0x15) { dev_err(&pdev->dev, "Invalid (reserved) pwm settings: 0x%02x\n", - (unsigned int)reg); + (unsigned int)data->pwm_enable); err = -ENODEV; goto exit_free; } @@ -1802,6 +1802,11 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) } if (err) goto exit_unregister_sysfs; + + for (i = 0; i < nr_fans; i++) + dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1, + (data->pwm_enable & (1 << 2 * i)) ? + "duty-cycle" : "RPM"); } data->hwmon_dev = hwmon_device_register(&pdev->dev); -- cgit v1.2.3 From 2f650631b3710622666367474b5475ff81ba486e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 7 Jan 2009 16:37:31 +0100 Subject: hwmon: (f71882fg) Fix fan_to/from_reg prototypes The RPM after conversion from / before conversion to a register value can be much more than 65535 (up to 1500000), so putting this into an u16 can cause overflows. This changes the functions to use an int to store / get RPM instead. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index a6dc3c7787f7..d867b377d4e9 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -810,12 +810,12 @@ static inline void superio_exit(int base) outb(SIO_LOCK_KEY, base); } -static inline u16 fan_from_reg(u16 reg) +static inline int fan_from_reg(u16 reg) { return reg ? (1500000 / reg) : 0; } -static inline u16 fan_to_reg(u16 fan) +static inline u16 fan_to_reg(int fan) { return fan ? (1500000 / fan) : 0; } -- cgit v1.2.3 From b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 7 Jan 2009 16:37:35 +0100 Subject: hwmon: Check for ACPI resource conflicts Check for ACPI resource conflicts in hwmon drivers. I've included all Super-I/O and PCI drivers. I've voluntarily left out: * Vendor-specific drivers: if they conflicted on any system, this would pretty much mean that they conflict on all systems, and we would know by now. * Legacy ISA drivers (lm78 and w83781d): they only support chips found on old designs were ACPI either wasn't supported or didn't deal with thermal management. * Drivers accessing the I/O resources indirectly (e.g. through SMBus): the checks are already done where they belong, i.e. in the bus drivers. Signed-off-by: Jean Delvare Acked-by: David Hubbard --- drivers/hwmon/f71882fg.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/hwmon/f71882fg.c') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index d867b377d4e9..609cafff86bc 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -28,6 +28,7 @@ #include #include #include +#include #define DRVNAME "f71882fg" @@ -1929,6 +1930,10 @@ static int __init f71882fg_device_add(unsigned short address, return -ENOMEM; res.name = f71882fg_pdev->name; + err = acpi_check_resource_conflict(&res); + if (err) + return err; + err = platform_device_add_resources(f71882fg_pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); -- cgit v1.2.3