Pull regmap fix from Mark Brown: "One fix here, for an interaction between noinc registers and caches. If a device uses noinc registers (which is rare) then we could corrupt registers after the noinc register in the cache" * tag 'regmap-fix-v6.7-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: prevent noinc writes from clobbering cache
Unified · Split
| @@ -1620,17 +1620,19 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, · 1619 unmodified lines | ||
| 1620 | 1620 | } |
| 1621 | 1621 | |
| 1622 | 1622 | if (!map->cache_bypass && map->format.parse_val) { |
| 1623 | − unsigned int ival; | |
| 1623 | + unsigned int ival, offset; | |
| 1624 | 1624 | int val_bytes = map->format.val_bytes; |
| 1625 | − for (i = 0; i < val_len / val_bytes; i++) { | |
| 1626 | − ival = map->format.parse_val(val + (i * val_bytes)); | |
| 1627 | − ret = regcache_write(map, | |
| 1628 | − reg + regmap_get_offset(map, i), | |
| 1629 | − ival); | |
| 1625 | + | |
| 1626 | + /* Cache the last written value for noinc writes */ | |
| 1627 | + i = noinc ? val_len - val_bytes : 0; | |
| 1628 | + for (; i < val_len; i += val_bytes) { | |
| 1629 | + ival = map->format.parse_val(val + i); | |
| 1630 | + offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes); | |
| 1631 | + ret = regcache_write(map, reg + offset, ival); | |
| 1630 | 1632 | if (ret) { |
| 1631 | 1633 | dev_err(map->dev, |
| 1632 | 1634 | "Error in caching of register: %x ret: %d\n", |
| 1633 | − reg + regmap_get_offset(map, i), ret); | |
| 1635 | + reg + offset, ret); | |
| 1634 | 1636 | return ret; |
| 1635 | 1637 | } |
| 1636 | 1638 | } |