summaryrefslogtreecommitdiff
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 8fc544aa8c78..b65e8338243f 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -209,6 +209,18 @@ static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
return true;
}
+static void regmap_format_12_20_write(struct regmap *map,
+ unsigned int reg, unsigned int val)
+{
+ u8 *out = map->work_buf;
+
+ out[0] = reg >> 4;
+ out[1] = (reg << 4) | (val >> 16);
+ out[2] = val >> 8;
+ out[3] = val;
+}
+
+
static void regmap_format_2_6_write(struct regmap *map,
unsigned int reg, unsigned int val)
{
@@ -695,13 +707,17 @@ struct regmap *__regmap_init(struct device *dev,
}
}
+ ret = -EINVAL; /* Later error paths rely on this */
+
if (config->disable_locking) {
map->lock = map->unlock = regmap_lock_unlock_none;
+ map->can_sleep = config->can_sleep;
regmap_debugfs_disable(map);
} else if (config->lock && config->unlock) {
map->lock = config->lock;
map->unlock = config->unlock;
map->lock_arg = config->lock_arg;
+ map->can_sleep = config->can_sleep;
} else if (config->use_hwlock) {
map->hwlock = hwspin_lock_request_specific(config->hwlock_id);
if (!map->hwlock) {
@@ -737,6 +753,7 @@ struct regmap *__regmap_init(struct device *dev,
mutex_init(&map->mutex);
map->lock = regmap_lock_mutex;
map->unlock = regmap_unlock_mutex;
+ map->can_sleep = true;
lockdep_set_class_and_name(&map->mutex,
lock_key, lock_name);
}
@@ -867,6 +884,16 @@ struct regmap *__regmap_init(struct device *dev,
}
break;
+ case 12:
+ switch (config->val_bits) {
+ case 20:
+ map->format.format_write = regmap_format_12_20_write;
+ break;
+ default:
+ goto err_hwlock;
+ }
+ break;
+
case 8:
map->format.format_reg = regmap_format_8;
break;
@@ -1443,6 +1470,8 @@ void regmap_exit(struct regmap *map)
}
if (map->hwlock)
hwspin_lock_free(map->hwlock);
+ if (map->lock == regmap_lock_mutex)
+ mutex_destroy(&map->mutex);
kfree_const(map->name);
kfree(map->patch);
kfree(map);
@@ -2330,8 +2359,12 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
if (ret != 0)
return ret;
- if (regs[i].delay_us)
- udelay(regs[i].delay_us);
+ if (regs[i].delay_us) {
+ if (map->can_sleep)
+ fsleep(regs[i].delay_us);
+ else
+ udelay(regs[i].delay_us);
+ }
base += n;
n = 0;
@@ -2367,8 +2400,12 @@ static int _regmap_multi_reg_write(struct regmap *map,
if (ret != 0)
return ret;
- if (regs[i].delay_us)
- udelay(regs[i].delay_us);
+ if (regs[i].delay_us) {
+ if (map->can_sleep)
+ fsleep(regs[i].delay_us);
+ else
+ udelay(regs[i].delay_us);
+ }
}
return 0;
}