diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-20 21:21:33 +0000 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-20 21:21:33 +0000 |
commit | aca1e172a1096ed3785e0da01d82943b7562527c (patch) | |
tree | 0826c140b4e31acd7f8546727498dd849f099ba6 /drivers/base/regmap/regmap.c | |
parent | 3bf06a1ad9b147ca3a64b119d70c4a7c0ace3695 (diff) | |
parent | 2a14d7d9b7439fe62082a60a7f8983ccb463d134 (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/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 677aeab24f7..1752f13ddeb 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, } EXPORT_SYMBOL_GPL(regmap_update_bits_check); +/** + * regmap_register_patch: Register and apply register updates to be applied + * on device initialistion + * + * @map: Register map to apply updates to. + * @regs: Values to update. + * @num_regs: Number of entries in regs. + * + * Register a set of register updates to be applied to the device + * whenever the device registers are synchronised with the cache and + * apply them immediately. Typically this is used to apply + * corrections to be applied to the device defaults on startup, such + * as the updates some vendors provide to undocumented registers. + */ +int regmap_register_patch(struct regmap *map, const struct reg_default *regs, + int num_regs) +{ + int i, ret; + bool bypass; + + /* If needed the implementation can be extended to support this */ + if (map->patch) + return -EBUSY; + + mutex_lock(&map->lock); + + bypass = map->cache_bypass; + + map->cache_bypass = true; + + /* Write out first; it's useful to apply even if we fail later. */ + for (i = 0; i < num_regs; i++) { + ret = _regmap_write(map, regs[i].reg, regs[i].def); + if (ret != 0) { + dev_err(map->dev, "Failed to write %x = %x: %d\n", + regs[i].reg, regs[i].def, ret); + goto out; + } + } + + map->patch = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL); + if (map->patch != NULL) { + memcpy(map->patch, regs, + num_regs * sizeof(struct reg_default)); + map->patch_regs = num_regs; + } else { + ret = -ENOMEM; + } + +out: + map->cache_bypass = bypass; + + mutex_unlock(&map->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(regmap_register_patch); + static int __init regmap_initcall(void) { regmap_debugfs_initcall(); |