diff options
author | Michael Lawnick <ml.lawnick@gmx.de> | 2010-08-11 18:21:02 +0200 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2010-08-11 18:21:02 +0200 |
commit | 0826374bff57411d239f2fcb15da3c35af0a93cd (patch) | |
tree | 514d4361cfc9cc546306612de3464def7fe8a7cd /drivers/i2c/i2c-dev.c | |
parent | i2c: Use a separate mutex for userspace client lists (diff) | |
download | linux-0826374bff57411d239f2fcb15da3c35af0a93cd.tar.xz linux-0826374bff57411d239f2fcb15da3c35af0a93cd.zip |
i2c: Multiplexed I2C bus core support
Add multiplexed bus core support. I2C multiplexer and switches
like pca954x get instantiated as new adapters per port.
Signed-off-by: Michael Lawnick <ml.lawnick@gmx.de>
Acked-by: Rodolfo Giometti <giometti@linux.it>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r-- | drivers/i2c/i2c-dev.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 0b0427f7d348..5f3a52d517c3 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -189,12 +189,50 @@ static int i2cdev_check(struct device *dev, void *addrp) return dev->driver ? -EBUSY : 0; } +/* walk up mux tree */ +static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) +{ + int result; + + result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); + + if (!result && i2c_parent_is_i2c_adapter(adapter)) + result = i2cdev_check_mux_parents( + to_i2c_adapter(adapter->dev.parent), addr); + + return result; +} + +/* recurse down mux tree */ +static int i2cdev_check_mux_children(struct device *dev, void *addrp) +{ + int result; + + if (dev->type == &i2c_adapter_type) + result = device_for_each_child(dev, addrp, + i2cdev_check_mux_children); + else + result = i2cdev_check(dev, addrp); + + return result; +} + /* This address checking function differs from the one in i2c-core in that it considers an address with a registered device, but no driver bound to it, as NOT busy. */ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - return device_for_each_child(&adapter->dev, &addr, i2cdev_check); + int result = 0; + + if (i2c_parent_is_i2c_adapter(adapter)) + result = i2cdev_check_mux_parents( + to_i2c_adapter(adapter->dev.parent), addr); + + if (!result) + result = device_for_each_child(&adapter->dev, &addr, + i2cdev_check_mux_children); + + return result; } static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, |