aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-29 15:32:28 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-30 09:52:25 -0400
commitf8bd822cbf953299b2957b45f6a43c08e7931ddc (patch)
treedd728ef96a28c472dbcaf1b95e43ebc1954666f4
parent78493f2d7b51d6f6d03982cee559c62dfab4c292 (diff)
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>
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regcache-rbtree.c48
-rw-r--r--drivers/base/regmap/regcache.c42
3 files changed, 51 insertions, 42 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index b01fe59fbfe8..01fbe48e8155 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -191,6 +191,9 @@ int regcache_read(struct regmap *map,
191int regcache_write(struct regmap *map, 191int regcache_write(struct regmap *map,
192 unsigned int reg, unsigned int value); 192 unsigned int reg, unsigned int value);
193int regcache_sync(struct regmap *map); 193int regcache_sync(struct regmap *map);
194int regcache_sync_block(struct regmap *map, void *block,
195 unsigned int block_base, unsigned int start,
196 unsigned int end);
194 197
195static inline const void *regcache_get_val_addr(struct regmap *map, 198static inline const void *regcache_get_val_addr(struct regmap *map,
196 const void *base, 199 const void *base,
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 00c3506f542f..1fdd8ec6af23 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -53,12 +53,6 @@ static unsigned int regcache_rbtree_get_register(struct regmap *map,
53 return regcache_get_val(map, rbnode->block, idx); 53 return regcache_get_val(map, rbnode->block, idx);
54} 54}
55 55
56static const void *regcache_rbtree_get_reg_addr(struct regmap *map,
57 struct regcache_rbtree_node *rbnode, unsigned int idx)
58{
59 return regcache_get_val_addr(map, rbnode->block, idx);
60}
61
62static void regcache_rbtree_set_register(struct regmap *map, 56static void regcache_rbtree_set_register(struct regmap *map,
63 struct regcache_rbtree_node *rbnode, 57 struct regcache_rbtree_node *rbnode,
64 unsigned int idx, unsigned int val) 58 unsigned int idx, unsigned int val)
@@ -390,11 +384,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
390 struct regcache_rbtree_ctx *rbtree_ctx; 384 struct regcache_rbtree_ctx *rbtree_ctx;
391 struct rb_node *node; 385 struct rb_node *node;
392 struct regcache_rbtree_node *rbnode; 386 struct regcache_rbtree_node *rbnode;
393 unsigned int regtmp;
394 unsigned int val;
395 const void *addr;
396 int ret; 387 int ret;
397 int i, base, end; 388 int base, end;
398 389
399 rbtree_ctx = map->cache; 390 rbtree_ctx = map->cache;
400 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { 391 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
@@ -417,40 +408,13 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
417 else 408 else
418 end = rbnode->blklen; 409 end = rbnode->blklen;
419 410
420 for (i = base; i < end; i++) { 411 ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg,
421 regtmp = rbnode->base_reg + (i * map->reg_stride); 412 base, end);
422 413 if (ret != 0)
423 if (!regcache_reg_present(map, regtmp)) 414 return ret;
424 continue;
425
426 val = regcache_rbtree_get_register(map, rbnode, i);
427
428 /* Is this the hardware default? If so skip. */
429 ret = regcache_lookup_reg(map, regtmp);
430 if (ret >= 0 && val == map->reg_defaults[ret].def)
431 continue;
432
433 map->cache_bypass = 1;
434
435 if (regmap_can_raw_write(map)) {
436 addr = regcache_rbtree_get_reg_addr(map,
437 rbnode, i);
438 ret = _regmap_raw_write(map, regtmp, addr,
439 map->format.val_bytes,
440 false);
441 } else {
442 ret = _regmap_write(map, regtmp, val);
443 }
444
445 map->cache_bypass = 0;
446 if (ret)
447 return ret;
448 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
449 regtmp, val);
450 }
451 } 415 }
452 416
453 return 0; 417 return regmap_async_complete(map);
454} 418}
455 419
456struct regcache_ops regcache_rbtree_ops = { 420struct regcache_ops regcache_rbtree_ops = {
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)
544 else 544 else
545 return -ENOENT; 545 return -ENOENT;
546} 546}
547
548int regcache_sync_block(struct regmap *map, void *block,
549 unsigned int block_base, unsigned int start,
550 unsigned int end)
551{
552 unsigned int i, regtmp, val;
553 const void *addr;
554 int ret;
555
556 for (i = start; i < end; i++) {
557 regtmp = block_base + (i * map->reg_stride);
558
559 if (!regcache_reg_present(map, regtmp))
560 continue;
561
562 val = regcache_get_val(map, block, i);
563
564 /* Is this the hardware default? If so skip. */
565 ret = regcache_lookup_reg(map, regtmp);
566 if (ret >= 0 && val == map->reg_defaults[ret].def)
567 continue;
568
569 map->cache_bypass = 1;
570
571 if (regmap_can_raw_write(map)) {
572 addr = regcache_get_val_addr(map, block, i);
573 ret = _regmap_raw_write(map, regtmp, addr,
574 map->format.val_bytes,
575 false);
576 } else {
577 ret = _regmap_write(map, regtmp, val);
578 }
579
580 map->cache_bypass = 0;
581 if (ret != 0)
582 return ret;
583 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
584 regtmp, val);
585 }
586
587 return 0;
588}