13 #include <linux/slab.h>
14 #include <linux/device.h>
16 #include <linux/rbtree.h>
21 static int regcache_rbtree_write(
struct regmap *
map,
unsigned int reg,
23 static int regcache_rbtree_exit(
struct regmap *
map);
41 static inline void regcache_rbtree_get_base_top_reg(
44 unsigned int *base,
unsigned int *
top)
50 static unsigned int regcache_rbtree_get_register(
52 unsigned int word_size)
58 unsigned int idx,
unsigned int val,
59 unsigned int word_size)
74 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
76 if (reg >= base_reg && reg <= top_reg)
80 node = rbtree_ctx->
root.rb_node;
83 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
85 if (reg >= base_reg && reg <= top_reg) {
88 }
else if (reg > top_reg) {
90 }
else if (reg < base_reg) {
98 static int regcache_rbtree_insert(
struct regmap *map,
struct rb_root *root,
103 unsigned int base_reg_tmp, top_reg_tmp;
112 regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
118 if (base_reg >= base_reg_tmp &&
119 base_reg <= top_reg_tmp)
121 else if (base_reg > top_reg_tmp)
122 new = &((*new)->rb_right);
123 else if (base_reg < base_reg_tmp)
124 new = &((*new)->rb_left);
128 rb_link_node(&rbnode->
node, parent,
new);
134 #ifdef CONFIG_DEBUG_FS
152 regcache_rbtree_get_base_top_reg(map, n, &base, &top);
153 this_registers = ((top - base) / map->
reg_stride) + 1;
154 seq_printf(s,
"%x-%x (%d)\n", base, top, this_registers);
157 registers += this_registers;
161 average = registers / nodes;
165 seq_printf(s,
"%d nodes, %d registers, average %d registers\n",
166 nodes, registers, average);
185 static void rbtree_debugfs_init(
struct regmap *map)
190 static void rbtree_debugfs_init(
struct regmap *map)
195 static int regcache_rbtree_init(
struct regmap *map)
205 rbtree_ctx = map->
cache;
210 ret = regcache_rbtree_write(map,
217 rbtree_debugfs_init(map);
222 regcache_rbtree_exit(map);
226 static int regcache_rbtree_exit(
struct regmap *map)
233 rbtree_ctx = map->
cache;
254 static int regcache_rbtree_read(
struct regmap *map,
255 unsigned int reg,
unsigned int *
value)
258 unsigned int reg_tmp;
260 rbnode = regcache_rbtree_lookup(map, reg);
263 *value = regcache_rbtree_get_register(rbnode, reg_tmp,
274 unsigned int pos,
unsigned int reg,
275 unsigned int value,
unsigned int word_size)
285 memmove(blk + (pos + 1) * word_size,
286 blk + pos * word_size,
287 (rbnode->
blklen - pos) * word_size);
295 regcache_rbtree_set_register(rbnode, pos, value, word_size);
299 static int regcache_rbtree_write(
struct regmap *map,
unsigned int reg,
306 unsigned int reg_tmp;
311 rbtree_ctx = map->
cache;
315 rbnode = regcache_rbtree_lookup(map, reg);
318 val = regcache_rbtree_get_register(rbnode, reg_tmp,
322 regcache_rbtree_set_register(rbnode, reg_tmp, value,
330 for (i = 0; i < rbnode_tmp->
blklen; i++) {
340 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
361 if (!rbnode->
block) {
366 regcache_rbtree_insert(map, &rbtree_ctx->
root, rbnode);
373 static int regcache_rbtree_sync(
struct regmap *map,
unsigned int min,
384 rbtree_ctx = map->
cache;
400 if (max < rbnode->base_reg + rbnode->
blklen)
405 for (i = base; i <
end; i++) {
407 val = regcache_rbtree_get_register(rbnode, i,
420 dev_dbg(map->
dev,
"Synced register %#x, value %#x\n",
431 .init = regcache_rbtree_init,
432 .exit = regcache_rbtree_exit,
433 .read = regcache_rbtree_read,
434 .write = regcache_rbtree_write,
435 .sync = regcache_rbtree_sync