[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c864a907-06d1-4665-9095-65d9cdecdcf5@nvidia.com>
Date: Tue, 27 Jan 2026 19:29:39 +0000
From: Jon Hunter <jonathanh@...dia.com>
To: "Sheetal ." <sheetal@...dia.com>, Mark Brown <broonie@...nel.org>
Cc: Sander Vanheule <sander@...nheule.net>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
"Rafael J . Wysocki" <rafael@...nel.org>, Danilo Krummrich
<dakr@...nel.org>, Liam Girdwood <lgirdwood@...il.com>,
Jaroslav Kysela <perex@...ex.cz>, Takashi Iwai <tiwai@...e.com>,
Thierry Reding <thierry.reding@...il.com>, Mohan kumar <mkumard@...dia.com>,
linux-kernel@...r.kernel.org, linux-sound@...r.kernel.org,
linux-tegra@...r.kernel.org
Subject: Re: [RFC PATCH v3 2/4] regmap: Add reg_default_cb callback for flat
cache defaults
On 23/01/2026 09:53, Sheetal . wrote:
> From: Sheetal <sheetal@...dia.com>
>
> Commit e062bdfdd6ad ("regmap: warn users about uninitialized flat cache")
> warns when REGCACHE_FLAT is used without full defaults. This causes
> false positives on hardware where many registers reset to zero but are
> not listed in reg_defaults, forcing drivers to maintain large tables
> just to silence the warning.
>
> Add a reg_default_cb() hook so drivers can supply defaults for registers
> not present in reg_defaults when populating REGCACHE_FLAT. This keeps
> the warning quiet for known zero-reset registers without bloating
> tables. Provide a generic regmap_default_zero_cb() helper for drivers
> that need zero defaults.
>
> The hook is only used for REGCACHE_FLAT; the core does not
> check readable/writeable access, so drivers must provide readable_reg/
> writeable_reg callbacks and handle holes in the register map.
>
> Signed-off-by: Sheetal <sheetal@...dia.com>
> ---
> drivers/base/regmap/internal.h | 3 +++
> drivers/base/regmap/regcache-flat.c | 19 +++++++++++++++++++
> drivers/base/regmap/regcache.c | 3 ++-
> drivers/base/regmap/regmap.c | 2 ++
> include/linux/regmap.h | 14 ++++++++++++++
> 5 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
> index 1477329410ec..5bf993165438 100644
> --- a/drivers/base/regmap/internal.h
> +++ b/drivers/base/regmap/internal.h
> @@ -117,6 +117,9 @@ struct regmap {
> void *val_buf, size_t val_size);
> int (*write)(void *context, const void *data, size_t count);
>
> + int (*reg_default_cb)(struct device *dev, unsigned int reg,
> + unsigned int *val);
> +
> unsigned long read_flag_mask;
> unsigned long write_flag_mask;
>
> diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c
> index 53cc59c84e2f..c924817e19b1 100644
> --- a/drivers/base/regmap/regcache-flat.c
> +++ b/drivers/base/regmap/regcache-flat.c
> @@ -79,6 +79,25 @@ static int regcache_flat_populate(struct regmap *map)
> __set_bit(index, cache->valid);
> }
>
> + if (map->reg_default_cb) {
> + dev_dbg(map->dev,
> + "Populating regcache_flat using reg_default_cb callback\n");
> +
> + for (i = 0; i <= map->max_register; i += map->reg_stride) {
> + unsigned int index = regcache_flat_get_index(map, i);
> + unsigned int value;
> +
> + if (test_bit(index, cache->valid))
> + continue;
> +
> + if (map->reg_default_cb(map->dev, i, &value))
> + continue;
> +
> + cache->data[index] = value;
> + __set_bit(index, cache->valid);
> + }
> + }
> +
> return 0;
> }
>
> diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
> index 319c342bf5a0..31bdbf37dbed 100644
> --- a/drivers/base/regmap/regcache.c
> +++ b/drivers/base/regmap/regcache.c
> @@ -223,7 +223,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
> goto err_free;
> }
>
> - if (map->num_reg_defaults && map->cache_ops->populate) {
> + if (map->cache_ops->populate &&
> + (map->num_reg_defaults || map->reg_default_cb)) {
> dev_dbg(map->dev, "Populating %s cache\n", map->cache_ops->name);
> map->lock(map->lock_arg);
> ret = map->cache_ops->populate(map);
> diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
> index ce9be3989a21..57c5551044ed 100644
> --- a/drivers/base/regmap/regmap.c
> +++ b/drivers/base/regmap/regmap.c
> @@ -811,6 +811,7 @@ struct regmap *__regmap_init(struct device *dev,
> map->precious_reg = config->precious_reg;
> map->writeable_noinc_reg = config->writeable_noinc_reg;
> map->readable_noinc_reg = config->readable_noinc_reg;
> + map->reg_default_cb = config->reg_default_cb;
> map->cache_type = config->cache_type;
>
> spin_lock_init(&map->async_lock);
> @@ -1433,6 +1434,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
> map->precious_reg = config->precious_reg;
> map->writeable_noinc_reg = config->writeable_noinc_reg;
> map->readable_noinc_reg = config->readable_noinc_reg;
> + map->reg_default_cb = config->reg_default_cb;
> map->cache_type = config->cache_type;
>
> ret = regmap_set_name(map, config);
> diff --git a/include/linux/regmap.h b/include/linux/regmap.h
> index b0b9be750d93..51940eeff872 100644
> --- a/include/linux/regmap.h
> +++ b/include/linux/regmap.h
> @@ -359,6 +359,10 @@ typedef void (*regmap_unlock)(void *);
> * @reg_defaults: Power on reset values for registers (for use with
> * register cache support).
> * @num_reg_defaults: Number of elements in reg_defaults.
> + * @reg_default_cb: Optional callback to return default values for registers
> + * not listed in reg_defaults. This is only used for
> + * REGCACHE_FLAT population; drivers must ensure the readable_reg/
> + * writeable_reg callbacks are defined to handle holes.
> *
> * @read_flag_mask: Mask to be set in the top bytes of the register when doing
> * a read.
> @@ -449,6 +453,8 @@ struct regmap_config {
> const struct regmap_access_table *rd_noinc_table;
> const struct reg_default *reg_defaults;
> unsigned int num_reg_defaults;
> + int (*reg_default_cb)(struct device *dev, unsigned int reg,
> + unsigned int *def);
> enum regcache_type cache_type;
> const void *reg_defaults_raw;
> unsigned int num_reg_defaults_raw;
> @@ -1349,6 +1355,14 @@ static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
> return regmap_update_bits_base(map, reg, mask, val, NULL, false, true);
> }
>
> +static inline int regmap_default_zero_cb(struct device *dev,
> + unsigned int reg,
> + unsigned int *def)
> +{
> + *def = 0;
> + return 0;
It might be worth ...
if (!def)
return -EINVAL;
*def = 0;
Otherwise ...
Reviewed-by: Jon Hunter <jonathanh@...dia.com>
Tested-by: Jon Hunter <jonathanh@...dia.com>
Thanks
Jon
--
nvpublic
Powered by blists - more mailing lists