aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r--drivers/base/regmap/regcache.c75
1 files changed, 19 insertions, 56 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 3455f833e473..d6c2d691b6e8 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -121,8 +121,6 @@ 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;
126 124
127 map->cache = NULL; 125 map->cache = NULL;
128 map->cache_ops = cache_types[i]; 126 map->cache_ops = cache_types[i];
@@ -181,7 +179,6 @@ void regcache_exit(struct regmap *map)
181 179
182 BUG_ON(!map->cache_ops); 180 BUG_ON(!map->cache_ops);
183 181
184 kfree(map->cache_present);
185 kfree(map->reg_defaults); 182 kfree(map->reg_defaults);
186 if (map->cache_free) 183 if (map->cache_free)
187 kfree(map->reg_defaults_raw); 184 kfree(map->reg_defaults_raw);
@@ -241,9 +238,6 @@ int regcache_write(struct regmap *map,
241 238
242 BUG_ON(!map->cache_ops); 239 BUG_ON(!map->cache_ops);
243 240
244 if (!regmap_writeable(map, reg))
245 return -EIO;
246
247 if (!regmap_volatile(map, reg)) 241 if (!regmap_volatile(map, reg))
248 return map->cache_ops->write(map, reg, value); 242 return map->cache_ops->write(map, reg, value);
249 243
@@ -410,22 +404,16 @@ EXPORT_SYMBOL_GPL(regcache_sync_region);
410int regcache_drop_region(struct regmap *map, unsigned int min, 404int regcache_drop_region(struct regmap *map, unsigned int min,
411 unsigned int max) 405 unsigned int max)
412{ 406{
413 unsigned int reg;
414 int ret = 0; 407 int ret = 0;
415 408
416 if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop)) 409 if (!map->cache_ops || !map->cache_ops->drop)
417 return -EINVAL; 410 return -EINVAL;
418 411
419 map->lock(map->lock_arg); 412 map->lock(map->lock_arg);
420 413
421 trace_regcache_drop_region(map->dev, min, max); 414 trace_regcache_drop_region(map->dev, min, max);
422 415
423 if (map->cache_present) 416 ret = map->cache_ops->drop(map, min, max);
424 for (reg = min; reg < max + 1; reg++)
425 clear_bit(reg, map->cache_present);
426
427 if (map->cache_ops && map->cache_ops->drop)
428 ret = map->cache_ops->drop(map, min, max);
429 417
430 map->unlock(map->lock_arg); 418 map->unlock(map->lock_arg);
431 419
@@ -493,42 +481,6 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
493} 481}
494EXPORT_SYMBOL_GPL(regcache_cache_bypass); 482EXPORT_SYMBOL_GPL(regcache_cache_bypass);
495 483
496int regcache_set_reg_present(struct regmap *map, unsigned int reg)
497{
498 unsigned long *cache_present;
499 unsigned int cache_present_size;
500 unsigned int nregs;
501 int i;
502
503 nregs = reg + 1;
504 cache_present_size = BITS_TO_LONGS(nregs);
505 cache_present_size *= sizeof(long);
506
507 if (!map->cache_present) {
508 cache_present = kmalloc(cache_present_size, GFP_KERNEL);
509 if (!cache_present)
510 return -ENOMEM;
511 bitmap_zero(cache_present, nregs);
512 map->cache_present = cache_present;
513 map->cache_present_nbits = nregs;
514 }
515
516 if (nregs > map->cache_present_nbits) {
517 cache_present = krealloc(map->cache_present,
518 cache_present_size, GFP_KERNEL);
519 if (!cache_present)
520 return -ENOMEM;
521 for (i = 0; i < nregs; i++)
522 if (i >= map->cache_present_nbits)
523 clear_bit(i, cache_present);
524 map->cache_present = cache_present;
525 map->cache_present_nbits = nregs;
526 }
527
528 set_bit(reg, map->cache_present);
529 return 0;
530}
531
532bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, 484bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
533 unsigned int val) 485 unsigned int val)
534{ 486{
@@ -620,7 +572,16 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
620 return -ENOENT; 572 return -ENOENT;
621} 573}
622 574
575static bool regcache_reg_present(unsigned long *cache_present, unsigned int idx)
576{
577 if (!cache_present)
578 return true;
579
580 return test_bit(idx, cache_present);
581}
582
623static int regcache_sync_block_single(struct regmap *map, void *block, 583static int regcache_sync_block_single(struct regmap *map, void *block,
584 unsigned long *cache_present,
624 unsigned int block_base, 585 unsigned int block_base,
625 unsigned int start, unsigned int end) 586 unsigned int start, unsigned int end)
626{ 587{
@@ -630,7 +591,7 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
630 for (i = start; i < end; i++) { 591 for (i = start; i < end; i++) {
631 regtmp = block_base + (i * map->reg_stride); 592 regtmp = block_base + (i * map->reg_stride);
632 593
633 if (!regcache_reg_present(map, regtmp)) 594 if (!regcache_reg_present(cache_present, i))
634 continue; 595 continue;
635 596
636 val = regcache_get_val(map, block, i); 597 val = regcache_get_val(map, block, i);
@@ -681,6 +642,7 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
681} 642}
682 643
683static int regcache_sync_block_raw(struct regmap *map, void *block, 644static int regcache_sync_block_raw(struct regmap *map, void *block,
645 unsigned long *cache_present,
684 unsigned int block_base, unsigned int start, 646 unsigned int block_base, unsigned int start,
685 unsigned int end) 647 unsigned int end)
686{ 648{
@@ -693,7 +655,7 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
693 for (i = start; i < end; i++) { 655 for (i = start; i < end; i++) {
694 regtmp = block_base + (i * map->reg_stride); 656 regtmp = block_base + (i * map->reg_stride);
695 657
696 if (!regcache_reg_present(map, regtmp)) { 658 if (!regcache_reg_present(cache_present, i)) {
697 ret = regcache_sync_block_raw_flush(map, &data, 659 ret = regcache_sync_block_raw_flush(map, &data,
698 base, regtmp); 660 base, regtmp);
699 if (ret != 0) 661 if (ret != 0)
@@ -724,13 +686,14 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
724} 686}
725 687
726int regcache_sync_block(struct regmap *map, void *block, 688int regcache_sync_block(struct regmap *map, void *block,
689 unsigned long *cache_present,
727 unsigned int block_base, unsigned int start, 690 unsigned int block_base, unsigned int start,
728 unsigned int end) 691 unsigned int end)
729{ 692{
730 if (regmap_can_raw_write(map)) 693 if (regmap_can_raw_write(map))
731 return regcache_sync_block_raw(map, block, block_base, 694 return regcache_sync_block_raw(map, block, cache_present,
732 start, end); 695 block_base, start, end);
733 else 696 else
734 return regcache_sync_block_single(map, block, block_base, 697 return regcache_sync_block_single(map, block, cache_present,
735 start, end); 698 block_base, start, end);
736} 699}