aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/regmap/internal.h13
-rw-r--r--drivers/base/regmap/regcache-rbtree.c60
-rw-r--r--drivers/base/regmap/regcache.c39
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,
201bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, 204bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
202 unsigned int val); 205 unsigned int val);
203int regcache_lookup_reg(struct regmap *map, unsigned int reg); 206int regcache_lookup_reg(struct regmap *map, unsigned int reg);
207int regcache_set_reg_present(struct regmap *map, unsigned int reg);
208
209static 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
205int _regmap_raw_write(struct regmap *map, unsigned int reg, 218int _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 {
36struct regcache_rbtree_ctx { 36struct 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
43static inline void regcache_rbtree_get_base_top_reg( 41static 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
208static 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
246static int regcache_rbtree_init(struct regmap *map) 206static 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
309static 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
320static int regcache_rbtree_read(struct regmap *map, 265static 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}
416EXPORT_SYMBOL_GPL(regcache_cache_bypass); 419EXPORT_SYMBOL_GPL(regcache_cache_bypass);
417 420
421int 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
418bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, 457bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
419 unsigned int val) 458 unsigned int val)
420{ 459{