diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 58f84c3a6fc1..e3ee9cabccb4 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -374,6 +374,9 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
374 | 374 | ||
375 | regmap_debugfs_init(map); | 375 | regmap_debugfs_init(map); |
376 | 376 | ||
377 | map->cache_bypass = false; | ||
378 | map->cache_only = false; | ||
379 | |||
377 | ret = regcache_init(map, config); | 380 | ret = regcache_init(map, config); |
378 | 381 | ||
379 | mutex_unlock(&map->lock); | 382 | mutex_unlock(&map->lock); |
@@ -783,6 +786,64 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, | |||
783 | } | 786 | } |
784 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); | 787 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); |
785 | 788 | ||
789 | /** | ||
790 | * regmap_register_patch: Register and apply register updates to be applied | ||
791 | * on device initialistion | ||
792 | * | ||
793 | * @map: Register map to apply updates to. | ||
794 | * @regs: Values to update. | ||
795 | * @num_regs: Number of entries in regs. | ||
796 | * | ||
797 | * Register a set of register updates to be applied to the device | ||
798 | * whenever the device registers are synchronised with the cache and | ||
799 | * apply them immediately. Typically this is used to apply | ||
800 | * corrections to be applied to the device defaults on startup, such | ||
801 | * as the updates some vendors provide to undocumented registers. | ||
802 | */ | ||
803 | int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | ||
804 | int num_regs) | ||
805 | { | ||
806 | int i, ret; | ||
807 | bool bypass; | ||
808 | |||
809 | /* If needed the implementation can be extended to support this */ | ||
810 | if (map->patch) | ||
811 | return -EBUSY; | ||
812 | |||
813 | mutex_lock(&map->lock); | ||
814 | |||
815 | bypass = map->cache_bypass; | ||
816 | |||
817 | map->cache_bypass = true; | ||
818 | |||
819 | /* Write out first; it's useful to apply even if we fail later. */ | ||
820 | for (i = 0; i < num_regs; i++) { | ||
821 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
822 | if (ret != 0) { | ||
823 | dev_err(map->dev, "Failed to write %x = %x: %d\n", | ||
824 | regs[i].reg, regs[i].def, ret); | ||
825 | goto out; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | map->patch = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL); | ||
830 | if (map->patch != NULL) { | ||
831 | memcpy(map->patch, regs, | ||
832 | num_regs * sizeof(struct reg_default)); | ||
833 | map->patch_regs = num_regs; | ||
834 | } else { | ||
835 | ret = -ENOMEM; | ||
836 | } | ||
837 | |||
838 | out: | ||
839 | map->cache_bypass = bypass; | ||
840 | |||
841 | mutex_unlock(&map->lock); | ||
842 | |||
843 | return ret; | ||
844 | } | ||
845 | EXPORT_SYMBOL_GPL(regmap_register_patch); | ||
846 | |||
786 | static int __init regmap_initcall(void) | 847 | static int __init regmap_initcall(void) |
787 | { | 848 | { |
788 | regmap_debugfs_initcall(); | 849 | regmap_debugfs_initcall(); |