diff options
Diffstat (limited to 'drivers')
-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 95d46a5ea7e7..b01fe59fbfe8 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -126,6 +126,9 @@ struct regmap { | |||
126 | void *cache; | 126 | void *cache; |
127 | u32 cache_dirty; | 127 | u32 cache_dirty; |
128 | 128 | ||
129 | unsigned long *cache_present; | ||
130 | unsigned int cache_present_nbits; | ||
131 | |||
129 | struct reg_default *patch; | 132 | struct reg_default *patch; |
130 | int patch_regs; | 133 | int patch_regs; |
131 | 134 | ||
@@ -201,6 +204,16 @@ unsigned int regcache_get_val(struct regmap *map, const void *base, | |||
201 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | 204 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, |
202 | unsigned int val); | 205 | unsigned int val); |
203 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); | 206 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); |
207 | int regcache_set_reg_present(struct regmap *map, unsigned int reg); | ||
208 | |||
209 | static inline bool regcache_reg_present(struct regmap *map, unsigned int reg) | ||
210 | { | ||
211 | if (!map->cache_present) | ||
212 | return true; | ||
213 | if (reg > map->cache_present_nbits) | ||
214 | return false; | ||
215 | return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg); | ||
216 | } | ||
204 | 217 | ||
205 | int _regmap_raw_write(struct regmap *map, unsigned int reg, | 218 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
206 | const void *val, size_t val_len, bool async); | 219 | 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 382a6deb3ca8..00c3506f542f 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -36,8 +36,6 @@ struct regcache_rbtree_node { | |||
36 | struct regcache_rbtree_ctx { | 36 | struct regcache_rbtree_ctx { |
37 | struct rb_root root; | 37 | struct rb_root root; |
38 | struct regcache_rbtree_node *cached_rbnode; | 38 | struct regcache_rbtree_node *cached_rbnode; |
39 | unsigned long *reg_present; | ||
40 | unsigned int reg_present_nbits; | ||
41 | }; | 39 | }; |
42 | 40 | ||
43 | static inline void regcache_rbtree_get_base_top_reg( | 41 | static inline void regcache_rbtree_get_base_top_reg( |
@@ -154,7 +152,7 @@ static int rbtree_show(struct seq_file *s, void *ignored) | |||
154 | map->lock(map); | 152 | map->lock(map); |
155 | 153 | ||
156 | mem_size = sizeof(*rbtree_ctx); | 154 | mem_size = sizeof(*rbtree_ctx); |
157 | mem_size += BITS_TO_LONGS(rbtree_ctx->reg_present_nbits) * sizeof(long); | 155 | mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long); |
158 | 156 | ||
159 | for (node = rb_first(&rbtree_ctx->root); node != NULL; | 157 | for (node = rb_first(&rbtree_ctx->root); node != NULL; |
160 | node = rb_next(node)) { | 158 | node = rb_next(node)) { |
@@ -205,44 +203,6 @@ static void rbtree_debugfs_init(struct regmap *map) | |||
205 | } | 203 | } |
206 | #endif | 204 | #endif |
207 | 205 | ||
208 | static int enlarge_reg_present_bitmap(struct regmap *map, unsigned int reg) | ||
209 | { | ||
210 | struct regcache_rbtree_ctx *rbtree_ctx; | ||
211 | unsigned long *reg_present; | ||
212 | unsigned int reg_present_size; | ||
213 | unsigned int nregs; | ||
214 | int i; | ||
215 | |||
216 | rbtree_ctx = map->cache; | ||
217 | nregs = reg + 1; | ||
218 | reg_present_size = BITS_TO_LONGS(nregs); | ||
219 | reg_present_size *= sizeof(long); | ||
220 | |||
221 | if (!rbtree_ctx->reg_present) { | ||
222 | reg_present = kmalloc(reg_present_size, GFP_KERNEL); | ||
223 | if (!reg_present) | ||
224 | return -ENOMEM; | ||
225 | bitmap_zero(reg_present, nregs); | ||
226 | rbtree_ctx->reg_present = reg_present; | ||
227 | rbtree_ctx->reg_present_nbits = nregs; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | if (nregs > rbtree_ctx->reg_present_nbits) { | ||
232 | reg_present = krealloc(rbtree_ctx->reg_present, | ||
233 | reg_present_size, GFP_KERNEL); | ||
234 | if (!reg_present) | ||
235 | return -ENOMEM; | ||
236 | for (i = 0; i < nregs; i++) | ||
237 | if (i >= rbtree_ctx->reg_present_nbits) | ||
238 | clear_bit(i, reg_present); | ||
239 | rbtree_ctx->reg_present = reg_present; | ||
240 | rbtree_ctx->reg_present_nbits = nregs; | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int regcache_rbtree_init(struct regmap *map) | 206 | static int regcache_rbtree_init(struct regmap *map) |
247 | { | 207 | { |
248 | struct regcache_rbtree_ctx *rbtree_ctx; | 208 | struct regcache_rbtree_ctx *rbtree_ctx; |
@@ -256,8 +216,6 @@ static int regcache_rbtree_init(struct regmap *map) | |||
256 | rbtree_ctx = map->cache; | 216 | rbtree_ctx = map->cache; |
257 | rbtree_ctx->root = RB_ROOT; | 217 | rbtree_ctx->root = RB_ROOT; |
258 | rbtree_ctx->cached_rbnode = NULL; | 218 | rbtree_ctx->cached_rbnode = NULL; |
259 | rbtree_ctx->reg_present = NULL; | ||
260 | rbtree_ctx->reg_present_nbits = 0; | ||
261 | 219 | ||
262 | for (i = 0; i < map->num_reg_defaults; i++) { | 220 | for (i = 0; i < map->num_reg_defaults; i++) { |
263 | ret = regcache_rbtree_write(map, | 221 | ret = regcache_rbtree_write(map, |
@@ -287,8 +245,6 @@ static int regcache_rbtree_exit(struct regmap *map) | |||
287 | if (!rbtree_ctx) | 245 | if (!rbtree_ctx) |
288 | return 0; | 246 | return 0; |
289 | 247 | ||
290 | kfree(rbtree_ctx->reg_present); | ||
291 | |||
292 | /* free up the rbtree */ | 248 | /* free up the rbtree */ |
293 | next = rb_first(&rbtree_ctx->root); | 249 | next = rb_first(&rbtree_ctx->root); |
294 | while (next) { | 250 | while (next) { |
@@ -306,17 +262,6 @@ static int regcache_rbtree_exit(struct regmap *map) | |||
306 | return 0; | 262 | return 0; |
307 | } | 263 | } |
308 | 264 | ||
309 | static int regcache_reg_present(struct regmap *map, unsigned int reg) | ||
310 | { | ||
311 | struct regcache_rbtree_ctx *rbtree_ctx; | ||
312 | |||
313 | rbtree_ctx = map->cache; | ||
314 | if (!(rbtree_ctx->reg_present[BIT_WORD(reg)] & BIT_MASK(reg))) | ||
315 | return 0; | ||
316 | return 1; | ||
317 | |||
318 | } | ||
319 | |||
320 | static int regcache_rbtree_read(struct regmap *map, | 265 | static int regcache_rbtree_read(struct regmap *map, |
321 | unsigned int reg, unsigned int *value) | 266 | unsigned int reg, unsigned int *value) |
322 | { | 267 | { |
@@ -378,10 +323,9 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
378 | 323 | ||
379 | rbtree_ctx = map->cache; | 324 | rbtree_ctx = map->cache; |
380 | /* update the reg_present bitmap, make space if necessary */ | 325 | /* update the reg_present bitmap, make space if necessary */ |
381 | ret = enlarge_reg_present_bitmap(map, reg); | 326 | ret = regcache_set_reg_present(map, reg); |
382 | if (ret < 0) | 327 | if (ret < 0) |
383 | return ret; | 328 | return ret; |
384 | set_bit(reg, rbtree_ctx->reg_present); | ||
385 | 329 | ||
386 | /* if we can't locate it in the cached rbnode we'll have | 330 | /* if we can't locate it in the cached rbnode we'll have |
387 | * to traverse the rbtree looking for it. | 331 | * to traverse the rbtree looking for it. |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 229c804e409e..0fedf4fa0116 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) | |||
121 | map->reg_defaults_raw = config->reg_defaults_raw; | 121 | map->reg_defaults_raw = config->reg_defaults_raw; |
122 | map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); | 122 | map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); |
123 | map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; | 123 | map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; |
124 | map->cache_present = NULL; | ||
125 | map->cache_present_nbits = 0; | ||
124 | 126 | ||
125 | map->cache = NULL; | 127 | map->cache = NULL; |
126 | map->cache_ops = cache_types[i]; | 128 | map->cache_ops = cache_types[i]; |
@@ -179,6 +181,7 @@ void regcache_exit(struct regmap *map) | |||
179 | 181 | ||
180 | BUG_ON(!map->cache_ops); | 182 | BUG_ON(!map->cache_ops); |
181 | 183 | ||
184 | kfree(map->cache_present); | ||
182 | kfree(map->reg_defaults); | 185 | kfree(map->reg_defaults); |
183 | if (map->cache_free) | 186 | if (map->cache_free) |
184 | kfree(map->reg_defaults_raw); | 187 | kfree(map->reg_defaults_raw); |
@@ -415,6 +418,42 @@ void regcache_cache_bypass(struct regmap *map, bool enable) | |||
415 | } | 418 | } |
416 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); | 419 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); |
417 | 420 | ||
421 | int regcache_set_reg_present(struct regmap *map, unsigned int reg) | ||
422 | { | ||
423 | unsigned long *cache_present; | ||
424 | unsigned int cache_present_size; | ||
425 | unsigned int nregs; | ||
426 | int i; | ||
427 | |||
428 | nregs = reg + 1; | ||
429 | cache_present_size = BITS_TO_LONGS(nregs); | ||
430 | cache_present_size *= sizeof(long); | ||
431 | |||
432 | if (!map->cache_present) { | ||
433 | cache_present = kmalloc(cache_present_size, GFP_KERNEL); | ||
434 | if (!cache_present) | ||
435 | return -ENOMEM; | ||
436 | bitmap_zero(cache_present, nregs); | ||
437 | map->cache_present = cache_present; | ||
438 | map->cache_present_nbits = nregs; | ||
439 | } | ||
440 | |||
441 | if (nregs > map->cache_present_nbits) { | ||
442 | cache_present = krealloc(map->cache_present, | ||
443 | cache_present_size, GFP_KERNEL); | ||
444 | if (!cache_present) | ||
445 | return -ENOMEM; | ||
446 | for (i = 0; i < nregs; i++) | ||
447 | if (i >= map->cache_present_nbits) | ||
448 | clear_bit(i, cache_present); | ||
449 | map->cache_present = cache_present; | ||
450 | map->cache_present_nbits = nregs; | ||
451 | } | ||
452 | |||
453 | set_bit(reg, map->cache_present); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
418 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | 457 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, |
419 | unsigned int val) | 458 | unsigned int val) |
420 | { | 459 | { |