Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (it87) Create voltage attributes only if voltage is enabled

On IT8782F and IT8783F, some voltage input pins may be disabled. Don't create
sysfs attribute files if that is the case.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Jean Delvare <khali@linux-fr.org>

authored by

Guenter Roeck and committed by
Guenter Roeck
9172b5d1 a7871def

+124 -38
+124 -38
drivers/hwmon/it87.c
··· 234 234 u8 beep_pin; 235 235 u8 internal; /* Internal sensors can be labeled */ 236 236 /* Features skipped based on config or DMI */ 237 + u16 skip_in; 237 238 u8 skip_vid; 238 239 u8 skip_fan; 239 240 u8 skip_pwm; ··· 1372 1371 } 1373 1372 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 1374 1373 1375 - static struct attribute *it87_attributes[] = { 1374 + static struct attribute *it87_attributes_in[9][5] = { 1375 + { 1376 1376 &sensor_dev_attr_in0_input.dev_attr.attr, 1377 - &sensor_dev_attr_in1_input.dev_attr.attr, 1378 - &sensor_dev_attr_in2_input.dev_attr.attr, 1379 - &sensor_dev_attr_in3_input.dev_attr.attr, 1380 - &sensor_dev_attr_in4_input.dev_attr.attr, 1381 - &sensor_dev_attr_in5_input.dev_attr.attr, 1382 - &sensor_dev_attr_in6_input.dev_attr.attr, 1383 - &sensor_dev_attr_in7_input.dev_attr.attr, 1384 - &sensor_dev_attr_in8_input.dev_attr.attr, 1385 1377 &sensor_dev_attr_in0_min.dev_attr.attr, 1386 - &sensor_dev_attr_in1_min.dev_attr.attr, 1387 - &sensor_dev_attr_in2_min.dev_attr.attr, 1388 - &sensor_dev_attr_in3_min.dev_attr.attr, 1389 - &sensor_dev_attr_in4_min.dev_attr.attr, 1390 - &sensor_dev_attr_in5_min.dev_attr.attr, 1391 - &sensor_dev_attr_in6_min.dev_attr.attr, 1392 - &sensor_dev_attr_in7_min.dev_attr.attr, 1393 1378 &sensor_dev_attr_in0_max.dev_attr.attr, 1394 - &sensor_dev_attr_in1_max.dev_attr.attr, 1395 - &sensor_dev_attr_in2_max.dev_attr.attr, 1396 - &sensor_dev_attr_in3_max.dev_attr.attr, 1397 - &sensor_dev_attr_in4_max.dev_attr.attr, 1398 - &sensor_dev_attr_in5_max.dev_attr.attr, 1399 - &sensor_dev_attr_in6_max.dev_attr.attr, 1400 - &sensor_dev_attr_in7_max.dev_attr.attr, 1401 1379 &sensor_dev_attr_in0_alarm.dev_attr.attr, 1380 + NULL 1381 + }, { 1382 + &sensor_dev_attr_in1_input.dev_attr.attr, 1383 + &sensor_dev_attr_in1_min.dev_attr.attr, 1384 + &sensor_dev_attr_in1_max.dev_attr.attr, 1402 1385 &sensor_dev_attr_in1_alarm.dev_attr.attr, 1386 + NULL 1387 + }, { 1388 + &sensor_dev_attr_in2_input.dev_attr.attr, 1389 + &sensor_dev_attr_in2_min.dev_attr.attr, 1390 + &sensor_dev_attr_in2_max.dev_attr.attr, 1403 1391 &sensor_dev_attr_in2_alarm.dev_attr.attr, 1392 + NULL 1393 + }, { 1394 + &sensor_dev_attr_in3_input.dev_attr.attr, 1395 + &sensor_dev_attr_in3_min.dev_attr.attr, 1396 + &sensor_dev_attr_in3_max.dev_attr.attr, 1404 1397 &sensor_dev_attr_in3_alarm.dev_attr.attr, 1398 + NULL 1399 + }, { 1400 + &sensor_dev_attr_in4_input.dev_attr.attr, 1401 + &sensor_dev_attr_in4_min.dev_attr.attr, 1402 + &sensor_dev_attr_in4_max.dev_attr.attr, 1405 1403 &sensor_dev_attr_in4_alarm.dev_attr.attr, 1404 + NULL 1405 + }, { 1406 + &sensor_dev_attr_in5_input.dev_attr.attr, 1407 + &sensor_dev_attr_in5_min.dev_attr.attr, 1408 + &sensor_dev_attr_in5_max.dev_attr.attr, 1406 1409 &sensor_dev_attr_in5_alarm.dev_attr.attr, 1410 + NULL 1411 + }, { 1412 + &sensor_dev_attr_in6_input.dev_attr.attr, 1413 + &sensor_dev_attr_in6_min.dev_attr.attr, 1414 + &sensor_dev_attr_in6_max.dev_attr.attr, 1407 1415 &sensor_dev_attr_in6_alarm.dev_attr.attr, 1416 + NULL 1417 + }, { 1418 + &sensor_dev_attr_in7_input.dev_attr.attr, 1419 + &sensor_dev_attr_in7_min.dev_attr.attr, 1420 + &sensor_dev_attr_in7_max.dev_attr.attr, 1408 1421 &sensor_dev_attr_in7_alarm.dev_attr.attr, 1422 + NULL 1423 + }, { 1424 + &sensor_dev_attr_in8_input.dev_attr.attr, 1425 + NULL 1426 + } }; 1409 1427 1428 + static const struct attribute_group it87_group_in[9] = { 1429 + { .attrs = it87_attributes_in[0] }, 1430 + { .attrs = it87_attributes_in[1] }, 1431 + { .attrs = it87_attributes_in[2] }, 1432 + { .attrs = it87_attributes_in[3] }, 1433 + { .attrs = it87_attributes_in[4] }, 1434 + { .attrs = it87_attributes_in[5] }, 1435 + { .attrs = it87_attributes_in[6] }, 1436 + { .attrs = it87_attributes_in[7] }, 1437 + { .attrs = it87_attributes_in[8] }, 1438 + }; 1439 + 1440 + static struct attribute *it87_attributes[] = { 1410 1441 &sensor_dev_attr_temp1_input.dev_attr.attr, 1411 1442 &sensor_dev_attr_temp2_input.dev_attr.attr, 1412 1443 &sensor_dev_attr_temp3_input.dev_attr.attr, ··· 1465 1432 .attrs = it87_attributes, 1466 1433 }; 1467 1434 1468 - static struct attribute *it87_attributes_beep[] = { 1435 + static struct attribute *it87_attributes_in_beep[] = { 1469 1436 &sensor_dev_attr_in0_beep.dev_attr.attr, 1470 1437 &sensor_dev_attr_in1_beep.dev_attr.attr, 1471 1438 &sensor_dev_attr_in2_beep.dev_attr.attr, ··· 1474 1441 &sensor_dev_attr_in5_beep.dev_attr.attr, 1475 1442 &sensor_dev_attr_in6_beep.dev_attr.attr, 1476 1443 &sensor_dev_attr_in7_beep.dev_attr.attr, 1444 + NULL 1445 + }; 1477 1446 1447 + static struct attribute *it87_attributes_beep[] = { 1478 1448 &sensor_dev_attr_temp1_beep.dev_attr.attr, 1479 1449 &sensor_dev_attr_temp2_beep.dev_attr.attr, 1480 1450 &sensor_dev_attr_temp3_beep.dev_attr.attr, ··· 1732 1696 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; 1733 1697 } else if (sio_data->type == it8783) { 1734 1698 int reg25, reg27, reg2A, reg2C, regEF; 1735 - bool uart6; 1736 1699 1737 1700 sio_data->skip_vid = 1; /* No VID */ 1738 1701 ··· 1743 1708 reg2C = superio_inb(IT87_SIO_PINX2_REG); 1744 1709 regEF = superio_inb(IT87_SIO_SPI_REG); 1745 1710 1746 - uart6 = reg2C & (1 << 2); 1747 - 1748 1711 /* Check if fan3 is there or not */ 1749 - if ((reg27 & (1 << 0)) || !uart6) 1712 + if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2))) 1750 1713 sio_data->skip_fan |= (1 << 2); 1751 1714 if ((reg25 & (1 << 4)) 1752 1715 || (!(reg2A & (1 << 1)) && (regEF & (1 << 0)))) ··· 1757 1724 sio_data->skip_pwm |= (1 << 1); 1758 1725 1759 1726 /* VIN5 */ 1760 - if ((reg27 & (1 << 0)) || uart6) 1761 - ; /* No VIN5 */ 1727 + if ((reg27 & (1 << 0)) || (reg2C & (1 << 2))) 1728 + sio_data->skip_in |= (1 << 5); /* No VIN5 */ 1762 1729 1763 1730 /* VIN6 */ 1764 - if ((reg27 & (1 << 1)) || uart6) 1765 - ; /* No VIN6 */ 1731 + if (reg27 & (1 << 1)) 1732 + sio_data->skip_in |= (1 << 6); /* No VIN6 */ 1766 1733 1767 1734 /* 1768 1735 * VIN7 1769 1736 * Does not depend on bit 2 of Reg2C, contrary to datasheet. 1770 1737 */ 1771 - if (reg27 & (1 << 2)) 1772 - ; /* No VIN7 (unless internal) */ 1738 + if (reg27 & (1 << 2)) { 1739 + /* 1740 + * The data sheet is a bit unclear regarding the 1741 + * internal voltage divider for VCCH5V. It says 1742 + * "This bit enables and switches VIN7 (pin 91) to the 1743 + * internal voltage divider for VCCH5V". 1744 + * This is different to other chips, where the internal 1745 + * voltage divider would connect VIN7 to an internal 1746 + * voltage source. Maybe that is the case here as well. 1747 + * 1748 + * Since we don't know for sure, re-route it if that is 1749 + * not the case, and ask the user to report if the 1750 + * resulting voltage is sane. 1751 + */ 1752 + if (!(reg2C & (1 << 1))) { 1753 + reg2C |= (1 << 1); 1754 + superio_outb(IT87_SIO_PINX2_REG, reg2C); 1755 + pr_notice("Routing internal VCCH5V to in7.\n"); 1756 + } 1757 + pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); 1758 + pr_notice("Please report if it displays a reasonable voltage.\n"); 1759 + } 1773 1760 1774 1761 if (reg2C & (1 << 0)) 1775 1762 sio_data->internal |= (1 << 0); ··· 1800 1747 1801 1748 } else { 1802 1749 int reg; 1750 + bool uart6; 1803 1751 1804 1752 superio_select(GPIO); 1805 1753 ··· 1838 1784 sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); 1839 1785 1840 1786 reg = superio_inb(IT87_SIO_PINX2_REG); 1787 + 1788 + uart6 = sio_data->type == it8782 && (reg & (1 << 2)); 1789 + 1841 1790 /* 1842 1791 * The IT8720F has no VIN7 pin, so VCCH should always be 1843 1792 * routed internally to VIN7 with an internal divider. ··· 1852 1795 * setting. So we force the internal routing in this case. 1853 1796 * 1854 1797 * On IT8782F, VIN7 is multiplexed with one of the UART6 pins. 1855 - * If UART6 is enabled, re-route VIN7 to the internal divider. 1798 + * If UART6 is enabled, re-route VIN7 to the internal divider 1799 + * if that is not already the case. 1856 1800 */ 1857 - if ((sio_data->type == it8720 || 1858 - (sio_data->type == it8782 && (reg & (1 << 2)))) 1859 - && !(reg & (1 << 1))) { 1801 + if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) { 1860 1802 reg |= (1 << 1); 1861 1803 superio_outb(IT87_SIO_PINX2_REG, reg); 1862 1804 pr_notice("Routing internal VCCH to in7\n"); ··· 1865 1809 if ((reg & (1 << 1)) || sio_data->type == it8721 || 1866 1810 sio_data->type == it8728) 1867 1811 sio_data->internal |= (1 << 1); 1812 + 1813 + /* 1814 + * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7. 1815 + * While VIN7 can be routed to the internal voltage divider, 1816 + * VIN5 and VIN6 are not available if UART6 is enabled. 1817 + */ 1818 + if (uart6) 1819 + sio_data->skip_in |= (1 << 5) | (1 << 6); 1868 1820 1869 1821 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; 1870 1822 } ··· 1911 1847 int i; 1912 1848 1913 1849 sysfs_remove_group(&dev->kobj, &it87_group); 1850 + for (i = 0; i < 9; i++) { 1851 + if (sio_data->skip_in & (1 << i)) 1852 + continue; 1853 + sysfs_remove_group(&dev->kobj, &it87_group_in[i]); 1854 + if (it87_attributes_in_beep[i]) 1855 + sysfs_remove_file(&dev->kobj, 1856 + it87_attributes_in_beep[i]); 1857 + } 1914 1858 if (sio_data->beep_pin) 1915 1859 sysfs_remove_group(&dev->kobj, &it87_group_beep); 1916 1860 for (i = 0; i < 5; i++) { ··· 2020 1948 err = sysfs_create_group(&dev->kobj, &it87_group); 2021 1949 if (err) 2022 1950 goto ERROR2; 1951 + 1952 + for (i = 0; i < 9; i++) { 1953 + if (sio_data->skip_in & (1 << i)) 1954 + continue; 1955 + err = sysfs_create_group(&dev->kobj, &it87_group_in[i]); 1956 + if (err) 1957 + goto ERROR4; 1958 + if (sio_data->beep_pin && it87_attributes_in_beep[i]) { 1959 + err = sysfs_create_file(&dev->kobj, 1960 + it87_attributes_in_beep[i]); 1961 + if (err) 1962 + goto ERROR4; 1963 + } 1964 + } 2023 1965 2024 1966 if (sio_data->beep_pin) { 2025 1967 err = sysfs_create_group(&dev->kobj, &it87_group_beep);