diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 45 |
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; } |