Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 115537
b: refs/heads/master
c: c656620
h: refs/heads/master
i:
  115535: bf5a8d5
v: v3
  • Loading branch information
Jean Delvare authored and Jean Delvare committed Oct 17, 2008
1 parent 97f5aed commit 8f7459a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2fbbbf148840332d614790ea00d9a7ecb38d648d
refs/heads/master: c6566206c6f9583b529d62f05fb67182978b959e
79 changes: 66 additions & 13 deletions trunk/drivers/hwmon/w83781d.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,7 @@ DIV_TO_REG(long val, enum chips type)
W83781D chips available (well, actually, that is probably never done; but
it is a clean illustration of how to handle a case like that). Finally,
a specific chip may be attached to *both* ISA and SMBus, and we would
not like to detect it double. Fortunately, in the case of the W83781D at
least, a register tells us what SMBus address we are on, so that helps
a bit - except if there could be more than one SMBus. Groan. No solution
for this yet. */
not like to detect it double. */

/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
the driver field to differentiate between I2C and ISA chips. */
Expand Down Expand Up @@ -852,13 +849,25 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
/* This function is called when:
* w83781d_driver is inserted (when this module is loaded), for each
available adapter
* when a new adapter is inserted (and w83781d_driver is still present) */
* when a new adapter is inserted (and w83781d_driver is still present)
We block updates of the ISA device to minimize the risk of concurrent
access to the same W83781D chip through different interfaces. */
static int
w83781d_attach_adapter(struct i2c_adapter *adapter)
{
struct w83781d_data *data;
int err;

if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, w83781d_detect);

data = pdev ? platform_get_drvdata(pdev) : NULL;
if (data)
mutex_lock(&data->update_lock);
err = i2c_probe(adapter, &addr_data, w83781d_detect);
if (data)
mutex_unlock(&data->update_lock);
return err;
}

/* Assumes that adapter is of I2C, not ISA variety.
Expand Down Expand Up @@ -1028,6 +1037,40 @@ static const struct attribute_group w83781d_group_opt = {
.attrs = w83781d_attributes_opt,
};

/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
{
struct w83781d_data *i2c, *isa;
int i;

if (!pdev) /* No ISA chip */
return 0;

i2c = i2c_get_clientdata(client);
isa = platform_get_drvdata(pdev);

if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
return 0; /* Address doesn't match */
if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
return 0; /* Chip type doesn't match */

/* We compare all the limit registers, the config register and the
* interrupt mask registers */
for (i = 0x2b; i <= 0x3d; i++) {
if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
return 0;
}
if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
w83781d_read_value(i2c, W83781D_REG_CONFIG))
return 0;
for (i = 0x43; i <= 0x46; i++) {
if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
return 0;
}

return 1;
}

/* No clean up is done on error, it's up to the caller */
static int
w83781d_create_files(struct device *dev, int kind, int is_isa)
Expand Down Expand Up @@ -1242,6 +1285,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
err = -EINVAL;
goto ERROR2;
}

if ((kind == w83781d || kind == w83782d)
&& w83781d_alias_detect(client, val1)) {
dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
"be the same as ISA device\n", address);
err = -ENODEV;
goto ERROR2;
}
}

if (kind == w83781d) {
Expand Down Expand Up @@ -1904,27 +1955,29 @@ sensors_w83781d_init(void)
{
int res;

res = i2c_add_driver(&w83781d_driver);
if (res)
goto exit;

/* We register the ISA device first, so that we can skip the
* registration of an I2C interface to the same device. */
if (w83781d_isa_found(isa_address)) {
res = platform_driver_register(&w83781d_isa_driver);
if (res)
goto exit_unreg_i2c_driver;
goto exit;

/* Sets global pdev as a side effect */
res = w83781d_isa_device_add(isa_address);
if (res)
goto exit_unreg_isa_driver;
}

res = i2c_add_driver(&w83781d_driver);
if (res)
goto exit_unreg_isa_device;

return 0;

exit_unreg_isa_device:
platform_device_unregister(pdev);
exit_unreg_isa_driver:
platform_driver_unregister(&w83781d_isa_driver);
exit_unreg_i2c_driver:
i2c_del_driver(&w83781d_driver);
exit:
return res;
}
Expand Down

0 comments on commit 8f7459a

Please sign in to comment.