diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-19 17:48:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-19 17:48:12 -0700 |
commit | 78975f23cba0cd195db01cdbd6eb48138a655890 (patch) | |
tree | 0e808c0cfe220bd8fb00d66985d71655345904cb /drivers/iio | |
parent | feaa7cb5c59416143432829b15826be76605b8fe (diff) | |
parent | 73e8b0528346e88a0624f2d9821f382cd6256677 (diff) | |
download | linux-78975f23cba0cd195db01cdbd6eb48138a655890.tar.bz2 |
Merge branch 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
- Peter Rosin did some major rework on the locking of i2c muxes by
seperating parent-locked muxes and mux-locked muxes.
This avoids deadlocks/workarounds when the mux itself needs i2c
commands for muxing. And as a side-effect, other workarounds in the
media layer could be eliminated. Also, Peter stepped up as the i2c
mux maintainer and will keep an eye on these changes.
- major updates to the octeon driver
- add a helper to the core to generate the address+rw_bit octal and
make drivers use it
- quite a bunch of driver updates
* 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (84 commits)
i2c: rcar: add DMA support
i2c: st: Implement bus clear
i2c: only check scl functions when using generic recovery
i2c: algo-bit: declare i2c_bit_quirk_no_clk_stretch as static
i2c: tegra: disable clock before returning error
[media] rtl2832: regmap is aware of lockdep, drop local locking hack
[media] rtl2832_sdr: get rid of empty regmap wrappers
[media] rtl2832: change the i2c gate to be mux-locked
[media] si2168: change the i2c gate to be mux-locked
iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
i2c: mux: document i2c muxes and elaborate on parent-/mux-locked muxes
i2c: mux: relax locking of the top i2c adapter during mux-locked muxing
i2c: muxes always lock the parent adapter
i2c: allow adapter drivers to override the adapter locking
i2c: uniphier: add "\n" at the end of error log
i2c: mv64xxx: remove CONFIG_HAVE_CLK conditionals
i2c: mv64xxx: use clk_{prepare_enable,disable_unprepare}
i2c: mv64xxx: handle probe deferral for the clock
i2c: mv64xxx: enable the driver on ARCH_MVEBU
i2c: octeon: Add workaround for broken irqs on CN3860
...
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 2 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 1 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 79 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 3 |
4 files changed, 26 insertions, 59 deletions
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index 2771106fd650..f62b8bd9ad7e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client) } else return 0; /* no secondary addr, which is OK */ } - st->mux_client = i2c_new_device(st->mux_adapter, &info); + st->mux_client = i2c_new_device(st->muxc->adapter[0], &info); if (!st->mux_client) return -ENODEV; } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index d192953e9a38..0c2bded2b5b7 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -23,7 +23,6 @@ #include <linux/kfifo.h> #include <linux/spinlock.h> #include <linux/iio/iio.h> -#include <linux/i2c-mux.h> #include <linux/acpi.h> #include "inv_mpu_iio.h" diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 5ee4e0dc093e..9ba1179105bd 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -15,7 +15,6 @@ #include <linux/delay.h> #include <linux/err.h> #include <linux/i2c.h> -#include <linux/i2c-mux.h> #include <linux/iio/iio.h> #include <linux/module.h> #include "inv_mpu_iio.h" @@ -25,46 +24,16 @@ static const struct regmap_config inv_mpu_regmap_config = { .val_bits = 8, }; -/* - * The i2c read/write needs to happen in unlocked mode. As the parent - * adapter is common. If we use locked versions, it will fail as - * the mux adapter will lock the parent i2c adapter, while calling - * select/deselect functions. - */ -static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client, - u8 reg, u8 d) +static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) { - int ret; - u8 buf[2] = {reg, d}; - struct i2c_msg msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = sizeof(buf), - .buf = buf, - } - }; - - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret != 1) - return ret; - - return 0; -} - -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, - u32 chan_id) -{ - struct i2c_client *client = mux_priv; - struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct iio_dev *indio_dev = i2c_mux_priv(muxc); struct inv_mpu6050_state *st = iio_priv(indio_dev); int ret = 0; /* Use the same mutex which was used everywhere to protect power-op */ mutex_lock(&indio_dev->mlock); if (!st->powerup_count) { - ret = inv_mpu6050_write_reg_unlocked(client, - st->reg->pwr_mgmt_1, 0); + ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); if (ret) goto write_error; @@ -73,10 +42,9 @@ static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, } if (!ret) { st->powerup_count++; - ret = inv_mpu6050_write_reg_unlocked(client, - st->reg->int_pin_cfg, - INV_MPU6050_INT_PIN_CFG | - INV_MPU6050_BIT_BYPASS_EN); + ret = regmap_write(st->map, st->reg->int_pin_cfg, + INV_MPU6050_INT_PIN_CFG | + INV_MPU6050_BIT_BYPASS_EN); } write_error: mutex_unlock(&indio_dev->mlock); @@ -84,21 +52,18 @@ write_error: return ret; } -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, - void *mux_priv, u32 chan_id) +static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id) { - struct i2c_client *client = mux_priv; - struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct iio_dev *indio_dev = i2c_mux_priv(muxc); struct inv_mpu6050_state *st = iio_priv(indio_dev); mutex_lock(&indio_dev->mlock); /* It doesn't really mattter, if any of the calls fails */ - inv_mpu6050_write_reg_unlocked(client, st->reg->int_pin_cfg, - INV_MPU6050_INT_PIN_CFG); + regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG); st->powerup_count--; if (!st->powerup_count) - inv_mpu6050_write_reg_unlocked(client, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_SLEEP); + regmap_write(st->map, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); mutex_unlock(&indio_dev->mlock); return 0; @@ -160,16 +125,18 @@ static int inv_mpu_probe(struct i2c_client *client, return result; st = iio_priv(dev_get_drvdata(&client->dev)); - st->mux_adapter = i2c_add_mux_adapter(client->adapter, - &client->dev, - client, - 0, 0, 0, - inv_mpu6050_select_bypass, - inv_mpu6050_deselect_bypass); - if (!st->mux_adapter) { - result = -ENODEV; + st->muxc = i2c_mux_alloc(client->adapter, &client->dev, + 1, 0, I2C_MUX_LOCKED, + inv_mpu6050_select_bypass, + inv_mpu6050_deselect_bypass); + if (!st->muxc) { + result = -ENOMEM; goto out_unreg_device; } + st->muxc->priv = dev_get_drvdata(&client->dev); + result = i2c_mux_add_adapter(st->muxc, 0, 0, 0); + if (result) + goto out_unreg_device; result = inv_mpu_acpi_create_mux_client(client); if (result) @@ -178,7 +145,7 @@ static int inv_mpu_probe(struct i2c_client *client, return 0; out_del_mux: - i2c_del_mux_adapter(st->mux_adapter); + i2c_mux_del_adapters(st->muxc); out_unreg_device: inv_mpu_core_remove(&client->dev); return result; @@ -190,7 +157,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct inv_mpu6050_state *st = iio_priv(indio_dev); inv_mpu_acpi_delete_mux_client(client); - i2c_del_mux_adapter(st->mux_adapter); + i2c_mux_del_adapters(st->muxc); return inv_mpu_core_remove(&client->dev); } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index e302a49703bf..bb3cef6d7059 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ #include <linux/i2c.h> +#include <linux/i2c-mux.h> #include <linux/kfifo.h> #include <linux/spinlock.h> #include <linux/iio/iio.h> @@ -127,7 +128,7 @@ struct inv_mpu6050_state { const struct inv_mpu6050_hw *hw; enum inv_devices chip_type; spinlock_t time_stamp_lock; - struct i2c_adapter *mux_adapter; + struct i2c_mux_core *muxc; struct i2c_client *mux_client; unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; |