Skip to content

Commit dc65b1e

Browse files
Sheetalbroonie
authored andcommitted
regmap: Add reg_default_cb callback for flat cache defaults
Commit e062bdf ("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>
1 parent 63804fe commit dc65b1e

5 files changed

Lines changed: 40 additions & 1 deletion

File tree

drivers/base/regmap/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ struct regmap {
117117
void *val_buf, size_t val_size);
118118
int (*write)(void *context, const void *data, size_t count);
119119

120+
int (*reg_default_cb)(struct device *dev, unsigned int reg,
121+
unsigned int *val);
122+
120123
unsigned long read_flag_mask;
121124
unsigned long write_flag_mask;
122125

drivers/base/regmap/regcache-flat.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,25 @@ static int regcache_flat_populate(struct regmap *map)
7979
__set_bit(index, cache->valid);
8080
}
8181

82+
if (map->reg_default_cb) {
83+
dev_dbg(map->dev,
84+
"Populating regcache_flat using reg_default_cb callback\n");
85+
86+
for (i = 0; i <= map->max_register; i += map->reg_stride) {
87+
unsigned int index = regcache_flat_get_index(map, i);
88+
unsigned int value;
89+
90+
if (test_bit(index, cache->valid))
91+
continue;
92+
93+
if (map->reg_default_cb(map->dev, i, &value))
94+
continue;
95+
96+
cache->data[index] = value;
97+
__set_bit(index, cache->valid);
98+
}
99+
}
100+
82101
return 0;
83102
}
84103

drivers/base/regmap/regcache.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
223223
goto err_free;
224224
}
225225

226-
if (map->num_reg_defaults && map->cache_ops->populate) {
226+
if (map->cache_ops->populate &&
227+
(map->num_reg_defaults || map->reg_default_cb)) {
227228
dev_dbg(map->dev, "Populating %s cache\n", map->cache_ops->name);
228229
map->lock(map->lock_arg);
229230
ret = map->cache_ops->populate(map);

drivers/base/regmap/regmap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ struct regmap *__regmap_init(struct device *dev,
813813
map->precious_reg = config->precious_reg;
814814
map->writeable_noinc_reg = config->writeable_noinc_reg;
815815
map->readable_noinc_reg = config->readable_noinc_reg;
816+
map->reg_default_cb = config->reg_default_cb;
816817
map->cache_type = config->cache_type;
817818

818819
spin_lock_init(&map->async_lock);
@@ -1435,6 +1436,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
14351436
map->precious_reg = config->precious_reg;
14361437
map->writeable_noinc_reg = config->writeable_noinc_reg;
14371438
map->readable_noinc_reg = config->readable_noinc_reg;
1439+
map->reg_default_cb = config->reg_default_cb;
14381440
map->cache_type = config->cache_type;
14391441

14401442
ret = regmap_set_name(map, config);

include/linux/regmap.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ typedef void (*regmap_unlock)(void *);
359359
* @reg_defaults: Power on reset values for registers (for use with
360360
* register cache support).
361361
* @num_reg_defaults: Number of elements in reg_defaults.
362+
* @reg_default_cb: Optional callback to return default values for registers
363+
* not listed in reg_defaults. This is only used for
364+
* REGCACHE_FLAT population; drivers must ensure the readable_reg/
365+
* writeable_reg callbacks are defined to handle holes.
362366
*
363367
* @read_flag_mask: Mask to be set in the top bytes of the register when doing
364368
* a read.
@@ -449,6 +453,8 @@ struct regmap_config {
449453
const struct regmap_access_table *rd_noinc_table;
450454
const struct reg_default *reg_defaults;
451455
unsigned int num_reg_defaults;
456+
int (*reg_default_cb)(struct device *dev, unsigned int reg,
457+
unsigned int *def);
452458
enum regcache_type cache_type;
453459
const void *reg_defaults_raw;
454460
unsigned int num_reg_defaults_raw;
@@ -1349,6 +1355,14 @@ static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
13491355
return regmap_update_bits_base(map, reg, mask, val, NULL, false, true);
13501356
}
13511357

1358+
static inline int regmap_default_zero_cb(struct device *dev,
1359+
unsigned int reg,
1360+
unsigned int *def)
1361+
{
1362+
*def = 0;
1363+
return 0;
1364+
}
1365+
13521366
int regmap_get_val_bytes(struct regmap *map);
13531367
int regmap_get_max_register(struct regmap *map);
13541368
int regmap_get_reg_stride(struct regmap *map);

0 commit comments

Comments
 (0)