aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regcache.c11
-rw-r--r--drivers/base/regmap/regmap.c73
3 files changed, 87 insertions, 0 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 1a02b7537c8b..d141b80479b5 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -75,6 +75,9 @@ struct regmap {
75 const void *reg_defaults_raw; 75 const void *reg_defaults_raw;
76 void *cache; 76 void *cache;
77 bool cache_dirty; 77 bool cache_dirty;
78
79 struct reg_default *patch;
80 int patch_regs;
78}; 81};
79 82
80struct regcache_ops { 83struct regcache_ops {
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d1daa5e9fadf..5cd2a37e7688 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -268,6 +268,17 @@ int regcache_sync(struct regmap *map)
268 map->cache_ops->name); 268 map->cache_ops->name);
269 name = map->cache_ops->name; 269 name = map->cache_ops->name;
270 trace_regcache_sync(map->dev, name, "start"); 270 trace_regcache_sync(map->dev, name, "start");
271
272 /* Apply any patch first */
273 for (i = 0; i < map->patch_regs; i++) {
274 ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
275 if (ret != 0) {
276 dev_err(map->dev, "Failed to write %x = %x: %d\n",
277 map->patch[i].reg, map->patch[i].def, ret);
278 goto out;
279 }
280 }
281
271 if (!map->cache_dirty) 282 if (!map->cache_dirty)
272 goto out; 283 goto out;
273 if (map->cache_ops->sync) { 284 if (map->cache_ops->sync) {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 65558034318f..7ac234f0b1c5 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -672,6 +672,79 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
672} 672}
673EXPORT_SYMBOL_GPL(regmap_update_bits_check); 673EXPORT_SYMBOL_GPL(regmap_update_bits_check);
674 674
675/**
676 * regmap_register_patch: Register and apply register updates to be applied
677 * on device initialistion
678 *
679 * @map: Register map to apply updates to.
680 * @regs: Values to update.
681 * @num_regs: Number of entries in regs.
682 *
683 * Register a set of register updates to be applied to the device
684 * whenever the device registers are synchronised with the cache and
685 * apply them immediately. Typically this is used to apply
686 * corrections to be applied to the device defaults on startup, such
687 * as the updates some vendors provide to undocumented registers.
688 */
689int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
690 int num_regs)
691{
692 int i, ret;
693 bool bypass;
694
695 /* If needed the implementation can be extended to support this */
696 if (map->patch)
697 return -EBUSY;
698
699 mutex_lock(&map->lock);
700
701 bypass = map->cache_bypass;
702
703 map->cache_bypass = true;
704
705 /* Write out first; it's useful to apply even if we fail later. */
706 for (i = 0; i < num_regs; i++) {
707 ret = _regmap_write(map, regs[i].reg, regs[i].def);
708 if (ret != 0) {
709 dev_err(map->dev, "Failed to write %x = %x: %d\n",
710 regs[i].reg, regs[i].def, ret);
711 goto out;
712 }
713 }
714
715 map->patch = kcalloc(sizeof(struct reg_default), num_regs, GFP_KERNEL);
716 if (map->patch != NULL) {
717 memcpy(map->patch, regs,
718 num_regs * sizeof(struct reg_default));
719 map->patch_regs = num_regs;
720 } else {
721 ret = -ENOMEM;
722 }
723
724out:
725 map->cache_bypass = bypass;
726
727 mutex_unlock(&map->lock);
728
729 return ret;
730}
731EXPORT_SYMBOL_GPL(regmap_register_patch);
732
733/*
734 * regmap_get_val_bytes(): Report the size of a register value
735 *
736 * Report the size of a register value, mainly intended to for use by
737 * generic infrastructure built on top of regmap.
738 */
739int regmap_get_val_bytes(struct regmap *map)
740{
741 if (map->format.format_write)
742 return -EINVAL;
743
744 return map->format.val_bytes;
745}
746EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
747
675static int __init regmap_initcall(void) 748static int __init regmap_initcall(void)
676{ 749{
677 regmap_debugfs_initcall(); 750 regmap_debugfs_initcall();