aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2012-01-16 16:51:48 -0500
committerJean Delvare <khali@endymion.delvare>2012-01-16 16:51:48 -0500
commit16b5dda22e3798e61bb008d2329d4f4d90ef764e (patch)
treef9b00eb0982045d496835b2ab0e829995c3d94d9
parentd6db23c7ce8d02896197394c1d741bdffe58ac54 (diff)
hwmon: (it87) Add IT8728F support
Until we get a datasheet for the IT8728F, treat it as fully compatible with the IT8721F, as it seems to work reasonably well. This closes kernel bug #27262. Signed-off-by: Jean Delvare <khali@linux-fr.org> Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>
-rw-r--r--Documentation/hwmon/it8713
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/it87.c61
3 files changed, 58 insertions, 20 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 6f496a586732..23b7def21ba8 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -26,6 +26,10 @@ Supported chips:
26 Prefix: 'it8721' 26 Prefix: 'it8721'
27 Addresses scanned: from Super I/O config space (8 I/O ports) 27 Addresses scanned: from Super I/O config space (8 I/O ports)
28 Datasheet: Not publicly available 28 Datasheet: Not publicly available
29 * IT8728F
30 Prefix: 'it8728'
31 Addresses scanned: from Super I/O config space (8 I/O ports)
32 Datasheet: Not publicly available
29 * SiS950 [clone of IT8705F] 33 * SiS950 [clone of IT8705F]
30 Prefix: 'it87' 34 Prefix: 'it87'
31 Addresses scanned: from Super I/O config space (8 I/O ports) 35 Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -71,7 +75,7 @@ Description
71----------- 75-----------
72 76
73This driver implements support for the IT8705F, IT8712F, IT8716F, 77This driver implements support for the IT8705F, IT8712F, IT8716F,
74IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips. 78IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips.
75 79
76These chips are 'Super I/O chips', supporting floppy disks, infrared ports, 80These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
77joysticks and other miscellaneous stuff. For hardware monitoring, they 81joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -105,6 +109,9 @@ The IT8726F is just bit enhanced IT8716F with additional hardware
105for AMD power sequencing. Therefore the chip will appear as IT8716F 109for AMD power sequencing. Therefore the chip will appear as IT8716F
106to userspace applications. 110to userspace applications.
107 111
112The IT8728F is considered compatible with the IT8721F, until a datasheet
113becomes available (hopefully.)
114
108Temperatures are measured in degrees Celsius. An alarm is triggered once 115Temperatures are measured in degrees Celsius. An alarm is triggered once
109when the Overtemperature Shutdown limit is crossed. 116when the Overtemperature Shutdown limit is crossed.
110 117
@@ -121,8 +128,8 @@ alarm is triggered if the voltage has crossed a programmable minimum or
121maximum limit. Note that minimum in this case always means 'closest to 128maximum limit. Note that minimum in this case always means 'closest to
122zero'; this is important for negative voltage measurements. All voltage 129zero'; this is important for negative voltage measurements. All voltage
123inputs can measure voltages between 0 and 4.08 volts, with a resolution of 130inputs can measure voltages between 0 and 4.08 volts, with a resolution of
1240.016 volt (except IT8721F/IT8758E: 0.012 volt.) The battery voltage in8 does 1310.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
125not have limit registers. 132voltage in8 does not have limit registers.
126 133
127On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside 134On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
128the chip (in7, in8 and optionally in3). The driver handles this transparently 135the chip (in7, in8 and optionally in3). The driver handles this transparently
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f468bbb6357a..02260406b9e4 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -474,8 +474,8 @@ config SENSORS_IT87
474 select HWMON_VID 474 select HWMON_VID
475 help 475 help
476 If you say yes here you get support for ITE IT8705F, IT8712F, 476 If you say yes here you get support for ITE IT8705F, IT8712F,
477 IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor 477 IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
478 chips, and the SiS960 clone. 478 sensor chips, and the SiS960 clone.
479 479
480 This driver can also be built as a module. If so, the module 480 This driver can also be built as a module. If so, the module
481 will be called it87. 481 will be called it87.
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 603ef2af2707..0054d6f9cec9 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -17,6 +17,7 @@
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 * IT8721F Super I/O chip w/LPC interface
19 * IT8726F Super I/O chip w/LPC interface 19 * IT8726F Super I/O chip w/LPC interface
20 * IT8728F Super I/O chip w/LPC interface
20 * IT8758E Super I/O chip w/LPC interface 21 * IT8758E Super I/O chip w/LPC interface
21 * Sis950 A clone of the IT8705F 22 * Sis950 A clone of the IT8705F
22 * 23 *
@@ -58,7 +59,7 @@
58 59
59#define DRVNAME "it87" 60#define DRVNAME "it87"
60 61
61enum chips { it87, it8712, it8716, it8718, it8720, it8721 }; 62enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 };
62 63
63static unsigned short force_id; 64static unsigned short force_id;
64module_param(force_id, ushort, 0); 65module_param(force_id, ushort, 0);
@@ -135,6 +136,7 @@ static inline void superio_exit(void)
135#define IT8720F_DEVID 0x8720 136#define IT8720F_DEVID 0x8720
136#define IT8721F_DEVID 0x8721 137#define IT8721F_DEVID 0x8721
137#define IT8726F_DEVID 0x8726 138#define IT8726F_DEVID 0x8726
139#define IT8728F_DEVID 0x8728
138#define IT87_ACT_REG 0x30 140#define IT87_ACT_REG 0x30
139#define IT87_BASE_REG 0x60 141#define IT87_BASE_REG 0x60
140 142
@@ -274,11 +276,31 @@ struct it87_data {
274 s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ 276 s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
275}; 277};
276 278
279static inline int has_12mv_adc(const struct it87_data *data)
280{
281 /*
282 * IT8721F and later have a 12 mV ADC, also with internal scaling
283 * on selected inputs.
284 */
285 return data->type == it8721
286 || data->type == it8728;
287}
288
289static inline int has_newer_autopwm(const struct it87_data *data)
290{
291 /*
292 * IT8721F and later have separate registers for the temperature
293 * mapping and the manual duty cycle.
294 */
295 return data->type == it8721
296 || data->type == it8728;
297}
298
277static u8 in_to_reg(const struct it87_data *data, int nr, long val) 299static u8 in_to_reg(const struct it87_data *data, int nr, long val)
278{ 300{
279 long lsb; 301 long lsb;
280 302
281 if (data->type == it8721) { 303 if (has_12mv_adc(data)) {
282 if (data->in_scaled & (1 << nr)) 304 if (data->in_scaled & (1 << nr))
283 lsb = 24; 305 lsb = 24;
284 else 306 else
@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val)
292 314
293static int in_from_reg(const struct it87_data *data, int nr, int val) 315static int in_from_reg(const struct it87_data *data, int nr, int val)
294{ 316{
295 if (data->type == it8721) { 317 if (has_12mv_adc(data)) {
296 if (data->in_scaled & (1 << nr)) 318 if (data->in_scaled & (1 << nr))
297 return val * 24; 319 return val * 24;
298 else 320 else
@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm)
329 351
330static u8 pwm_to_reg(const struct it87_data *data, long val) 352static u8 pwm_to_reg(const struct it87_data *data, long val)
331{ 353{
332 if (data->type == it8721) 354 if (has_newer_autopwm(data))
333 return val; 355 return val;
334 else 356 else
335 return val >> 1; 357 return val >> 1;
@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val)
337 359
338static int pwm_from_reg(const struct it87_data *data, u8 reg) 360static int pwm_from_reg(const struct it87_data *data, u8 reg)
339{ 361{
340 if (data->type == it8721) 362 if (has_newer_autopwm(data))
341 return reg; 363 return reg;
342 else 364 else
343 return (reg & 0x7f) << 1; 365 return (reg & 0x7f) << 1;
@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data)
374 || data->type == it8716 396 || data->type == it8716
375 || data->type == it8718 397 || data->type == it8718
376 || data->type == it8720 398 || data->type == it8720
377 || data->type == it8721; 399 || data->type == it8721
400 || data->type == it8728;
378} 401}
379 402
380static inline int has_old_autopwm(const struct it87_data *data) 403static inline int has_old_autopwm(const struct it87_data *data)
@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev,
842 data->fan_main_ctrl); 865 data->fan_main_ctrl);
843 } else { 866 } else {
844 if (val == 1) /* Manual mode */ 867 if (val == 1) /* Manual mode */
845 data->pwm_ctrl[nr] = data->type == it8721 ? 868 data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
846 data->pwm_temp_map[nr] : 869 data->pwm_temp_map[nr] :
847 data->pwm_duty[nr]; 870 data->pwm_duty[nr];
848 else /* Automatic mode */ 871 else /* Automatic mode */
@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
870 return -EINVAL; 893 return -EINVAL;
871 894
872 mutex_lock(&data->update_lock); 895 mutex_lock(&data->update_lock);
873 if (data->type == it8721) { 896 if (has_newer_autopwm(data)) {
874 /* If we are in automatic mode, the PWM duty cycle register 897 /* If we are in automatic mode, the PWM duty cycle register
875 * is read-only so we can't write the value */ 898 * is read-only so we can't write the value */
876 if (data->pwm_ctrl[nr] & 0x80) { 899 if (data->pwm_ctrl[nr] & 0x80) {
@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
1311 struct it87_data *data = dev_get_drvdata(dev); 1334 struct it87_data *data = dev_get_drvdata(dev);
1312 int nr = to_sensor_dev_attr(attr)->index; 1335 int nr = to_sensor_dev_attr(attr)->index;
1313 1336
1314 return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr] 1337 return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
1315 : labels[nr]); 1338 : labels[nr]);
1316} 1339}
1317static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); 1340static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
1318static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); 1341static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address,
1605 case IT8721F_DEVID: 1628 case IT8721F_DEVID:
1606 sio_data->type = it8721; 1629 sio_data->type = it8721;
1607 break; 1630 break;
1631 case IT8728F_DEVID:
1632 sio_data->type = it8728;
1633 break;
1608 case 0xffff: /* No device at all */ 1634 case 0xffff: /* No device at all */
1609 goto exit; 1635 goto exit;
1610 default: 1636 default:
@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address,
1646 superio_select(GPIO); 1672 superio_select(GPIO);
1647 1673
1648 reg = superio_inb(IT87_SIO_GPIO3_REG); 1674 reg = superio_inb(IT87_SIO_GPIO3_REG);
1649 if (sio_data->type == it8721) { 1675 if (sio_data->type == it8721 || sio_data->type == it8728) {
1650 /* The IT8721F/IT8758E doesn't have VID pins at all */ 1676 /*
1677 * The IT8721F/IT8758E doesn't have VID pins at all,
1678 * not sure about the IT8728F.
1679 */
1651 sio_data->skip_vid = 1; 1680 sio_data->skip_vid = 1;
1652 } else { 1681 } else {
1653 /* We need at least 4 VID pins */ 1682 /* We need at least 4 VID pins */
@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address,
1692 } 1721 }
1693 if (reg & (1 << 0)) 1722 if (reg & (1 << 0))
1694 sio_data->internal |= (1 << 0); 1723 sio_data->internal |= (1 << 0);
1695 if ((reg & (1 << 1)) || sio_data->type == it8721) 1724 if ((reg & (1 << 1)) || sio_data->type == it8721 ||
1725 sio_data->type == it8728)
1696 sio_data->internal |= (1 << 1); 1726 sio_data->internal |= (1 << 1);
1697 1727
1698 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; 1728 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
1770 "it8718", 1800 "it8718",
1771 "it8720", 1801 "it8720",
1772 "it8721", 1802 "it8721",
1803 "it8728",
1773 }; 1804 };
1774 1805
1775 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 1806 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
1807 enable_pwm_interface = it87_check_pwm(dev); 1838 enable_pwm_interface = it87_check_pwm(dev);
1808 1839
1809 /* Starting with IT8721F, we handle scaling of internal voltages */ 1840 /* Starting with IT8721F, we handle scaling of internal voltages */
1810 if (data->type == it8721) { 1841 if (has_12mv_adc(data)) {
1811 if (sio_data->internal & (1 << 0)) 1842 if (sio_data->internal & (1 << 0))
1812 data->in_scaled |= (1 << 3); /* in3 is AVCC */ 1843 data->in_scaled |= (1 << 3); /* in3 is AVCC */
1813 if (sio_data->internal & (1 << 1)) 1844 if (sio_data->internal & (1 << 1))
@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
2093static void it87_update_pwm_ctrl(struct it87_data *data, int nr) 2124static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
2094{ 2125{
2095 data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); 2126 data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
2096 if (data->type == it8721) { 2127 if (has_newer_autopwm(data)) {
2097 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; 2128 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
2098 data->pwm_duty[nr] = it87_read_value(data, 2129 data->pwm_duty[nr] = it87_read_value(data,
2099 IT87_REG_PWM_DUTY(nr)); 2130 IT87_REG_PWM_DUTY(nr));