diff options
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r-- | drivers/base/regmap/regcache.c | 75 |
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); | |||
410 | int regcache_drop_region(struct regmap *map, unsigned int min, | 404 | int 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 | } |
494 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); | 482 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); |
495 | 483 | ||
496 | int 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 | |||
532 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | 484 | bool 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 | ||
575 | static 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 | |||
623 | static int regcache_sync_block_single(struct regmap *map, void *block, | 583 | static 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 | ||
683 | static int regcache_sync_block_raw(struct regmap *map, void *block, | 644 | static 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 | ||
726 | int regcache_sync_block(struct regmap *map, void *block, | 688 | int 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 | } |