return 0;
}
+static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+ unsigned int val)
+{
+ int ret;
+
+ /* If we don't know the chip just got reset, then sync everything. */
+ if (!map->no_sync_defaults)
+ return true;
+
+ /* Is this the hardware default? If so skip. */
+ ret = regcache_lookup_reg(map, reg);
+ if (ret >= 0 && val == map->reg_defaults[ret].def)
+ return false;
+ return true;
+}
+
static int regcache_default_sync(struct regmap *map, unsigned int min,
unsigned int max)
{
if (ret)
return ret;
- /* Is this the hardware default? If so skip. */
- ret = regcache_lookup_reg(map, reg);
- if (ret >= 0 && val == map->reg_defaults[ret].def)
+ if (!regcache_reg_needs_sync(map, reg, val))
continue;
map->cache_bypass = 1;
/* Restore the bypass state */
map->async = false;
map->cache_bypass = bypass;
+ map->no_sync_defaults = false;
map->unlock(map->lock_arg);
regmap_async_complete(map);
/* Restore the bypass state */
map->cache_bypass = bypass;
map->async = false;
+ map->no_sync_defaults = false;
map->unlock(map->lock_arg);
regmap_async_complete(map);
EXPORT_SYMBOL_GPL(regcache_cache_only);
/**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
*
* @map: map to mark
*
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend. If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
*/
void regcache_mark_dirty(struct regmap *map)
{
map->lock(map->lock_arg);
map->cache_dirty = true;
+ map->no_sync_defaults = true;
map->unlock(map->lock_arg);
}
EXPORT_SYMBOL_GPL(regcache_mark_dirty);
continue;
val = regcache_get_val(map, block, i);
-
- /* Is this the hardware default? If so skip. */
- ret = regcache_lookup_reg(map, regtmp);
- if (ret >= 0 && val == map->reg_defaults[ret].def)
+ if (!regcache_reg_needs_sync(map, regtmp, val))
continue;
map->cache_bypass = 1;
}
val = regcache_get_val(map, block, i);
-
- /* Is this the hardware default? If so skip. */
- ret = regcache_lookup_reg(map, regtmp);
- if (ret >= 0 && val == map->reg_defaults[ret].def) {
+ if (!regcache_reg_needs_sync(map, regtmp, val)) {
ret = regcache_sync_block_raw_flush(map, &data,
base, regtmp);
if (ret != 0)