X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=it87.c;h=533d243a80d363b884062c29c15e74855bd011c5;hb=78afa4ee1a02b2d56e81b470a7c0d900e996e43e;hp=594301973270f2982aa2507f3c49a26af764054f;hpb=247605bba62619909d3e2cf1974313856e016ddb;p=groeck-it87 diff --git a/it87.c b/it87.c index 5943019..533d243 100644 --- a/it87.c +++ b/it87.c @@ -146,13 +146,10 @@ static inline int superio_enter(int ioreg) * Try to reserve ioreg and ioreg + 1 for exclusive access. */ if (!request_muxed_region(ioreg, 2, DRVNAME)) - goto error; + return -EBUSY; __superio_enter(ioreg); return 0; - -error: - return -EBUSY; } static inline void superio_exit(int ioreg, bool doexit) @@ -193,10 +190,13 @@ static inline void superio_exit(int ioreg, bool doexit) #define IT8655E_DEVID 0x8655 #define IT8665E_DEVID 0x8665 #define IT8686E_DEVID 0x8686 -#define IT87_ACT_REG 0x30 -#define IT87_BASE_REG 0x60 -/* Logical device 7 registers (IT8712F and later) */ +/* Logical device 4 (Environmental Monitor) registers */ +#define IT87_ACT_REG 0x30 +#define IT87_BASE_REG 0x60 +#define IT87_SPECIAL_CFG_REG 0xf3 /* special configuration register */ + +/* Logical device 7 (GPIO) registers (IT8712F and later) */ #define IT87_SIO_GPIO1_REG 0x25 #define IT87_SIO_GPIO2_REG 0x26 #define IT87_SIO_GPIO3_REG 0x27 @@ -335,6 +335,8 @@ struct it87_devices { u8 num_temp_map; /* Number of temperature sources for pwm */ u8 peci_mask; u8 old_peci_mask; + u8 smbus_bitmap; /* SMBus enable bits in extra config register */ + u8 ec_special_config; }; #define FEAT_12MV_ADC BIT(0) @@ -618,6 +620,7 @@ static const struct it87_devices it87_devices[] = { .num_temp_limit = 6, .num_temp_offset = 6, .num_temp_map = 6, + .smbus_bitmap = BIT(1) | BIT(2), }, [it8628] = { .name = "it8628", @@ -641,6 +644,7 @@ static const struct it87_devices it87_devices[] = { .num_temp_limit = 6, .num_temp_offset = 6, .num_temp_map = 6, + .smbus_bitmap = BIT(2), }, [it8665] = { .name = "it8665", @@ -652,6 +656,7 @@ static const struct it87_devices it87_devices[] = { .num_temp_limit = 6, .num_temp_offset = 6, .num_temp_map = 6, + .smbus_bitmap = BIT(2), }, [it8686] = { .name = "it8686", @@ -663,6 +668,7 @@ static const struct it87_devices it87_devices[] = { .num_temp_limit = 6, .num_temp_offset = 6, .num_temp_map = 7, + .smbus_bitmap = BIT(1) | BIT(2), }, }; @@ -703,6 +709,8 @@ static const struct it87_devices it87_devices[] = { struct it87_sio_data { enum chips type; + u8 sioaddr; + u8 doexit; /* Values read from Super-I/O config space */ u8 revision; u8 vid_value; @@ -714,6 +722,8 @@ struct it87_sio_data { u8 skip_fan; u8 skip_pwm; u8 skip_temp; + u8 smbus_bitmap; + u8 ec_special_config; }; /* @@ -727,6 +737,11 @@ struct it87_data { u8 peci_mask; u8 old_peci_mask; + u8 smbus_bitmap; /* !=0 if SMBus needs to be disabled */ + u8 ec_special_config; /* EC special config register restore value */ + u8 sioaddr; /* SIO port address */ + bool doexit; /* true if exit from sio config is ok */ + const u8 *REG_FAN; const u8 *REG_FANX; const u8 *REG_FAN_MIN; @@ -910,6 +925,39 @@ static const unsigned int pwm_freq[8] = { 750000, }; +static int smbus_disable(struct it87_data *data) +{ + int err; + + if (data->smbus_bitmap) { + err = superio_enter(data->sioaddr); + if (err) + return err; + superio_select(data->sioaddr, PME); + superio_outb(data->sioaddr, IT87_SPECIAL_CFG_REG, + data->ec_special_config & ~data->smbus_bitmap); + superio_exit(data->sioaddr, data->doexit); + } + return 0; +} + +static int smbus_enable(struct it87_data *data) +{ + int err; + + if (data->smbus_bitmap) { + err = superio_enter(data->sioaddr); + if (err) + return err; + + superio_select(data->sioaddr, PME); + superio_outb(data->sioaddr, IT87_SPECIAL_CFG_REG, + data->ec_special_config); + superio_exit(data->sioaddr, data->doexit); + } + return 0; +} + static int _it87_read_value(struct it87_data *data, u8 reg) { outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); @@ -941,6 +989,7 @@ static u8 it87_set_bank(struct it87_data *data, u8 bank) /* * Must be called with data->update_lock held, except during initialization. + * Must be called with SMBus accesses disabled. * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, * would slow down the IT87 access and should not be necessary. */ @@ -958,6 +1007,7 @@ static int it87_read_value(struct it87_data *data, u16 reg) /* * Must be called with data->update_lock held, except during initialization. + * Must be called with SMBus accesses disabled * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, * would slow down the IT87 access and should not be necessary. */ @@ -1023,12 +1073,32 @@ static void it87_update_pwm_ctrl(struct it87_data *data, int nr) } } +static int it87_lock(struct it87_data *data) +{ + int err; + + mutex_lock(&data->update_lock); + err = smbus_disable(data); + if (err) + mutex_unlock(&data->update_lock); + return err; +} + +static void it87_unlock(struct it87_data *data) +{ + smbus_enable(data); + mutex_unlock(&data->update_lock); +} + static struct it87_data *it87_update_device(struct device *dev) { struct it87_data *data = dev_get_drvdata(dev); + int err; int i; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return ERR_PTR(err); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1135,9 +1205,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->last_updated = jiffies; data->valid = 1; } - - mutex_unlock(&data->update_lock); - + it87_unlock(data); return data; } @@ -1149,6 +1217,9 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, int index = sattr->index; int nr = sattr->nr; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index])); } @@ -1160,17 +1231,21 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, int index = sattr->index; int nr = sattr->nr; unsigned long val; + int err; if (kstrtoul(buf, 10, &val) < 0) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + data->in[nr][index] = in_to_reg(data, nr, val); it87_write_value(data, index == 1 ? IT87_REG_VIN_MIN(nr) : IT87_REG_VIN_MAX(nr), data->in[nr][index]); - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1237,6 +1312,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, int index = sattr->index; struct it87_data *data = it87_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index])); } @@ -1249,11 +1327,14 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); long val; u8 reg, regval; + int err; if (kstrtol(buf, 10, &val) < 0) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; switch (index) { default: @@ -1276,7 +1357,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, data->temp[nr][index] = TEMP_TO_REG(val); it87_write_value(data, reg, data->temp[nr][index]); - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1397,8 +1478,12 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct it87_data *data = it87_update_device(dev); - int type = get_temp_type(data, sensor_attr->index); + int type; + + if (IS_ERR(data)) + return PTR_ERR(data); + type = get_temp_type(data, sensor_attr->index); return sprintf(buf, "%d\n", type); } @@ -1411,10 +1496,15 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); long val; u8 reg, extra; + int err; if (kstrtol(buf, 10, &val) < 0) return -EINVAL; + err = it87_lock(data); + if (err) + return err; + reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); reg &= ~(1 << nr); reg &= ~(8 << nr); @@ -1437,17 +1527,19 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, reg |= (nr + 1) << 6; else if (has_temp_old_peci(data, nr) && val == 6) extra |= 0x80; - else if (val != 0) - return -EINVAL; + else if (val != 0) { + count = -EINVAL; + goto unlock; + } - mutex_lock(&data->update_lock); data->sensor = reg; data->extra = extra; it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); if (has_temp_old_peci(data, nr)) it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); +unlock: + it87_unlock(data); return count; } @@ -1489,6 +1581,9 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, int speed; struct it87_data *data = it87_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + speed = has_16bit_fans(data) ? FAN16_FROM_REG(data->fan[nr][index]) : FAN_FROM_REG(data->fan[nr][index], @@ -1503,6 +1598,9 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%lu\n", DIV_FROM_REG(data->fan_div[nr])); } @@ -1513,6 +1611,9 @@ static ssize_t show_pwm_enable(struct device *dev, struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", pwm_mode(data, nr)); } @@ -1523,6 +1624,9 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", pwm_from_reg(data, data->pwm_duty[nr])); } @@ -1536,6 +1640,9 @@ static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, unsigned int freq; int index; + if (IS_ERR(data)) + return PTR_ERR(data); + if (has_pwm_freq2(data) && nr == 1) index = (data->extra >> 4) & 0x07; else @@ -1555,12 +1662,15 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); long val; + int err; u8 reg; if (kstrtol(buf, 10, &val) < 0) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; if (has_16bit_fans(data)) { data->fan[nr][index] = FAN16_TO_REG(val); @@ -1586,8 +1696,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, it87_write_value(data, data->REG_FAN_MIN[nr], data->fan[nr][index]); } - - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1598,13 +1707,16 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); int nr = sensor_attr->index; unsigned long val; - int min; + int min, err; u8 old; if (kstrtoul(buf, 10, &val) < 0) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + old = it87_read_value(data, IT87_REG_FAN_DIV); /* Save fan min limit */ @@ -1631,8 +1743,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, /* Restore fan min limit */ data->fan[nr][1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(data, data->REG_FAN_MIN[nr], data->fan[nr][1]); - - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1673,6 +1784,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); int nr = sensor_attr->index; long val; + int err; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2) return -EINVAL; @@ -1683,7 +1795,10 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, return -EINVAL; } - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err;; + it87_update_pwm_ctrl(data, nr); if (val == 0) { @@ -1737,8 +1852,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, data->fan_main_ctrl); } } - - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1749,11 +1863,15 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); int nr = sensor_attr->index; long val; + int err; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + it87_update_pwm_ctrl(data, nr); if (has_newer_autopwm(data)) { /* @@ -1761,8 +1879,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, * is read-only so we can't write the value. */ if (data->pwm_ctrl[nr] & 0x80) { - mutex_unlock(&data->update_lock); - return -EBUSY; + count = -EBUSY; + goto unlock; } data->pwm_duty[nr] = pwm_to_reg(data, val); it87_write_value(data, IT87_REG_PWM_DUTY[nr], @@ -1779,7 +1897,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_ctrl[nr]); } } - mutex_unlock(&data->update_lock); +unlock: + it87_unlock(data); return count; } @@ -1790,6 +1909,7 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, struct it87_data *data = dev_get_drvdata(dev); int nr = sensor_attr->index; unsigned long val; + int err; int i; if (kstrtoul(buf, 10, &val) < 0) @@ -1804,7 +1924,10 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, break; } - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + if (nr == 0) { data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; data->fan_ctl |= i << 4; @@ -1814,8 +1937,7 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, data->extra |= i << 4; it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); } - mutex_unlock(&data->update_lock); - + it87_unlock(data); return count; } @@ -1826,6 +1948,9 @@ static ssize_t show_pwm_temp_map(struct device *dev, struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", data->pwm_temp_map[nr] + 1); } @@ -1837,6 +1962,7 @@ static ssize_t set_pwm_temp_map(struct device *dev, struct it87_data *data = dev_get_drvdata(dev); int nr = sensor_attr->index; unsigned long val; + int err; u8 map; if (kstrtoul(buf, 10, &val) < 0) @@ -1847,7 +1973,10 @@ static ssize_t set_pwm_temp_map(struct device *dev, map = val - 1; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + it87_update_pwm_ctrl(data, nr); data->pwm_temp_map[nr] = map; /* @@ -1858,7 +1987,7 @@ static ssize_t set_pwm_temp_map(struct device *dev, data->pwm_ctrl[nr] = temp_map_to_reg(data, nr, map); it87_write_value(data, data->REG_PWM[nr], data->pwm_ctrl[nr]); } - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1871,6 +2000,9 @@ static ssize_t show_auto_pwm(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->nr; int point = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", pwm_from_reg(data, data->auto_pwm[nr][point])); } @@ -1885,18 +2017,22 @@ static ssize_t set_auto_pwm(struct device *dev, struct device_attribute *attr, int point = sensor_attr->index; int regaddr; long val; + int err; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + data->auto_pwm[nr][point] = pwm_to_reg(data, val); if (has_newer_autopwm(data)) regaddr = IT87_REG_AUTO_TEMP(nr, 3); else regaddr = IT87_REG_AUTO_PWM(nr, point); it87_write_value(data, regaddr, data->auto_pwm[nr][point]); - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1907,6 +2043,9 @@ static ssize_t show_auto_pwm_slope(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", data->auto_pwm[nr][1] & 0x7f); } @@ -1918,15 +2057,19 @@ static ssize_t set_auto_pwm_slope(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; unsigned long val; + int err; if (kstrtoul(buf, 10, &val) < 0 || val > 127) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + data->auto_pwm[nr][1] = (data->auto_pwm[nr][1] & 0x80) | val; it87_write_value(data, IT87_REG_AUTO_TEMP(nr, 4), data->auto_pwm[nr][1]); - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -1940,6 +2083,9 @@ static ssize_t show_auto_temp(struct device *dev, struct device_attribute *attr, int point = sensor_attr->index; int reg; + if (IS_ERR(data)) + return PTR_ERR(data); + if (has_old_autopwm(data) || point) reg = data->auto_temp[nr][point]; else @@ -1958,11 +2104,15 @@ static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr, int point = sensor_attr->index; long val; int reg; + int err; if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + if (has_newer_autopwm(data) && !point) { reg = data->auto_temp[nr][1] - TEMP_TO_REG(val); reg = clamp_val(reg, 0, 0x1f) | (data->auto_temp[nr][0] & 0xe0); @@ -1975,7 +2125,7 @@ static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr, point--; it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), reg); } - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -2160,6 +2310,9 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, { struct it87_data *data = it87_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%u\n", data->alarms); } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); @@ -2170,6 +2323,9 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, struct it87_data *data = it87_update_device(dev); int bitnr = to_sensor_dev_attr(attr)->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); } @@ -2178,24 +2334,22 @@ static ssize_t clear_intrusion(struct device *dev, size_t count) { struct it87_data *data = dev_get_drvdata(dev); - int config; + int err, config; long val; if (kstrtol(buf, 10, &val) < 0 || val != 0) return -EINVAL; - mutex_lock(&data->update_lock); - config = it87_read_value(data, IT87_REG_CONFIG); - if (config < 0) { - count = config; - } else { - config |= BIT(5); - it87_write_value(data, IT87_REG_CONFIG, config); - /* Invalidate cache to force re-read */ - data->valid = 0; - } - mutex_unlock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + config = it87_read_value(data, IT87_REG_CONFIG); + config |= BIT(5); + it87_write_value(data, IT87_REG_CONFIG, config); + /* Invalidate cache to force re-read */ + data->valid = 0; + it87_unlock(data); return count; } @@ -2228,6 +2382,9 @@ static ssize_t show_beep(struct device *dev, struct device_attribute *attr, struct it87_data *data = it87_update_device(dev); int bitnr = to_sensor_dev_attr(attr)->index; + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); } @@ -2237,18 +2394,22 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr, int bitnr = to_sensor_dev_attr(attr)->index; struct it87_data *data = dev_get_drvdata(dev); long val; + int err; if (kstrtol(buf, 10, &val) < 0 || (val != 0 && val != 1)) return -EINVAL; - mutex_lock(&data->update_lock); + err = it87_lock(data); + if (err) + return err; + data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); if (val) data->beeps |= BIT(bitnr); else data->beeps &= ~BIT(bitnr); it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); - mutex_unlock(&data->update_lock); + it87_unlock(data); return count; } @@ -2304,6 +2465,9 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, { struct it87_data *data = it87_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%ld\n", (long)vid_from_reg(data->vid, data->vrm)); } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); @@ -2789,6 +2953,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, if (err) return err; + sio_data->sioaddr = sioaddr; + err = -ENODEV; chip_type = superio_inw(sioaddr, DEVID); if (chip_type == 0xffff) @@ -2905,6 +3071,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, goto exit; } + sio_data->doexit = doexit; + err = 0; sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f; pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, @@ -3237,6 +3405,10 @@ static int __init it87_find(int sioaddr, unsigned short *address, /* Check for pwm2, fan2 */ if (reg29 & BIT(1)) sio_data->skip_pwm |= BIT(1); + /* + * Note: Table 6-1 in datasheet claims that FAN_TAC2 + * would be enabled with 29h[2]=0. + */ if (reg2d & BIT(4)) sio_data->skip_fan |= BIT(1); @@ -3267,7 +3439,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, sio_data->skip_fan |= BIT(3); if (reg26 & BIT(5)) sio_data->skip_pwm |= BIT(4); - if (!(reg26 & BIT(4))) + if (reg26 & BIT(4)) sio_data->skip_fan |= BIT(4); } @@ -3383,6 +3555,15 @@ static int __init it87_find(int sioaddr, unsigned short *address, if (sio_data->beep_pin) pr_info("Beeping is supported\n"); + if (config->smbus_bitmap) { + u8 reg; + + superio_select(sioaddr, PME); + reg = superio_inb(sioaddr, IT87_SPECIAL_CFG_REG); + sio_data->ec_special_config = reg; + sio_data->smbus_bitmap = reg & config->smbus_bitmap; + } + exit: superio_exit(sioaddr, doexit); return err; @@ -3660,6 +3841,7 @@ static int it87_probe(struct platform_device *pdev) struct it87_sio_data *sio_data = dev_get_platdata(dev); int enable_pwm_interface; struct device *hwmon_dev; + int err; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, @@ -3676,6 +3858,10 @@ static int it87_probe(struct platform_device *pdev) data->addr = res->start; data->type = sio_data->type; + data->sioaddr = sio_data->sioaddr; + data->smbus_bitmap = sio_data->smbus_bitmap; + data->ec_special_config = sio_data->ec_special_config; + data->doexit = sio_data->doexit; data->features = it87_devices[sio_data->type].features; data->num_temp_limit = it87_devices[sio_data->type].num_temp_limit; data->num_temp_offset = it87_devices[sio_data->type].num_temp_offset; @@ -3706,11 +3892,6 @@ static int it87_probe(struct platform_device *pdev) break; } - /* Now, we do the remaining detection. */ - if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) || - it87_read_value(data, IT87_REG_CHIPID) != 0x90) - return -ENODEV; - platform_set_drvdata(pdev, data); mutex_init(&data->update_lock); @@ -3718,6 +3899,17 @@ static int it87_probe(struct platform_device *pdev) /* Initialize register pointers */ it87_init_regs(pdev); + err = smbus_disable(data); + if (err) + return err; + + /* Now, we do the remaining detection. */ + if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) || + it87_read_value(data, IT87_REG_CHIPID) != 0x90) { + smbus_enable(data); + return -ENODEV; + } + /* Check PWM configuration */ enable_pwm_interface = it87_check_pwm(dev); @@ -3774,6 +3966,8 @@ static int it87_probe(struct platform_device *pdev) /* Initialize the IT87 chip */ it87_init_device(pdev); + smbus_enable(data); + if (!sio_data->skip_vid) { data->has_vid = true; data->vrm = vid_which_vrm();