diff options
-rw-r--r-- | drivers/base/regmap/internal.h | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 60 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 39 |
3 files changed, 54 insertions, 58 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 95d46a5ea7e..b01fe59fbfe 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -126,6 +126,9 @@ struct regmap { void *cache; u32 cache_dirty; + unsigned long *cache_present; + unsigned int cache_present_nbits; + struct reg_default *patch; int patch_regs; @@ -201,6 +204,16 @@ unsigned int regcache_get_val(struct regmap *map, const void *base, bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val); int regcache_lookup_reg(struct regmap *map, unsigned int reg); +int regcache_set_reg_present(struct regmap *map, unsigned int reg); + +static inline bool regcache_reg_present(struct regmap *map, unsigned int reg) +{ + if (!map->cache_present) + return true; + if (reg > map->cache_present_nbits) + return false; + return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg); +} int _regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len, bool async); diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 382a6deb3ca..00c3506f542 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -36,8 +36,6 @@ struct regcache_rbtree_node { struct regcache_rbtree_ctx { struct rb_root root; struct regcache_rbtree_node *cached_rbnode; - unsigned long *reg_present; - unsigned int reg_present_nbits; }; static inline void regcache_rbtree_get_base_top_reg( @@ -154,7 +152,7 @@ static int rbtree_show(struct seq_file *s, void *ignored) map->lock(map); mem_size = sizeof(*rbtree_ctx); - mem_size += BITS_TO_LONGS(rbtree_ctx->reg_present_nbits) * sizeof(long); + mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long); for (node = rb_first(&rbtree_ctx->root); node != NULL; node = rb_next(node)) { @@ -205,44 +203,6 @@ static void rbtree_debugfs_init(struct regmap *map) } #endif -static int enlarge_reg_present_bitmap(struct regmap *map, unsigned int reg) -{ - struct regcache_rbtree_ctx *rbtree_ctx; - unsigned long *reg_present; - unsigned int reg_present_size; - unsigned int nregs; - int i; - - rbtree_ctx = map->cache; - nregs = reg + 1; - reg_present_size = BITS_TO_LONGS(nregs); - reg_present_size *= sizeof(long); - - if (!rbtree_ctx->reg_present) { - reg_present = kmalloc(reg_present_size, GFP_KERNEL); - if (!reg_present) - return -ENOMEM; - bitmap_zero(reg_present, nregs); - rbtree_ctx->reg_present = reg_present; - rbtree_ctx->reg_present_nbits = nregs; - return 0; - } - - if (nregs > rbtree_ctx->reg_present_nbits) { - reg_present = krealloc(rbtree_ctx->reg_present, - reg_present_size, GFP_KERNEL); - if (!reg_present) - return -ENOMEM; - for (i = 0; i < nregs; i++) - if (i >= rbtree_ctx->reg_present_nbits) - clear_bit(i, reg_present); - rbtree_ctx->reg_present = reg_present; - rbtree_ctx->reg_present_nbits = nregs; - } - - return 0; -} - static int regcache_rbtree_init(struct regmap *map) { struct regcache_rbtree_ctx *rbtree_ctx; @@ -256,8 +216,6 @@ static int regcache_rbtree_init(struct regmap *map) rbtree_ctx = map->cache; rbtree_ctx->root = RB_ROOT; rbtree_ctx->cached_rbnode = NULL; - rbtree_ctx->reg_present = NULL; - rbtree_ctx->reg_present_nbits = 0; for (i = 0; i < map->num_reg_defaults; i++) { ret = regcache_rbtree_write(map, @@ -287,8 +245,6 @@ static int regcache_rbtree_exit(struct regmap *map) if (!rbtree_ctx) return 0; - kfree(rbtree_ctx->reg_present); - /* free up the rbtree */ next = rb_first(&rbtree_ctx->root); while (next) { @@ -306,17 +262,6 @@ static int regcache_rbtree_exit(struct regmap *map) return 0; } -static int regcache_reg_present(struct regmap *map, unsigned int reg) -{ - struct regcache_rbtree_ctx *rbtree_ctx; - - rbtree_ctx = map->cache; - if (!(rbtree_ctx->reg_present[BIT_WORD(reg)] & BIT_MASK(reg))) - return 0; - return 1; - -} - static int regcache_rbtree_read(struct regmap *map, unsigned int reg, unsigned int *value) { @@ -378,10 +323,9 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, rbtree_ctx = map->cache; /* update the reg_present bitmap, make space if necessary */ - ret = enlarge_reg_present_bitmap(map, reg); + ret = regcache_set_reg_present(map, reg); if (ret < 0) return ret; - set_bit(reg, rbtree_ctx->reg_present); /* if we can't locate it in the cached rbnode we'll have * to traverse the rbtree looking for it. diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 229c804e409..0fedf4fa011 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -121,6 +121,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) map->reg_defaults_raw = config->reg_defaults_raw; map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; + map->cache_present = NULL; + map->cache_present_nbits = 0; map->cache = NULL; map->cache_ops = cache_types[i]; @@ -179,6 +181,7 @@ void regcache_exit(struct regmap *map) BUG_ON(!map->cache_ops); + kfree(map->cache_present); kfree(map->reg_defaults); if (map->cache_free) kfree(map->reg_defaults_raw); @@ -415,6 +418,42 @@ void regcache_cache_bypass(struct regmap *map, bool enable) } EXPORT_SYMBOL_GPL(regcache_cache_bypass); +int regcache_set_reg_present(struct regmap *map, unsigned int reg) +{ + unsigned long *cache_present; + unsigned int cache_present_size; + unsigned int nregs; + int i; + + nregs = reg + 1; + cache_present_size = BITS_TO_LONGS(nregs); + cache_present_size *= sizeof(long); + + if (!map->cache_present) { + cache_present = kmalloc(cache_present_size, GFP_KERNEL); + if (!cache_present) + return -ENOMEM; + bitmap_zero(cache_present, nregs); + map->cache_present = cache_present; + map->cache_present_nbits = nregs; + } + + if (nregs > map->cache_present_nbits) { + cache_present = krealloc(map->cache_present, + cache_present_size, GFP_KERNEL); + if (!cache_present) + return -ENOMEM; + for (i = 0; i < nregs; i++) + if (i >= map->cache_present_nbits) + clear_bit(i, cache_present); + map->cache_present = cache_present; + map->cache_present_nbits = nregs; + } + + set_bit(reg, map->cache_present); + return 0; +} + bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val) { |