diff options
author | Maarten ter Huurne <maarten@treewalker.org> | 2013-06-02 18:15:26 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-06-03 06:50:50 -0400 |
commit | d856fce41b74ecf2004d99f781e44abd7815d7f8 (patch) | |
tree | 3f0c545028c60409c87d2b6e39d3cd6a2bac24fa | |
parent | 92ab1aab59c61b3e05200b9aa0e05ab770059142 (diff) |
regmap: Implemented default cache sync operation
This can be used for cache types for which syncing values one by one is
equally efficient as syncing a range, such as the flat cache.
Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | drivers/base/regmap/regcache.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4bfa219ef37d..e69102696533 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -250,6 +250,38 @@ int regcache_write(struct regmap *map, | |||
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | 252 | ||
253 | static int regcache_default_sync(struct regmap *map, unsigned int min, | ||
254 | unsigned int max) | ||
255 | { | ||
256 | unsigned int reg; | ||
257 | |||
258 | for (reg = min; reg <= max; reg++) { | ||
259 | unsigned int val; | ||
260 | int ret; | ||
261 | |||
262 | if (regmap_volatile(map, reg)) | ||
263 | continue; | ||
264 | |||
265 | ret = regcache_read(map, reg, &val); | ||
266 | if (ret) | ||
267 | return ret; | ||
268 | |||
269 | /* Is this the hardware default? If so skip. */ | ||
270 | ret = regcache_lookup_reg(map, reg); | ||
271 | if (ret >= 0 && val == map->reg_defaults[ret].def) | ||
272 | continue; | ||
273 | |||
274 | map->cache_bypass = 1; | ||
275 | ret = _regmap_write(map, reg, val); | ||
276 | map->cache_bypass = 0; | ||
277 | if (ret) | ||
278 | return ret; | ||
279 | dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
253 | /** | 285 | /** |
254 | * regcache_sync: Sync the register cache with the hardware. | 286 | * regcache_sync: Sync the register cache with the hardware. |
255 | * | 287 | * |
@@ -268,7 +300,7 @@ int regcache_sync(struct regmap *map) | |||
268 | const char *name; | 300 | const char *name; |
269 | unsigned int bypass; | 301 | unsigned int bypass; |
270 | 302 | ||
271 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); | 303 | BUG_ON(!map->cache_ops); |
272 | 304 | ||
273 | map->lock(map->lock_arg); | 305 | map->lock(map->lock_arg); |
274 | /* Remember the initial bypass state */ | 306 | /* Remember the initial bypass state */ |
@@ -297,7 +329,10 @@ int regcache_sync(struct regmap *map) | |||
297 | } | 329 | } |
298 | map->cache_bypass = 0; | 330 | map->cache_bypass = 0; |
299 | 331 | ||
300 | ret = map->cache_ops->sync(map, 0, map->max_register); | 332 | if (map->cache_ops->sync) |
333 | ret = map->cache_ops->sync(map, 0, map->max_register); | ||
334 | else | ||
335 | ret = regcache_default_sync(map, 0, map->max_register); | ||
301 | 336 | ||
302 | if (ret == 0) | 337 | if (ret == 0) |
303 | map->cache_dirty = false; | 338 | map->cache_dirty = false; |
@@ -331,7 +366,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min, | |||
331 | const char *name; | 366 | const char *name; |
332 | unsigned int bypass; | 367 | unsigned int bypass; |
333 | 368 | ||
334 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); | 369 | BUG_ON(!map->cache_ops); |
335 | 370 | ||
336 | map->lock(map->lock_arg); | 371 | map->lock(map->lock_arg); |
337 | 372 | ||
@@ -346,7 +381,10 @@ int regcache_sync_region(struct regmap *map, unsigned int min, | |||
346 | if (!map->cache_dirty) | 381 | if (!map->cache_dirty) |
347 | goto out; | 382 | goto out; |
348 | 383 | ||
349 | ret = map->cache_ops->sync(map, min, max); | 384 | if (map->cache_ops->sync) |
385 | ret = map->cache_ops->sync(map, min, max); | ||
386 | else | ||
387 | ret = regcache_default_sync(map, min, max); | ||
350 | 388 | ||
351 | out: | 389 | out: |
352 | trace_regcache_sync(map->dev, name, "stop region"); | 390 | trace_regcache_sync(map->dev, name, "stop region"); |