diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index be10a4ff6609..28e89fd7c28d 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -669,6 +669,64 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, | |||
669 | } | 669 | } |
670 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); | 670 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); |
671 | 671 | ||
672 | /** | ||
673 | * regmap_register_patch: Register and apply register updates to be applied | ||
674 | * on device initialistion | ||
675 | * | ||
676 | * @map: Register map to apply updates to. | ||
677 | * @regs: Values to update. | ||
678 | * @num_regs: Number of entries in regs. | ||
679 | * | ||
680 | * Register a set of register updates to be applied to the device | ||
681 | * whenever the device registers are synchronised with the cache and | ||
682 | * apply them immediately. Typically this is used to apply | ||
683 | * corrections to be applied to the device defaults on startup, such | ||
684 | * as the updates some vendors provide to undocumented registers. | ||
685 | */ | ||
686 | int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | ||
687 | int num_regs) | ||
688 | { | ||
689 | int i, ret; | ||
690 | bool bypass; | ||
691 | |||
692 | /* If needed the implementation can be extended to support this */ | ||
693 | if (map->patch) | ||
694 | return -EBUSY; | ||
695 | |||
696 | mutex_lock(&map->lock); | ||
697 | |||
698 | bypass = map->cache_bypass; | ||
699 | |||
700 | map->cache_bypass = true; | ||
701 | |||
702 | /* Write out first; it's useful to apply even if we fail later. */ | ||
703 | for (i = 0; i < num_regs; i++) { | ||
704 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
705 | if (ret != 0) { | ||
706 | dev_err(map->dev, "Failed to write %x = %x: %d\n", | ||
707 | regs[i].reg, regs[i].def, ret); | ||
708 | goto out; | ||
709 | } | ||
710 | } | ||
711 | |||
712 | map->patch = kcalloc(sizeof(struct reg_default), num_regs, GFP_KERNEL); | ||
713 | if (map->patch != NULL) { | ||
714 | memcpy(map->patch, regs, | ||
715 | num_regs * sizeof(struct reg_default)); | ||
716 | map->patch_regs = num_regs; | ||
717 | } else { | ||
718 | ret = -ENOMEM; | ||
719 | } | ||
720 | |||
721 | out: | ||
722 | map->cache_bypass = bypass; | ||
723 | |||
724 | mutex_unlock(&map->lock); | ||
725 | |||
726 | return ret; | ||
727 | } | ||
728 | EXPORT_SYMBOL_GPL(regmap_register_patch); | ||
729 | |||
672 | static int __init regmap_initcall(void) | 730 | static int __init regmap_initcall(void) |
673 | { | 731 | { |
674 | regmap_debugfs_initcall(); | 732 | regmap_debugfs_initcall(); |