summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJin Park <jinyoungp@nvidia.com>2011-08-19 19:58:41 +0900
committerVarun Colbert <vcolbert@nvidia.com>2011-08-19 15:36:52 -0700
commitba16a9c9891fc415add3fbe1fe794a27b4213e77 (patch)
tree035b7b4dd4d69e8f3ff54cc42dbb65434f507060
parent2cb7615e6400838bbeeb8270c7af9e85b54a134f (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.c99
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/aat2870-regulator.c20
-rw-r--r--include/linux/mfd/aat2870.h3
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;