aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-20 16:21:33 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-20 16:21:33 -0500
commitaca1e172a1096ed3785e0da01d82943b7562527c (patch)
tree0826c140b4e31acd7f8546727498dd849f099ba6 /drivers/base/regmap
parent3bf06a1ad9b147ca3a64b119d70c4a7c0ace3695 (diff)
parent2a14d7d9b7439fe62082a60a7f8983ccb463d134 (diff)
Merge branch 'topic/patch' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into regmap-drivers
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regcache.c14
-rw-r--r--drivers/base/regmap/regmap.c58
3 files changed, 75 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..e9032c329067 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -268,8 +268,22 @@ 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
271 if (!map->cache_dirty) 272 if (!map->cache_dirty)
272 goto out; 273 goto out;
274
275 /* Apply any patch first */
276 map->cache_bypass = 1;
277 for (i = 0; i < map->patch_regs; i++) {
278 ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
279 if (ret != 0) {
280 dev_err(map->dev, "Failed to write %x = %x: %d\n",
281 map->patch[i].reg, map->patch[i].def, ret);
282 goto out;
283 }
284 }
285 map->cache_bypass = 0;
286
273 if (map->cache_ops->sync) { 287 if (map->cache_ops->sync) {
274 ret = map->cache_ops->sync(map); 288 ret = map->cache_ops->sync(map);
275 } else { 289 } else {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 677aeab24f75..1752f13ddebc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -711,6 +711,64 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
711} 711}
712EXPORT_SYMBOL_GPL(regmap_update_bits_check); 712EXPORT_SYMBOL_GPL(regmap_update_bits_check);
713 713
714/**
715 * regmap_register_patch: Register and apply register updates to be applied
716 * on device initialistion
717 *
718 * @map: Register map to apply updates to.
719 * @regs: Values to update.
720 * @num_regs: Number of entries in regs.
721 *
722 * Register a set of register updates to be applied to the device
723 * whenever the device registers are synchronised with the cache and
724 * apply them immediately. Typically this is used to apply
725 * corrections to be applied to the device defaults on startup, such
726 * as the updates some vendors provide to undocumented registers.
727 */
728int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
729 int num_regs)
730{
731 int i, ret;
732 bool bypass;
733
734 /* If needed the implementation can be extended to support this */
735 if (map->patch)
736 return -EBUSY;
737
738 mutex_lock(&map->lock);
739
740 bypass = map->cache_bypass;
741
742 map->cache_bypass = true;
743
744 /* Write out first; it's useful to apply even if we fail later. */
745 for (i = 0; i < num_regs; i++) {
746 ret = _regmap_write(map, regs[i].reg, regs[i].def);
747 if (ret != 0) {
748 dev_err(map->dev, "Failed to write %x = %x: %d\n",
749 regs[i].reg, regs[i].def, ret);
750 goto out;
751 }
752 }
753
754 map->patch = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL);
755 if (map->patch != NULL) {
756 memcpy(map->patch, regs,
757 num_regs * sizeof(struct reg_default));
758 map->patch_regs = num_regs;
759 } else {
760 ret = -ENOMEM;
761 }
762
763out:
764 map->cache_bypass = bypass;
765
766 mutex_unlock(&map->lock);
767
768 return ret;
769}
770EXPORT_SYMBOL_GPL(regmap_register_patch);
771
714static int __init regmap_initcall(void) 772static int __init regmap_initcall(void)
715{ 773{
716 regmap_debugfs_initcall(); 774 regmap_debugfs_initcall();