diff options
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r-- | drivers/base/regmap/regcache.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index bb317db6818f..da4d9843520f 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -545,9 +545,43 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg) return -ENOENT; } -int regcache_sync_block(struct regmap *map, void *block, - unsigned int block_base, unsigned int start, - unsigned int end) +static int regcache_sync_block_single(struct regmap *map, void *block, + unsigned int block_base, + unsigned int start, unsigned int end) +{ + unsigned int i, regtmp, val; + 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; + + 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; +} + +int regcache_sync_block_raw(struct regmap *map, void *block, + unsigned int block_base, unsigned int start, + unsigned int end) { unsigned int i, regtmp, val; const void *addr; @@ -568,14 +602,10 @@ int regcache_sync_block(struct regmap *map, void *block, 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); - } + addr = regcache_get_val_addr(map, block, i); + ret = _regmap_raw_write(map, regtmp, addr, + map->format.val_bytes, + false); map->cache_bypass = 0; if (ret != 0) @@ -586,3 +616,15 @@ int regcache_sync_block(struct regmap *map, void *block, return 0; } + +int regcache_sync_block(struct regmap *map, void *block, + unsigned int block_base, unsigned int start, + unsigned int end) +{ + if (regmap_can_raw_write(map)) + return regcache_sync_block_raw(map, block, block_base, + start, end); + else + return regcache_sync_block_single(map, block, block_base, + start, end); +} |