summaryrefslogtreecommitdiff
path: root/drivers/base/regmap/regcache.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-29 23:32:28 +0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-30 17:52:25 +0400
commitf8bd822cbf953299b2957b45f6a43c08e7931ddc (patch)
treedd728ef96a28c472dbcaf1b95e43ebc1954666f4 /drivers/base/regmap/regcache.c
parent78493f2d7b51d6f6d03982cee559c62dfab4c292 (diff)
downloadlinux-f8bd822cbf953299b2957b45f6a43c08e7931ddc.tar.xz
regmap: cache: Factor out block sync
The idea of holding blocks of registers in device format is shared between at least rbtree and lzo cache formats so split out the loop that does the sync from the rbtree code so optimisations on it can be reused. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Reviewed-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r--drivers/base/regmap/regcache.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 0fedf4fa0116..bb317db6818f 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -544,3 +544,45 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
else
return -ENOENT;
}
+
+int regcache_sync_block(struct regmap *map, void *block,
+ unsigned int block_base, unsigned int start,
+ unsigned int end)
+{
+ unsigned int i, regtmp, val;
+ const void *addr;
+ int ret;
+
+ for (i = start; i < end; i++) {
+ regtmp = block_base + (i * map->reg_stride);
+
+ if (!regcache_reg_present(map, regtmp))
+ 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)
+ continue;
+
+ map->cache_bypass = 1;
+
+ if (regmap_can_raw_write(map)) {
+ addr = regcache_get_val_addr(map, block, i);
+ ret = _regmap_raw_write(map, regtmp, addr,
+ map->format.val_bytes,
+ false);
+ } else {
+ ret = _regmap_write(map, regtmp, val);
+ }
+
+ map->cache_bypass = 0;
+ if (ret != 0)
+ return ret;
+ dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+ regtmp, val);
+ }
+
+ return 0;
+}