diff options
| -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"); |
