diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/w83781d.c | 63 |
1 files changed, 26 insertions, 37 deletions
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 1a729a749277..50580c883053 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -4,7 +4,7 @@ | |||
4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, | 4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, |
5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
7 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | 7 | Copyright (c) 2007 - 2008 Jean Delvare <khali@linux-fr.org> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
@@ -198,22 +198,16 @@ DIV_TO_REG(long val, enum chips type) | |||
198 | return i; | 198 | return i; |
199 | } | 199 | } |
200 | 200 | ||
201 | /* There are some complications in a module like this. First off, W83781D chips | ||
202 | may be both present on the SMBus and the ISA bus, and we have to handle | ||
203 | those cases separately at some places. Second, there might be several | ||
204 | W83781D chips available (well, actually, that is probably never done; but | ||
205 | it is a clean illustration of how to handle a case like that). Finally, | ||
206 | a specific chip may be attached to *both* ISA and SMBus, and we would | ||
207 | not like to detect it double. */ | ||
208 | |||
209 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use | ||
210 | the driver field to differentiate between I2C and ISA chips. */ | ||
211 | struct w83781d_data { | 201 | struct w83781d_data { |
212 | struct i2c_client client; | 202 | struct i2c_client client; |
213 | struct device *hwmon_dev; | 203 | struct device *hwmon_dev; |
214 | struct mutex lock; | 204 | struct mutex lock; |
215 | enum chips type; | 205 | enum chips type; |
216 | 206 | ||
207 | /* For ISA device only */ | ||
208 | const char *name; | ||
209 | int isa_addr; | ||
210 | |||
217 | struct mutex update_lock; | 211 | struct mutex update_lock; |
218 | char valid; /* !=0 if following fields are valid */ | 212 | char valid; /* !=0 if following fields are valid */ |
219 | unsigned long last_updated; /* In jiffies */ | 213 | unsigned long last_updated; /* In jiffies */ |
@@ -1625,7 +1619,7 @@ static ssize_t | |||
1625 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | 1619 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) |
1626 | { | 1620 | { |
1627 | struct w83781d_data *data = dev_get_drvdata(dev); | 1621 | struct w83781d_data *data = dev_get_drvdata(dev); |
1628 | return sprintf(buf, "%s\n", data->client.name); | 1622 | return sprintf(buf, "%s\n", data->name); |
1629 | } | 1623 | } |
1630 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 1624 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
1631 | 1625 | ||
@@ -1671,7 +1665,6 @@ static int w83781d_alias_detect(struct i2c_client *client, u8 chipid) | |||
1671 | static int | 1665 | static int |
1672 | w83781d_read_value_isa(struct w83781d_data *data, u16 reg) | 1666 | w83781d_read_value_isa(struct w83781d_data *data, u16 reg) |
1673 | { | 1667 | { |
1674 | struct i2c_client *client = &data->client; | ||
1675 | int word_sized, res; | 1668 | int word_sized, res; |
1676 | 1669 | ||
1677 | word_sized = (((reg & 0xff00) == 0x100) | 1670 | word_sized = (((reg & 0xff00) == 0x100) |
@@ -1681,23 +1674,23 @@ w83781d_read_value_isa(struct w83781d_data *data, u16 reg) | |||
1681 | || ((reg & 0x00ff) == 0x55)); | 1674 | || ((reg & 0x00ff) == 0x55)); |
1682 | if (reg & 0xff00) { | 1675 | if (reg & 0xff00) { |
1683 | outb_p(W83781D_REG_BANK, | 1676 | outb_p(W83781D_REG_BANK, |
1684 | client->addr + W83781D_ADDR_REG_OFFSET); | 1677 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1685 | outb_p(reg >> 8, | 1678 | outb_p(reg >> 8, |
1686 | client->addr + W83781D_DATA_REG_OFFSET); | 1679 | data->isa_addr + W83781D_DATA_REG_OFFSET); |
1687 | } | 1680 | } |
1688 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1681 | outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1689 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); | 1682 | res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET); |
1690 | if (word_sized) { | 1683 | if (word_sized) { |
1691 | outb_p((reg & 0xff) + 1, | 1684 | outb_p((reg & 0xff) + 1, |
1692 | client->addr + W83781D_ADDR_REG_OFFSET); | 1685 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1693 | res = | 1686 | res = |
1694 | (res << 8) + inb_p(client->addr + | 1687 | (res << 8) + inb_p(data->isa_addr + |
1695 | W83781D_DATA_REG_OFFSET); | 1688 | W83781D_DATA_REG_OFFSET); |
1696 | } | 1689 | } |
1697 | if (reg & 0xff00) { | 1690 | if (reg & 0xff00) { |
1698 | outb_p(W83781D_REG_BANK, | 1691 | outb_p(W83781D_REG_BANK, |
1699 | client->addr + W83781D_ADDR_REG_OFFSET); | 1692 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1700 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1693 | outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); |
1701 | } | 1694 | } |
1702 | return res; | 1695 | return res; |
1703 | } | 1696 | } |
@@ -1705,7 +1698,6 @@ w83781d_read_value_isa(struct w83781d_data *data, u16 reg) | |||
1705 | static void | 1698 | static void |
1706 | w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) | 1699 | w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) |
1707 | { | 1700 | { |
1708 | struct i2c_client *client = &data->client; | ||
1709 | int word_sized; | 1701 | int word_sized; |
1710 | 1702 | ||
1711 | word_sized = (((reg & 0xff00) == 0x100) | 1703 | word_sized = (((reg & 0xff00) == 0x100) |
@@ -1714,22 +1706,22 @@ w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) | |||
1714 | || ((reg & 0x00ff) == 0x55)); | 1706 | || ((reg & 0x00ff) == 0x55)); |
1715 | if (reg & 0xff00) { | 1707 | if (reg & 0xff00) { |
1716 | outb_p(W83781D_REG_BANK, | 1708 | outb_p(W83781D_REG_BANK, |
1717 | client->addr + W83781D_ADDR_REG_OFFSET); | 1709 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1718 | outb_p(reg >> 8, | 1710 | outb_p(reg >> 8, |
1719 | client->addr + W83781D_DATA_REG_OFFSET); | 1711 | data->isa_addr + W83781D_DATA_REG_OFFSET); |
1720 | } | 1712 | } |
1721 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1713 | outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1722 | if (word_sized) { | 1714 | if (word_sized) { |
1723 | outb_p(value >> 8, | 1715 | outb_p(value >> 8, |
1724 | client->addr + W83781D_DATA_REG_OFFSET); | 1716 | data->isa_addr + W83781D_DATA_REG_OFFSET); |
1725 | outb_p((reg & 0xff) + 1, | 1717 | outb_p((reg & 0xff) + 1, |
1726 | client->addr + W83781D_ADDR_REG_OFFSET); | 1718 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1727 | } | 1719 | } |
1728 | outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET); | 1720 | outb_p(value & 0xff, data->isa_addr + W83781D_DATA_REG_OFFSET); |
1729 | if (reg & 0xff00) { | 1721 | if (reg & 0xff00) { |
1730 | outb_p(W83781D_REG_BANK, | 1722 | outb_p(W83781D_REG_BANK, |
1731 | client->addr + W83781D_ADDR_REG_OFFSET); | 1723 | data->isa_addr + W83781D_ADDR_REG_OFFSET); |
1732 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1724 | outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); |
1733 | } | 1725 | } |
1734 | } | 1726 | } |
1735 | 1727 | ||
@@ -1774,7 +1766,6 @@ w83781d_isa_probe(struct platform_device *pdev) | |||
1774 | int err, reg; | 1766 | int err, reg; |
1775 | struct w83781d_data *data; | 1767 | struct w83781d_data *data; |
1776 | struct resource *res; | 1768 | struct resource *res; |
1777 | const char *name; | ||
1778 | 1769 | ||
1779 | /* Reserve the ISA region */ | 1770 | /* Reserve the ISA region */ |
1780 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1771 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
@@ -1790,21 +1781,19 @@ w83781d_isa_probe(struct platform_device *pdev) | |||
1790 | goto exit_release_region; | 1781 | goto exit_release_region; |
1791 | } | 1782 | } |
1792 | mutex_init(&data->lock); | 1783 | mutex_init(&data->lock); |
1793 | data->client.addr = res->start; | 1784 | data->isa_addr = res->start; |
1794 | i2c_set_clientdata(&data->client, data); | ||
1795 | platform_set_drvdata(pdev, data); | 1785 | platform_set_drvdata(pdev, data); |
1796 | 1786 | ||
1797 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); | 1787 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); |
1798 | switch (reg) { | 1788 | switch (reg) { |
1799 | case 0x30: | 1789 | case 0x30: |
1800 | data->type = w83782d; | 1790 | data->type = w83782d; |
1801 | name = "w83782d"; | 1791 | data->name = "w83782d"; |
1802 | break; | 1792 | break; |
1803 | default: | 1793 | default: |
1804 | data->type = w83781d; | 1794 | data->type = w83781d; |
1805 | name = "w83781d"; | 1795 | data->name = "w83781d"; |
1806 | } | 1796 | } |
1807 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
1808 | 1797 | ||
1809 | /* Initialize the W83781D chip */ | 1798 | /* Initialize the W83781D chip */ |
1810 | w83781d_init_device(&pdev->dev); | 1799 | w83781d_init_device(&pdev->dev); |
@@ -1846,7 +1835,7 @@ w83781d_isa_remove(struct platform_device *pdev) | |||
1846 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | 1835 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); |
1847 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | 1836 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); |
1848 | device_remove_file(&pdev->dev, &dev_attr_name); | 1837 | device_remove_file(&pdev->dev, &dev_attr_name); |
1849 | release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2); | 1838 | release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2); |
1850 | kfree(data); | 1839 | kfree(data); |
1851 | 1840 | ||
1852 | return 0; | 1841 | return 0; |