aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regcache.c
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@chromium.org>2015-05-05 18:14:14 -0400
committerMark Brown <broonie@kernel.org>2015-05-06 08:01:25 -0400
commit1c79771a7270278e6ff486edf4dfeb8c4fc01ee0 (patch)
tree7abac0b5aa1dc6601f3b8f541f393643b86207df /drivers/base/regmap/regcache.c
parent3969fa080661dcdf20d04392b900189086e04c2c (diff)
regmap: Use regcache_mark_dirty() to indicate power loss or reset
Existing regmap users call regcache_mark_dirty() as part of the suspend/resume sequence, to tell regcache that non-default values need to be resynced post-resume. Add an internal "no_sync_defaults" regmap flag to remember this state, so that regcache_sync() can differentiate between these two cases: 1) HW was reset, so any cache values that match map->reg_defaults can be safely skipped. On some chips there are a lot of registers in the reg_defaults list, so this optimization speeds things up quite a bit. 2) HW was not reset (maybe it was just clock-gated), so if we cached any writes, they should be sent to the hardware regardless of whether they match the HW default. Currently this will write out all values in the regcache, since we don't maintain per-register dirty bits. Suggested-by: Mark Brown <broonie@kernel.org> Signed-off-by: Kevin Cernekee <cernekee@chromium.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r--drivers/base/regmap/regcache.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index c58493eaf050..b9862d741a56 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -254,6 +254,10 @@ static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
254{ 254{
255 int ret; 255 int ret;
256 256
257 /* If we don't know the chip just got reset, then sync everything. */
258 if (!map->no_sync_defaults)
259 return true;
260
257 /* Is this the hardware default? If so skip. */ 261 /* Is this the hardware default? If so skip. */
258 ret = regcache_lookup_reg(map, reg); 262 ret = regcache_lookup_reg(map, reg);
259 if (ret >= 0 && val == map->reg_defaults[ret].def) 263 if (ret >= 0 && val == map->reg_defaults[ret].def)
@@ -352,6 +356,7 @@ out:
352 /* Restore the bypass state */ 356 /* Restore the bypass state */
353 map->async = false; 357 map->async = false;
354 map->cache_bypass = bypass; 358 map->cache_bypass = bypass;
359 map->no_sync_defaults = false;
355 map->unlock(map->lock_arg); 360 map->unlock(map->lock_arg);
356 361
357 regmap_async_complete(map); 362 regmap_async_complete(map);
@@ -407,6 +412,7 @@ out:
407 /* Restore the bypass state */ 412 /* Restore the bypass state */
408 map->cache_bypass = bypass; 413 map->cache_bypass = bypass;
409 map->async = false; 414 map->async = false;
415 map->no_sync_defaults = false;
410 map->unlock(map->lock_arg); 416 map->unlock(map->lock_arg);
411 417
412 regmap_async_complete(map); 418 regmap_async_complete(map);
@@ -471,18 +477,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
471EXPORT_SYMBOL_GPL(regcache_cache_only); 477EXPORT_SYMBOL_GPL(regcache_cache_only);
472 478
473/** 479/**
474 * regcache_mark_dirty: Mark the register cache as dirty 480 * regcache_mark_dirty: Indicate that HW registers were reset to default values
475 * 481 *
476 * @map: map to mark 482 * @map: map to mark
477 * 483 *
478 * Mark the register cache as dirty, for example due to the device 484 * Inform regcache that the device has been powered down or reset, so that
479 * having been powered down for suspend. If the cache is not marked 485 * on resume, regcache_sync() knows to write out all non-default values
480 * as dirty then the cache sync will be suppressed. 486 * stored in the cache.
487 *
488 * If this function is not called, regcache_sync() will assume that
489 * the hardware state still matches the cache state, modulo any writes that
490 * happened when cache_only was true.
481 */ 491 */
482void regcache_mark_dirty(struct regmap *map) 492void regcache_mark_dirty(struct regmap *map)
483{ 493{
484 map->lock(map->lock_arg); 494 map->lock(map->lock_arg);
485 map->cache_dirty = true; 495 map->cache_dirty = true;
496 map->no_sync_defaults = true;
486 map->unlock(map->lock_arg); 497 map->unlock(map->lock_arg);
487} 498}
488EXPORT_SYMBOL_GPL(regcache_mark_dirty); 499EXPORT_SYMBOL_GPL(regcache_mark_dirty);