diff options
| -rw-r--r-- | drivers/hwmon/it87.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 3827aa9aa11e..117d66fcded6 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -231,7 +231,8 @@ static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; | |||
| 231 | struct it87_devices { | 231 | struct it87_devices { |
| 232 | const char *name; | 232 | const char *name; |
| 233 | u16 features; | 233 | u16 features; |
| 234 | u16 peci_mask; | 234 | u8 peci_mask; |
| 235 | u8 old_peci_mask; | ||
| 235 | }; | 236 | }; |
| 236 | 237 | ||
| 237 | #define FEAT_12MV_ADC (1 << 0) | 238 | #define FEAT_12MV_ADC (1 << 0) |
| @@ -240,6 +241,7 @@ struct it87_devices { | |||
| 240 | #define FEAT_16BIT_FANS (1 << 3) | 241 | #define FEAT_16BIT_FANS (1 << 3) |
| 241 | #define FEAT_TEMP_OFFSET (1 << 4) | 242 | #define FEAT_TEMP_OFFSET (1 << 4) |
| 242 | #define FEAT_TEMP_PECI (1 << 5) | 243 | #define FEAT_TEMP_PECI (1 << 5) |
| 244 | #define FEAT_TEMP_OLD_PECI (1 << 6) | ||
| 243 | 245 | ||
| 244 | static const struct it87_devices it87_devices[] = { | 246 | static const struct it87_devices it87_devices[] = { |
| 245 | [it87] = { | 247 | [it87] = { |
| @@ -256,17 +258,22 @@ static const struct it87_devices it87_devices[] = { | |||
| 256 | }, | 258 | }, |
| 257 | [it8718] = { | 259 | [it8718] = { |
| 258 | .name = "it8718", | 260 | .name = "it8718", |
| 259 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | 261 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET |
| 262 | | FEAT_TEMP_OLD_PECI, | ||
| 263 | .old_peci_mask = 0x4, | ||
| 260 | }, | 264 | }, |
| 261 | [it8720] = { | 265 | [it8720] = { |
| 262 | .name = "it8720", | 266 | .name = "it8720", |
| 263 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | 267 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET |
| 268 | | FEAT_TEMP_OLD_PECI, | ||
| 269 | .old_peci_mask = 0x4, | ||
| 264 | }, | 270 | }, |
| 265 | [it8721] = { | 271 | [it8721] = { |
| 266 | .name = "it8721", | 272 | .name = "it8721", |
| 267 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | 273 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS |
| 268 | | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI, | 274 | | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI, |
| 269 | .peci_mask = 0x05, | 275 | .peci_mask = 0x05, |
| 276 | .old_peci_mask = 0x02, /* Actually reports PCH */ | ||
| 270 | }, | 277 | }, |
| 271 | [it8728] = { | 278 | [it8728] = { |
| 272 | .name = "it8728", | 279 | .name = "it8728", |
| @@ -276,11 +283,15 @@ static const struct it87_devices it87_devices[] = { | |||
| 276 | }, | 283 | }, |
| 277 | [it8782] = { | 284 | [it8782] = { |
| 278 | .name = "it8782", | 285 | .name = "it8782", |
| 279 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | 286 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET |
| 287 | | FEAT_TEMP_OLD_PECI, | ||
| 288 | .old_peci_mask = 0x4, | ||
| 280 | }, | 289 | }, |
| 281 | [it8783] = { | 290 | [it8783] = { |
| 282 | .name = "it8783", | 291 | .name = "it8783", |
| 283 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | 292 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET |
| 293 | | FEAT_TEMP_OLD_PECI, | ||
| 294 | .old_peci_mask = 0x4, | ||
| 284 | }, | 295 | }, |
| 285 | }; | 296 | }; |
| 286 | 297 | ||
| @@ -291,6 +302,9 @@ static const struct it87_devices it87_devices[] = { | |||
| 291 | #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) | 302 | #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) |
| 292 | #define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \ | 303 | #define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \ |
| 293 | ((data)->peci_mask & (1 << nr))) | 304 | ((data)->peci_mask & (1 << nr))) |
| 305 | #define has_temp_old_peci(data, nr) \ | ||
| 306 | (((data)->features & FEAT_TEMP_OLD_PECI) && \ | ||
| 307 | ((data)->old_peci_mask & (1 << nr))) | ||
| 294 | 308 | ||
| 295 | struct it87_sio_data { | 309 | struct it87_sio_data { |
| 296 | enum chips type; | 310 | enum chips type; |
| @@ -315,7 +329,8 @@ struct it87_data { | |||
| 315 | struct device *hwmon_dev; | 329 | struct device *hwmon_dev; |
| 316 | enum chips type; | 330 | enum chips type; |
| 317 | u16 features; | 331 | u16 features; |
| 318 | u16 peci_mask; | 332 | u8 peci_mask; |
| 333 | u8 old_peci_mask; | ||
| 319 | 334 | ||
| 320 | unsigned short addr; | 335 | unsigned short addr; |
| 321 | const char *name; | 336 | const char *name; |
| @@ -329,7 +344,8 @@ struct it87_data { | |||
| 329 | u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */ | 344 | u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */ |
| 330 | u8 has_temp; /* Bitfield, temp sensors enabled */ | 345 | u8 has_temp; /* Bitfield, temp sensors enabled */ |
| 331 | s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ | 346 | s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ |
| 332 | u8 sensor; /* Register value */ | 347 | u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */ |
| 348 | u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */ | ||
| 333 | u8 fan_div[3]; /* Register encoding, shifted right */ | 349 | u8 fan_div[3]; /* Register encoding, shifted right */ |
| 334 | u8 vid; /* Register encoding, combined */ | 350 | u8 vid; /* Register encoding, combined */ |
| 335 | u8 vrm; | 351 | u8 vrm; |
| @@ -623,8 +639,10 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, | |||
| 623 | int nr = sensor_attr->index; | 639 | int nr = sensor_attr->index; |
| 624 | struct it87_data *data = it87_update_device(dev); | 640 | struct it87_data *data = it87_update_device(dev); |
| 625 | u8 reg = data->sensor; /* In case value is updated while used */ | 641 | u8 reg = data->sensor; /* In case value is updated while used */ |
| 642 | u8 extra = data->extra; | ||
| 626 | 643 | ||
| 627 | if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) | 644 | if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) |
| 645 | || (has_temp_old_peci(data, nr) && (extra & 0x80))) | ||
| 628 | return sprintf(buf, "6\n"); /* Intel PECI */ | 646 | return sprintf(buf, "6\n"); /* Intel PECI */ |
| 629 | if (reg & (1 << nr)) | 647 | if (reg & (1 << nr)) |
| 630 | return sprintf(buf, "3\n"); /* thermal diode */ | 648 | return sprintf(buf, "3\n"); /* thermal diode */ |
| @@ -641,7 +659,7 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, | |||
| 641 | 659 | ||
| 642 | struct it87_data *data = dev_get_drvdata(dev); | 660 | struct it87_data *data = dev_get_drvdata(dev); |
| 643 | long val; | 661 | long val; |
| 644 | u8 reg; | 662 | u8 reg, extra; |
| 645 | 663 | ||
| 646 | if (kstrtol(buf, 10, &val) < 0) | 664 | if (kstrtol(buf, 10, &val) < 0) |
| 647 | return -EINVAL; | 665 | return -EINVAL; |
| @@ -651,6 +669,9 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, | |||
| 651 | reg &= ~(8 << nr); | 669 | reg &= ~(8 << nr); |
| 652 | if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1 || val == 6)) | 670 | if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1 || val == 6)) |
| 653 | reg &= 0x3f; | 671 | reg &= 0x3f; |
| 672 | extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); | ||
| 673 | if (has_temp_old_peci(data, nr) && ((extra & 0x80) || val == 6)) | ||
| 674 | extra &= 0x7f; | ||
| 654 | if (val == 2) { /* backwards compatibility */ | 675 | if (val == 2) { /* backwards compatibility */ |
| 655 | dev_warn(dev, | 676 | dev_warn(dev, |
| 656 | "Sensor type 2 is deprecated, please use 4 instead\n"); | 677 | "Sensor type 2 is deprecated, please use 4 instead\n"); |
| @@ -663,12 +684,17 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, | |||
| 663 | reg |= 8 << nr; | 684 | reg |= 8 << nr; |
| 664 | else if (has_temp_peci(data, nr) && val == 6) | 685 | else if (has_temp_peci(data, nr) && val == 6) |
| 665 | reg |= (nr + 1) << 6; | 686 | reg |= (nr + 1) << 6; |
| 687 | else if (has_temp_old_peci(data, nr) && val == 6) | ||
| 688 | extra |= 0x80; | ||
| 666 | else if (val != 0) | 689 | else if (val != 0) |
| 667 | return -EINVAL; | 690 | return -EINVAL; |
| 668 | 691 | ||
| 669 | mutex_lock(&data->update_lock); | 692 | mutex_lock(&data->update_lock); |
| 670 | data->sensor = reg; | 693 | data->sensor = reg; |
| 694 | data->extra = extra; | ||
| 671 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); | 695 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); |
| 696 | if (has_temp_old_peci(data, nr)) | ||
| 697 | it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); | ||
| 672 | data->valid = 0; /* Force cache refresh */ | 698 | data->valid = 0; /* Force cache refresh */ |
| 673 | mutex_unlock(&data->update_lock); | 699 | mutex_unlock(&data->update_lock); |
| 674 | return count; | 700 | return count; |
| @@ -1980,6 +2006,7 @@ static int it87_probe(struct platform_device *pdev) | |||
| 1980 | data->type = sio_data->type; | 2006 | data->type = sio_data->type; |
| 1981 | data->features = it87_devices[sio_data->type].features; | 2007 | data->features = it87_devices[sio_data->type].features; |
| 1982 | data->peci_mask = it87_devices[sio_data->type].peci_mask; | 2008 | data->peci_mask = it87_devices[sio_data->type].peci_mask; |
| 2009 | data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask; | ||
| 1983 | data->name = it87_devices[sio_data->type].name; | 2010 | data->name = it87_devices[sio_data->type].name; |
| 1984 | /* | 2011 | /* |
| 1985 | * IT8705F Datasheet 0.4.1, 3h == Version G. | 2012 | * IT8705F Datasheet 0.4.1, 3h == Version G. |
| @@ -2461,6 +2488,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 2461 | it87_update_pwm_ctrl(data, i); | 2488 | it87_update_pwm_ctrl(data, i); |
| 2462 | 2489 | ||
| 2463 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 2490 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
| 2491 | data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); | ||
| 2464 | /* | 2492 | /* |
| 2465 | * The IT8705F does not have VID capability. | 2493 | * The IT8705F does not have VID capability. |
| 2466 | * The IT8718F and later don't use IT87_REG_VID for the | 2494 | * The IT8718F and later don't use IT87_REG_VID for the |
