Commit 4d4cfd1656b5f6c88eae51c40741a695b108b006

Authored by Mark Brown
1 parent ac8d91c801

regmap: Allow drivers to sync only part of the register cache

Provide a regcache_sync_region() operation which allows drivers to
write only part of the cache back to the hardware. This is intended
for use in cases like power domains or DSP memories where part of the
device register map may be reset without fully resetting the device.

Fully supporting these devices is likely to require additional work to
make specific regions of the register map cache only while they are in
reset, but this is enough for most devices.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 2 changed files with 47 additions and 0 deletions Side-by-side Diff

drivers/base/regmap/regcache.c
... ... @@ -299,6 +299,51 @@
299 299 EXPORT_SYMBOL_GPL(regcache_sync);
300 300  
301 301 /**
  302 + * regcache_sync_region: Sync part of the register cache with the hardware.
  303 + *
  304 + * @map: map to sync.
  305 + * @min: first register to sync
  306 + * @max: last register to sync
  307 + *
  308 + * Write all non-default register values in the specified region to
  309 + * the hardware.
  310 + *
  311 + * Return a negative value on failure, 0 on success.
  312 + */
  313 +int regcache_sync_region(struct regmap *map, unsigned int min,
  314 + unsigned int max)
  315 +{
  316 + int ret = 0;
  317 + const char *name;
  318 + unsigned int bypass;
  319 +
  320 + BUG_ON(!map->cache_ops || !map->cache_ops->sync);
  321 +
  322 + mutex_lock(&map->lock);
  323 +
  324 + /* Remember the initial bypass state */
  325 + bypass = map->cache_bypass;
  326 +
  327 + name = map->cache_ops->name;
  328 + dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max);
  329 +
  330 + trace_regcache_sync(map->dev, name, "start region");
  331 +
  332 + if (!map->cache_dirty)
  333 + goto out;
  334 +
  335 + ret = map->cache_ops->sync(map, min, max);
  336 +
  337 +out:
  338 + trace_regcache_sync(map->dev, name, "stop region");
  339 + /* Restore the bypass state */
  340 + map->cache_bypass = bypass;
  341 + mutex_unlock(&map->lock);
  342 +
  343 + return ret;
  344 +}
  345 +
  346 +/**
302 347 * regcache_cache_only: Put a register map into cache only mode
303 348 *
304 349 * @map: map to configure
include/linux/regmap.h
... ... @@ -145,6 +145,8 @@
145 145 bool *change);
146 146  
147 147 int regcache_sync(struct regmap *map);
  148 +int regcache_sync_region(struct regmap *map, unsigned int min,
  149 + unsigned int max);
148 150 void regcache_cache_only(struct regmap *map, bool enable);
149 151 void regcache_cache_bypass(struct regmap *map, bool enable);
150 152 void regcache_mark_dirty(struct regmap *map);