aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/w83781d.c63
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. */
211struct w83781d_data { 201struct 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
1625show_name(struct device *dev, struct device_attribute *devattr, char *buf) 1619show_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}
1630static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 1624static 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)
1671static int 1665static int
1672w83781d_read_value_isa(struct w83781d_data *data, u16 reg) 1666w83781d_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)
1705static void 1698static void
1706w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) 1699w83781d_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;