regmap: reg_default_cb for flat cache defaults
Subsystems (5)
v3 cover regmap: reg_default_cb for flat cache defaults
From: sheetal <[email protected]>
This series adds a reg_default_cb callback for REGCACHE_FLAT to provide defaults for registers not listed in reg_defaults. Defaults are loaded eagerly during regcache init and the callback can use writeable_reg to filter valid addresses and avoid holes.
Tegra ASoC drivers set reg_default_cb and add writeable_reg filtering for AHUB RX holes to prevent invalid addresses from being marked valid.
Changes in v3:
- Add AHUB writeable_reg filtering for RX holes.
- Replace flat_cache_default_is_zero flag with reg_default_cb callback
- Load defaults at regcache init using reg_default_cb
- Set reg_default_cb in Tegra ASoC drivers
- Add KUnit coverage for reg_default_cb callback
Note:
"ASoC: tegra: set reg_default_cb callback" patch depends on "ASoC: tegra: Add AHUB writeable_reg for RX holes" patch, hence included in this series.
Sheetal (4):
ASoC: tegra: Add AHUB writeable_reg for RX holes
regmap: Add reg_default_cb callback for flat cache defaults
ASoC: tegra: set reg_default_cb callback
regmap: add KUnit coverage for reg_default_cb callback
drivers/base/regmap/internal.h | 3 + drivers/base/regmap/regcache-flat.c | 19 ++++++ drivers/base/regmap/regcache.c | 3 +- drivers/base/regmap/regmap-kunit.c | 91 +++++++++++++++++++++++++++++ drivers/base/regmap/regmap.c | 2 + include/linux/regmap.h | 14 +++++ sound/soc/tegra/tegra186_asrc.c | 1 + sound/soc/tegra/tegra186_dspk.c | 1 + sound/soc/tegra/tegra210_admaif.c | 3 + sound/soc/tegra/tegra210_adx.c | 2 + sound/soc/tegra/tegra210_ahub.c | 60 +++++++++++++++++++ sound/soc/tegra/tegra210_ahub.h | 30 ++++++++++ sound/soc/tegra/tegra210_amx.c | 3 + sound/soc/tegra/tegra210_dmic.c | 1 + sound/soc/tegra/tegra210_i2s.c | 2 + sound/soc/tegra/tegra210_mbdrc.c | 1 + sound/soc/tegra/tegra210_mixer.c | 1 + sound/soc/tegra/tegra210_mvc.c | 1 + sound/soc/tegra/tegra210_ope.c | 1 + sound/soc/tegra/tegra210_peq.c | 1 + sound/soc/tegra/tegra210_sfc.c | 1 + 21 files changed, 240 insertions(+), 1 deletion(-)
Signature · 1 line
2.34.1
RFC PATCH v3 1/4 ASoC: tegra: Add AHUB writeable_reg for RX holes
From: Sheetal <[email protected]>
Add writeable_reg callbacks for Tegra210/186 AHUB RX registers so the flat cache only treats valid RX locations as writable, avoiding holes in the register map.
--- sound/soc/tegra/tegra210_ahub.c | 57 +++++++++++++++++++++++++++++++++ sound/soc/tegra/tegra210_ahub.h | 30 +++++++++++++++++ 2 files changed, 87 insertions(+)
sound/soc/tegra/tegra210_ahub.c +57 -0
@@ -2049,6 +2049,61 @@ static const struct snd_soc_component_driver tegra264_ahub_component = { .num_dapm_routes = ARRAY_SIZE(tegra264_ahub_routes), }; +static bool tegra210_ahub_wr_reg (struct device *dev,unsigned int reg) +{ +int part; + +if (reg %TEGRA210_XBAR_RX_STRIDE ) +return false; + +for (part =0 ; part <TEGRA210_XBAR_UPDATE_MAX_REG ; part++) { +switch (reg & ~(part *TEGRA210_XBAR_PART1_RX )) { + case TEGRA210_AXBAR_PART_0_ADMAIF_RX1_0 ... TEGRA210_AXBAR_PART_0_ADMAIF_RX10_0: + case TEGRA210_AXBAR_PART_0_I2S1_RX1_0 ... TEGRA210_AXBAR_PART_0_I2S5_RX1_0: + case TEGRA210_AXBAR_PART_0_SFC1_RX1_0 ... TEGRA210_AXBAR_PART_0_SFC4_RX1_0: + case TEGRA210_AXBAR_PART_0_MIXER1_RX1_0 ... TEGRA210_AXBAR_PART_0_MIXER1_RX10_0: + case TEGRA210_AXBAR_PART_0_SPDIF1_RX1_0 ... TEGRA210_AXBAR_PART_0_SPDIF1_RX2_0: + case TEGRA210_AXBAR_PART_0_AFC1_RX1_0 ... TEGRA210_AXBAR_PART_0_AFC6_RX1_0: + case TEGRA210_AXBAR_PART_0_OPE1_RX1_0 ... TEGRA210_AXBAR_PART_0_OPE2_RX1_0: +case TEGRA210_AXBAR_PART_0_SPKPROT1_RX1_0 : + case TEGRA210_AXBAR_PART_0_MVC1_RX1_0 ... TEGRA210_AXBAR_PART_0_MVC2_RX1_0: + case TEGRA210_AXBAR_PART_0_AMX1_RX1_0 ... TEGRA210_AXBAR_PART_0_ADX2_RX1_0: +return true; +default : +break ; + } + } + +return false; +} + +static bool tegra186_ahub_wr_reg (struct device *dev,unsigned int reg) +{ +int part; + +if (reg %TEGRA210_XBAR_RX_STRIDE ) +return false; + +for (part =0 ; part <TEGRA186_XBAR_UPDATE_MAX_REG ; part++) { +switch (reg & ~(part *TEGRA210_XBAR_PART1_RX )) { + case TEGRA210_AXBAR_PART_0_ADMAIF_RX1_0 ... TEGRA186_AXBAR_PART_0_I2S6_RX1_0: + case TEGRA210_AXBAR_PART_0_SFC1_RX1_0 ... TEGRA210_AXBAR_PART_0_SFC4_RX1_0: + case TEGRA210_AXBAR_PART_0_MIXER1_RX1_0 ... TEGRA210_AXBAR_PART_0_MIXER1_RX10_0: + case TEGRA186_AXBAR_PART_0_DSPK1_RX1_0 ... TEGRA186_AXBAR_PART_0_DSPK2_RX1_0: + case TEGRA210_AXBAR_PART_0_AFC1_RX1_0 ... TEGRA210_AXBAR_PART_0_AFC6_RX1_0: +case TEGRA210_AXBAR_PART_0_OPE1_RX1_0 : + case TEGRA186_AXBAR_PART_0_MVC1_RX1_0 ... TEGRA186_AXBAR_PART_0_MVC2_RX1_0: + case TEGRA186_AXBAR_PART_0_AMX1_RX1_0 ... TEGRA186_AXBAR_PART_0_AMX3_RX4_0: + case TEGRA210_AXBAR_PART_0_ADX1_RX1_0 ... TEGRA186_AXBAR_PART_0_ASRC1_RX7_0: +return true; +default : +break ; + } + } + +return false; +} +static bool tegra264_ahub_wr_reg (struct device *dev,unsigned int reg) {int part;
@@ -2076,6 +2131,7 @@ static const struct regmap_config tegra210_ahub_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .writeable_reg = tegra210_ahub_wr_reg, .max_register = TEGRA210_MAX_REGISTER_ADDR, .cache_type = REGCACHE_FLAT, };
@@ -2084,6 +2140,7 @@ static const struct regmap_config tegra186_ahub_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .writeable_reg = tegra186_ahub_wr_reg, .max_register = TEGRA186_MAX_REGISTER_ADDR, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_ahub.h +30 -0
@@ -68,6 +68,36 @@#define TEGRA210_MAX_REGISTER_ADDR (TEGRA210_XBAR_PART2_RX + \ (TEGRA210_XBAR_RX_STRIDE * (TEGRA210_XBAR_AUDIO_RX_COUNT - 1))) +/* AXBAR register offsets */ +#define TEGRA186_AXBAR_PART_0_AMX1_RX1_0 0x120 +#define TEGRA186_AXBAR_PART_0_AMX3_RX4_0 0x14c +#define TEGRA186_AXBAR_PART_0_ASRC1_RX7_0 0x1a8 +#define TEGRA186_AXBAR_PART_0_DSPK1_RX1_0 0xc0 +#define TEGRA186_AXBAR_PART_0_DSPK2_RX1_0 0xc4 +#define TEGRA186_AXBAR_PART_0_I2S6_RX1_0 0x54 +#define TEGRA186_AXBAR_PART_0_MVC1_RX1_0 0x110 +#define TEGRA186_AXBAR_PART_0_MVC2_RX1_0 0x114 +#define TEGRA210_AXBAR_PART_0_ADMAIF_RX10_0 0x24 +#define TEGRA210_AXBAR_PART_0_ADMAIF_RX1_0 0x0 +#define TEGRA210_AXBAR_PART_0_ADX1_RX1_0 0x160 +#define TEGRA210_AXBAR_PART_0_ADX2_RX1_0 0x164 +#define TEGRA210_AXBAR_PART_0_AFC1_RX1_0 0xd0 +#define TEGRA210_AXBAR_PART_0_AFC6_RX1_0 0xe4 +#define TEGRA210_AXBAR_PART_0_AMX1_RX1_0 0x140 +#define TEGRA210_AXBAR_PART_0_I2S1_RX1_0 0x40 +#define TEGRA210_AXBAR_PART_0_I2S5_RX1_0 0x50 +#define TEGRA210_AXBAR_PART_0_MIXER1_RX10_0 0xa4 +#define TEGRA210_AXBAR_PART_0_MIXER1_RX1_0 0x80 +#define TEGRA210_AXBAR_PART_0_MVC1_RX1_0 0x120 +#define TEGRA210_AXBAR_PART_0_MVC2_RX1_0 0x124 +#define TEGRA210_AXBAR_PART_0_OPE1_RX1_0 0x100 +#define TEGRA210_AXBAR_PART_0_OPE2_RX1_0 0x104 +#define TEGRA210_AXBAR_PART_0_SFC1_RX1_0 0x60 +#define TEGRA210_AXBAR_PART_0_SFC4_RX1_0 0x6c +#define TEGRA210_AXBAR_PART_0_SPDIF1_RX1_0 0xc0 +#define TEGRA210_AXBAR_PART_0_SPDIF1_RX2_0 0xc4 +#define TEGRA210_AXBAR_PART_0_SPKPROT1_RX1_0 0x110 +#define MUX_REG (id) (TEGRA210_XBAR_RX_STRIDE * (id))#define MUX_VALUE (npart, nbit) (1 + (nbit) + (npart) * 32)
Signature · 1 line
2.34.1
Re: [RFC PATCH v3 1/4] ASoC: tegra: Add AHUB writeable_reg for RX holes
Quoted 8 lines · Sheetal .
From: Sheetal <[email protected]>
Add
writeable_regcallbacks for Tegra210/186 AHUB RX registers so the flat cache only treats valid RX locations as writable, avoiding holes in the register map.Fixes 16e1bcc2caf4 ("ASoC: tegra: Add Tegra210 based AHUB driver")Signed-off-by Sheetal <[email protected]>
Thanks
Jon
Signature · 1 line
nvpublic
RFC PATCH v3 2/4 regmap: Add reg_default_cb callback for flat cache defaults
In reply to Sheetal .From: Sheetal <[email protected]>
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.
--- 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(-)
drivers/base/regmap/internal.h +3 -0
@@ -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;
drivers/base/regmap/regcache-flat.c +19 -0
@@ -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 ; }
drivers/base/regmap/regcache.c +2 -1
@@ -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);
drivers/base/regmap/regmap.c +2 -0
@@ -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);
include/linux/regmap.h +14 -0
@@ -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);
Signature · 1 line
2.34.1
Re: [RFC PATCH v3 2/4] regmap: Add reg_default_cb callback for flat cache defaults
Quoted 130 lines · Sheetal .
From: Sheetal <[email protected]>
Commit
e062bdfdd6ad("regmap: warn users about uninitialized flat cache") warns whenREGCACHE_FLATis used without full defaults. This causes false positives on hardware where many registers reset to zero but are not listed inreg_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 inreg_defaultswhen populatingREGCACHE_FLAT. This keeps the warning quiet for known zero-reset registers without bloating tables. Provide a genericregmap_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_regcallbacks and handle holes in the register map.Signed-off-by Sheetal <[email protected]>--- 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(-)drivers/base/regmap/internal.h +3
-0@@ -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;drivers/base/regmap/regcache-flat.c +19
-0@@ -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 ; }drivers/base/regmap/regcache.c +2
-1@@ -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);drivers/base/regmap/regmap.c +2
-0@@ -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);include/linux/regmap.h +6
-0@@ -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;
include/linux/regmap.h static inline int regmap_write_bits(struct regmap *map, unsigned int reg, · line 1363
Quoted 9 lines
include/linux/regmap.h +6
-0@@ -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 ...
Thanks
Jon
Signature · 1 line
nvpublic
RFC PATCH v3 3/4 ASoC: tegra: set reg_default_cb callback
In reply to Sheetal .From: Sheetal <[email protected]>
Set reg_default_cb so REGCACHE_FLAT can supply zero defaults without large reg_defaults tables, simplifying cache initialization for zero-reset registers.
--- sound/soc/tegra/tegra186_asrc.c | 1 + sound/soc/tegra/tegra186_dspk.c | 1 + sound/soc/tegra/tegra210_admaif.c | 3 +++ sound/soc/tegra/tegra210_adx.c | 2 ++ sound/soc/tegra/tegra210_ahub.c | 3 +++ sound/soc/tegra/tegra210_amx.c | 3 +++ sound/soc/tegra/tegra210_dmic.c | 1 + sound/soc/tegra/tegra210_i2s.c | 2 ++ sound/soc/tegra/tegra210_mbdrc.c | 1 + sound/soc/tegra/tegra210_mixer.c | 1 + sound/soc/tegra/tegra210_mvc.c | 1 + sound/soc/tegra/tegra210_ope.c | 1 + sound/soc/tegra/tegra210_peq.c | 1 + sound/soc/tegra/tegra210_sfc.c | 1 + 14 files changed, 22 insertions(+)
sound/soc/tegra/tegra186_asrc.c +1 -0
@@ -950,6 +950,7 @@ static const struct regmap_config tegra186_asrc_regmap_config = { .volatile_reg = tegra186_asrc_volatile_reg, .reg_defaults = tegra186_asrc_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra186_asrc_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra186_dspk.c +1 -0
@@ -467,6 +467,7 @@ static const struct regmap_config tegra186_dspk_regmap = { .volatile_reg = tegra186_dspk_volatile_reg, .reg_defaults = tegra186_dspk_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra186_dspk_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_admaif.c +3 -0
@@ -241,6 +241,7 @@ static const struct regmap_config tegra210_admaif_regmap_config = { .volatile_reg = tegra_admaif_volatile_reg, .reg_defaults = tegra210_admaif_reg_defaults, .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -254,6 +255,7 @@ static const struct regmap_config tegra186_admaif_regmap_config = { .volatile_reg = tegra_admaif_volatile_reg, .reg_defaults = tegra186_admaif_reg_defaults, .num_reg_defaults = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -267,6 +269,7 @@ static const struct regmap_config tegra264_admaif_regmap_config = { .volatile_reg = tegra_admaif_volatile_reg, .reg_defaults = tegra264_admaif_reg_defaults, .num_reg_defaults = TEGRA264_ADMAIF_CHANNEL_COUNT * 6 + 1, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_adx.c +2 -0
@@ -625,6 +625,7 @@ static const struct regmap_config tegra210_adx_regmap_config = { .volatile_reg = tegra210_adx_volatile_reg, .reg_defaults = tegra210_adx_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_adx_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -638,6 +639,7 @@ static const struct regmap_config tegra264_adx_regmap_config = { .volatile_reg = tegra264_adx_volatile_reg, .reg_defaults = tegra264_adx_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra264_adx_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_ahub.c +3 -0
@@ -2133,6 +2133,7 @@ static const struct regmap_config tegra210_ahub_regmap_config = { .reg_stride = 4, .writeable_reg = tegra210_ahub_wr_reg, .max_register = TEGRA210_MAX_REGISTER_ADDR, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -2142,6 +2143,7 @@ static const struct regmap_config tegra186_ahub_regmap_config = { .reg_stride = 4, .writeable_reg = tegra186_ahub_wr_reg, .max_register = TEGRA186_MAX_REGISTER_ADDR, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -2151,6 +2153,7 @@ static const struct regmap_config tegra264_ahub_regmap_config = { .reg_stride = 4, .writeable_reg = tegra264_ahub_wr_reg, .max_register = TEGRA264_MAX_REGISTER_ADDR, + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_amx.c +3 -0
@@ -654,6 +654,7 @@ static const struct regmap_config tegra210_amx_regmap_config = { .volatile_reg = tegra210_amx_volatile_reg, .reg_defaults = tegra210_amx_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_amx_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -667,6 +668,7 @@ static const struct regmap_config tegra194_amx_regmap_config = { .volatile_reg = tegra210_amx_volatile_reg, .reg_defaults = tegra210_amx_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_amx_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -680,6 +682,7 @@ static const struct regmap_config tegra264_amx_regmap_config = { .volatile_reg = tegra264_amx_volatile_reg, .reg_defaults = tegra264_amx_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra264_amx_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_dmic.c +1 -0
@@ -483,6 +483,7 @@ static const struct regmap_config tegra210_dmic_regmap_config = { .volatile_reg = tegra210_dmic_volatile_reg, .reg_defaults = tegra210_dmic_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_i2s.c +2 -0
@@ -997,6 +997,7 @@ static const struct regmap_config tegra210_regmap_conf = { .volatile_reg = tegra210_i2s_volatile_reg, .reg_defaults = tegra210_i2s_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_i2s_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
@@ -1044,6 +1045,7 @@ static const struct regmap_config tegra264_regmap_conf = { .volatile_reg = tegra264_i2s_volatile_reg, .reg_defaults = tegra264_i2s_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra264_i2s_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_mbdrc.c +1 -0
@@ -763,6 +763,7 @@ static const struct regmap_config tegra210_mbdrc_regmap_cfg = { .precious_reg = tegra210_mbdrc_precious_reg, .reg_defaults = tegra210_mbdrc_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_mbdrc_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_mixer.c +1 -0
@@ -608,6 +608,7 @@ static const struct regmap_config tegra210_mixer_regmap_config = { .precious_reg = tegra210_mixer_precious_reg, .reg_defaults = tegra210_mixer_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_mixer_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_mvc.c +1 -0
@@ -699,6 +699,7 @@ static const struct regmap_config tegra210_mvc_regmap_config = { .volatile_reg = tegra210_mvc_volatile_reg, .reg_defaults = tegra210_mvc_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_mvc_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_ope.c +1 -0
@@ -297,6 +297,7 @@ static const struct regmap_config tegra210_ope_regmap_config = { .volatile_reg = tegra210_ope_volatile_reg, .reg_defaults = tegra210_ope_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_ope_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_peq.c +1 -0
@@ -306,6 +306,7 @@ static const struct regmap_config tegra210_peq_regmap_config = { .precious_reg = tegra210_peq_precious_reg, .reg_defaults = tegra210_peq_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_peq_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
sound/soc/tegra/tegra210_sfc.c +1 -0
@@ -3569,6 +3569,7 @@ static const struct regmap_config tegra210_sfc_regmap_config = { .precious_reg = tegra210_sfc_precious_reg, .reg_defaults = tegra210_sfc_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tegra210_sfc_reg_defaults), + .reg_default_cb = regmap_default_zero_cb, .cache_type = REGCACHE_FLAT, };
Signature · 1 line
2.34.1
Re: [RFC PATCH v3 3/4] ASoC: tegra: set reg_default_cb callback
Quoted 7 lines · Sheetal .
From: Sheetal <[email protected]>
Set
reg_default_cbsoREGCACHE_FLATcan supply zero defaults without largereg_defaultstables, simplifying cache initialization for zero-reset registers.Signed-off-by Sheetal <[email protected]>
Thanks
Jon
Signature · 1 line
nvpublic
RFC PATCH v3 4/4 regmap: add KUnit coverage for reg_default_cb callback
In reply to Sheetal .From: Sheetal <[email protected]>
Add a flat-cache KUnit test that verifies reg_defaults are honored while missing entries are populated via the reg_default_cb callback without hardware reads. This exercises the new callback path added for REGCACHE_FLAT defaults.
Test: ./tools/testing/kunit/kunit.py run regmap Result:
======== reg_default_callback_populates_flat_cache ======== [PASSED] flat-default @0x0
[PASSED] flat-default fast I/O @0x0
[PASSED] flat-default @0x2001
==== [PASSED] reg_default_callback_populates_flat_cache ====
--- drivers/base/regmap/regmap-kunit.c | 91 ++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+)
drivers/base/regmap/regmap-kunit.c +91 -0
@@ -15,6 +15,8 @@ KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_action, regmap_exit, struct regmap *);struct regmap_test_priv {struct device *dev; +bool *reg_default_called; +unsigned int reg_default_max; };struct regmap_test_param {
@@ -118,6 +120,14 @@ static const struct regmap_test_param real_cache_types_only_list[] = {KUNIT_ARRAY_PARAM (real_cache_types_only, real_cache_types_only_list, param_to_desc); +static const struct regmap_test_param flat_cache_types_list[] = { + { .cache =REGCACHE_FLAT , .from_reg =0 }, + { .cache =REGCACHE_FLAT , .from_reg =0 , .fast_io = true }, + { .cache =REGCACHE_FLAT , .from_reg =0x2001 }, +}; + +KUNIT_ARRAY_PARAM (flat_cache_types, flat_cache_types_list, param_to_desc); +static const struct regmap_test_param real_cache_types_list[] = { { .cache =REGCACHE_FLAT , .from_reg =0 }, { .cache =REGCACHE_FLAT , .from_reg =0 , .fast_io = true },
@@ -248,6 +258,37 @@ static bool reg_5_false(struct device *dev, unsigned int reg)return reg != (param->from_reg +5 ); } +static unsigned int reg_default_expected (unsigned int reg) +{ +return 0x5a5a0000 | (reg &0xffff ); +} + +static int reg_default_test_cb (struct device *dev,unsigned int reg, +unsigned int *def) +{ +struct kunit *test =dev_get_drvdata (dev); +struct regmap_test_priv *priv = test->priv; + +if (priv && priv->reg_default_called && reg <= priv->reg_default_max) + priv->reg_default_called[reg] = true; + + *def =reg_default_expected (reg); +return 0 ; +} + +static void expect_reg_default_value (struct kunit *test,struct regmap *map, +struct regmap_ram_data *data, +struct regmap_test_priv *priv, +unsigned int reg) +{ +unsigned int val; + +KUNIT_EXPECT_TRUE (test, priv->reg_default_called[reg]); +KUNIT_EXPECT_EQ (test,0 ,regmap_read (map, reg, &val)); +KUNIT_EXPECT_EQ (test,reg_default_expected (reg), val); +KUNIT_EXPECT_FALSE (test, data->read[reg]); +} +static void basic_read_write (struct kunit *test) {struct regmap *map;
@@ -628,6 +669,54 @@ static void reg_defaults(struct kunit *test)KUNIT_EXPECT_EQ (test, config.cache_type ==REGCACHE_NONE , data->read[i]); } +static void reg_default_callback_populates_flat_cache (struct kunit *test) +{ +const struct regmap_test_param *param = test->param_value; +struct regmap_test_priv *priv = test->priv; +struct regmap *map; +struct regmap_config config; +struct regmap_ram_data *data; +unsigned int reg, val; +unsigned int defaults_end; + + config = test_regmap_config; + config.num_reg_defaults =3 ; + config.max_register = param->from_reg +BLOCK_TEST_SIZE -1 ; + config.reg_default_cb = reg_default_test_cb; + + priv->reg_default_max = config.max_register; + priv->reg_default_called =kunit_kcalloc (test, config.max_register +1 , +sizeof (*priv->reg_default_called), +GFP_KERNEL ); +KUNIT_ASSERT_NOT_NULL (test, priv->reg_default_called); + + map =gen_regmap (test, &config, &data); +KUNIT_ASSERT_FALSE (test,IS_ERR (map)); +if (IS_ERR (map)) +return ; + +for (reg =0 ; reg <= config.max_register; reg++) + data->read[reg] = false; + + defaults_end = param->from_reg + config.num_reg_defaults -1 ; + +for (reg = param->from_reg; reg <= defaults_end; reg++) { +KUNIT_EXPECT_FALSE (test, priv->reg_default_called[reg]); +KUNIT_EXPECT_EQ (test,0 ,regmap_read (map, reg, &val)); +KUNIT_EXPECT_EQ (test, data->vals[reg], val); +KUNIT_EXPECT_FALSE (test, data->read[reg]); + } + +if (param->from_reg >0 ) +expect_reg_default_value (test, map, data, priv,0 ); + +if (defaults_end +1 <= config.max_register) +expect_reg_default_value (test, map, data, priv, defaults_end +1 ); + +if (config.max_register > defaults_end +1 ) +expect_reg_default_value (test, map, data, priv, config.max_register); +} +static void reg_defaults_read_dev (struct kunit *test) {struct regmap *map;
@@ -2058,6 +2147,8 @@ static struct kunit_case regmap_test_cases[] = {KUNIT_CASE_PARAM (write_readonly, regcache_types_gen_params),KUNIT_CASE_PARAM (read_writeonly, regcache_types_gen_params),KUNIT_CASE_PARAM (reg_defaults, regcache_types_gen_params), +KUNIT_CASE_PARAM (reg_default_callback_populates_flat_cache, + flat_cache_types_gen_params),KUNIT_CASE_PARAM (reg_defaults_read_dev, regcache_types_gen_params),KUNIT_CASE_PARAM (register_patch, regcache_types_gen_params), KUNIT_CASE_PARAM(stride, regcache_types_gen_params),
Signature · 1 line
2.34.1
Mark Brown
maintainerRe: (subset) [RFC PATCH v3 0/4] regmap: reg_default_cb for flat cache defaults
In reply to Sheetal .Quoted 9 lines · Sheetal .
This series adds a
reg_default_cbcallback forREGCACHE_FLATto provide defaults for registers not listed inreg_defaults. Defaults are loaded eagerly during regcache init and the callback can usewriteable_regto filter valid addresses and avoid holes.Tegra ASoC drivers set
reg_default_cband addwriteable_regfiltering for AHUB RX holes to prevent invalid addresses from being marked valid.[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next
Thanks!
[2/4] regmap: Add reg_default_cb callback for flat cache defaults
commit: dc65b1ed4bb34ab6235ff2cc6a917b9295c04c2c
[4/4] regmap: add KUnit coverage for reg_default_cb callback
commit: 70a65c53d228562cf0c8ae0f38c847d2a5dd59e6All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Mark Brown
maintainerRe: (subset) [RFC PATCH v3 0/4] regmap: reg_default_cb for flat cache defaults
In reply to Sheetal .Quoted 9 lines · Sheetal .
This series adds a
reg_default_cbcallback forREGCACHE_FLATto provide defaults for registers not listed inreg_defaults. Defaults are loaded eagerly during regcache init and the callback can usewriteable_regto filter valid addresses and avoid holes.Tegra ASoC drivers set
reg_default_cband addwriteable_regfiltering for AHUB RX holes to prevent invalid addresses from being marked valid.[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/4] ASoC: tegra: Add AHUB writeable_reg for RX holes
commit: 0ba6286a71581aaf8413a55b9bd90ea3463fd23b
[3/4] ASoC: tegra: set reg_default_cb callback
commit: 9409d18bf7d58ab716337749e28e2caba0d64cb0All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark