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:
commit
55f7f090a6
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue