diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 116 |
2 files changed, 96 insertions, 24 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index aefb9e6db237..a56f6adf3b76 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -428,8 +428,8 @@ config SENSORS_IT87 | |||
428 | select HWMON_VID | 428 | select HWMON_VID |
429 | help | 429 | help |
430 | If you say yes here you get support for ITE IT8705F, IT8712F, | 430 | If you say yes here you get support for ITE IT8705F, IT8712F, |
431 | IT8716F, IT8718F, IT8720F and IT8726F sensor chips, and the | 431 | IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor |
432 | SiS960 clone. | 432 | chips, and the SiS960 clone. |
433 | 433 | ||
434 | This driver can also be built as a module. If so, the module | 434 | This driver can also be built as a module. If so, the module |
435 | will be called it87. | 435 | will be called it87. |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 7a3616ccbf05..14a5d981be7d 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -15,7 +15,9 @@ | |||
15 | * IT8716F Super I/O chip w/LPC interface | 15 | * IT8716F Super I/O chip w/LPC interface |
16 | * IT8718F Super I/O chip w/LPC interface | 16 | * IT8718F Super I/O chip w/LPC interface |
17 | * IT8720F Super I/O chip w/LPC interface | 17 | * IT8720F Super I/O chip w/LPC interface |
18 | * IT8721F Super I/O chip w/LPC interface | ||
18 | * IT8726F Super I/O chip w/LPC interface | 19 | * IT8726F Super I/O chip w/LPC interface |
20 | * IT8758E Super I/O chip w/LPC interface | ||
19 | * Sis950 A clone of the IT8705F | 21 | * Sis950 A clone of the IT8705F |
20 | * | 22 | * |
21 | * Copyright (C) 2001 Chris Gauthron | 23 | * Copyright (C) 2001 Chris Gauthron |
@@ -54,7 +56,7 @@ | |||
54 | 56 | ||
55 | #define DRVNAME "it87" | 57 | #define DRVNAME "it87" |
56 | 58 | ||
57 | enum chips { it87, it8712, it8716, it8718, it8720 }; | 59 | enum chips { it87, it8712, it8716, it8718, it8720, it8721 }; |
58 | 60 | ||
59 | static unsigned short force_id; | 61 | static unsigned short force_id; |
60 | module_param(force_id, ushort, 0); | 62 | module_param(force_id, ushort, 0); |
@@ -126,6 +128,7 @@ superio_exit(void) | |||
126 | #define IT8716F_DEVID 0x8716 | 128 | #define IT8716F_DEVID 0x8716 |
127 | #define IT8718F_DEVID 0x8718 | 129 | #define IT8718F_DEVID 0x8718 |
128 | #define IT8720F_DEVID 0x8720 | 130 | #define IT8720F_DEVID 0x8720 |
131 | #define IT8721F_DEVID 0x8721 | ||
129 | #define IT8726F_DEVID 0x8726 | 132 | #define IT8726F_DEVID 0x8726 |
130 | #define IT87_ACT_REG 0x30 | 133 | #define IT87_ACT_REG 0x30 |
131 | #define IT87_BASE_REG 0x60 | 134 | #define IT87_BASE_REG 0x60 |
@@ -229,6 +232,7 @@ struct it87_data { | |||
229 | char valid; /* !=0 if following fields are valid */ | 232 | char valid; /* !=0 if following fields are valid */ |
230 | unsigned long last_updated; /* In jiffies */ | 233 | unsigned long last_updated; /* In jiffies */ |
231 | 234 | ||
235 | u16 in_scaled; /* Internal voltage sensors are scaled */ | ||
232 | u8 in[9]; /* Register value */ | 236 | u8 in[9]; /* Register value */ |
233 | u8 in_max[8]; /* Register value */ | 237 | u8 in_max[8]; /* Register value */ |
234 | u8 in_min[8]; /* Register value */ | 238 | u8 in_min[8]; /* Register value */ |
@@ -260,8 +264,32 @@ struct it87_data { | |||
260 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ | 264 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ |
261 | }; | 265 | }; |
262 | 266 | ||
263 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255)) | 267 | static u8 in_to_reg(const struct it87_data *data, int nr, long val) |
264 | #define IN_FROM_REG(val) ((val) * 16) | 268 | { |
269 | long lsb; | ||
270 | |||
271 | if (data->type == it8721) { | ||
272 | if (data->in_scaled & (1 << nr)) | ||
273 | lsb = 24; | ||
274 | else | ||
275 | lsb = 12; | ||
276 | } else | ||
277 | lsb = 16; | ||
278 | |||
279 | val = DIV_ROUND_CLOSEST(val, lsb); | ||
280 | return SENSORS_LIMIT(val, 0, 255); | ||
281 | } | ||
282 | |||
283 | static int in_from_reg(const struct it87_data *data, int nr, int val) | ||
284 | { | ||
285 | if (data->type == it8721) { | ||
286 | if (data->in_scaled & (1 << nr)) | ||
287 | return val * 24; | ||
288 | else | ||
289 | return val * 12; | ||
290 | } else | ||
291 | return val * 16; | ||
292 | } | ||
265 | 293 | ||
266 | static inline u8 FAN_TO_REG(long rpm, int div) | 294 | static inline u8 FAN_TO_REG(long rpm, int div) |
267 | { | 295 | { |
@@ -289,8 +317,22 @@ static inline u16 FAN16_TO_REG(long rpm) | |||
289 | ((val) + 500) / 1000), -128, 127)) | 317 | ((val) + 500) / 1000), -128, 127)) |
290 | #define TEMP_FROM_REG(val) ((val) * 1000) | 318 | #define TEMP_FROM_REG(val) ((val) * 1000) |
291 | 319 | ||
292 | #define PWM_TO_REG(val) ((val) >> 1) | 320 | static u8 pwm_to_reg(const struct it87_data *data, long val) |
293 | #define PWM_FROM_REG(val) (((val) & 0x7f) << 1) | 321 | { |
322 | if (data->type == it8721) | ||
323 | return val; | ||
324 | else | ||
325 | return val >> 1; | ||
326 | } | ||
327 | |||
328 | static int pwm_from_reg(const struct it87_data *data, u8 reg) | ||
329 | { | ||
330 | if (data->type == it8721) | ||
331 | return reg; | ||
332 | else | ||
333 | return (reg & 0x7f) << 1; | ||
334 | } | ||
335 | |||
294 | 336 | ||
295 | static int DIV_TO_REG(int val) | 337 | static int DIV_TO_REG(int val) |
296 | { | 338 | { |
@@ -321,7 +363,8 @@ static inline int has_16bit_fans(const struct it87_data *data) | |||
321 | || (data->type == it8712 && data->revision >= 0x08) | 363 | || (data->type == it8712 && data->revision >= 0x08) |
322 | || data->type == it8716 | 364 | || data->type == it8716 |
323 | || data->type == it8718 | 365 | || data->type == it8718 |
324 | || data->type == it8720; | 366 | || data->type == it8720 |
367 | || data->type == it8721; | ||
325 | } | 368 | } |
326 | 369 | ||
327 | static inline int has_old_autopwm(const struct it87_data *data) | 370 | static inline int has_old_autopwm(const struct it87_data *data) |
@@ -359,7 +402,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, | |||
359 | int nr = sensor_attr->index; | 402 | int nr = sensor_attr->index; |
360 | 403 | ||
361 | struct it87_data *data = it87_update_device(dev); | 404 | struct it87_data *data = it87_update_device(dev); |
362 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); | 405 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr])); |
363 | } | 406 | } |
364 | 407 | ||
365 | static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, | 408 | static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, |
@@ -369,7 +412,7 @@ static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, | |||
369 | int nr = sensor_attr->index; | 412 | int nr = sensor_attr->index; |
370 | 413 | ||
371 | struct it87_data *data = it87_update_device(dev); | 414 | struct it87_data *data = it87_update_device(dev); |
372 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); | 415 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_min[nr])); |
373 | } | 416 | } |
374 | 417 | ||
375 | static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, | 418 | static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, |
@@ -379,7 +422,7 @@ static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, | |||
379 | int nr = sensor_attr->index; | 422 | int nr = sensor_attr->index; |
380 | 423 | ||
381 | struct it87_data *data = it87_update_device(dev); | 424 | struct it87_data *data = it87_update_device(dev); |
382 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); | 425 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_max[nr])); |
383 | } | 426 | } |
384 | 427 | ||
385 | static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | 428 | static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, |
@@ -395,7 +438,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | |||
395 | return -EINVAL; | 438 | return -EINVAL; |
396 | 439 | ||
397 | mutex_lock(&data->update_lock); | 440 | mutex_lock(&data->update_lock); |
398 | data->in_min[nr] = IN_TO_REG(val); | 441 | data->in_min[nr] = in_to_reg(data, nr, val); |
399 | it87_write_value(data, IT87_REG_VIN_MIN(nr), | 442 | it87_write_value(data, IT87_REG_VIN_MIN(nr), |
400 | data->in_min[nr]); | 443 | data->in_min[nr]); |
401 | mutex_unlock(&data->update_lock); | 444 | mutex_unlock(&data->update_lock); |
@@ -414,7 +457,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
414 | return -EINVAL; | 457 | return -EINVAL; |
415 | 458 | ||
416 | mutex_lock(&data->update_lock); | 459 | mutex_lock(&data->update_lock); |
417 | data->in_max[nr] = IN_TO_REG(val); | 460 | data->in_max[nr] = in_to_reg(data, nr, val); |
418 | it87_write_value(data, IT87_REG_VIN_MAX(nr), | 461 | it87_write_value(data, IT87_REG_VIN_MAX(nr), |
419 | data->in_max[nr]); | 462 | data->in_max[nr]); |
420 | mutex_unlock(&data->update_lock); | 463 | mutex_unlock(&data->update_lock); |
@@ -644,7 +687,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
644 | int nr = sensor_attr->index; | 687 | int nr = sensor_attr->index; |
645 | 688 | ||
646 | struct it87_data *data = it87_update_device(dev); | 689 | struct it87_data *data = it87_update_device(dev); |
647 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr])); | 690 | return sprintf(buf, "%d\n", |
691 | pwm_from_reg(data, data->pwm_duty[nr])); | ||
648 | } | 692 | } |
649 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | 693 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, |
650 | char *buf) | 694 | char *buf) |
@@ -814,7 +858,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
814 | return -EINVAL; | 858 | return -EINVAL; |
815 | 859 | ||
816 | mutex_lock(&data->update_lock); | 860 | mutex_lock(&data->update_lock); |
817 | data->pwm_duty[nr] = PWM_TO_REG(val); | 861 | data->pwm_duty[nr] = pwm_to_reg(data, val); |
818 | /* If we are in manual mode, write the duty cycle immediately; | 862 | /* If we are in manual mode, write the duty cycle immediately; |
819 | * otherwise, just store it for later use. */ | 863 | * otherwise, just store it for later use. */ |
820 | if (!(data->pwm_ctrl[nr] & 0x80)) { | 864 | if (!(data->pwm_ctrl[nr] & 0x80)) { |
@@ -918,7 +962,8 @@ static ssize_t show_auto_pwm(struct device *dev, | |||
918 | int nr = sensor_attr->nr; | 962 | int nr = sensor_attr->nr; |
919 | int point = sensor_attr->index; | 963 | int point = sensor_attr->index; |
920 | 964 | ||
921 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point])); | 965 | return sprintf(buf, "%d\n", |
966 | pwm_from_reg(data, data->auto_pwm[nr][point])); | ||
922 | } | 967 | } |
923 | 968 | ||
924 | static ssize_t set_auto_pwm(struct device *dev, | 969 | static ssize_t set_auto_pwm(struct device *dev, |
@@ -935,7 +980,7 @@ static ssize_t set_auto_pwm(struct device *dev, | |||
935 | return -EINVAL; | 980 | return -EINVAL; |
936 | 981 | ||
937 | mutex_lock(&data->update_lock); | 982 | mutex_lock(&data->update_lock); |
938 | data->auto_pwm[nr][point] = PWM_TO_REG(val); | 983 | data->auto_pwm[nr][point] = pwm_to_reg(data, val); |
939 | it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), | 984 | it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), |
940 | data->auto_pwm[nr][point]); | 985 | data->auto_pwm[nr][point]); |
941 | mutex_unlock(&data->update_lock); | 986 | mutex_unlock(&data->update_lock); |
@@ -1205,9 +1250,16 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr, | |||
1205 | "5VSB", | 1250 | "5VSB", |
1206 | "Vbat", | 1251 | "Vbat", |
1207 | }; | 1252 | }; |
1253 | static const char *labels_it8721[] = { | ||
1254 | "+3.3V", | ||
1255 | "3VSB", | ||
1256 | "Vbat", | ||
1257 | }; | ||
1258 | struct it87_data *data = dev_get_drvdata(dev); | ||
1208 | int nr = to_sensor_dev_attr(attr)->index; | 1259 | int nr = to_sensor_dev_attr(attr)->index; |
1209 | 1260 | ||
1210 | return sprintf(buf, "%s\n", labels[nr]); | 1261 | return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr] |
1262 | : labels[nr]); | ||
1211 | } | 1263 | } |
1212 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); | 1264 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); |
1213 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); | 1265 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); |
@@ -1492,6 +1544,9 @@ static int __init it87_find(unsigned short *address, | |||
1492 | case IT8720F_DEVID: | 1544 | case IT8720F_DEVID: |
1493 | sio_data->type = it8720; | 1545 | sio_data->type = it8720; |
1494 | break; | 1546 | break; |
1547 | case IT8721F_DEVID: | ||
1548 | sio_data->type = it8721; | ||
1549 | break; | ||
1495 | case 0xffff: /* No device at all */ | 1550 | case 0xffff: /* No device at all */ |
1496 | goto exit; | 1551 | goto exit; |
1497 | default: | 1552 | default: |
@@ -1532,11 +1587,17 @@ static int __init it87_find(unsigned short *address, | |||
1532 | int reg; | 1587 | int reg; |
1533 | 1588 | ||
1534 | superio_select(GPIO); | 1589 | superio_select(GPIO); |
1535 | /* We need at least 4 VID pins */ | 1590 | |
1536 | reg = superio_inb(IT87_SIO_GPIO3_REG); | 1591 | reg = superio_inb(IT87_SIO_GPIO3_REG); |
1537 | if (reg & 0x0f) { | 1592 | if (sio_data->type == it8721) { |
1538 | pr_info("it87: VID is disabled (pins used for GPIO)\n"); | 1593 | /* The IT8721F/IT8758E doesn't have VID pins at all */ |
1539 | sio_data->skip_vid = 1; | 1594 | sio_data->skip_vid = 1; |
1595 | } else { | ||
1596 | /* We need at least 4 VID pins */ | ||
1597 | if (reg & 0x0f) { | ||
1598 | pr_info("it87: VID is disabled (pins used for GPIO)\n"); | ||
1599 | sio_data->skip_vid = 1; | ||
1600 | } | ||
1540 | } | 1601 | } |
1541 | 1602 | ||
1542 | /* Check if fan3 is there or not */ | 1603 | /* Check if fan3 is there or not */ |
@@ -1574,7 +1635,7 @@ static int __init it87_find(unsigned short *address, | |||
1574 | } | 1635 | } |
1575 | if (reg & (1 << 0)) | 1636 | if (reg & (1 << 0)) |
1576 | sio_data->internal |= (1 << 0); | 1637 | sio_data->internal |= (1 << 0); |
1577 | if (reg & (1 << 1)) | 1638 | if ((reg & (1 << 1)) || sio_data->type == it8721) |
1578 | sio_data->internal |= (1 << 1); | 1639 | sio_data->internal |= (1 << 1); |
1579 | 1640 | ||
1580 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 1641 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; |
@@ -1652,6 +1713,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1652 | "it8716", | 1713 | "it8716", |
1653 | "it8718", | 1714 | "it8718", |
1654 | "it8720", | 1715 | "it8720", |
1716 | "it8721", | ||
1655 | }; | 1717 | }; |
1656 | 1718 | ||
1657 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1719 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
@@ -1688,6 +1750,16 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1688 | /* Check PWM configuration */ | 1750 | /* Check PWM configuration */ |
1689 | enable_pwm_interface = it87_check_pwm(dev); | 1751 | enable_pwm_interface = it87_check_pwm(dev); |
1690 | 1752 | ||
1753 | /* Starting with IT8721F, we handle scaling of internal voltages */ | ||
1754 | if (data->type == it8721) { | ||
1755 | if (sio_data->internal & (1 << 0)) | ||
1756 | data->in_scaled |= (1 << 3); /* in3 is AVCC */ | ||
1757 | if (sio_data->internal & (1 << 1)) | ||
1758 | data->in_scaled |= (1 << 7); /* in7 is VSB */ | ||
1759 | if (sio_data->internal & (1 << 2)) | ||
1760 | data->in_scaled |= (1 << 8); /* in8 is Vbat */ | ||
1761 | } | ||
1762 | |||
1691 | /* Initialize the IT87 chip */ | 1763 | /* Initialize the IT87 chip */ |
1692 | it87_init_device(pdev); | 1764 | it87_init_device(pdev); |
1693 | 1765 | ||
@@ -2053,7 +2125,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
2053 | 2125 | ||
2054 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 2126 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
2055 | /* The 8705 does not have VID capability. | 2127 | /* The 8705 does not have VID capability. |
2056 | The 8718 and the 8720 don't use IT87_REG_VID for the | 2128 | The 8718 and later don't use IT87_REG_VID for the |
2057 | same purpose. */ | 2129 | same purpose. */ |
2058 | if (data->type == it8712 || data->type == it8716) { | 2130 | if (data->type == it8712 || data->type == it8716) { |
2059 | data->vid = it87_read_value(data, IT87_REG_VID); | 2131 | data->vid = it87_read_value(data, IT87_REG_VID); |
@@ -2153,7 +2225,7 @@ static void __exit sm_it87_exit(void) | |||
2153 | 2225 | ||
2154 | MODULE_AUTHOR("Chris Gauthron, " | 2226 | MODULE_AUTHOR("Chris Gauthron, " |
2155 | "Jean Delvare <khali@linux-fr.org>"); | 2227 | "Jean Delvare <khali@linux-fr.org>"); |
2156 | MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver"); | 2228 | MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver"); |
2157 | module_param(update_vbat, bool, 0); | 2229 | module_param(update_vbat, bool, 0); |
2158 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 2230 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
2159 | module_param(fix_pwm_polarity, bool, 0); | 2231 | module_param(fix_pwm_polarity, bool, 0); |