diff options
author | Jin Park <jinyoungp@nvidia.com> | 2011-08-19 19:58:41 +0900 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-19 15:36:52 -0700 |
commit | ba16a9c9891fc415add3fbe1fe794a27b4213e77 (patch) | |
tree | 035b7b4dd4d69e8f3ff54cc42dbb65434f507060 | |
parent | 2cb7615e6400838bbeeb8270c7af9e85b54a134f (diff) |
mfd: aat2870: Add io mutex into I2C update function.
Adding io mutex into I2C update function to prevent race condition
problem.
Signed-off-by: Jin Park <jinyoungp@nvidia.com>
Change-Id: Ibff85a825a6716bfc88eea55704bbbcc565cf962
Reviewed-on: http://git-master/r/48136
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r-- | drivers/mfd/aat2870-core.c | 99 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 2 | ||||
-rw-r--r-- | drivers/regulator/aat2870-regulator.c | 20 | ||||
-rw-r--r-- | include/linux/mfd/aat2870.h | 3 |
4 files changed, 60 insertions, 64 deletions
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 6d7e868b8b23..9deb3f34751b 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -103,53 +103,41 @@ static struct mfd_cell aat2870_devs[] = { }, }; -static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val) +static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val) { - struct i2c_client *client = aat2870->client; - int ret = 0; + int ret; if (addr >= AAT2870_REG_NUM) { dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr); return -EINVAL; } - mutex_lock(&aat2870->io_lock); - if (!aat2870->reg_cache[addr].readable) { *val = aat2870->reg_cache[addr].value; - goto out_unlock; + goto out; } - ret = i2c_master_send(client, &addr, 1); + ret = i2c_master_send(aat2870->client, &addr, 1); if (ret < 0) - goto out_unlock; - if (ret != 1) { - ret = -EIO; - goto out_unlock; - } + return ret; + if (ret != 1) + return -EIO; - ret = i2c_master_recv(client, val, 1); + ret = i2c_master_recv(aat2870->client, val, 1); if (ret < 0) - goto out_unlock; - if (ret != 1) { - ret = -EIO; - goto out_unlock; - } - - ret = 0; - -out_unlock: - mutex_unlock(&aat2870->io_lock); - dev_dbg(&client->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val); + return ret; + if (ret != 1) + return -EIO; - return ret; +out: + dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val); + return 0; } -static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) +static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) { - struct i2c_client *client = aat2870->client; u8 msg[2]; - int ret = 0; + int ret; if (addr >= AAT2870_REG_NUM) { dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr); @@ -162,47 +150,62 @@ static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) return -EINVAL; } - mutex_lock(&aat2870->io_lock); - msg[0] = addr; msg[1] = val; - ret = i2c_master_send(client, msg, 2); + ret = i2c_master_send(aat2870->client, msg, 2); if (ret < 0) - goto out_unlock; - if (ret != 2) { - ret = -EIO; - goto out_unlock; - } + return ret; + if (ret != 2) + return -EIO; aat2870->reg_cache[addr].value = val; - ret = 0; -out_unlock: + dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val); + return 0; +} + +static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val) +{ + int ret; + + mutex_lock(&aat2870->io_lock); + ret = __aat2870_read(aat2870, addr, val); + mutex_unlock(&aat2870->io_lock); + + return ret; +} + +static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) +{ + int ret; + + mutex_lock(&aat2870->io_lock); + ret = __aat2870_write(aat2870, addr, val); mutex_unlock(&aat2870->io_lock); - dev_dbg(&client->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val); return ret; } -static int aat2870_update_bits(struct aat2870_data *aat2870, u8 addr, - u8 mask, u8 val) +static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask, + u8 val) { int change; u8 old_val, new_val; int ret; - ret = aat2870->read(aat2870, addr, &old_val); + mutex_lock(&aat2870->io_lock); + + ret = __aat2870_read(aat2870, addr, &old_val); if (ret) - return ret; + goto out_unlock; new_val = (old_val & ~mask) | (val & mask); change = old_val != new_val; if (change) - ret = aat2870->write(aat2870, addr, new_val); + ret = __aat2870_write(aat2870, addr, new_val); - dev_dbg(&aat2870->client->dev, - "update_bits: change=%d, addr=0x%02x, old=0x%02x, new=0x%02x\n", - change, addr, old_val, new_val); +out_unlock: + mutex_unlock(&aat2870->io_lock); return ret; } @@ -396,7 +399,7 @@ static int aat2870_i2c_probe(struct i2c_client *client, aat2870->uninit = pdata->uninit; aat2870->read = aat2870_read; aat2870->write = aat2870_write; - aat2870->update_bits = aat2870_update_bits; + aat2870->update = aat2870_update; mutex_init(&aat2870->io_lock); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index ae25549efeef..db02ef4ca442 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -295,7 +295,7 @@ config REGULATOR_GPIO_SWITCH gpios. config REGULATOR_AAT2870 - bool "AnalogicTech AAT2870 Regulators" + tristate "AnalogicTech AAT2870 Regulators" depends on MFD_AAT2870_CORE help If you have a AnalogicTech AAT2870 say Y to enable the diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index a119fff6eefc..ae6ddaf3e5a2 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -82,8 +82,8 @@ static int aat2870_ldo_set_voltage(struct regulator_dev *rdev, if (i >= ri->desc.n_voltages) return -EINVAL; - return aat2870->update_bits(aat2870, ri->voltage_addr, - ri->voltage_mask, val); + return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask, + val); } static int aat2870_ldo_get_voltage(struct regulator_dev *rdev) @@ -109,8 +109,8 @@ static int aat2870_ldo_enable(struct regulator_dev *rdev) struct aat2870_regulator *ri = rdev_get_drvdata(rdev); struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); - return aat2870->update_bits(aat2870, ri->enable_addr, - ri->enable_mask, ri->enable_mask); + return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, + ri->enable_mask); } static int aat2870_ldo_disable(struct regulator_dev *rdev) @@ -118,8 +118,7 @@ static int aat2870_ldo_disable(struct regulator_dev *rdev) struct aat2870_regulator *ri = rdev_get_drvdata(rdev); struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); - return aat2870->update_bits(aat2870, ri->enable_addr, - ri->enable_mask, 0); + return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0); } static int aat2870_ldo_is_enabled(struct regulator_dev *rdev) @@ -202,15 +201,9 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) static int aat2870_regulator_probe(struct platform_device *pdev) { - struct regulator_init_data *init_data = pdev->dev.platform_data; struct aat2870_regulator *ri; struct regulator_dev *rdev; - if (!init_data) { - dev_err(&pdev->dev, "No regulator init data\n"); - return -ENXIO; - } - ri = aat2870_get_regulator(pdev->id); if (!ri) { dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id); @@ -218,7 +211,8 @@ static int aat2870_regulator_probe(struct platform_device *pdev) } ri->pdev = pdev; - rdev = regulator_register(&ri->desc, &pdev->dev, init_data, ri); + rdev = regulator_register(&ri->desc, &pdev->dev, + pdev->dev.platform_data, ri); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h index d34944e784cf..89212df05622 100644 --- a/include/linux/mfd/aat2870.h +++ b/include/linux/mfd/aat2870.h @@ -145,8 +145,7 @@ struct aat2870_data { /* i2c io funcntions */ int (*read)(struct aat2870_data *aat2870, u8 addr, u8 *val); int (*write)(struct aat2870_data *aat2870, u8 addr, u8 val); - int (*update_bits)(struct aat2870_data *aat2870, u8 addr, u8 mask, - u8 val); + int (*update)(struct aat2870_data *aat2870, u8 addr, u8 mask, u8 val); /* for debugfs */ struct dentry *dentry_root; |