aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/it87.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2012-03-25 00:49:54 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2012-05-20 22:41:50 -0400
commit9172b5d124c2f54374d8cc5ed6098ecd8fb988cd (patch)
treed80082b7b3f22fde5ad01af253f45c5bd5435833 /drivers/hwmon/it87.c
parenta7871def65887dd42b51b89c674a90c085e934c9 (diff)
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>
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r--drivers/hwmon/it87.c162
1 files changed, 124 insertions, 38 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index aebac1334ff6..bef8732f08b1 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -234,6 +234,7 @@ struct it87_sio_data {
234 u8 beep_pin; 234 u8 beep_pin;
235 u8 internal; /* Internal sensors can be labeled */ 235 u8 internal; /* Internal sensors can be labeled */
236 /* Features skipped based on config or DMI */ 236 /* Features skipped based on config or DMI */
237 u16 skip_in;
237 u8 skip_vid; 238 u8 skip_vid;
238 u8 skip_fan; 239 u8 skip_fan;
239 u8 skip_pwm; 240 u8 skip_pwm;
@@ -1371,41 +1372,73 @@ static ssize_t show_name(struct device *dev, struct device_attribute
1371} 1372}
1372static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 1373static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1373 1374
1374static struct attribute *it87_attributes[] = { 1375static struct attribute *it87_attributes_in[9][5] = {
1376{
1375 &sensor_dev_attr_in0_input.dev_attr.attr, 1377 &sensor_dev_attr_in0_input.dev_attr.attr,
1376 &sensor_dev_attr_in1_input.dev_attr.attr,
1377 &sensor_dev_attr_in2_input.dev_attr.attr,
1378 &sensor_dev_attr_in3_input.dev_attr.attr,
1379 &sensor_dev_attr_in4_input.dev_attr.attr,
1380 &sensor_dev_attr_in5_input.dev_attr.attr,
1381 &sensor_dev_attr_in6_input.dev_attr.attr,
1382 &sensor_dev_attr_in7_input.dev_attr.attr,
1383 &sensor_dev_attr_in8_input.dev_attr.attr,
1384 &sensor_dev_attr_in0_min.dev_attr.attr, 1378 &sensor_dev_attr_in0_min.dev_attr.attr,
1385 &sensor_dev_attr_in1_min.dev_attr.attr,
1386 &sensor_dev_attr_in2_min.dev_attr.attr,
1387 &sensor_dev_attr_in3_min.dev_attr.attr,
1388 &sensor_dev_attr_in4_min.dev_attr.attr,
1389 &sensor_dev_attr_in5_min.dev_attr.attr,
1390 &sensor_dev_attr_in6_min.dev_attr.attr,
1391 &sensor_dev_attr_in7_min.dev_attr.attr,
1392 &sensor_dev_attr_in0_max.dev_attr.attr, 1379 &sensor_dev_attr_in0_max.dev_attr.attr,
1393 &sensor_dev_attr_in1_max.dev_attr.attr,
1394 &sensor_dev_attr_in2_max.dev_attr.attr,
1395 &sensor_dev_attr_in3_max.dev_attr.attr,
1396 &sensor_dev_attr_in4_max.dev_attr.attr,
1397 &sensor_dev_attr_in5_max.dev_attr.attr,
1398 &sensor_dev_attr_in6_max.dev_attr.attr,
1399 &sensor_dev_attr_in7_max.dev_attr.attr,
1400 &sensor_dev_attr_in0_alarm.dev_attr.attr, 1380 &sensor_dev_attr_in0_alarm.dev_attr.attr,
1381 NULL
1382}, {
1383 &sensor_dev_attr_in1_input.dev_attr.attr,
1384 &sensor_dev_attr_in1_min.dev_attr.attr,
1385 &sensor_dev_attr_in1_max.dev_attr.attr,
1401 &sensor_dev_attr_in1_alarm.dev_attr.attr, 1386 &sensor_dev_attr_in1_alarm.dev_attr.attr,
1387 NULL
1388}, {
1389 &sensor_dev_attr_in2_input.dev_attr.attr,
1390 &sensor_dev_attr_in2_min.dev_attr.attr,
1391 &sensor_dev_attr_in2_max.dev_attr.attr,
1402 &sensor_dev_attr_in2_alarm.dev_attr.attr, 1392 &sensor_dev_attr_in2_alarm.dev_attr.attr,
1393 NULL
1394}, {
1395 &sensor_dev_attr_in3_input.dev_attr.attr,
1396 &sensor_dev_attr_in3_min.dev_attr.attr,
1397 &sensor_dev_attr_in3_max.dev_attr.attr,
1403 &sensor_dev_attr_in3_alarm.dev_attr.attr, 1398 &sensor_dev_attr_in3_alarm.dev_attr.attr,
1399 NULL
1400}, {
1401 &sensor_dev_attr_in4_input.dev_attr.attr,
1402 &sensor_dev_attr_in4_min.dev_attr.attr,
1403 &sensor_dev_attr_in4_max.dev_attr.attr,
1404 &sensor_dev_attr_in4_alarm.dev_attr.attr, 1404 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1405 NULL
1406}, {
1407 &sensor_dev_attr_in5_input.dev_attr.attr,
1408 &sensor_dev_attr_in5_min.dev_attr.attr,
1409 &sensor_dev_attr_in5_max.dev_attr.attr,
1405 &sensor_dev_attr_in5_alarm.dev_attr.attr, 1410 &sensor_dev_attr_in5_alarm.dev_attr.attr,
1411 NULL
1412}, {
1413 &sensor_dev_attr_in6_input.dev_attr.attr,
1414 &sensor_dev_attr_in6_min.dev_attr.attr,
1415 &sensor_dev_attr_in6_max.dev_attr.attr,
1406 &sensor_dev_attr_in6_alarm.dev_attr.attr, 1416 &sensor_dev_attr_in6_alarm.dev_attr.attr,
1417 NULL
1418}, {
1419 &sensor_dev_attr_in7_input.dev_attr.attr,
1420 &sensor_dev_attr_in7_min.dev_attr.attr,
1421 &sensor_dev_attr_in7_max.dev_attr.attr,
1407 &sensor_dev_attr_in7_alarm.dev_attr.attr, 1422 &sensor_dev_attr_in7_alarm.dev_attr.attr,
1423 NULL
1424}, {
1425 &sensor_dev_attr_in8_input.dev_attr.attr,
1426 NULL
1427} };
1428
1429static const struct attribute_group it87_group_in[9] = {
1430 { .attrs = it87_attributes_in[0] },
1431 { .attrs = it87_attributes_in[1] },
1432 { .attrs = it87_attributes_in[2] },
1433 { .attrs = it87_attributes_in[3] },
1434 { .attrs = it87_attributes_in[4] },
1435 { .attrs = it87_attributes_in[5] },
1436 { .attrs = it87_attributes_in[6] },
1437 { .attrs = it87_attributes_in[7] },
1438 { .attrs = it87_attributes_in[8] },
1439};
1408 1440
1441static struct attribute *it87_attributes[] = {
1409 &sensor_dev_attr_temp1_input.dev_attr.attr, 1442 &sensor_dev_attr_temp1_input.dev_attr.attr,
1410 &sensor_dev_attr_temp2_input.dev_attr.attr, 1443 &sensor_dev_attr_temp2_input.dev_attr.attr,
1411 &sensor_dev_attr_temp3_input.dev_attr.attr, 1444 &sensor_dev_attr_temp3_input.dev_attr.attr,
@@ -1432,7 +1465,7 @@ static const struct attribute_group it87_group = {
1432 .attrs = it87_attributes, 1465 .attrs = it87_attributes,
1433}; 1466};
1434 1467
1435static struct attribute *it87_attributes_beep[] = { 1468static struct attribute *it87_attributes_in_beep[] = {
1436 &sensor_dev_attr_in0_beep.dev_attr.attr, 1469 &sensor_dev_attr_in0_beep.dev_attr.attr,
1437 &sensor_dev_attr_in1_beep.dev_attr.attr, 1470 &sensor_dev_attr_in1_beep.dev_attr.attr,
1438 &sensor_dev_attr_in2_beep.dev_attr.attr, 1471 &sensor_dev_attr_in2_beep.dev_attr.attr,
@@ -1441,7 +1474,10 @@ static struct attribute *it87_attributes_beep[] = {
1441 &sensor_dev_attr_in5_beep.dev_attr.attr, 1474 &sensor_dev_attr_in5_beep.dev_attr.attr,
1442 &sensor_dev_attr_in6_beep.dev_attr.attr, 1475 &sensor_dev_attr_in6_beep.dev_attr.attr,
1443 &sensor_dev_attr_in7_beep.dev_attr.attr, 1476 &sensor_dev_attr_in7_beep.dev_attr.attr,
1477 NULL
1478};
1444 1479
1480static struct attribute *it87_attributes_beep[] = {
1445 &sensor_dev_attr_temp1_beep.dev_attr.attr, 1481 &sensor_dev_attr_temp1_beep.dev_attr.attr,
1446 &sensor_dev_attr_temp2_beep.dev_attr.attr, 1482 &sensor_dev_attr_temp2_beep.dev_attr.attr,
1447 &sensor_dev_attr_temp3_beep.dev_attr.attr, 1483 &sensor_dev_attr_temp3_beep.dev_attr.attr,
@@ -1696,7 +1732,6 @@ static int __init it87_find(unsigned short *address,
1696 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; 1732 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
1697 } else if (sio_data->type == it8783) { 1733 } else if (sio_data->type == it8783) {
1698 int reg25, reg27, reg2A, reg2C, regEF; 1734 int reg25, reg27, reg2A, reg2C, regEF;
1699 bool uart6;
1700 1735
1701 sio_data->skip_vid = 1; /* No VID */ 1736 sio_data->skip_vid = 1; /* No VID */
1702 1737
@@ -1708,10 +1743,8 @@ static int __init it87_find(unsigned short *address,
1708 reg2C = superio_inb(IT87_SIO_PINX2_REG); 1743 reg2C = superio_inb(IT87_SIO_PINX2_REG);
1709 regEF = superio_inb(IT87_SIO_SPI_REG); 1744 regEF = superio_inb(IT87_SIO_SPI_REG);
1710 1745
1711 uart6 = reg2C & (1 << 2);
1712
1713 /* Check if fan3 is there or not */ 1746 /* Check if fan3 is there or not */
1714 if ((reg27 & (1 << 0)) || !uart6) 1747 if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
1715 sio_data->skip_fan |= (1 << 2); 1748 sio_data->skip_fan |= (1 << 2);
1716 if ((reg25 & (1 << 4)) 1749 if ((reg25 & (1 << 4))
1717 || (!(reg2A & (1 << 1)) && (regEF & (1 << 0)))) 1750 || (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
@@ -1724,19 +1757,39 @@ static int __init it87_find(unsigned short *address,
1724 sio_data->skip_pwm |= (1 << 1); 1757 sio_data->skip_pwm |= (1 << 1);
1725 1758
1726 /* VIN5 */ 1759 /* VIN5 */
1727 if ((reg27 & (1 << 0)) || uart6) 1760 if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
1728 ; /* No VIN5 */ 1761 sio_data->skip_in |= (1 << 5); /* No VIN5 */
1729 1762
1730 /* VIN6 */ 1763 /* VIN6 */
1731 if ((reg27 & (1 << 1)) || uart6) 1764 if (reg27 & (1 << 1))
1732 ; /* No VIN6 */ 1765 sio_data->skip_in |= (1 << 6); /* No VIN6 */
1733 1766
1734 /* 1767 /*
1735 * VIN7 1768 * VIN7
1736 * Does not depend on bit 2 of Reg2C, contrary to datasheet. 1769 * Does not depend on bit 2 of Reg2C, contrary to datasheet.
1737 */ 1770 */
1738 if (reg27 & (1 << 2)) 1771 if (reg27 & (1 << 2)) {
1739 ; /* No VIN7 (unless internal) */ 1772 /*
1773 * The data sheet is a bit unclear regarding the
1774 * internal voltage divider for VCCH5V. It says
1775 * "This bit enables and switches VIN7 (pin 91) to the
1776 * internal voltage divider for VCCH5V".
1777 * This is different to other chips, where the internal
1778 * voltage divider would connect VIN7 to an internal
1779 * voltage source. Maybe that is the case here as well.
1780 *
1781 * Since we don't know for sure, re-route it if that is
1782 * not the case, and ask the user to report if the
1783 * resulting voltage is sane.
1784 */
1785 if (!(reg2C & (1 << 1))) {
1786 reg2C |= (1 << 1);
1787 superio_outb(IT87_SIO_PINX2_REG, reg2C);
1788 pr_notice("Routing internal VCCH5V to in7.\n");
1789 }
1790 pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
1791 pr_notice("Please report if it displays a reasonable voltage.\n");
1792 }
1740 1793
1741 if (reg2C & (1 << 0)) 1794 if (reg2C & (1 << 0))
1742 sio_data->internal |= (1 << 0); 1795 sio_data->internal |= (1 << 0);
@@ -1747,6 +1800,7 @@ static int __init it87_find(unsigned short *address,
1747 1800
1748 } else { 1801 } else {
1749 int reg; 1802 int reg;
1803 bool uart6;
1750 1804
1751 superio_select(GPIO); 1805 superio_select(GPIO);
1752 1806
@@ -1784,6 +1838,9 @@ static int __init it87_find(unsigned short *address,
1784 sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); 1838 sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
1785 1839
1786 reg = superio_inb(IT87_SIO_PINX2_REG); 1840 reg = superio_inb(IT87_SIO_PINX2_REG);
1841
1842 uart6 = sio_data->type == it8782 && (reg & (1 << 2));
1843
1787 /* 1844 /*
1788 * The IT8720F has no VIN7 pin, so VCCH should always be 1845 * The IT8720F has no VIN7 pin, so VCCH should always be
1789 * routed internally to VIN7 with an internal divider. 1846 * routed internally to VIN7 with an internal divider.
@@ -1795,11 +1852,10 @@ static int __init it87_find(unsigned short *address,
1795 * setting. So we force the internal routing in this case. 1852 * setting. So we force the internal routing in this case.
1796 * 1853 *
1797 * On IT8782F, VIN7 is multiplexed with one of the UART6 pins. 1854 * On IT8782F, VIN7 is multiplexed with one of the UART6 pins.
1798 * If UART6 is enabled, re-route VIN7 to the internal divider. 1855 * If UART6 is enabled, re-route VIN7 to the internal divider
1856 * if that is not already the case.
1799 */ 1857 */
1800 if ((sio_data->type == it8720 || 1858 if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) {
1801 (sio_data->type == it8782 && (reg & (1 << 2))))
1802 && !(reg & (1 << 1))) {
1803 reg |= (1 << 1); 1859 reg |= (1 << 1);
1804 superio_outb(IT87_SIO_PINX2_REG, reg); 1860 superio_outb(IT87_SIO_PINX2_REG, reg);
1805 pr_notice("Routing internal VCCH to in7\n"); 1861 pr_notice("Routing internal VCCH to in7\n");
@@ -1810,6 +1866,14 @@ static int __init it87_find(unsigned short *address,
1810 sio_data->type == it8728) 1866 sio_data->type == it8728)
1811 sio_data->internal |= (1 << 1); 1867 sio_data->internal |= (1 << 1);
1812 1868
1869 /*
1870 * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7.
1871 * While VIN7 can be routed to the internal voltage divider,
1872 * VIN5 and VIN6 are not available if UART6 is enabled.
1873 */
1874 if (uart6)
1875 sio_data->skip_in |= (1 << 5) | (1 << 6);
1876
1813 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; 1877 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
1814 } 1878 }
1815 if (sio_data->beep_pin) 1879 if (sio_data->beep_pin)
@@ -1847,6 +1911,14 @@ static void it87_remove_files(struct device *dev)
1847 int i; 1911 int i;
1848 1912
1849 sysfs_remove_group(&dev->kobj, &it87_group); 1913 sysfs_remove_group(&dev->kobj, &it87_group);
1914 for (i = 0; i < 9; i++) {
1915 if (sio_data->skip_in & (1 << i))
1916 continue;
1917 sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
1918 if (it87_attributes_in_beep[i])
1919 sysfs_remove_file(&dev->kobj,
1920 it87_attributes_in_beep[i]);
1921 }
1850 if (sio_data->beep_pin) 1922 if (sio_data->beep_pin)
1851 sysfs_remove_group(&dev->kobj, &it87_group_beep); 1923 sysfs_remove_group(&dev->kobj, &it87_group_beep);
1852 for (i = 0; i < 5; i++) { 1924 for (i = 0; i < 5; i++) {
@@ -1949,6 +2021,20 @@ static int __devinit it87_probe(struct platform_device *pdev)
1949 if (err) 2021 if (err)
1950 goto ERROR2; 2022 goto ERROR2;
1951 2023
2024 for (i = 0; i < 9; i++) {
2025 if (sio_data->skip_in & (1 << i))
2026 continue;
2027 err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
2028 if (err)
2029 goto ERROR4;
2030 if (sio_data->beep_pin && it87_attributes_in_beep[i]) {
2031 err = sysfs_create_file(&dev->kobj,
2032 it87_attributes_in_beep[i]);
2033 if (err)
2034 goto ERROR4;
2035 }
2036 }
2037
1952 if (sio_data->beep_pin) { 2038 if (sio_data->beep_pin) {
1953 err = sysfs_create_group(&dev->kobj, &it87_group_beep); 2039 err = sysfs_create_group(&dev->kobj, &it87_group_beep);
1954 if (err) 2040 if (err)