summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Wolsieffer <ben.wolsieffer@hefring.com>2023-11-01 10:29:27 -0400
committerMark Brown <broonie@kernel.org>2023-11-01 20:22:55 +0000
commit984a4afdc87a1fc226fd657b1cd8255c13d3fc1a (patch)
treef3b04c66377f7a41d3a7b157782005562214b841
parent6a2e332c2cbddd17d7dcb8f334953593f1324c8e (diff)
regmap: prevent noinc writes from clobbering cache
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>
-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 884cb51c8f67..784eb9ba56fe 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1620,17 +1620,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;
}
}