aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-10-17 11:51:18 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-10-17 11:51:18 -0400
commitc6566206c6f9583b529d62f05fb67182978b959e (patch)
tree57cf79949a43531fb95b1a6ad81728ffba95cf8e
parent2fbbbf148840332d614790ea00d9a7ecb38d648d (diff)
hwmon: (w83781d) Detect alias chips
The W83781D and W83782D can be accessed either on the I2C bus or the ISA bus. We must not access the same chip through both interfaces. So far we were relying on the user passing the correct ignore parameter to skip the registration of the I2C interface as suggested by sensors-detect, but this is fragile: the user may load the w83781d driver without running sensors-detect, and the i2c bus numbers are not stable across reboots and hardware changes. So, better detect alias chips in the driver directly, and skip any I2C chip which is obviously an alias of the ISA chip. This is done by comparing the value of 26 selected registers. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Wolfgang Grandegger <wg@grandegger.com>
-rw-r--r--drivers/hwmon/w83781d.c79
1 files changed, 66 insertions, 13 deletions
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 136bec3fd645..1c00d9f7c14d 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -205,10 +205,7 @@ DIV_TO_REG(long val, enum chips type)
205 W83781D chips available (well, actually, that is probably never done; but 205 W83781D chips available (well, actually, that is probably never done; but
206 it is a clean illustration of how to handle a case like that). Finally, 206 it is a clean illustration of how to handle a case like that). Finally,
207 a specific chip may be attached to *both* ISA and SMBus, and we would 207 a specific chip may be attached to *both* ISA and SMBus, and we would
208 not like to detect it double. Fortunately, in the case of the W83781D at 208 not like to detect it double. */
209 least, a register tells us what SMBus address we are on, so that helps
210 a bit - except if there could be more than one SMBus. Groan. No solution
211 for this yet. */
212 209
213/* For ISA chips, we abuse the i2c_client addr and name fields. We also use 210/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
214 the driver field to differentiate between I2C and ISA chips. */ 211 the driver field to differentiate between I2C and ISA chips. */
@@ -852,13 +849,25 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
852/* This function is called when: 849/* This function is called when:
853 * w83781d_driver is inserted (when this module is loaded), for each 850 * w83781d_driver is inserted (when this module is loaded), for each
854 available adapter 851 available adapter
855 * when a new adapter is inserted (and w83781d_driver is still present) */ 852 * when a new adapter is inserted (and w83781d_driver is still present)
853 We block updates of the ISA device to minimize the risk of concurrent
854 access to the same W83781D chip through different interfaces. */
856static int 855static int
857w83781d_attach_adapter(struct i2c_adapter *adapter) 856w83781d_attach_adapter(struct i2c_adapter *adapter)
858{ 857{
858 struct w83781d_data *data;
859 int err;
860
859 if (!(adapter->class & I2C_CLASS_HWMON)) 861 if (!(adapter->class & I2C_CLASS_HWMON))
860 return 0; 862 return 0;
861 return i2c_probe(adapter, &addr_data, w83781d_detect); 863
864 data = pdev ? platform_get_drvdata(pdev) : NULL;
865 if (data)
866 mutex_lock(&data->update_lock);
867 err = i2c_probe(adapter, &addr_data, w83781d_detect);
868 if (data)
869 mutex_unlock(&data->update_lock);
870 return err;
862} 871}
863 872
864/* Assumes that adapter is of I2C, not ISA variety. 873/* Assumes that adapter is of I2C, not ISA variety.
@@ -1028,6 +1037,40 @@ static const struct attribute_group w83781d_group_opt = {
1028 .attrs = w83781d_attributes_opt, 1037 .attrs = w83781d_attributes_opt,
1029}; 1038};
1030 1039
1040/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
1041static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
1042{
1043 struct w83781d_data *i2c, *isa;
1044 int i;
1045
1046 if (!pdev) /* No ISA chip */
1047 return 0;
1048
1049 i2c = i2c_get_clientdata(client);
1050 isa = platform_get_drvdata(pdev);
1051
1052 if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
1053 return 0; /* Address doesn't match */
1054 if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
1055 return 0; /* Chip type doesn't match */
1056
1057 /* We compare all the limit registers, the config register and the
1058 * interrupt mask registers */
1059 for (i = 0x2b; i <= 0x3d; i++) {
1060 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1061 return 0;
1062 }
1063 if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
1064 w83781d_read_value(i2c, W83781D_REG_CONFIG))
1065 return 0;
1066 for (i = 0x43; i <= 0x46; i++) {
1067 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1068 return 0;
1069 }
1070
1071 return 1;
1072}
1073
1031/* No clean up is done on error, it's up to the caller */ 1074/* No clean up is done on error, it's up to the caller */
1032static int 1075static int
1033w83781d_create_files(struct device *dev, int kind, int is_isa) 1076w83781d_create_files(struct device *dev, int kind, int is_isa)
@@ -1242,6 +1285,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
1242 err = -EINVAL; 1285 err = -EINVAL;
1243 goto ERROR2; 1286 goto ERROR2;
1244 } 1287 }
1288
1289 if ((kind == w83781d || kind == w83782d)
1290 && w83781d_alias_detect(client, val1)) {
1291 dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
1292 "be the same as ISA device\n", address);
1293 err = -ENODEV;
1294 goto ERROR2;
1295 }
1245 } 1296 }
1246 1297
1247 if (kind == w83781d) { 1298 if (kind == w83781d) {
@@ -1904,14 +1955,12 @@ sensors_w83781d_init(void)
1904{ 1955{
1905 int res; 1956 int res;
1906 1957
1907 res = i2c_add_driver(&w83781d_driver); 1958 /* We register the ISA device first, so that we can skip the
1908 if (res) 1959 * registration of an I2C interface to the same device. */
1909 goto exit;
1910
1911 if (w83781d_isa_found(isa_address)) { 1960 if (w83781d_isa_found(isa_address)) {
1912 res = platform_driver_register(&w83781d_isa_driver); 1961 res = platform_driver_register(&w83781d_isa_driver);
1913 if (res) 1962 if (res)
1914 goto exit_unreg_i2c_driver; 1963 goto exit;
1915 1964
1916 /* Sets global pdev as a side effect */ 1965 /* Sets global pdev as a side effect */
1917 res = w83781d_isa_device_add(isa_address); 1966 res = w83781d_isa_device_add(isa_address);
@@ -1919,12 +1968,16 @@ sensors_w83781d_init(void)
1919 goto exit_unreg_isa_driver; 1968 goto exit_unreg_isa_driver;
1920 } 1969 }
1921 1970
1971 res = i2c_add_driver(&w83781d_driver);
1972 if (res)
1973 goto exit_unreg_isa_device;
1974
1922 return 0; 1975 return 0;
1923 1976
1977 exit_unreg_isa_device:
1978 platform_device_unregister(pdev);
1924 exit_unreg_isa_driver: 1979 exit_unreg_isa_driver:
1925 platform_driver_unregister(&w83781d_isa_driver); 1980 platform_driver_unregister(&w83781d_isa_driver);
1926 exit_unreg_i2c_driver:
1927 i2c_del_driver(&w83781d_driver);
1928 exit: 1981 exit:
1929 return res; 1982 return res;
1930} 1983}