regmap: Updates for v6.9
Just two updates this time around, a rework of max_register handling which enables us to support devices with only one register better and a new test which will be used to validate use of some new SPI optimisations which will be coming in during this merge window. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmXvE9UACgkQJNaLcl1U h9DNtgf/UQGqI/+Kph8HZ1JIItK/ehOxXB2Mdri696TzgJ0rXHJQhfIKkU4I4rBv E090LWqJ0GazdpAEOFmf0YTBVBlCKjzb0IWtaNUz+/6/X27xrzw5ZuGfRj+gdQWo AJNfrtDw73rpgypEg3hCxQvBGFoT6uQvfqwzEiCBDv98Tlin6L9ZJ1tInCv6B6Bo I0DS6zvWx8E99NXG847Q3lVVRCaHY7xamrF1BURt1N0D97SkR41HmEaBkDalME8g lqxVB1YKsT6GwYYKmevDEoMMFg6CHTXCegl1zTmPjR4GGEih0M6j1VD6DFPCeCMr XnkQAj4lY2XUksYi5fPhhy5x1aT6Ww== =kW6Y -----END PGP SIGNATURE----- Merge tag 'regmap-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap Pull regmap updates from Mark Brown: "Just two updates this time around, a rework of max_register handling which enables us to support devices with only one register better and a new test which will be used to validate use of some new SPI optimisations which will be coming in during this merge window" * tag 'regmap-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: kunit: Add a test for ranges in combination with windows regmap: rework ->max_register handling
This commit is contained in:
commit
b30f2db0b7
@ -93,6 +93,7 @@ struct regmap {
|
||||
#endif
|
||||
|
||||
unsigned int max_register;
|
||||
bool max_register_is_set;
|
||||
bool (*writeable_reg)(struct device *dev, unsigned int reg);
|
||||
bool (*readable_reg)(struct device *dev, unsigned int reg);
|
||||
bool (*volatile_reg)(struct device *dev, unsigned int reg);
|
||||
|
@ -23,7 +23,7 @@ static int regcache_flat_init(struct regmap *map)
|
||||
int i;
|
||||
unsigned int *cache;
|
||||
|
||||
if (!map || map->reg_stride_order < 0 || !map->max_register)
|
||||
if (!map || map->reg_stride_order < 0 || !map->max_register_is_set)
|
||||
return -EINVAL;
|
||||
|
||||
map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
|
||||
|
@ -187,8 +187,10 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!map->max_register && map->num_reg_defaults_raw)
|
||||
if (!map->max_register_is_set && map->num_reg_defaults_raw) {
|
||||
map->max_register = (map->num_reg_defaults_raw - 1) * map->reg_stride;
|
||||
map->max_register_is_set = true;
|
||||
}
|
||||
|
||||
if (map->cache_ops->init) {
|
||||
dev_dbg(map->dev, "Initializing %s cache\n",
|
||||
|
@ -1341,6 +1341,71 @@ static void raw_sync(struct kunit *test)
|
||||
regmap_exit(map);
|
||||
}
|
||||
|
||||
static void raw_ranges(struct kunit *test)
|
||||
{
|
||||
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
|
||||
struct regmap *map;
|
||||
struct regmap_config config;
|
||||
struct regmap_ram_data *data;
|
||||
unsigned int val;
|
||||
int i;
|
||||
|
||||
config = raw_regmap_config;
|
||||
config.volatile_reg = test_range_all_volatile;
|
||||
config.ranges = &test_range;
|
||||
config.num_ranges = 1;
|
||||
config.max_register = test_range.range_max;
|
||||
|
||||
map = gen_raw_regmap(&config, t, &data);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
|
||||
/* Reset the page to a non-zero value to trigger a change */
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.selector_reg,
|
||||
test_range.range_max));
|
||||
|
||||
/* Check we set the page and use the window for writes */
|
||||
data->written[test_range.selector_reg] = false;
|
||||
data->written[test_range.window_start] = false;
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
|
||||
|
||||
data->written[test_range.selector_reg] = false;
|
||||
data->written[test_range.window_start] = false;
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_write(map,
|
||||
test_range.range_min +
|
||||
test_range.window_len,
|
||||
0));
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
|
||||
|
||||
/* Same for reads */
|
||||
data->written[test_range.selector_reg] = false;
|
||||
data->read[test_range.window_start] = false;
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, test_range.range_min, &val));
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
|
||||
KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
|
||||
|
||||
data->written[test_range.selector_reg] = false;
|
||||
data->read[test_range.window_start] = false;
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_read(map,
|
||||
test_range.range_min +
|
||||
test_range.window_len,
|
||||
&val));
|
||||
KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
|
||||
KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
|
||||
|
||||
/* No physical access triggered in the virtual range */
|
||||
for (i = test_range.range_min; i < test_range.range_max; i++) {
|
||||
KUNIT_EXPECT_FALSE(test, data->read[i]);
|
||||
KUNIT_EXPECT_FALSE(test, data->written[i]);
|
||||
}
|
||||
|
||||
regmap_exit(map);
|
||||
}
|
||||
|
||||
static struct kunit_case regmap_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
|
||||
@ -1368,6 +1433,7 @@ static struct kunit_case regmap_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
|
||||
KUNIT_CASE_PARAM(raw_noinc_write, raw_test_types_gen_params),
|
||||
KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(raw_ranges, raw_test_cache_types_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -89,7 +89,7 @@ EXPORT_SYMBOL_GPL(regmap_check_range_table);
|
||||
|
||||
bool regmap_writeable(struct regmap *map, unsigned int reg)
|
||||
{
|
||||
if (map->max_register && reg > map->max_register)
|
||||
if (map->max_register_is_set && reg > map->max_register)
|
||||
return false;
|
||||
|
||||
if (map->writeable_reg)
|
||||
@ -112,7 +112,7 @@ bool regmap_cached(struct regmap *map, unsigned int reg)
|
||||
if (!map->cache_ops)
|
||||
return false;
|
||||
|
||||
if (map->max_register && reg > map->max_register)
|
||||
if (map->max_register_is_set && reg > map->max_register)
|
||||
return false;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
@ -129,7 +129,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
|
||||
if (!map->reg_read)
|
||||
return false;
|
||||
|
||||
if (map->max_register && reg > map->max_register)
|
||||
if (map->max_register_is_set && reg > map->max_register)
|
||||
return false;
|
||||
|
||||
if (map->format.format_write)
|
||||
@ -787,6 +787,7 @@ struct regmap *__regmap_init(struct device *dev,
|
||||
map->bus = bus;
|
||||
map->bus_context = bus_context;
|
||||
map->max_register = config->max_register;
|
||||
map->max_register_is_set = map->max_register ?: config->max_register_is_0;
|
||||
map->wr_table = config->wr_table;
|
||||
map->rd_table = config->rd_table;
|
||||
map->volatile_table = config->volatile_table;
|
||||
@ -1412,6 +1413,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
|
||||
regmap_debugfs_exit(map);
|
||||
|
||||
map->max_register = config->max_register;
|
||||
map->max_register_is_set = map->max_register ?: config->max_register_is_0;
|
||||
map->writeable_reg = config->writeable_reg;
|
||||
map->readable_reg = config->readable_reg;
|
||||
map->volatile_reg = config->volatile_reg;
|
||||
@ -3383,7 +3385,7 @@ EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
|
||||
*/
|
||||
int regmap_get_max_register(struct regmap *map)
|
||||
{
|
||||
return map->max_register ? map->max_register : -EINVAL;
|
||||
return map->max_register_is_set ? map->max_register : -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_get_max_register);
|
||||
|
||||
|
@ -332,6 +332,10 @@ typedef void (*regmap_unlock)(void *);
|
||||
* @io_port: Support IO port accessors. Makes sense only when MMIO vs. IO port
|
||||
* access can be distinguished.
|
||||
* @max_register: Optional, specifies the maximum valid register address.
|
||||
* @max_register_is_0: Optional, specifies that zero value in @max_register
|
||||
* should be taken into account. This is a workaround to
|
||||
* apply handling of @max_register for regmap that contains
|
||||
* only one register.
|
||||
* @wr_table: Optional, points to a struct regmap_access_table specifying
|
||||
* valid ranges for write access.
|
||||
* @rd_table: As above, for read access.
|
||||
@ -422,6 +426,7 @@ struct regmap_config {
|
||||
bool io_port;
|
||||
|
||||
unsigned int max_register;
|
||||
bool max_register_is_0;
|
||||
const struct regmap_access_table *wr_table;
|
||||
const struct regmap_access_table *rd_table;
|
||||
const struct regmap_access_table *volatile_table;
|
||||
|
Loading…
Reference in New Issue
Block a user