Commit c145d5c628c8ca02dabbf6829ae19ce525d42796
Committed by
Jean Delvare
1 parent
d8ec26d7f8
Exists in
master
and in
16 other branches
hwmon: (it87) Add support for the ITE IT8603E
Add support for IT8603E. This closes bug #57861: https://bugzilla.kernel.org/show_bug.cgi?id=57861 [JD: Fixes and clean-ups.] Signed-off-by: Rudolf Marek <r.marek@assembler.cz> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Showing 3 changed files with 106 additions and 28 deletions Side-by-side Diff
Documentation/hwmon/it87
... | ... | @@ -2,6 +2,10 @@ |
2 | 2 | ================== |
3 | 3 | |
4 | 4 | Supported chips: |
5 | + * IT8603E | |
6 | + Prefix: 'it8603' | |
7 | + Addresses scanned: from Super I/O config space (8 I/O ports) | |
8 | + Datasheet: Not publicly available | |
5 | 9 | * IT8705F |
6 | 10 | Prefix: 'it87' |
7 | 11 | Addresses scanned: from Super I/O config space (8 I/O ports) |
... | ... | @@ -90,7 +94,7 @@ |
90 | 94 | Description |
91 | 95 | ----------- |
92 | 96 | |
93 | -This driver implements support for the IT8705F, IT8712F, IT8716F, | |
97 | +This driver implements support for the IT8603E, IT8705F, IT8712F, IT8716F, | |
94 | 98 | IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8771E, IT8772E, |
95 | 99 | IT8782F, IT8783E/F, and SiS950 chips. |
96 | 100 | |
... | ... | @@ -129,6 +133,10 @@ |
129 | 133 | The IT8728F, IT8771E, and IT8772E are considered compatible with the IT8721F, |
130 | 134 | until a datasheet becomes available (hopefully.) |
131 | 135 | |
136 | +The IT8603E is a custom design, hardware monitoring part is similar to | |
137 | +IT8728F. It only supports 16-bit fan mode, the full speed mode of the | |
138 | +fan is not supported (value 0 of pwmX_enable). | |
139 | + | |
132 | 140 | Temperatures are measured in degrees Celsius. An alarm is triggered once |
133 | 141 | when the Overtemperature Shutdown limit is crossed. |
134 | 142 | |
135 | 143 | |
... | ... | @@ -145,13 +153,16 @@ |
145 | 153 | maximum limit. Note that minimum in this case always means 'closest to |
146 | 154 | zero'; this is important for negative voltage measurements. All voltage |
147 | 155 | inputs can measure voltages between 0 and 4.08 volts, with a resolution of |
148 | -0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery | |
149 | -voltage in8 does not have limit registers. | |
156 | +0.016 volt (except IT8603E, IT8721F/IT8758E and IT8728F: 0.012 volt.) The | |
157 | +battery voltage in8 does not have limit registers. | |
150 | 158 | |
151 | -On the IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs are | |
152 | -internal and scaled inside the chip (in7 (optional for IT8782F and IT8783E/F), | |
153 | -in8 and optionally in3). The driver handles this transparently so user-space | |
154 | -doesn't have to care. | |
159 | +On the IT8603E, IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs | |
160 | +are internal and scaled inside the chip: | |
161 | +* in3 (optional) | |
162 | +* in7 (optional for IT8782F and IT8783E/F) | |
163 | +* in8 (always) | |
164 | +* in9 (relevant for IT8603E only) | |
165 | +The driver handles this transparently so user-space doesn't have to care. | |
155 | 166 | |
156 | 167 | The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value: |
157 | 168 | the voltage level your processor should work with. This is hardcoded by |
drivers/hwmon/Kconfig
... | ... | @@ -573,8 +573,8 @@ |
573 | 573 | help |
574 | 574 | If you say yes here you get support for ITE IT8705F, IT8712F, |
575 | 575 | IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, |
576 | - IT8771E, IT8772E, IT8782F, and IT8783E/F sensor chips, and the | |
577 | - SiS950 clone. | |
576 | + IT8771E, IT8772E, IT8782F, IT8783E/F and IT8603E sensor chips, | |
577 | + and the SiS950 clone. | |
578 | 578 | |
579 | 579 | This driver can also be built as a module. If so, the module |
580 | 580 | will be called it87. |
drivers/hwmon/it87.c
... | ... | @@ -10,7 +10,8 @@ |
10 | 10 | * This driver supports only the Environment Controller in the IT8705F and |
11 | 11 | * similar parts. The other devices are supported by different drivers. |
12 | 12 | * |
13 | - * Supports: IT8705F Super I/O chip w/LPC interface | |
13 | + * Supports: IT8603E Super I/O chip w/LPC interface | |
14 | + * IT8705F Super I/O chip w/LPC interface | |
14 | 15 | * IT8712F Super I/O chip w/LPC interface |
15 | 16 | * IT8716F Super I/O chip w/LPC interface |
16 | 17 | * IT8718F Super I/O chip w/LPC interface |
... | ... | @@ -64,7 +65,7 @@ |
64 | 65 | #define DRVNAME "it87" |
65 | 66 | |
66 | 67 | enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771, |
67 | - it8772, it8782, it8783 }; | |
68 | + it8772, it8782, it8783, it8603 }; | |
68 | 69 | |
69 | 70 | static unsigned short force_id; |
70 | 71 | module_param(force_id, ushort, 0); |
... | ... | @@ -146,6 +147,7 @@ |
146 | 147 | #define IT8772E_DEVID 0x8772 |
147 | 148 | #define IT8782F_DEVID 0x8782 |
148 | 149 | #define IT8783E_DEVID 0x8783 |
150 | +#define IT8306E_DEVID 0x8603 | |
149 | 151 | #define IT87_ACT_REG 0x30 |
150 | 152 | #define IT87_BASE_REG 0x60 |
151 | 153 | |
... | ... | @@ -315,6 +317,12 @@ |
315 | 317 | | FEAT_TEMP_OLD_PECI, |
316 | 318 | .old_peci_mask = 0x4, |
317 | 319 | }, |
320 | + [it8603] = { | |
321 | + .name = "it8603", | |
322 | + .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | |
323 | + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI, | |
324 | + .peci_mask = 0x07, | |
325 | + }, | |
318 | 326 | }; |
319 | 327 | |
320 | 328 | #define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS) |
... | ... | @@ -361,7 +369,7 @@ |
361 | 369 | unsigned long last_updated; /* In jiffies */ |
362 | 370 | |
363 | 371 | u16 in_scaled; /* Internal voltage sensors are scaled */ |
364 | - u8 in[9][3]; /* [nr][0]=in, [1]=min, [2]=max */ | |
372 | + u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */ | |
365 | 373 | u8 has_fan; /* Bitfield, fans enabled */ |
366 | 374 | u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */ |
367 | 375 | u8 has_temp; /* Bitfield, temp sensors enabled */ |
... | ... | @@ -578,6 +586,7 @@ |
578 | 586 | 7, 2); |
579 | 587 | |
580 | 588 | static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0); |
589 | +static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0); | |
581 | 590 | |
582 | 591 | /* 3 temperatures */ |
583 | 592 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, |
... | ... | @@ -734,7 +743,7 @@ |
734 | 743 | { |
735 | 744 | int ctrl = data->fan_main_ctrl & (1 << nr); |
736 | 745 | |
737 | - if (ctrl == 0) /* Full speed */ | |
746 | + if (ctrl == 0 && data->type != it8603) /* Full speed */ | |
738 | 747 | return 0; |
739 | 748 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ |
740 | 749 | return 2; |
... | ... | @@ -929,6 +938,10 @@ |
929 | 938 | return -EINVAL; |
930 | 939 | } |
931 | 940 | |
941 | + /* IT8603E does not have on/off mode */ | |
942 | + if (val == 0 && data->type == it8603) | |
943 | + return -EINVAL; | |
944 | + | |
932 | 945 | mutex_lock(&data->update_lock); |
933 | 946 | |
934 | 947 | if (val == 0) { |
... | ... | @@ -948,10 +961,13 @@ |
948 | 961 | else /* Automatic mode */ |
949 | 962 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; |
950 | 963 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); |
951 | - /* set SmartGuardian mode */ | |
952 | - data->fan_main_ctrl |= (1 << nr); | |
953 | - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, | |
954 | - data->fan_main_ctrl); | |
964 | + | |
965 | + if (data->type != it8603) { | |
966 | + /* set SmartGuardian mode */ | |
967 | + data->fan_main_ctrl |= (1 << nr); | |
968 | + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, | |
969 | + data->fan_main_ctrl); | |
970 | + } | |
955 | 971 | } |
956 | 972 | |
957 | 973 | mutex_unlock(&data->update_lock); |
... | ... | @@ -1415,6 +1431,8 @@ |
1415 | 1431 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); |
1416 | 1432 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); |
1417 | 1433 | static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); |
1434 | +/* special AVCC3 IT8306E in9 */ | |
1435 | +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0); | |
1418 | 1436 | |
1419 | 1437 | static ssize_t show_name(struct device *dev, struct device_attribute |
1420 | 1438 | *devattr, char *buf) |
... | ... | @@ -1424,7 +1442,7 @@ |
1424 | 1442 | } |
1425 | 1443 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
1426 | 1444 | |
1427 | -static struct attribute *it87_attributes_in[9][5] = { | |
1445 | +static struct attribute *it87_attributes_in[10][5] = { | |
1428 | 1446 | { |
1429 | 1447 | &sensor_dev_attr_in0_input.dev_attr.attr, |
1430 | 1448 | &sensor_dev_attr_in0_min.dev_attr.attr, |
1431 | 1449 | |
... | ... | @@ -1476,9 +1494,12 @@ |
1476 | 1494 | }, { |
1477 | 1495 | &sensor_dev_attr_in8_input.dev_attr.attr, |
1478 | 1496 | NULL |
1497 | +}, { | |
1498 | + &sensor_dev_attr_in9_input.dev_attr.attr, | |
1499 | + NULL | |
1479 | 1500 | } }; |
1480 | 1501 | |
1481 | -static const struct attribute_group it87_group_in[9] = { | |
1502 | +static const struct attribute_group it87_group_in[10] = { | |
1482 | 1503 | { .attrs = it87_attributes_in[0] }, |
1483 | 1504 | { .attrs = it87_attributes_in[1] }, |
1484 | 1505 | { .attrs = it87_attributes_in[2] }, |
... | ... | @@ -1488,6 +1509,7 @@ |
1488 | 1509 | { .attrs = it87_attributes_in[6] }, |
1489 | 1510 | { .attrs = it87_attributes_in[7] }, |
1490 | 1511 | { .attrs = it87_attributes_in[8] }, |
1512 | + { .attrs = it87_attributes_in[9] }, | |
1491 | 1513 | }; |
1492 | 1514 | |
1493 | 1515 | static struct attribute *it87_attributes_temp[3][6] = { |
... | ... | @@ -1546,7 +1568,8 @@ |
1546 | 1568 | &sensor_dev_attr_in5_beep.dev_attr.attr, |
1547 | 1569 | &sensor_dev_attr_in6_beep.dev_attr.attr, |
1548 | 1570 | &sensor_dev_attr_in7_beep.dev_attr.attr, |
1549 | - NULL | |
1571 | + NULL, | |
1572 | + NULL, | |
1550 | 1573 | }; |
1551 | 1574 | |
1552 | 1575 | static struct attribute *it87_attributes_temp_beep[] = { |
... | ... | @@ -1685,6 +1708,7 @@ |
1685 | 1708 | &sensor_dev_attr_in3_label.dev_attr.attr, |
1686 | 1709 | &sensor_dev_attr_in7_label.dev_attr.attr, |
1687 | 1710 | &sensor_dev_attr_in8_label.dev_attr.attr, |
1711 | + &sensor_dev_attr_in9_label.dev_attr.attr, | |
1688 | 1712 | NULL |
1689 | 1713 | }; |
1690 | 1714 | |
... | ... | @@ -1742,6 +1766,9 @@ |
1742 | 1766 | case IT8783E_DEVID: |
1743 | 1767 | sio_data->type = it8783; |
1744 | 1768 | break; |
1769 | + case IT8306E_DEVID: | |
1770 | + sio_data->type = it8603; | |
1771 | + break; | |
1745 | 1772 | case 0xffff: /* No device at all */ |
1746 | 1773 | goto exit; |
1747 | 1774 | default: |
1748 | 1775 | |
... | ... | @@ -1763,11 +1790,15 @@ |
1763 | 1790 | |
1764 | 1791 | err = 0; |
1765 | 1792 | sio_data->revision = superio_inb(DEVREV) & 0x0f; |
1766 | - pr_info("Found IT%04xF chip at 0x%x, revision %d\n", | |
1767 | - chip_type, *address, sio_data->revision); | |
1793 | + pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type, | |
1794 | + chip_type == 0x8603 ? 'E' : 'F', *address, | |
1795 | + sio_data->revision); | |
1768 | 1796 | |
1769 | 1797 | /* in8 (Vbat) is always internal */ |
1770 | 1798 | sio_data->internal = (1 << 2); |
1799 | + /* Only the IT8603E has in9 */ | |
1800 | + if (sio_data->type != it8603) | |
1801 | + sio_data->skip_in |= (1 << 9); | |
1771 | 1802 | |
1772 | 1803 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ |
1773 | 1804 | if (sio_data->type == it87) { |
1774 | 1805 | |
... | ... | @@ -1844,7 +1875,38 @@ |
1844 | 1875 | sio_data->internal |= (1 << 1); |
1845 | 1876 | |
1846 | 1877 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; |
1878 | + } else if (sio_data->type == it8603) { | |
1879 | + int reg27, reg29; | |
1847 | 1880 | |
1881 | + sio_data->skip_vid = 1; /* No VID */ | |
1882 | + superio_select(GPIO); | |
1883 | + | |
1884 | + reg27 = superio_inb(IT87_SIO_GPIO3_REG); | |
1885 | + | |
1886 | + /* Check if fan3 is there or not */ | |
1887 | + if (reg27 & (1 << 6)) | |
1888 | + sio_data->skip_pwm |= (1 << 2); | |
1889 | + if (reg27 & (1 << 7)) | |
1890 | + sio_data->skip_fan |= (1 << 2); | |
1891 | + | |
1892 | + /* Check if fan2 is there or not */ | |
1893 | + reg29 = superio_inb(IT87_SIO_GPIO5_REG); | |
1894 | + if (reg29 & (1 << 1)) | |
1895 | + sio_data->skip_pwm |= (1 << 1); | |
1896 | + if (reg29 & (1 << 2)) | |
1897 | + sio_data->skip_fan |= (1 << 1); | |
1898 | + | |
1899 | + sio_data->skip_in |= (1 << 5); /* No VIN5 */ | |
1900 | + sio_data->skip_in |= (1 << 6); /* No VIN6 */ | |
1901 | + | |
1902 | + /* no fan4 */ | |
1903 | + sio_data->skip_pwm |= (1 << 3); | |
1904 | + sio_data->skip_fan |= (1 << 3); | |
1905 | + | |
1906 | + sio_data->internal |= (1 << 1); /* in7 is VSB */ | |
1907 | + sio_data->internal |= (1 << 3); /* in9 is AVCC */ | |
1908 | + | |
1909 | + sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | |
1848 | 1910 | } else { |
1849 | 1911 | int reg; |
1850 | 1912 | bool uart6; |
... | ... | @@ -1966,7 +2028,7 @@ |
1966 | 2028 | int i; |
1967 | 2029 | |
1968 | 2030 | sysfs_remove_group(&dev->kobj, &it87_group); |
1969 | - for (i = 0; i < 9; i++) { | |
2031 | + for (i = 0; i < 10; i++) { | |
1970 | 2032 | if (sio_data->skip_in & (1 << i)) |
1971 | 2033 | continue; |
1972 | 2034 | sysfs_remove_group(&dev->kobj, &it87_group_in[i]); |
... | ... | @@ -2080,6 +2142,8 @@ |
2080 | 2142 | data->in_scaled |= (1 << 7); /* in7 is VSB */ |
2081 | 2143 | if (sio_data->internal & (1 << 2)) |
2082 | 2144 | data->in_scaled |= (1 << 8); /* in8 is Vbat */ |
2145 | + if (sio_data->internal & (1 << 3)) | |
2146 | + data->in_scaled |= (1 << 9); /* in9 is AVCC */ | |
2083 | 2147 | } else if (sio_data->type == it8782 || sio_data->type == it8783) { |
2084 | 2148 | if (sio_data->internal & (1 << 0)) |
2085 | 2149 | data->in_scaled |= (1 << 3); /* in3 is VCC5V */ |
... | ... | @@ -2102,7 +2166,7 @@ |
2102 | 2166 | if (err) |
2103 | 2167 | return err; |
2104 | 2168 | |
2105 | - for (i = 0; i < 9; i++) { | |
2169 | + for (i = 0; i < 10; i++) { | |
2106 | 2170 | if (sio_data->skip_in & (1 << i)) |
2107 | 2171 | continue; |
2108 | 2172 | err = sysfs_create_group(&dev->kobj, &it87_group_in[i]); |
... | ... | @@ -2202,7 +2266,7 @@ |
2202 | 2266 | } |
2203 | 2267 | |
2204 | 2268 | /* Export labels for internal sensors */ |
2205 | - for (i = 0; i < 3; i++) { | |
2269 | + for (i = 0; i < 4; i++) { | |
2206 | 2270 | if (!(sio_data->internal & (1 << i))) |
2207 | 2271 | continue; |
2208 | 2272 | err = sysfs_create_file(&dev->kobj, |
... | ... | @@ -2383,8 +2447,9 @@ |
2383 | 2447 | } |
2384 | 2448 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; |
2385 | 2449 | |
2386 | - /* Set tachometers to 16-bit mode if needed */ | |
2387 | - if (has_16bit_fans(data)) { | |
2450 | + /* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?) | |
2451 | + * has it by default */ | |
2452 | + if (has_16bit_fans(data) && data->type != it8603) { | |
2388 | 2453 | tmp = it87_read_value(data, IT87_REG_FAN_16BIT); |
2389 | 2454 | if (~tmp & 0x07 & data->has_fan) { |
2390 | 2455 | dev_dbg(&pdev->dev, |
... | ... | @@ -2464,6 +2529,8 @@ |
2464 | 2529 | } |
2465 | 2530 | /* in8 (battery) has no limit registers */ |
2466 | 2531 | data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); |
2532 | + if (data->type == it8603) | |
2533 | + data->in[9][0] = it87_read_value(data, 0x2f); | |
2467 | 2534 | |
2468 | 2535 | for (i = 0; i < 5; i++) { |
2469 | 2536 | /* Skip disabled fans */ |