Loading drivers/base/regmap/internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading drivers/base/regmap/regcache.c +14 −0 Original line number Diff line number Diff line Loading @@ -268,8 +268,22 @@ int regcache_sync(struct regmap *map) map->cache_ops->name); name = map->cache_ops->name; trace_regcache_sync(map->dev, name, "start"); if (!map->cache_dirty) goto out; /* Apply any patch first */ map->cache_bypass = 1; 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; } } map->cache_bypass = 0; if (map->cache_ops->sync) { ret = map->cache_ops->sync(map); } else { Loading drivers/base/regmap/regmap.c +58 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading include/linux/regmap.h +3 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,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 Loading
drivers/base/regmap/internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
drivers/base/regmap/regcache.c +14 −0 Original line number Diff line number Diff line Loading @@ -268,8 +268,22 @@ int regcache_sync(struct regmap *map) map->cache_ops->name); name = map->cache_ops->name; trace_regcache_sync(map->dev, name, "start"); if (!map->cache_dirty) goto out; /* Apply any patch first */ map->cache_bypass = 1; 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; } } map->cache_bypass = 0; if (map->cache_ops->sync) { ret = map->cache_ops->sync(map); } else { Loading
drivers/base/regmap/regmap.c +58 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
include/linux/regmap.h +3 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,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