Commit 22f0d90a34827812413bb3fbeda6a2a79bb58423

Authored by Mark Brown
1 parent dcd6c92267

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>

Showing 4 changed files with 75 additions and 0 deletions Side-by-side Diff

drivers/base/regmap/internal.h
... ... @@ -75,6 +75,9 @@
75 75 const void *reg_defaults_raw;
76 76 void *cache;
77 77 bool cache_dirty;
  78 +
  79 + struct reg_default *patch;
  80 + int patch_regs;
78 81 };
79 82  
80 83 struct regcache_ops {
drivers/base/regmap/regcache.c
... ... @@ -268,6 +268,17 @@
268 268 map->cache_ops->name);
269 269 name = map->cache_ops->name;
270 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 282 if (!map->cache_dirty)
272 283 goto out;
273 284 if (map->cache_ops->sync) {
drivers/base/regmap/regmap.c
... ... @@ -669,6 +669,64 @@
669 669 }
670 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 730 static int __init regmap_initcall(void)
673 731 {
674 732 regmap_debugfs_initcall();
include/linux/regmap.h
... ... @@ -149,6 +149,9 @@
149 149 void regcache_cache_bypass(struct regmap *map, bool enable);
150 150 void regcache_mark_dirty(struct regmap *map);
151 151  
  152 +int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
  153 + int num_regs);
  154 +
152 155 /**
153 156 * Description of an IRQ for the generic regmap irq_chip.
154 157 *