regmap: Add reg_default_cb callback for flat cache defaults
Commit e062bdfdd6 ("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@nvidia.com>
Link: https://patch.msgid.link/20260123095346.1258556-3-sheetal@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
63804fed14
commit
dc65b1ed4b
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -813,6 +813,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);
|
||||
|
|
@ -1435,6 +1436,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
int regmap_get_val_bytes(struct regmap *map);
|
||||
int regmap_get_max_register(struct regmap *map);
|
||||
int regmap_get_reg_stride(struct regmap *map);
|
||||
|
|
|
|||
Loading…
Reference in New Issue