summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorBen Wolsieffer <ben.wolsieffer@hefring.com>2023-11-01 17:29:27 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-11-20 13:52:15 +0300
commit713629765f25b7011462007cc99dec1ad9bf825d (patch)
treeaee2cb6252d54df2fa10893d98b96b176b1a964e /drivers/base
parent7ec7b7d3f2b807cdf3c4323bb15588e42402d244 (diff)
downloadlinux-713629765f25b7011462007cc99dec1ad9bf825d.tar.xz
regmap: prevent noinc writes from clobbering cache
[ Upstream commit 984a4afdc87a1fc226fd657b1cd8255c13d3fc1a ] Currently, noinc writes are cached as if they were standard incrementing writes, overwriting unrelated register values in the cache. Instead, we want to cache the last value written to the register, as is done in the accelerated noinc handler (regmap_noinc_readwrite). Fixes: cdf6b11daa77 ("regmap: Add regmap_noinc_write API") Signed-off-by: Ben Wolsieffer <ben.wolsieffer@hefring.com> Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@hefring.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regmap.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index df1f78abdf26..140af27f591a 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1702,17 +1702,19 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
}
if (!map->cache_bypass && map->format.parse_val) {
- unsigned int ival;
+ unsigned int ival, offset;
int val_bytes = map->format.val_bytes;
- for (i = 0; i < val_len / val_bytes; i++) {
- ival = map->format.parse_val(val + (i * val_bytes));
- ret = regcache_write(map,
- reg + regmap_get_offset(map, i),
- ival);
+
+ /* Cache the last written value for noinc writes */
+ i = noinc ? val_len - val_bytes : 0;
+ for (; i < val_len; i += val_bytes) {
+ ival = map->format.parse_val(val + i);
+ offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
+ ret = regcache_write(map, reg + offset, ival);
if (ret) {
dev_err(map->dev,
"Error in caching of register: %x ret: %d\n",
- reg + regmap_get_offset(map, i), ret);
+ reg + offset, ret);
return ret;
}
}