MODULE_PARM_DESC(force_i2c,
"Initialize the i2c address of the sensors");
-static int reset;
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
-
static int init = 1;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
/* modified from kernel/include/traps.c */
static int REG; /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
#define W83627HF_REG_PWM1 0x5A
#define W83627HF_REG_PWM2 0x5B
+static const u8 W83627THF_REG_PWM_ENABLE[] = {
+ 0x04, /* FAN 1 mode */
+ 0x04, /* FAN 2 mode */
+ 0x12, /* FAN AUX mode */
+};
+static const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
+
#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */
#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */
#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */
return (0x80 | (180000UL / (val << 8)));
}
-#define BEEP_MASK_FROM_REG(val) (val)
-#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
-#define BEEP_ENABLE_TO_REG(val) ((val)?1:0)
-#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
+#define BEEP_MASK_FROM_REG(val) ((val) & 0xff7fff)
+#define BEEP_MASK_TO_REG(val) ((val) & 0xff7fff)
#define DIV_FROM_REG(val) (1 << (val))
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
u32 beep_mask; /* Register encoding, combined */
- u8 beep_enable; /* Boolean */
u8 pwm[3]; /* Register value */
+ u8 pwm_enable[3]; /* 1 = manual
+ 2 = thermal cruise (also called SmartFan I)
+ 3 = fan speed cruise */
u8 pwm_freq[3]; /* Register value */
u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode;
4 = thermistor */
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-#define show_beep_reg(REG, reg) \
-static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct w83627hf_data *data = w83627hf_update_device(dev); \
- return sprintf(buf,"%ld\n", \
- (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
+static ssize_t
+show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ int bitnr = to_sensor_dev_attr(attr)->index;
+ return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
-show_beep_reg(ENABLE, enable)
-show_beep_reg(MASK, mask)
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
-#define BEEP_ENABLE 0 /* Store beep_enable */
-#define BEEP_MASK 1 /* Store beep_mask */
+static ssize_t
+show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n",
+ (long)BEEP_MASK_FROM_REG(data->beep_mask));
+}
static ssize_t
-store_beep_reg(struct device *dev, const char *buf, size_t count,
- int update_mask)
+store_beep_mask(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct w83627hf_data *data = dev_get_drvdata(dev);
- u32 val, val2;
+ unsigned long val;
val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
- if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
- data->beep_mask = BEEP_MASK_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
- data->beep_mask & 0xff);
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
- ((data->beep_mask) >> 16) & 0xff);
- val2 = (data->beep_mask >> 8) & 0x7f;
- } else { /* We are storing beep_enable */
- val2 =
- w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
- data->beep_enable = BEEP_ENABLE_TO_REG(val);
- }
-
+ /* preserve beep enable */
+ data->beep_mask = (data->beep_mask & 0x8000)
+ | BEEP_MASK_TO_REG(val);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
+ data->beep_mask & 0xff);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
+ ((data->beep_mask) >> 16) & 0xff);
w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
- val2 | data->beep_enable << 7);
+ (data->beep_mask >> 8) & 0xff);
mutex_unlock(&data->update_lock);
return count;
}
-#define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- return show_beep_##reg(dev, attr, buf); \
-} \
-static ssize_t \
-store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
- return store_beep_reg(dev, buf, count, BEEP_##REG); \
-} \
-static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
- show_regs_beep_##reg, store_regs_beep_##reg);
+static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+ show_beep_mask, store_beep_mask);
+
+static ssize_t
+show_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ int bitnr = to_sensor_dev_attr(attr)->index;
+ return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ int bitnr = to_sensor_dev_attr(attr)->index;
+ unsigned long bit;
+ u8 reg;
+
+ bit = simple_strtoul(buf, NULL, 10);
+ if (bit & ~1)
+ return -EINVAL;
-sysfs_beep(ENABLE, enable);
-sysfs_beep(MASK, mask);
+ mutex_lock(&data->update_lock);
+ if (bit)
+ data->beep_mask |= (1 << bitnr);
+ else
+ data->beep_mask &= ~(1 << bitnr);
+
+ if (bitnr < 8) {
+ reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
+ if (bit)
+ reg |= (1 << bitnr);
+ else
+ reg &= ~(1 << bitnr);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
+ } else if (bitnr < 16) {
+ reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
+ if (bit)
+ reg |= (1 << (bitnr - 8));
+ else
+ reg &= ~(1 << (bitnr - 8));
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
+ } else {
+ reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
+ if (bit)
+ reg |= (1 << (bitnr - 16));
+ else
+ reg &= ~(1 << (bitnr - 16));
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
+ }
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 0);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 2);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 3);
+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 8);
+static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 9);
+static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 10);
+static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 16);
+static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 17);
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 6);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 7);
+static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 11);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 4);
+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 5);
+static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 13);
+static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 15);
static ssize_t
show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
+static ssize_t
+show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_enable[nr]);
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ u8 reg;
+
+ if (!val || (val > 3)) /* modes 1, 2 and 3 are supported */
+ return -EINVAL;
+ mutex_lock(&data->update_lock);
+ data->pwm_enable[nr] = val;
+ reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
+ reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
+ reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
+ w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 2);
+
static ssize_t
show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
{
VAL = sioaddr + 1;
superio_enter();
- val= superio_inb(DEVID);
+ val = force_id ? force_id : superio_inb(DEVID);
switch (val) {
case W627_DEVID:
sio_data->type = w83627hf;
#define VIN_UNIT_ATTRS(_X_) \
&sensor_dev_attr_in##_X_##_input.dev_attr.attr, \
&sensor_dev_attr_in##_X_##_min.dev_attr.attr, \
- &sensor_dev_attr_in##_X_##_max.dev_attr.attr
+ &sensor_dev_attr_in##_X_##_max.dev_attr.attr, \
+ &sensor_dev_attr_in##_X_##_alarm.dev_attr.attr, \
+ &sensor_dev_attr_in##_X_##_beep.dev_attr.attr
#define FAN_UNIT_ATTRS(_X_) \
&sensor_dev_attr_fan##_X_##_input.dev_attr.attr, \
&sensor_dev_attr_fan##_X_##_min.dev_attr.attr, \
- &sensor_dev_attr_fan##_X_##_div.dev_attr.attr
+ &sensor_dev_attr_fan##_X_##_div.dev_attr.attr, \
+ &sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr, \
+ &sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
#define TEMP_UNIT_ATTRS(_X_) \
&sensor_dev_attr_temp##_X_##_input.dev_attr.attr, \
&sensor_dev_attr_temp##_X_##_max.dev_attr.attr, \
&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr, \
- &sensor_dev_attr_temp##_X_##_type.dev_attr.attr
+ &sensor_dev_attr_temp##_X_##_type.dev_attr.attr, \
+ &sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr, \
+ &sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
static struct attribute *w83627hf_attributes[] = {
&dev_attr_in0_input.attr,
&dev_attr_in0_min.attr,
&dev_attr_in0_max.attr,
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
+ &sensor_dev_attr_in0_beep.dev_attr.attr,
VIN_UNIT_ATTRS(2),
VIN_UNIT_ATTRS(3),
VIN_UNIT_ATTRS(4),
TEMP_UNIT_ATTRS(2),
&dev_attr_alarms.attr,
- &dev_attr_beep_enable.attr,
+ &sensor_dev_attr_beep_enable.dev_attr.attr,
&dev_attr_beep_mask.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_pwm1_freq.dev_attr.attr,
&sensor_dev_attr_pwm2_freq.dev_attr.attr,
&sensor_dev_attr_pwm3_freq.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+
NULL
};
&sensor_dev_attr_in5_min.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in5_max.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in5_alarm.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in5_beep.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in6_input.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in6_min.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in6_max.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in6_alarm.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in6_beep.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_pwm1_freq.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in1_min.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_in1_max.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in1_alarm.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_in1_beep.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_fan3_input.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_fan3_min.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_fan3_div.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_fan3_alarm.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_fan3_beep.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_temp3_input.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_temp3_max.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_temp3_max_hyst.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_temp3_alarm.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_temp3_beep.dev_attr))
|| (err = device_create_file(dev,
&sensor_dev_attr_temp3_type.dev_attr)))
goto ERROR4;
&sensor_dev_attr_pwm3_freq.dev_attr)))
goto ERROR4;
+ if (data->type != w83627hf)
+ if ((err = device_create_file(dev,
+ &sensor_dev_attr_pwm1_enable.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_pwm2_enable.dev_attr)))
+ goto ERROR4;
+
+ if (data->type == w83627thf || data->type == w83637hf
+ || data->type == w83687thf)
+ if ((err = device_create_file(dev,
+ &sensor_dev_attr_pwm3_enable.dev_attr)))
+ goto ERROR4;
+
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
enum chips type = data->type;
u8 tmp;
- if (reset) {
- /* Resetting the chip has been the default for a long time,
- but repeatedly caused problems (fans going to full
- speed...) so it is now optional. It might even go away if
- nobody reports it as being useful, as I see very little
- reason why this would be needed at all. */
- dev_info(&pdev->dev, "If reset=1 solved a problem you were "
- "having, please report!\n");
-
- /* save this register */
- i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG);
- /* Reset all except Watchdog values and last conversion values
- This sets fan-divs to 2, among others */
- w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80);
- /* Restore the register and disable power-on abnormal beep.
- This saves FAN 1/2/3 input/output values set by BIOS. */
- w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
- /* Disable master beep-enable (reset turns it on).
- Individual beeps should be reset to off but for some reason
- disabling this bit helps some people not get beeped */
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0);
- }
-
/* Minimize conflicts with other winbond i2c-only clients... */
/* disable i2c subclients... how to disable main i2c client?? */
/* force i2c address to relatively uncommon address */
(w83627hf_read_value(data,
W83781D_REG_CONFIG) & 0xf7)
| 0x01);
+
+ /* Enable VBAT monitoring if needed */
+ tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
+ if (!(tmp & 0x01))
+ w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
}
static void w83627hf_update_fan_div(struct w83627hf_data *data)
{
struct w83627hf_data *data = dev_get_drvdata(dev);
int i, num_temps = (data->type == w83697hf) ? 2 : 3;
+ int num_pwms = (data->type == w83697hf) ? 2 : 3;
mutex_lock(&data->update_lock);
break;
}
}
+ if (data->type != w83627hf) {
+ for (i = 0; i < num_pwms; i++) {
+ u8 tmp = w83627hf_read_value(data,
+ W83627THF_REG_PWM_ENABLE[i]);
+ data->pwm_enable[i] =
+ ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
+ & 0x03) + 1;
+ }
+ }
for (i = 0; i < num_temps; i++) {
data->temp[i] = w83627hf_read_value(
data, w83627hf_reg_temp[i]);
(w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
(w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
- data->beep_enable = i >> 7;
- data->beep_mask = ((i & 0x7f) << 8) |
+ data->beep_mask = (i << 8) |
w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
data->last_updated = jiffies;