[lm-sensors] [PATCH 2.6.25.4] f71882.c driver, Added PWM/FAN control.
Mark van Doesburg
mark.vandoesburg at hetnet.nl
Mon Jun 30 21:23:00 CEST 2008
Hello Hans,
I've finisched the two patches, so here they are.
Regards,
Mark.
--- /tmp/linux-2.6.25.4/drivers/hwmon/f71882fg.c 2008-05-15 17:00:12.000000000 +0200
+++ drivers/hwmon/f71882fg.c 2008-06-30 21:02:45.000000000 +0200
@@ -194,79 +194,79 @@
__ATTR( name, S_IRUGO, show_name, NULL ),
};
-static struct sensor_device_attribute f71882fg_in_temp_attr[] =
+static struct sensor_device_attribute_2 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)
+ SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
+ SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, 0),
+ SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 1, 0),
+ SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, 1, 0),
+ SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 1, 0),
+ SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, 0),
+ SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, 0),
+ SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, 0),
+ SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, 0),
+ SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 6, 0),
+ SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 7, 0),
+ SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0),
+ 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, 1, 0),
+ SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 1, 0),
+ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+ store_temp_max_hyst, 1, 0),
+ SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 1, 0),
+ SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1, 0),
+ SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 1, 0),
+ SENSOR_ATTR_2(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 1, 0),
+ SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1, 0),
+ SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1, 0),
+ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
+ SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 2, 0),
+ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+ store_temp_max_hyst, 2, 0),
+ SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 2, 0),
+ SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 2, 0),
+ SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 2, 0),
+ SENSOR_ATTR_2(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 2, 0),
+ SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2, 0),
+ SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2, 0)
};
-static struct sensor_device_attribute f71882fg_fan_attr[] =
+static struct sensor_device_attribute_2 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)
+ 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, 1, 0),
+ SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 1, 0),
+ SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1, 0),
+ SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, 0),
+ SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 2, 0),
+ SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2, 0),
+ SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, 0),
+ SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 3, 0),
+ SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3, 0)
};
@@ -423,7 +423,7 @@
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)
@@ -436,7 +436,7 @@
*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");
@@ -448,7 +448,7 @@
*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);
@@ -467,7 +467,7 @@
*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");
@@ -479,7 +479,7 @@
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);
}
@@ -513,7 +513,7 @@
*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");
@@ -525,7 +525,7 @@
*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);
@@ -544,7 +544,7 @@
*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");
@@ -556,7 +556,7 @@
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);
}
@@ -565,7 +565,7 @@
*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);
}
@@ -574,7 +574,7 @@
*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)
@@ -592,7 +592,7 @@
*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);
@@ -602,7 +602,7 @@
*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;
@@ -642,7 +642,7 @@
*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);
}
@@ -651,7 +651,7 @@
*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)
@@ -669,7 +669,7 @@
*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);
@@ -679,7 +679,7 @@
*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]);
}
@@ -688,7 +688,7 @@
*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");
@@ -700,7 +700,7 @@
*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);
@@ -719,7 +719,7 @@
*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");
@@ -731,7 +731,7 @@
*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");
--- attr2 2008-06-30 21:02:45.000000000 +0200
+++ f71882fg.c 2008-06-30 21:12:57.000000000 +0200
@@ -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,18 @@
#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 +92,12 @@
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, 0);
+MODULE_PARM_DESC(fan_mode,
+ "List of fan modes (for four fans) (0=don't change, 1=pwm, 2=rpm");
+
+
static struct platform_device *f71882fg_pdev = NULL;
/* Super-I/O Function prototypes */
@@ -88,6 +108,7 @@
static inline void superio_exit(int base);
static inline u16 fan_from_reg ( u16 reg );
+static inline u16 fan_to_reg ( u16 reg );
struct f71882fg_data {
unsigned short addr;
@@ -104,6 +125,8 @@
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];
@@ -114,11 +137,19 @@
u8 temp_status;
u8 temp_beep;
u8 temp_diode_open;
+ u8 pwm[4];
+ u8 pwm_enable;
+ u8 pwm_type;
+ 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];
};
static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg);
static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg);
static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val);
+static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val);
/* Sysfs in*/
static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
@@ -136,6 +167,10 @@
/* 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
@@ -173,6 +208,36 @@
static ssize_t show_name(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);
+
static int __devinit f71882fg_probe(struct platform_device * pdev);
static int __devexit f71882fg_remove(struct platform_device *pdev);
static int __init f71882fg_init(void);
@@ -252,21 +317,181 @@
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, 1, 0),
+ SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed,
+ store_fan_full_speed, 1, 0),
SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
store_fan_beep, 1, 0),
SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1, 0),
SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, 0),
+ SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed,
+ store_fan_full_speed, 2, 0),
SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
store_fan_beep, 2, 0),
SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2, 0),
SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, 0),
+ SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, show_fan_full_speed,
+ store_fan_full_speed, 3, 0),
SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
store_fan_beep, 3, 0),
- SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3, 0)
+ SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3, 0),
+
+ 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_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_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,
+ 0, 1),
+ SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 2),
+ SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 3),
+ SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 4),
+ 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,
+ 0, 1),
+ SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 2),
+ SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 3),
+
+ SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1, 0),
+ SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 1, 0),
+ SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 1, 0),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst, store_pwm_auto_point_temp_hyst,
+ 1, 0),
+ SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel, store_pwm_auto_point_channel, 1, 0),
+ SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 0),
+ 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,
+ 1, 2),
+ SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 3),
+ SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 4),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 0),
+ 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,
+ 1, 2),
+ SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 3),
+
+ SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2, 0),
+ SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 2, 0),
+ SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 2, 0),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst, store_pwm_auto_point_temp_hyst,
+ 2, 0),
+ SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel, store_pwm_auto_point_channel, 2, 0),
+ SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 0),
+ SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 1),
+ 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,
+ 2, 3),
+ SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 4),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 0),
+ SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 1),
+ 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,
+ 2, 3),
+
+ SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 3, 0),
+ SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 3, 0),
+ SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 3, 0),
+ SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst, store_pwm_auto_point_temp_hyst,
+ 3, 0),
+ SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel, store_pwm_auto_point_channel, 3, 0),
+ SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 0),
+ SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 1),
+ SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 2),
+ 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,
+ 3, 4),
+ SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 0),
+ SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 1),
+ SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 2),
+ SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 3)
};
@@ -310,6 +535,11 @@
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;
@@ -338,6 +568,15 @@
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);
@@ -399,9 +638,37 @@
data->fan_status = f71882fg_read8(data,
F71882FG_REG_FAN_STATUS);
- for (nr = 0; nr < 4; nr++)
+ data->pwm_type = f71882fg_read8(data,
+ F71882FG_REG_PWM_TYPE);
+ 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->fan[nr] = f71882fg_read16(data,
- F71882FG_REG_FAN(nr));
+ 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->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));
+ data->pwm_auto_point_temp[nr][point]=
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_TEMP(nr,
+ point));
+ }
+ }
data->in_status = f71882fg_read8(data,
F71882FG_REG_IN_STATUS);
@@ -432,6 +699,34 @@
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;
+ int val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ if(data->pwm_enable&(1<<(2*nr)))
+ count=-EINVAL;
+ else
+ f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr),
+ fan_to_reg(val));
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+
static ssize_t show_fan_beep(struct device *dev, struct device_attribute
*devattr, char *buf)
{
@@ -739,6 +1034,276 @@
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
+ val=255*fan_from_reg(data->fan_target[nr])
+ /fan_from_reg(data->fan_full_speed[nr]);
+ 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;
+ int val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ if(data->pwm_enable&(1<<(2*nr)))
+ // PWM mode
+ f71882fg_write8(data, F71882FG_REG_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));
+ }
+ 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(2&(data->pwm_enable>>(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;
+ int val = simple_strtoul(buf, NULL, 10);
+ if(val<0 || 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; // RPM mode
+ case 2: data->pwm_enable&=~(1<<(2*nr)); break; // Duty cycle mode
+ }
+ f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
+ mutex_unlock(&data->update_lock);
+ if(!val)
+ store_pwm(dev,devattr,"255",4);
+
+ 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);
+
+ mutex_lock(&data->update_lock);
+ if(data->pwm_enable&(1<<(2*pwm))) {
+ // PWM mode
+ f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm,point), val);
+ } 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);
+ }
+ 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;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+
+ switch(nr) {
+ case 0: result=data->pwm_auto_point_hyst[0]&15; break;
+ case 1: result=data->pwm_auto_point_hyst[0]>>4; break;
+ case 2: result=data->pwm_auto_point_hyst[1]&15; break;
+ case 3: result=data->pwm_auto_point_hyst[1]>>4; break;
+ default: result=-1;
+ }
+
+ 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 = 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);
+ val&=15;
+ 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;
+ }
+
+ mutex_lock(&data->update_lock);
+ if(nr==0 || nr==1)
+ f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val);
+ else
+ f71882fg_write8(data, F71882FG_REG_FAN_HYST1, 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=1&(data->pwm_auto_point_mapping[nr]>>4);
+
+ 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);
+ if(val)
+ val=data->pwm_auto_point_mapping[nr]|(1<<4);
+ else
+ val=data->pwm_auto_point_mapping[nr]&(~(1<<4));
+ mutex_lock(&data->update_lock);
+ f71882fg_write8(data, F71882FG_REG_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);
+ result>>=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;
+ int val = simple_strtoul(buf, NULL, 10);
+ switch(val) {
+ case 1: val=1; break;
+ case 2: val=2; break;
+ case 4: val=3; break;
+ default: return -EINVAL;
+ }
+ val|=data->pwm_auto_point_mapping[nr]&0xfc;
+ mutex_lock(&data->update_lock);
+ f71882fg_write8(data, F71882FG_REG_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", 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;
+ int val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ f71882fg_write8(data, F71882FG_REG_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)
{
More information about the lm-sensors
mailing list