--- drivers/i2c/chips/it87.c.orig 2005-04-08 14:26:45.000000000 +0200 +++ drivers/i2c/chips/it87.c 2005-04-08 19:08:57.000000000 +0200 @@ -150,6 +150,15 @@ #define IT87_REG_TEMP_ENABLE 0x51 #define IT87_REG_CHIPID 0x58 +#define IT87_REG_OFF_TEMP(nr) ((nr==2)?0x70:((nr==1)?0x68:0x60)) +#define IT87_REG_LOW_TEMP(nr) ((nr==2)?0x71:((nr==1)?0x69:0x61)) +#define IT87_REG_MED_TEMP(nr) ((nr==2)?0x72:((nr==1)?0x6a:0x62)) +#define IT87_REG_HI_TEMP(nr) ((nr==2)?0x73:((nr==1)?0x6b:0x63)) +#define IT87_REG_FULL_TEMP(nr) ((nr==2)?0x74:((nr==1)?0x6c:0x64)) + +#define IT87_REG_LOW_PWM(nr) ((nr==2)?0x75:((nr==1)?0x6d:0x65)) +#define IT87_REG_MED_PWM(nr) ((nr==2)?0x76:((nr==1)?0x6e:0x66)) +#define IT87_REG_HI_PWM(nr) ((nr==2)?0x77:((nr==1)?0x6f:0x67)) #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) #define IN_FROM_REG(val) ((val) * 16) @@ -165,6 +174,10 @@ #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) +#define PWM_TO_REG(val) ((val) >> 1) + +#define PWM_FROM_REG(val) (((val)&0x7f) << 1) + #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ ((val)+500)/1000),-128,127)) #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) @@ -202,6 +215,11 @@ u8 in_min[9]; /* Register value */ u8 fan[3]; /* Register value */ u8 fan_min[3]; /* Register value */ + u8 pwm_mode[3]; /* PWM bit 7 (0 = software, 1 = automatic) */ + u8 pwm_tmpin[3]; /* PWM bits 1-0 when bit 7 == 1*/ + u8 pwm_value[3]; /* PWM bits 6-0 when bit 7 == 0 */ + u8 fan_main_ctrl; /* Register value */ + u8 fan_ctl; /* Register value */ u8 temp[3]; /* Register value */ u8 temp_high[3]; /* Register value */ u8 temp_low[3]; /* Register value */ @@ -210,10 +228,27 @@ u8 vid; /* Register encoding, combined */ int vrm; u32 alarms; /* Register encoding, combined */ - u8 fan_main_ctrl; /* Register value */ u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ }; +/* Modes that the it87's fan controllers can be in. */ +enum it87_pwm_modes { + PWM_OFF, /* pwm settings disabled, only on/off available */ + PWM_SOFTWARE, /* manual pwm enabled for userspace software to adjust */ + PWM_AUTOMATIC /* automatic pwm, it87 adjusts speed according to settings */ +}; + +static inline enum it87_pwm_modes it87_pwm_mode(struct it87_data *data, int nr) { + if (data->fan_main_ctrl & (1 << nr)) { + if (data->pwm_mode[nr] == 0) + return PWM_SOFTWARE; + else + return PWM_AUTOMATIC; + } else { + return PWM_OFF; + } +} + static int it87_attach_adapter(struct i2c_adapter *adapter); static int it87_find(int *address); @@ -452,6 +487,83 @@ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); } +static ssize_t show_fan_pwm(struct device *dev, char *buf, int nr) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm_value[nr])); +} +static ssize_t show_fan_pwm_enable (struct device *dev, char *buf, int nr) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%d\n", (data->fan_main_ctrl & (1 << nr)) != 0); +} +static ssize_t show_fan_enable (struct device *dev, char *buf, int nr) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%d\n", (data->fan_ctl & (1 << nr)) != 0); +} +static ssize_t show_fan_auto_enable (struct device *dev, char *buf, int nr) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_mode[nr]); +} +static ssize_t show_fan_auto_temp_channel (struct device *dev, char *buf, int nr) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_tmpin[nr] ? (data->pwm_tmpin[nr] << 1) : 1 ); +} +static ssize_t show_fan_auto_temp_off (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_OFF_TEMP(nr)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(temp)); +} +static ssize_t show_fan_auto_temp_min (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_LOW_TEMP(nr)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(temp)); +} +static ssize_t show_fan_auto_temp_low (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_MED_TEMP(nr)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(temp)); +} +static ssize_t show_fan_auto_temp_medium (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_HI_TEMP(nr)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(temp)); +} +static ssize_t show_fan_auto_temp_max (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_FULL_TEMP(nr)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(temp)); +} +static ssize_t show_fan_auto_pwm_min (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_LOW_PWM(nr)); + return sprintf(buf, "%d\n", temp); +} +static ssize_t show_fan_auto_pwm_low (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_MED_PWM(nr)); + return sprintf(buf, "%d\n", temp); +} +static ssize_t show_fan_auto_pwm_medium (struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 temp = it87_read_value(client, IT87_REG_HI_PWM(nr)); + return sprintf(buf, "%d\n", temp); +} +static ssize_t show_fan_auto_pwm_max (struct device *dev, char *buf, int nr) +{ + return sprintf(buf, "%d\n", 255); +} static ssize_t show_fan_min(struct device *dev, char *buf, int nr) { struct it87_data *data = it87_update_device(dev); @@ -562,6 +674,176 @@ return count; } +static ssize_t set_fan_pwm(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + if (it87_pwm_mode(data, nr) != PWM_SOFTWARE) + return -1; + if (val < 0 || val > 255) + return -1; + data->pwm_value[nr] = PWM_TO_REG(val); + it87_write_value(client, IT87_REG_PWM(nr), data->pwm_value[nr]); + return count; +} +static ssize_t set_fan_pwm_enable (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + if (val == 1) + data->fan_main_ctrl |= 1 << nr; + else if (val == 0) + data->fan_main_ctrl &= ~(1 << nr); + else + return -1; + data->fan_main_ctrl |= 0x70; + it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); + return count; +} +static ssize_t set_fan_enable (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + if (it87_pwm_mode(data, nr) != PWM_OFF) + return -1; + if (val == 1) + data->fan_ctl |= 1 << nr; + else if (val == 0) + data->fan_ctl &= ~(1 << nr); + else + return -1; + it87_write_value(client, IT87_REG_FAN_CTL, (1 << 7) | data->fan_ctl); + return count; +} +static ssize_t set_fan_auto_enable (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + u8 lowbits; + + if (it87_pwm_mode(data, nr) == PWM_OFF) + return -1; + + if (val == 1) { + data->pwm_mode[nr] = 1; + lowbits = data->pwm_tmpin[nr]; + } else if (val == 0) { + data->pwm_mode[nr] = 0; + lowbits = data->pwm_value[nr]; + } else + return -1; + it87_write_value(client, IT87_REG_PWM(nr), + data->pwm_mode[nr] << 7 | lowbits); + return count; +} +static ssize_t set_fan_auto_temp_channel (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + if (it87_pwm_mode(data, nr) != PWM_AUTOMATIC) + return -1; + if (!(val == 1 || val == 2 || val == 4)) + return -1; + data->pwm_tmpin[nr] = val >> 1; + it87_write_value(client, IT87_REG_PWM(nr), 1 << 7 | data->pwm_tmpin[nr]); + return count; +} +static ssize_t set_fan_auto_temp_off (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_OFF_TEMP(nr), TEMP_TO_REG(val)); + return count; +} +static ssize_t set_fan_auto_temp_min (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_LOW_TEMP(nr), TEMP_TO_REG(val)); + return count; +} +static ssize_t set_fan_auto_temp_low (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_MED_TEMP(nr), TEMP_TO_REG(val)); + return count; +} +static ssize_t set_fan_auto_temp_medium (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_HI_TEMP(nr), TEMP_TO_REG(val)); + return count; +} +static ssize_t set_fan_auto_temp_max (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_FULL_TEMP(nr), TEMP_TO_REG(val)); + return count; +} +static ssize_t set_fan_auto_pwm_min (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_LOW_PWM(nr), val); + return count; +} +static ssize_t set_fan_auto_pwm_low (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_MED_PWM(nr), val); + return count; +} +static ssize_t set_fan_auto_pwm_medium (struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + int val = simple_strtol(buf, NULL, 10); + + it87_write_value(client, IT87_REG_HI_PWM(nr), val); + return count; +} +static ssize_t set_fan_auto_pwm_max (struct device *dev, const char *buf, + size_t count, int nr) +{ + int val = simple_strtol(buf, NULL, 10); + + if (val != 255) + return -1; + return count; +} + #define show_fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ @@ -575,6 +857,75 @@ { \ return show_fan_div(dev, buf, offset - 1); \ } \ +static ssize_t show_fan_##offset##_pwm (struct device *dev, char *buf) \ +{ \ + return show_fan_pwm(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_pwm_enable (struct device *dev, \ + char *buf) \ +{ \ + return show_fan_pwm_enable(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_enable (struct device *dev, \ + char *buf) \ +{ \ + return show_fan_enable(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_enable (struct device *dev, \ + char *buf) \ +{ \ + return show_fan_auto_enable(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_channel ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_channel(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_off ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_off(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_min ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_min(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_low ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_low(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_medium ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_medium(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_temp_max ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_temp_max(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_pwm_min ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_pwm_min(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_pwm_low ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_pwm_low(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_pwm_medium ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_pwm_medium(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t show_fan_##offset##_auto_pwm_max ( \ + struct device *dev, char *buf) \ +{ \ + return show_fan_auto_pwm_max(dev, buf, 0x##offset - 1); \ +} \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ @@ -585,12 +936,123 @@ { \ return set_fan_div(dev, buf, count, offset - 1); \ } \ +static ssize_t set_fan_##offset##_pwm (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_fan_pwm(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_pwm_enable (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_fan_pwm_enable(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_enable (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_fan_enable(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_enable (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_fan_auto_enable(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_channel ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_channel(dev, buf, count, \ + 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_off ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_off(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_min ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_min(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_low ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_low(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_medium ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_medium(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_temp_max ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_temp_max(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_pwm_min ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_pwm_min(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_pwm_low ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_pwm_low(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_pwm_medium ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_pwm_medium(dev, buf, count, 0x##offset - 1); \ +} \ +static ssize_t set_fan_##offset##_auto_pwm_max ( \ + struct device *dev, const char *buf, size_t count) \ +{ \ + return set_fan_auto_pwm_max(dev, buf, count, 0x##offset - 1); \ +} \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan_##offset##_min, set_fan_##offset##_min); \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_div, set_fan_##offset##_div); - + show_fan_##offset##_div, set_fan_##offset##_div); \ +static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_pwm, set_fan_##offset##_pwm); \ +static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_pwm_enable, \ + set_fan_##offset##_pwm_enable); \ +static DEVICE_ATTR(fan##offset##_enable, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_enable, set_fan_##offset##_enable); \ +static DEVICE_ATTR(fan##offset##_auto_enable, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_enable, \ + set_fan_##offset##_auto_enable); \ +static DEVICE_ATTR(fan##offset##_auto_temp_channel, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_channel, \ + set_fan_##offset##_auto_temp_channel); \ +static DEVICE_ATTR(fan##offset##_auto_temp_off, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_off, \ + set_fan_##offset##_auto_temp_off); \ +static DEVICE_ATTR(fan##offset##_auto_temp_min, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_min, \ + set_fan_##offset##_auto_temp_min); \ +static DEVICE_ATTR(fan##offset##_auto_temp_low, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_low, \ + set_fan_##offset##_auto_temp_low); \ +static DEVICE_ATTR(fan##offset##_auto_temp_medium, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_medium, \ + set_fan_##offset##_auto_temp_medium); \ +static DEVICE_ATTR(fan##offset##_auto_temp_max, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_temp_max, \ + set_fan_##offset##_auto_temp_max); \ +static DEVICE_ATTR(fan##offset##_auto_pwm_min, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_pwm_min, \ + set_fan_##offset##_auto_pwm_min); \ +static DEVICE_ATTR(fan##offset##_auto_pwm_low, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_pwm_low, \ + set_fan_##offset##_auto_pwm_low); \ +static DEVICE_ATTR(fan##offset##_auto_pwm_medium, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_pwm_medium, \ + set_fan_##offset##_auto_pwm_medium); \ +static DEVICE_ATTR(fan##offset##_auto_pwm_max, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_auto_pwm_max, \ + set_fan_##offset##_auto_pwm_max); + show_fan_offset(1); show_fan_offset(2); show_fan_offset(3); @@ -883,6 +1345,48 @@ device_create_file(&new_client->dev, &dev_attr_fan1_div); device_create_file(&new_client->dev, &dev_attr_fan2_div); device_create_file(&new_client->dev, &dev_attr_fan3_div); + device_create_file(&new_client->dev, &dev_attr_fan1_pwm); + device_create_file(&new_client->dev, &dev_attr_fan2_pwm); + device_create_file(&new_client->dev, &dev_attr_fan3_pwm); + device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); + device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable); + device_create_file(&new_client->dev, &dev_attr_fan3_pwm_enable); + device_create_file(&new_client->dev, &dev_attr_fan1_enable); + device_create_file(&new_client->dev, &dev_attr_fan2_enable); + device_create_file(&new_client->dev, &dev_attr_fan3_enable); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_enable); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_enable); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_enable); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_channel); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_channel); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_channel); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_low); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_low); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_low); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_medium); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_medium); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_medium); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_pwm_low); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_pwm_low); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_pwm_low); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_pwm_medium); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_pwm_medium); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_pwm_medium); + device_create_file(&new_client->dev, &dev_attr_fan1_auto_pwm_max); + device_create_file(&new_client->dev, &dev_attr_fan2_auto_pwm_max); + device_create_file(&new_client->dev, &dev_attr_fan3_auto_pwm_max); device_create_file(&new_client->dev, &dev_attr_alarms); if (enable_pwm_interface) { device_create_file(&new_client->dev, &dev_attr_pwm1_enable); @@ -1024,6 +1528,14 @@ } } + /* Check poloarity of FAN_CTL3-1 registers (which are low active after a reset) */ + tmp = it87_read_value(client, IT87_REG_FAN_CTL); + if ((tmp & (1 << 7)) == 0) { + /* Set polarity of FAN_CTL3-1 to active high */ + tmp |= (1 << 7) | 0x7; + it87_write_value(client, IT87_REG_FAN_CTL, tmp); + } + /* Start monitoring */ it87_write_value(client, IT87_REG_CONFIG, (it87_read_value(client, IT87_REG_CONFIG) & 0x36) @@ -1085,6 +1597,18 @@ data->fan_div[1] = (i >> 3) & 0x07; data->fan_div[2] = (i & 0x40) ? 3 : 1; + for (i = 0; i < 3; i++) { + u8 pwm; + pwm = it87_read_value(client, IT87_REG_PWM(i)); + data->pwm_mode[i] = (pwm >> 7); + if (it87_pwm_mode(data, i) == PWM_AUTOMATIC) + data->pwm_tmpin[i] = pwm & 0x03; + else if (it87_pwm_mode(data, i) == PWM_SOFTWARE) + data->pwm_value[i] = pwm & 0x7f; + } + data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); + data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); + data->alarms = it87_read_value(client, IT87_REG_ALARM1) | (it87_read_value(client, IT87_REG_ALARM2) << 8) |