Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: arizona: Use new regmap features for manual register patch

On the wm5102 the register patches are applied manually, rather than by
the regmap core. This application is wrapped in calls to
regcache_cache_bypass. However, this is dangerous as other threads may
be accessing the hardware at the same time as the pm_runtime operations
and if they do so during the period whilst cache_bypass is enabled those
writes will miss the cache when they shouldn't.

Apply the register patch using the new regmap_multi_reg_write_bypassed
function to avoid this problem. Also remove the call to
regcache_cache_bypass from the hardware patch application as it is
unneeded there and creates a similar window for writes to miss the
cache.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>

authored by

Charles Keepax and committed by
Mark Brown
1c18d2ca 6bf13103

+4 -21
-4
drivers/mfd/arizona-core.c
··· 251 251 unsigned int fll, sysclk; 252 252 int ret, err; 253 253 254 - regcache_cache_bypass(arizona->regmap, true); 255 - 256 254 /* Cache existing FLL and SYSCLK settings */ 257 255 ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll); 258 256 if (ret != 0) { ··· 319 321 "Failed to re-apply old FLL settings: %d\n", 320 322 err); 321 323 } 322 - 323 - regcache_cache_bypass(arizona->regmap, false); 324 324 325 325 if (ret != 0) 326 326 return ret;
+4 -17
drivers/mfd/wm5102-tables.c
··· 80 80 int wm5102_patch(struct arizona *arizona) 81 81 { 82 82 const struct reg_default *wm5102_patch; 83 - int ret = 0; 84 - int i, patch_size; 83 + int patch_size; 85 84 86 85 switch (arizona->rev) { 87 86 case 0: ··· 91 92 patch_size = ARRAY_SIZE(wm5102_revb_patch); 92 93 } 93 94 94 - regcache_cache_bypass(arizona->regmap, true); 95 - 96 - for (i = 0; i < patch_size; i++) { 97 - ret = regmap_write(arizona->regmap, wm5102_patch[i].reg, 98 - wm5102_patch[i].def); 99 - if (ret != 0) { 100 - dev_err(arizona->dev, "Failed to write %x = %x: %d\n", 101 - wm5102_patch[i].reg, wm5102_patch[i].def, ret); 102 - goto out; 103 - } 104 - } 105 - 106 - out: 107 - regcache_cache_bypass(arizona->regmap, false); 108 - return ret; 95 + return regmap_multi_reg_write_bypassed(arizona->regmap, 96 + wm5102_patch, 97 + patch_size); 109 98 } 110 99 111 100 static const struct regmap_irq wm5102_aod_irqs[ARIZONA_NUM_IRQ] = {