[RFC PATCH v2 1/3] regmap: Add flat_cache_default_is_zero flag for flat cache

Sheetal . posted 3 patches 3 weeks, 6 days ago
[RFC PATCH v2 1/3] regmap: Add flat_cache_default_is_zero flag for flat cache
Posted by Sheetal . 3 weeks, 6 days ago
From: Sheetal <sheetal@nvidia.com>

Commit e062bdfdd6ad ("regmap: warn users about uninitialized flat
cache") added a warning for drivers using REGCACHE_FLAT when reading
registers not present in reg_defaults.

For hardware where registers have a power-on-reset value of zero
or drivers that wish to treat zero as a valid cache default, adding
all such registers to reg_defaults has drawbacks:

1. Maintenance burden: Drivers must list every readable register
   regardless of its reset value.

2. No functional benefit: Entries like { REG, 0x0 } only set the
   validity bit; the flat cache value is already zero.

3. Code bloat: Large reg_defaults arrays increase driver size.

Add a flat_cache_default_is_zero flag to struct regmap_config. When
set, the flat cache marks registers as valid on first read instead
of warning.

The valid bit is set on first read rather than marking all registers
valid at init time for the following reasons:
- Avoids writes to register holes or unused addresses during sync.
- Safer for drivers that don't have writeable_reg callback defined.

Signed-off-by: Sheetal <sheetal@nvidia.com>
---
 drivers/base/regmap/internal.h      |  2 ++
 drivers/base/regmap/regcache-flat.c | 12 ++++++++----
 drivers/base/regmap/regcache.c      |  1 +
 include/linux/regmap.h              |  1 +
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 1477329410ec..xxxxxxxxxxxx 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -157,6 +157,8 @@ struct regmap {
 	bool cache_dirty;
 	/* if set, the HW registers are known to match map->reg_defaults */
 	bool no_sync_defaults;
+	/* if set, zero is a valid default for REGCACHE_FLAT cache type registers not in reg_defaults */
+	bool flat_cache_default_is_zero;
 
 	struct reg_sequence *patch;
 	int patch_regs;
diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c
index 53cc59c84e2f..xxxxxxxxxxxx 100644
--- a/drivers/base/regmap/regcache-flat.c
+++ b/drivers/base/regmap/regcache-flat.c
@@ -88,10 +88,14 @@ static int regcache_flat_read(struct regmap *map,
 	struct regcache_flat_data *cache = map->cache;
 	unsigned int index = regcache_flat_get_index(map, reg);
 
-	/* legacy behavior: ignore validity, but warn the user */
-	if (unlikely(!test_bit(index, cache->valid)))
-		dev_warn_once(map->dev,
-			"using zero-initialized flat cache, this may cause unexpected behavior");
+	/* legacy behavior: ignore validity, but warn if zero is not a valid default */
+	if (unlikely(!test_bit(index, cache->valid))) {
+		if (map->flat_cache_default_is_zero)
+			set_bit(index, cache->valid);
+		else
+			dev_warn_once(map->dev,
+				      "using zero-initialized flat cache, this may cause unexpected behavior");
+	}
 
 	*value = cache->data[index];
 
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 319c342bf5a0..xxxxxxxxxxxx 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -177,6 +177,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	map->reg_defaults_raw = config->reg_defaults_raw;
 	map->cache_word_size = BITS_TO_BYTES(config->val_bits);
 	map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
+	map->flat_cache_default_is_zero = config->flat_cache_default_is_zero;
 
 	map->cache = NULL;
 	map->cache_ops = cache_types[i];
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index b0b9be750d93..xxxxxxxxxxxx 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -452,6 +452,7 @@ struct regmap_config {
 	enum regcache_type cache_type;
 	const void *reg_defaults_raw;
 	unsigned int num_reg_defaults_raw;
+	bool flat_cache_default_is_zero;
 
 	unsigned long read_flag_mask;
 	unsigned long write_flag_mask;
-- 
2.34.1
Re: [RFC PATCH v2 1/3] regmap: Add flat_cache_default_is_zero flag for flat cache
Posted by Sander Vanheule 3 weeks, 5 days ago
Hi,

On Mon, 2026-01-12 at 09:58 +0530, Sheetal . wrote:
> From: Sheetal <sheetal@nvidia.com>
> 
> Commit e062bdfdd6ad ("regmap: warn users about uninitialized flat
> cache") added a warning for drivers using REGCACHE_FLAT when reading
> registers not present in reg_defaults.
> 
> For hardware where registers have a power-on-reset value of zero
> or drivers that wish to treat zero as a valid cache default, adding
> all such registers to reg_defaults has drawbacks:
> 
> 1. Maintenance burden: Drivers must list every readable register
>    regardless of its reset value.

If you would extend regmap_config to accept a callback for defaults, this burden
could be reduced to near-zero if it was a simple wrapper for the writeable_regs
and/or readable_regs callbacks. I.e. "return 0x0 if readable or writable".


> 2. No functional benefit: Entries like { REG, 0x0 } only set the
>    validity bit; the flat cache value is already zero.

There is a functional benefit: it allows regmap_sync() to do what it is supposed
to do: check if a cached register matches the reset value to omit writing the
cached value to hardware after a reset.


> 3. Code bloat: Large reg_defaults arrays increase driver size.

As I argued before, bloat would be limited if the user could provide tables or
callbacks for defaults.

> 
> Add a flat_cache_default_is_zero flag to struct regmap_config. When
> set, the flat cache marks registers as valid on first read instead
> of warning.
> 
> The valid bit is set on first read rather than marking all registers
> valid at init time for the following reasons:
> - Avoids writes to register holes or unused addresses during sync.
> - Safer for drivers that don't have writeable_reg callback defined.

These are benefits of using a sparse cache, but on closer inspection don't
actually apply here. You can validate this in your kunit test if you also do the
negative check: assert that registers outside of the written range are left
untouched (written == 0).

Because regcache_read() will never return -ENOENT with this option enabled,
regmap_sync() will see all registers as "written". Since there are no defaults
to check against, this will cause regmap_sync() to write to *all* writable
registers. With this patch, you are just reverting to the old behaviour where
regmap_sync() silently overwrites registers you never accessed with 0.


Best,
Sander
Re: [RFC PATCH v2 1/3] regmap: Add flat_cache_default_is_zero flag for flat cache
Posted by Mark Brown 3 weeks, 5 days ago
On Mon, Jan 12, 2026 at 08:09:33PM +0100, Sander Vanheule wrote:
> On Mon, 2026-01-12 at 09:58 +0530, Sheetal . wrote:

> > 1. Maintenance burden: Drivers must list every readable register
> >    regardless of its reset value.

> If you would extend regmap_config to accept a callback for defaults, this burden
> could be reduced to near-zero if it was a simple wrapper for the writeable_regs
> and/or readable_regs callbacks. I.e. "return 0x0 if readable or writable".

That does seem like a good idea.