diff options
-rw-r--r-- | drivers/base/regmap/internal.h | 3 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 19 | ||||
-rw-r--r-- | include/linux/regmap.h | 3 |
3 files changed, 21 insertions, 4 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 3d80c4b43f72..8a59359e145f 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -161,6 +161,9 @@ struct regmap { void *selector_work_buf; /* Scratch buffer used for selector */ struct hwspinlock *hwlock; + + /* if set, the regmap core can sleep */ + bool can_sleep; }; struct regcache_ops { diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index a417cb1a11dc..2807e544658e 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -697,11 +697,13 @@ struct regmap *__regmap_init(struct device *dev, 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 +739,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); } @@ -2230,8 +2233,12 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map, if (ret != 0) return ret; - if (regs[i].delay_us) - fsleep(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; @@ -2267,8 +2274,12 @@ static int _regmap_multi_reg_write(struct regmap *map, if (ret != 0) return ret; - if (regs[i].delay_us) - fsleep(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; } diff --git a/include/linux/regmap.h b/include/linux/regmap.h index d865d8fea535..0c49d59168b5 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -342,6 +342,7 @@ typedef void (*regmap_unlock)(void *); * @hwlock_id: Specify the hardware spinlock id. * @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE, * HWLOCK_IRQ or 0. + * @can_sleep: Optional, specifies whether regmap operations can sleep. */ struct regmap_config { const char *name; @@ -398,6 +399,8 @@ struct regmap_config { bool use_hwlock; unsigned int hwlock_id; unsigned int hwlock_mode; + + bool can_sleep; }; /** |