diff options
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1002befd87d..25763d2223b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -80,6 +80,13 @@ superio_inb(int reg) return inb(VAL); } +static inline void +superio_outb(int reg, int val) +{ + outb(reg, REG); + outb(val, VAL); +} + static int superio_inw(int reg) { int val; @@ -539,14 +546,14 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); long val; + u8 reg; if (strict_strtol(buf, 10, &val) < 0) return -EINVAL; - mutex_lock(&data->update_lock); - - data->sensor &= ~(1 << nr); - data->sensor &= ~(8 << nr); + reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); + reg &= ~(1 << nr); + reg &= ~(8 << nr); if (val == 2) { /* backwards compatibility */ dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " "instead\n"); @@ -554,14 +561,16 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, } /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ if (val == 3) - data->sensor |= 1 << nr; + reg |= 1 << nr; else if (val == 4) - data->sensor |= 8 << nr; - else if (val != 0) { - mutex_unlock(&data->update_lock); + reg |= 8 << nr; + else if (val != 0) return -EINVAL; - } + + mutex_lock(&data->update_lock); + data->sensor = reg; it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); + data->valid = 0; /* Force cache refresh */ mutex_unlock(&data->update_lock); return count; } @@ -1515,6 +1524,21 @@ static int __init it87_find(unsigned short *address, sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); reg = superio_inb(IT87_SIO_PINX2_REG); + /* + * The IT8720F has no VIN7 pin, so VCCH should always be + * routed internally to VIN7 with an internal divider. + * Curiously, there still is a configuration bit to control + * this, which means it can be set incorrectly. And even + * more curiously, many boards out there are improperly + * configured, even though the IT8720F datasheet claims + * that the internal routing of VCCH to VIN7 is the default + * setting. So we force the internal routing in this case. + */ + if (sio_data->type == it8720 && !(reg & (1 << 1))) { + reg |= (1 << 1); + superio_outb(IT87_SIO_PINX2_REG, reg); + pr_notice("it87: Routing internal VCCH to in7\n"); + } if (reg & (1 << 0)) pr_info("it87: in3 is VCC (+5V)\n"); if (reg & (1 << 1)) @@ -1841,14 +1865,10 @@ static void __devinit it87_init_device(struct platform_device *pdev) it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); } - /* Check if temperature channels are reset manually or by some reason */ - tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); - if ((tmp & 0x3f) == 0) { - /* Temp1,Temp3=thermistor; Temp2=thermal diode */ - tmp = (tmp & 0xc0) | 0x2a; - it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp); - } - data->sensor = tmp; + /* Temperature channels are not forcibly enabled, as they can be + * set to two different sensor types and we can't guess which one + * is correct for a given system. These channels can be enabled at + * run-time through the temp{1-3}_type sysfs accessors if needed. */ /* Check if voltage monitors are reset manually or by some reason */ tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); |