regmap: implement register striding
[deliverable/linux.git] / drivers / base / regmap / regcache-rbtree.c
index fb14a6343d4f52c780d186a31a3a39313dac02be..e6732cf7c06eea7aedf62e383a390ef3e61c3fe2 100644 (file)
@@ -39,11 +39,12 @@ struct regcache_rbtree_ctx {
 };
 
 static inline void regcache_rbtree_get_base_top_reg(
+       struct regmap *map,
        struct regcache_rbtree_node *rbnode,
        unsigned int *base, unsigned int *top)
 {
        *base = rbnode->base_reg;
-       *top = rbnode->base_reg + rbnode->blklen - 1;
+       *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
 }
 
 static unsigned int regcache_rbtree_get_register(
@@ -70,7 +71,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
 
        rbnode = rbtree_ctx->cached_rbnode;
        if (rbnode) {
-               regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+               regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+                                                &top_reg);
                if (reg >= base_reg && reg <= top_reg)
                        return rbnode;
        }
@@ -78,7 +80,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
        node = rbtree_ctx->root.rb_node;
        while (node) {
                rbnode = container_of(node, struct regcache_rbtree_node, node);
-               regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+               regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+                                                &top_reg);
                if (reg >= base_reg && reg <= top_reg) {
                        rbtree_ctx->cached_rbnode = rbnode;
                        return rbnode;
@@ -92,7 +95,7 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
        return NULL;
 }
 
-static int regcache_rbtree_insert(struct rb_root *root,
+static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root,
                                  struct regcache_rbtree_node *rbnode)
 {
        struct rb_node **new, *parent;
@@ -106,7 +109,7 @@ static int regcache_rbtree_insert(struct rb_root *root,
                rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
                                          node);
                /* base and top registers of the current rbnode */
-               regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+               regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
                                                 &top_reg_tmp);
                /* base register of the rbnode to be added */
                base_reg = rbnode->base_reg;
@@ -138,24 +141,31 @@ static int rbtree_show(struct seq_file *s, void *ignored)
        unsigned int base, top;
        int nodes = 0;
        int registers = 0;
+       int this_registers, average;
 
-       mutex_lock(&map->lock);
+       map->lock(map);
 
        for (node = rb_first(&rbtree_ctx->root); node != NULL;
             node = rb_next(node)) {
                n = container_of(node, struct regcache_rbtree_node, node);
 
-               regcache_rbtree_get_base_top_reg(n, &base, &top);
-               seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1);
+               regcache_rbtree_get_base_top_reg(map, n, &base, &top);
+               this_registers = ((top - base) / map->reg_stride) + 1;
+               seq_printf(s, "%x-%x (%d)\n", base, top, this_registers);
 
                nodes++;
-               registers += top - base + 1;
+               registers += this_registers;
        }
 
+       if (nodes)
+               average = registers / nodes;
+       else
+               average = 0;
+
        seq_printf(s, "%d nodes, %d registers, average %d registers\n",
-                  nodes, registers, registers / nodes);
+                  nodes, registers, average);
 
-       mutex_unlock(&map->lock);
+       map->unlock(map);
 
        return 0;
 }
@@ -249,7 +259,7 @@ static int regcache_rbtree_read(struct regmap *map,
 
        rbnode = regcache_rbtree_lookup(map, reg);
        if (rbnode) {
-               reg_tmp = reg - rbnode->base_reg;
+               reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
                *value = regcache_rbtree_get_register(rbnode, reg_tmp,
                                                      map->cache_word_size);
        } else {
@@ -304,7 +314,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
         */
        rbnode = regcache_rbtree_lookup(map, reg);
        if (rbnode) {
-               reg_tmp = reg - rbnode->base_reg;
+               reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
                val = regcache_rbtree_get_register(rbnode, reg_tmp,
                                                   map->cache_word_size);
                if (val == value)
@@ -315,13 +325,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                /* look for an adjacent register to the one we are about to add */
                for (node = rb_first(&rbtree_ctx->root); node;
                     node = rb_next(node)) {
-                       rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
+                       rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
+                                             node);
                        for (i = 0; i < rbnode_tmp->blklen; i++) {
-                               reg_tmp = rbnode_tmp->base_reg + i;
-                               if (abs(reg_tmp - reg) != 1)
+                               reg_tmp = rbnode_tmp->base_reg +
+                                               (i * map->reg_stride);
+                               if (abs(reg_tmp - reg) != map->reg_stride)
                                        continue;
                                /* decide where in the block to place our register */
-                               if (reg_tmp + 1 == reg)
+                               if (reg_tmp + map->reg_stride == reg)
                                        pos = i + 1;
                                else
                                        pos = i;
@@ -351,7 +363,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                        return -ENOMEM;
                }
                regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
-               regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
+               regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
                rbtree_ctx->cached_rbnode = rbnode;
        }
 
@@ -391,7 +403,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                        end = rbnode->blklen;
 
                for (i = base; i < end; i++) {
-                       regtmp = rbnode->base_reg + i;
+                       regtmp = rbnode->base_reg + (i * map->reg_stride);
                        val = regcache_rbtree_get_register(rbnode, i,
                                                           map->cache_word_size);
 
This page took 0.028068 seconds and 5 git commands to generate.