From 0bc796e66b5d2d336d2eb7e025216ca1584015b5 Mon Sep 17 00:00:00 2001 From: Ben Wolsieffer Date: Wed, 1 Nov 2023 10:29:27 -0400 Subject: [PATCH] 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 Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@hefring.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- drivers/base/regmap/regmap.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 3edff8606ac9..7bc603145bd9 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1643,17 +1643,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; } }