regmap: Inital export of the patching implementation

An initial export of the regmap register patch implementation, mostly
 for integration into ASoC so it can be used by drivers there which have
 conflicting updates already.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPHwbvAAoJEBus8iNuMP3dBFcQAIcGUi8EeL3hzN5KclOSOJcZ
 eZmlaASCL155ZL134Z3EcjMEcqgzAl5RwnoL9pN+Lg01uglPcnhCfgb2dQTMskMF
 7vazhldguQn2GxthMky55kGxJMdXHINoAFRKjSK2Js19dEdvbMgbElyCgXY5aaj6
 5W8ORPiQWurlHQHrtsEyFe+/1SboNAb2QrB63+w2hw1A6w3h9RnZ3lFiVL9/TIEz
 6mQG83s7pvaco8v6z9PD9V0j2KskI56JkZL0p6xcl2CxFplL4ha3Cqu3KjJqDULz
 vubab4BeaYjA0mTjVPsku0MWq+Sj9TrfoQMAbIsKiRZ4d7vd6XaRqc/8qnu7LHtd
 +LfMpXc2SEsKA4WtA7Flllj7NEsklYOY085wfzDhHdzjyvTL7qJjWqnlbjz3WC+5
 6pvcnJzCXOyK3Y6W8EeEiVRkCeuckAILDQaX5Kb3WmAxMeIrqCoaonIVmRHCeavs
 zugbAHGVY6XPQKUb89RjXyKcorreETL8jRsWMasnqUUmNMvLnBKdIEp7ohKp4JYN
 uXgDNihtRxupNjBvCrQyHR5tjOKca4Xw5C8A5p5nL3j0mJMbhGxaTyQC8NJ5ki5v
 gjA/xypWkob4fzi9jfxdJIThzEOIWey9DHcnvDa9w6wIFNc+LDjKTXw+ReOvWyWP
 M3KBzlVT+Lm4eB7atPB6
 =HfF+
 -----END PGP SIGNATURE-----

Merge tag 'regmap-patch-initial' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into for-3.4

regmap: Inital export of the patching implementation

An initial export of the regmap register patch implementation, mostly
for integration into ASoC so it can be used by drivers there which have
conflicting updates already.
This commit is contained in:
Mark Brown 2012-01-24 19:48:04 +00:00
commit 55f7f090a6
4 changed files with 75 additions and 0 deletions

View File

@ -75,6 +75,9 @@ struct regmap {
const void *reg_defaults_raw;
void *cache;
bool cache_dirty;
struct reg_default *patch;
int patch_regs;
};
struct regcache_ops {

View File

@ -268,6 +268,17 @@ int regcache_sync(struct regmap *map)
map->cache_ops->name);
name = map->cache_ops->name;
trace_regcache_sync(map->dev, name, "start");
/* Apply any patch first */
for (i = 0; i < map->patch_regs; i++) {
ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
if (ret != 0) {
dev_err(map->dev, "Failed to write %x = %x: %d\n",
map->patch[i].reg, map->patch[i].def, ret);
goto out;
}
}
if (!map->cache_dirty)
goto out;
if (map->cache_ops->sync) {

View File

@ -669,6 +669,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(sizeof(struct reg_default), num_regs, 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();

View File

@ -149,6 +149,9 @@ void regcache_cache_only(struct regmap *map, bool enable);
void regcache_cache_bypass(struct regmap *map, bool enable);
void regcache_mark_dirty(struct regmap *map);
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
int num_regs);
/**
* Description of an IRQ for the generic regmap irq_chip.
*