]> git.karo-electronics.de Git - linux-beck.git/commitdiff
regmap: Allow drivers to sync only part of the register cache
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 23 Feb 2012 20:53:37 +0000 (20:53 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 24 Feb 2012 14:52:41 +0000 (14:52 +0000)
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>
drivers/base/regmap/regcache.c
include/linux/regmap.h

index aec5a7486a294d6837bf8bb087d97dd8bee60342..b35f8751471d8950a9fbcb306bda29fc34707113 100644 (file)
@@ -298,6 +298,51 @@ out:
 }
 EXPORT_SYMBOL_GPL(regcache_sync);
 
+/**
+ * regcache_sync_region: Sync part  of the register cache with the hardware.
+ *
+ * @map: map to sync.
+ * @min: first register to sync
+ * @max: last register to sync
+ *
+ * Write all non-default register values in the specified region to
+ * the hardware.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_sync_region(struct regmap *map, unsigned int min,
+                        unsigned int max)
+{
+       int ret = 0;
+       const char *name;
+       unsigned int bypass;
+
+       BUG_ON(!map->cache_ops || !map->cache_ops->sync);
+
+       mutex_lock(&map->lock);
+
+       /* Remember the initial bypass state */
+       bypass = map->cache_bypass;
+
+       name = map->cache_ops->name;
+       dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max);
+
+       trace_regcache_sync(map->dev, name, "start region");
+
+       if (!map->cache_dirty)
+               goto out;
+
+       ret = map->cache_ops->sync(map, min, max);
+
+out:
+       trace_regcache_sync(map->dev, name, "stop region");
+       /* Restore the bypass state */
+       map->cache_bypass = bypass;
+       mutex_unlock(&map->lock);
+
+       return ret;
+}
+
 /**
  * regcache_cache_only: Put a register map into cache only mode
  *
index 860739a8a6dde429d637e27202df78509342fb71..5ff7d44730e5c9597b31e1a7e36f8596f20c6c05 100644 (file)
@@ -145,6 +145,8 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
                             bool *change);
 
 int regcache_sync(struct regmap *map);
+int regcache_sync_region(struct regmap *map, unsigned int min,
+                        unsigned int max);
 void regcache_cache_only(struct regmap *map, bool enable);
 void regcache_cache_bypass(struct regmap *map, bool enable);
 void regcache_mark_dirty(struct regmap *map);