aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-21 07:01:14 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-23 09:01:18 -0500
commit22f0d90a34827812413bb3fbeda6a2a79bb58423 (patch)
treec54935a6e2637408da23aa261c81f89dffa0724e /drivers/base/regmap/regmap.c
parentdcd6c92267155e70a94b3927bce681ce74b80d1f (diff)
regmap: Support register patch sets
Device manufacturers frequently provide register sequences, usually not fully documented, to be run at startup in order to provide better defaults for devices (for example, improving performance in the light of silicon evaluation). Support such updates by allowing drivers to register update sets with the core. These updates will be written to the device immediately and will also be rewritten when the cache is synced. The assumption is that the reason for resyncing the cache will always be that the device has been powered off. If this turns out to not be the case then a separate operation can be provided. Currently the implementation only allows a single set of updates to be specified for a device, this could be extended in future. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c58
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}
670EXPORT_SYMBOL_GPL(regmap_update_bits_check); 670EXPORT_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 */
686int 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
721out:
722 map->cache_bypass = bypass;
723
724 mutex_unlock(&map->lock);
725
726 return ret;
727}
728EXPORT_SYMBOL_GPL(regmap_register_patch);
729
672static int __init regmap_initcall(void) 730static int __init regmap_initcall(void)
673{ 731{
674 regmap_debugfs_initcall(); 732 regmap_debugfs_initcall();