summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2014-02-05 14:40:26 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2014-02-05 07:32:14 -0800
commit2a718abbac2b08cbb6672ccd46559bffff3a930c (patch)
treefb75b274f74b094c88dbc06bd41643171527a9b6 /drivers/mfd
parentad1dc56fa44ef4058ca3ea38e6ba3be8ba226cb4 (diff)
mfd: as3722: provide customized lock to regmap
Add customized locking mechanism for register access of as3722 device through regmap. This will help to bypass the locking mechanism when as3722 device get accessed in the atomic context. Bug 1443347 Change-Id: I43bd44554759387135e1e03741655ebd6472631f Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/363719
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/as3722.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index 9dc4554292ae..b6365a2e8bba 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -322,6 +322,29 @@ static const struct regmap_range as3722_writable_ranges[] = {
regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG),
};
+static void as3722_regmap_config_lock(void *lock)
+{
+ struct as3722 *as3722 = lock;
+
+ if (as3722->shutdown && (in_atomic() || irqs_disabled())) {
+ dev_info(as3722->dev, "Xfer without lock\n");
+ return;
+ }
+
+ mutex_lock(&as3722->mutex_config);
+}
+
+static void as3722_regmap_config_unlock(void *lock)
+{
+ struct as3722 *as3722 = lock;
+
+ if (as3722->shutdown && (in_atomic() || irqs_disabled()))
+ return;
+
+ mutex_unlock(&as3722->mutex_config);
+}
+
+
static const struct regmap_access_table as3722_writable_table = {
.yes_ranges = as3722_writable_ranges,
.n_yes_ranges = ARRAY_SIZE(as3722_writable_ranges),
@@ -337,7 +360,7 @@ static const struct regmap_access_table as3722_volatile_table = {
.n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges),
};
-static const struct regmap_config as3722_regmap_config = {
+static struct regmap_config as3722_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = AS3722_MAX_REGISTER,
@@ -345,6 +368,8 @@ static const struct regmap_config as3722_regmap_config = {
.rd_table = &as3722_readable_table,
.wr_table = &as3722_writable_table,
.volatile_table = &as3722_volatile_table,
+ .lock = as3722_regmap_config_lock,
+ .unlock = as3722_regmap_config_unlock,
};
static int as3722_i2c_of_probe(struct i2c_client *i2c,
@@ -411,6 +436,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
as3722->dev = &i2c->dev;
as3722->chip_irq = i2c->irq;
i2c_set_clientdata(i2c, as3722);
+ as3722->client = i2c;
ret = as3722_i2c_non_of_probe(i2c, as3722);
if (ret < 0) {
@@ -419,7 +445,10 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
return ret;
}
- as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config);
+ mutex_init(&as3722->mutex_config);
+ as3722_regmap_config.lock_arg = as3722;
+ as3722->regmap = devm_regmap_init_i2c(i2c,
+ (const struct regmap_config *)&as3722_regmap_config);
if (IS_ERR(as3722->regmap)) {
ret = PTR_ERR(as3722->regmap);
dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
@@ -477,6 +506,13 @@ static int as3722_i2c_remove(struct i2c_client *i2c)
return 0;
}
+static void as3722_i2c_shutdown(struct i2c_client *i2c)
+{
+ struct as3722 *as3722 = i2c_get_clientdata(i2c);
+
+ as3722->shutdown = true;
+}
+
static const struct of_device_id as3722_of_match[] = {
{ .compatible = "ams,as3722", },
{},
@@ -497,6 +533,7 @@ static struct i2c_driver as3722_i2c_driver = {
},
.probe = as3722_i2c_probe,
.remove = as3722_i2c_remove,
+ .shutdown = as3722_i2c_shutdown,
.id_table = as3722_i2c_id,
};