mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
regmap: Updates for v6.11
There's one new feature here, a regmap_multi_reg_read() matching the existing write function which has some IIO users coming. This allows atomic reads from multiple registers without the need to wrap a higher level lock in the client driver just for regmap (which already has locks anyway). We also have one fix for the KUnit tests, and a bunch of cleanups. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmaVJRsACgkQJNaLcl1U h9CQcAf+PhHwUoxBextaJzy2HQe9CFV71/I4GEj0MTrtpqKDhmO8AQnsI4dKXr/9 hZPUPR7+6qw7N12NdZQcT6hIX9CnhdiaNALo4ANvG5KlxFljhFbv2sBg1QAgb+Ks 2gLapB4HY0jso+6urNEN5rvucFpf4Mxlz5ilrk3kuuJaC/xf6/QXoU5/9PjPyD5s ZuCBMg5G0BIIdwc9SFGJPv1UUJ0H6Aj/1ZQNo/JVtIj8uGt8TuvnUrmOxdnHRN1U b5AMjLnSYMtwRg7Nd/DCINmwPN+I0X79gNE4SG1LAOlQIChhW+47HuGWyCM40jGO p4X8o/zID9hw5q3y6CpwYvrJ5GRZbA== =ETId -----END PGP SIGNATURE----- Merge tag 'regmap-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap Pull regmap updates from Mark Brown: "There's one new feature here, a regmap_multi_reg_read() matching the existing write function which has some IIO users coming. This allows atomic reads from multiple registers without the need to wrap a higher level lock in the client driver just for regmap (which already has locks anyway). We also have one fix for the KUnit tests, and a bunch of cleanups" * tag 'regmap-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: kunit: Add test cases for regmap_multi_reg_(read,write}() regmap: Implement regmap_multi_reg_read() regmap-irq: handle const struct regmap_irq_sub_irq_map const_structs.checkpatch: add regmap structs regmap: add missing MODULE_DESCRIPTION() macros regmap-i2c: add missing MODULE_DESCRIPTION() macro regmap: kunit: Use array_size() and sizeof(*ptr) consistently regmap: maple: Switch to use kmemdup_array() regmap: cache: Switch to use kmemdup_array() regmap: cache: Use correct type of the rb_for_each() parameter regmap: Switch to use kmemdup_array() regmap: kunit: add missing MODULE_DESCRIPTION() regmap: kunit: Fix memory leaks in gen_regmap() and gen_raw_regmap()
This commit is contained in:
commit
25617a5c45
@ -132,9 +132,9 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
|
|||||||
lower_index = mas.index;
|
lower_index = mas.index;
|
||||||
lower_last = min -1;
|
lower_last = min -1;
|
||||||
|
|
||||||
lower = kmemdup(entry, ((min - mas.index) *
|
lower = kmemdup_array(entry,
|
||||||
sizeof(unsigned long)),
|
min - mas.index, sizeof(*lower),
|
||||||
map->alloc_flags);
|
map->alloc_flags);
|
||||||
if (!lower) {
|
if (!lower) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
@ -145,10 +145,9 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
|
|||||||
upper_index = max + 1;
|
upper_index = max + 1;
|
||||||
upper_last = mas.last;
|
upper_last = mas.last;
|
||||||
|
|
||||||
upper = kmemdup(&entry[max - mas.index + 1],
|
upper = kmemdup_array(&entry[max - mas.index + 1],
|
||||||
((mas.last - max) *
|
mas.last - max, sizeof(*upper),
|
||||||
sizeof(unsigned long)),
|
map->alloc_flags);
|
||||||
map->alloc_flags);
|
|
||||||
if (!upper) {
|
if (!upper) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
|
@ -170,8 +170,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
|
|||||||
* a copy of it.
|
* a copy of it.
|
||||||
*/
|
*/
|
||||||
if (config->reg_defaults) {
|
if (config->reg_defaults) {
|
||||||
tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults *
|
tmp_buf = kmemdup_array(config->reg_defaults, map->num_reg_defaults,
|
||||||
sizeof(struct reg_default), GFP_KERNEL);
|
sizeof(*map->reg_defaults), GFP_KERNEL);
|
||||||
if (!tmp_buf)
|
if (!tmp_buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
map->reg_defaults = tmp_buf;
|
map->reg_defaults = tmp_buf;
|
||||||
@ -407,7 +407,7 @@ out:
|
|||||||
* have gone out of sync, force writes of all the paging
|
* have gone out of sync, force writes of all the paging
|
||||||
* registers.
|
* registers.
|
||||||
*/
|
*/
|
||||||
rb_for_each(node, 0, &map->range_tree, rbtree_all) {
|
rb_for_each(node, NULL, &map->range_tree, rbtree_all) {
|
||||||
struct regmap_range_node *this =
|
struct regmap_range_node *this =
|
||||||
rb_entry(node, struct regmap_range_node, node);
|
rb_entry(node, struct regmap_range_node, node);
|
||||||
|
|
||||||
|
@ -86,4 +86,5 @@ struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_ac97);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_ac97);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - AC'97 support");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -397,4 +397,5 @@ struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_i2c);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_i2c);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - I2C support");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -305,8 +305,8 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data,
|
|||||||
unsigned int b)
|
unsigned int b)
|
||||||
{
|
{
|
||||||
const struct regmap_irq_chip *chip = data->chip;
|
const struct regmap_irq_chip *chip = data->chip;
|
||||||
|
const struct regmap_irq_sub_irq_map *subreg;
|
||||||
struct regmap *map = data->map;
|
struct regmap *map = data->map;
|
||||||
struct regmap_irq_sub_irq_map *subreg;
|
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
|
||||||
|
@ -145,9 +145,9 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||||||
const struct regmap_test_param *param = test->param_value;
|
const struct regmap_test_param *param = test->param_value;
|
||||||
struct regmap_test_priv *priv = test->priv;
|
struct regmap_test_priv *priv = test->priv;
|
||||||
unsigned int *buf;
|
unsigned int *buf;
|
||||||
struct regmap *ret;
|
struct regmap *ret = ERR_PTR(-ENOMEM);
|
||||||
size_t size;
|
size_t size;
|
||||||
int i;
|
int i, error;
|
||||||
struct reg_default *defaults;
|
struct reg_default *defaults;
|
||||||
|
|
||||||
config->cache_type = param->cache;
|
config->cache_type = param->cache;
|
||||||
@ -163,7 +163,7 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||||||
config->max_register += (BLOCK_TEST_SIZE * config->reg_stride);
|
config->max_register += (BLOCK_TEST_SIZE * config->reg_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
size = (config->max_register + 1) * sizeof(unsigned int);
|
size = array_size(config->max_register + 1, sizeof(*buf));
|
||||||
buf = kmalloc(size, GFP_KERNEL);
|
buf = kmalloc(size, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
@ -172,15 +172,17 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||||||
|
|
||||||
*data = kzalloc(sizeof(**data), GFP_KERNEL);
|
*data = kzalloc(sizeof(**data), GFP_KERNEL);
|
||||||
if (!(*data))
|
if (!(*data))
|
||||||
return ERR_PTR(-ENOMEM);
|
goto out_free;
|
||||||
(*data)->vals = buf;
|
(*data)->vals = buf;
|
||||||
|
|
||||||
if (config->num_reg_defaults) {
|
if (config->num_reg_defaults) {
|
||||||
defaults = kcalloc(config->num_reg_defaults,
|
defaults = kunit_kcalloc(test,
|
||||||
sizeof(struct reg_default),
|
config->num_reg_defaults,
|
||||||
GFP_KERNEL);
|
sizeof(struct reg_default),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!defaults)
|
if (!defaults)
|
||||||
return ERR_PTR(-ENOMEM);
|
goto out_free;
|
||||||
|
|
||||||
config->reg_defaults = defaults;
|
config->reg_defaults = defaults;
|
||||||
|
|
||||||
for (i = 0; i < config->num_reg_defaults; i++) {
|
for (i = 0; i < config->num_reg_defaults; i++) {
|
||||||
@ -190,12 +192,19 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_init_ram(priv->dev, config, *data);
|
ret = regmap_init_ram(priv->dev, config, *data);
|
||||||
if (IS_ERR(ret)) {
|
if (IS_ERR(ret))
|
||||||
kfree(buf);
|
goto out_free;
|
||||||
kfree(*data);
|
|
||||||
} else {
|
/* This calls regmap_exit() on failure, which frees buf and *data */
|
||||||
kunit_add_action(test, regmap_exit_action, ret);
|
error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
|
||||||
}
|
if (error)
|
||||||
|
ret = ERR_PTR(error);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
kfree(buf);
|
||||||
|
kfree(*data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -295,6 +304,77 @@ static void bulk_read(struct kunit *test)
|
|||||||
KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
|
KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void multi_write(struct kunit *test)
|
||||||
|
{
|
||||||
|
struct regmap *map;
|
||||||
|
struct regmap_config config;
|
||||||
|
struct regmap_ram_data *data;
|
||||||
|
struct reg_sequence sequence[BLOCK_TEST_SIZE];
|
||||||
|
unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
config = test_regmap_config;
|
||||||
|
|
||||||
|
map = gen_regmap(test, &config, &data);
|
||||||
|
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||||
|
if (IS_ERR(map))
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_random_bytes(&val, sizeof(val));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data written via the multi API can be read back with single
|
||||||
|
* reads.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||||
|
sequence[i].reg = i;
|
||||||
|
sequence[i].def = val[i];
|
||||||
|
sequence[i].delay_us = 0;
|
||||||
|
}
|
||||||
|
KUNIT_EXPECT_EQ(test, 0,
|
||||||
|
regmap_multi_reg_write(map, sequence, BLOCK_TEST_SIZE));
|
||||||
|
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||||
|
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval[i]));
|
||||||
|
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
|
||||||
|
|
||||||
|
/* If using a cache the cache satisfied the read */
|
||||||
|
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||||
|
KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void multi_read(struct kunit *test)
|
||||||
|
{
|
||||||
|
struct regmap *map;
|
||||||
|
struct regmap_config config;
|
||||||
|
struct regmap_ram_data *data;
|
||||||
|
unsigned int regs[BLOCK_TEST_SIZE];
|
||||||
|
unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
config = test_regmap_config;
|
||||||
|
|
||||||
|
map = gen_regmap(test, &config, &data);
|
||||||
|
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||||
|
if (IS_ERR(map))
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_random_bytes(&val, sizeof(val));
|
||||||
|
|
||||||
|
/* Data written as single writes can be read via the multi API */
|
||||||
|
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||||
|
regs[i] = i;
|
||||||
|
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, val[i]));
|
||||||
|
}
|
||||||
|
KUNIT_EXPECT_EQ(test, 0,
|
||||||
|
regmap_multi_reg_read(map, regs, rval, BLOCK_TEST_SIZE));
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
|
||||||
|
|
||||||
|
/* If using a cache the cache satisfied the read */
|
||||||
|
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||||
|
KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static void read_bypassed(struct kunit *test)
|
static void read_bypassed(struct kunit *test)
|
||||||
{
|
{
|
||||||
const struct regmap_test_param *param = test->param_value;
|
const struct regmap_test_param *param = test->param_value;
|
||||||
@ -759,10 +839,9 @@ static void stress_insert(struct kunit *test)
|
|||||||
if (IS_ERR(map))
|
if (IS_ERR(map))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vals = kunit_kcalloc(test, sizeof(unsigned long), config.max_register,
|
buf_sz = array_size(sizeof(*vals), config.max_register);
|
||||||
GFP_KERNEL);
|
vals = kunit_kmalloc(test, buf_sz, GFP_KERNEL);
|
||||||
KUNIT_ASSERT_FALSE(test, vals == NULL);
|
KUNIT_ASSERT_FALSE(test, vals == NULL);
|
||||||
buf_sz = sizeof(unsigned long) * config.max_register;
|
|
||||||
|
|
||||||
get_random_bytes(vals, buf_sz);
|
get_random_bytes(vals, buf_sz);
|
||||||
|
|
||||||
@ -1497,16 +1576,17 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
|
|||||||
struct regmap_test_priv *priv = test->priv;
|
struct regmap_test_priv *priv = test->priv;
|
||||||
const struct regmap_test_param *param = test->param_value;
|
const struct regmap_test_param *param = test->param_value;
|
||||||
u16 *buf;
|
u16 *buf;
|
||||||
struct regmap *ret;
|
struct regmap *ret = ERR_PTR(-ENOMEM);
|
||||||
size_t size = (config->max_register + 1) * config->reg_bits / 8;
|
int i, error;
|
||||||
int i;
|
|
||||||
struct reg_default *defaults;
|
struct reg_default *defaults;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
config->cache_type = param->cache;
|
config->cache_type = param->cache;
|
||||||
config->val_format_endian = param->val_endian;
|
config->val_format_endian = param->val_endian;
|
||||||
config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
|
config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
|
||||||
config->cache_type == REGCACHE_MAPLE;
|
config->cache_type == REGCACHE_MAPLE;
|
||||||
|
|
||||||
|
size = array_size(config->max_register + 1, BITS_TO_BYTES(config->reg_bits));
|
||||||
buf = kmalloc(size, GFP_KERNEL);
|
buf = kmalloc(size, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
@ -1515,15 +1595,16 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
|
|||||||
|
|
||||||
*data = kzalloc(sizeof(**data), GFP_KERNEL);
|
*data = kzalloc(sizeof(**data), GFP_KERNEL);
|
||||||
if (!(*data))
|
if (!(*data))
|
||||||
return ERR_PTR(-ENOMEM);
|
goto out_free;
|
||||||
(*data)->vals = (void *)buf;
|
(*data)->vals = (void *)buf;
|
||||||
|
|
||||||
config->num_reg_defaults = config->max_register + 1;
|
config->num_reg_defaults = config->max_register + 1;
|
||||||
defaults = kcalloc(config->num_reg_defaults,
|
defaults = kunit_kcalloc(test,
|
||||||
sizeof(struct reg_default),
|
config->num_reg_defaults,
|
||||||
GFP_KERNEL);
|
sizeof(struct reg_default),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!defaults)
|
if (!defaults)
|
||||||
return ERR_PTR(-ENOMEM);
|
goto out_free;
|
||||||
config->reg_defaults = defaults;
|
config->reg_defaults = defaults;
|
||||||
|
|
||||||
for (i = 0; i < config->num_reg_defaults; i++) {
|
for (i = 0; i < config->num_reg_defaults; i++) {
|
||||||
@ -1536,7 +1617,8 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
|
|||||||
defaults[i].def = be16_to_cpu(buf[i]);
|
defaults[i].def = be16_to_cpu(buf[i]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ERR_PTR(-EINVAL);
|
ret = ERR_PTR(-EINVAL);
|
||||||
|
goto out_free;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1548,12 +1630,19 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
|
|||||||
config->num_reg_defaults = 0;
|
config->num_reg_defaults = 0;
|
||||||
|
|
||||||
ret = regmap_init_raw_ram(priv->dev, config, *data);
|
ret = regmap_init_raw_ram(priv->dev, config, *data);
|
||||||
if (IS_ERR(ret)) {
|
if (IS_ERR(ret))
|
||||||
kfree(buf);
|
goto out_free;
|
||||||
kfree(*data);
|
|
||||||
} else {
|
/* This calls regmap_exit() on failure, which frees buf and *data */
|
||||||
kunit_add_action(test, regmap_exit_action, ret);
|
error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
|
||||||
}
|
if (error)
|
||||||
|
ret = ERR_PTR(error);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
kfree(buf);
|
||||||
|
kfree(*data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1597,7 +1686,7 @@ static void raw_read_defaults(struct kunit *test)
|
|||||||
if (IS_ERR(map))
|
if (IS_ERR(map))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
val_len = sizeof(*rval) * (config.max_register + 1);
|
val_len = array_size(sizeof(*rval), config.max_register + 1);
|
||||||
rval = kunit_kmalloc(test, val_len, GFP_KERNEL);
|
rval = kunit_kmalloc(test, val_len, GFP_KERNEL);
|
||||||
KUNIT_ASSERT_TRUE(test, rval != NULL);
|
KUNIT_ASSERT_TRUE(test, rval != NULL);
|
||||||
if (!rval)
|
if (!rval)
|
||||||
@ -1887,6 +1976,8 @@ static struct kunit_case regmap_test_cases[] = {
|
|||||||
KUNIT_CASE_PARAM(read_bypassed_volatile, real_cache_types_gen_params),
|
KUNIT_CASE_PARAM(read_bypassed_volatile, real_cache_types_gen_params),
|
||||||
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
|
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
|
||||||
KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
|
KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(multi_write, regcache_types_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(multi_read, regcache_types_gen_params),
|
||||||
KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
|
KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
|
||||||
KUNIT_CASE_PARAM(read_writeonly, 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_defaults, regcache_types_gen_params),
|
||||||
@ -1958,4 +2049,5 @@ static struct kunit_suite regmap_test_suite = {
|
|||||||
};
|
};
|
||||||
kunit_test_suite(regmap_test_suite);
|
kunit_test_suite(regmap_test_suite);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Regmap KUnit tests");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -83,4 +83,5 @@ struct regmap *__regmap_init_ram(struct device *dev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__regmap_init_ram);
|
EXPORT_SYMBOL_GPL(__regmap_init_ram);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - Memory region");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -142,4 +142,5 @@ struct regmap *__regmap_init_raw_ram(struct device *dev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__regmap_init_raw_ram);
|
EXPORT_SYMBOL_GPL(__regmap_init_raw_ram);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - Memory region with raw access");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -125,4 +125,5 @@ struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_sccb);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_sccb);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - SCCB support");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -68,4 +68,5 @@ struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_slimbus);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_slimbus);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - SLIMbus support");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -710,4 +710,5 @@ struct regmap *__devm_regmap_init_spi_avmm(struct spi_device *spi,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_spi_avmm);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spi_avmm);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - SPI AVMM support");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -222,4 +222,5 @@ struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *sdev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - SPMI support");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -234,4 +234,5 @@ struct regmap *__devm_regmap_init_w1(struct device *w1_dev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Register map access API - W1 (1-Wire) support");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -2347,7 +2347,7 @@ out:
|
|||||||
} else {
|
} else {
|
||||||
void *wval;
|
void *wval;
|
||||||
|
|
||||||
wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
|
wval = kmemdup_array(val, val_count, val_bytes, map->alloc_flags);
|
||||||
if (!wval)
|
if (!wval)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -3101,8 +3101,53 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_fields_read);
|
EXPORT_SYMBOL_GPL(regmap_fields_read);
|
||||||
|
|
||||||
|
static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
|
||||||
|
unsigned int *regs, void *val, size_t val_count)
|
||||||
|
{
|
||||||
|
u32 *u32 = val;
|
||||||
|
u16 *u16 = val;
|
||||||
|
u8 *u8 = val;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
map->lock(map->lock_arg);
|
||||||
|
|
||||||
|
for (i = 0; i < val_count; i++) {
|
||||||
|
unsigned int ival;
|
||||||
|
|
||||||
|
if (regs) {
|
||||||
|
if (!IS_ALIGNED(regs[i], map->reg_stride)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = _regmap_read(map, regs[i], &ival);
|
||||||
|
} else {
|
||||||
|
ret = _regmap_read(map, reg + regmap_get_offset(map, i), &ival);
|
||||||
|
}
|
||||||
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
switch (map->format.val_bytes) {
|
||||||
|
case 4:
|
||||||
|
u32[i] = ival;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
u16[i] = ival;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
u8[i] = ival;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
map->unlock(map->lock_arg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regmap_bulk_read() - Read multiple registers from the device
|
* regmap_bulk_read() - Read multiple sequential registers from the device
|
||||||
*
|
*
|
||||||
* @map: Register map to read from
|
* @map: Register map to read from
|
||||||
* @reg: First register to be read from
|
* @reg: First register to be read from
|
||||||
@ -3132,47 +3177,35 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
|||||||
for (i = 0; i < val_count * val_bytes; i += val_bytes)
|
for (i = 0; i < val_count * val_bytes; i += val_bytes)
|
||||||
map->format.parse_inplace(val + i);
|
map->format.parse_inplace(val + i);
|
||||||
} else {
|
} else {
|
||||||
u32 *u32 = val;
|
ret = _regmap_bulk_read(map, reg, NULL, val, val_count);
|
||||||
u16 *u16 = val;
|
|
||||||
u8 *u8 = val;
|
|
||||||
|
|
||||||
map->lock(map->lock_arg);
|
|
||||||
|
|
||||||
for (i = 0; i < val_count; i++) {
|
|
||||||
unsigned int ival;
|
|
||||||
|
|
||||||
ret = _regmap_read(map, reg + regmap_get_offset(map, i),
|
|
||||||
&ival);
|
|
||||||
if (ret != 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
switch (map->format.val_bytes) {
|
|
||||||
case 4:
|
|
||||||
u32[i] = ival;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
u16[i] = ival;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
u8[i] = ival;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
map->unlock(map->lock_arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
|
trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_bulk_read);
|
EXPORT_SYMBOL_GPL(regmap_bulk_read);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_multi_reg_read() - Read multiple non-sequential registers from the device
|
||||||
|
*
|
||||||
|
* @map: Register map to read from
|
||||||
|
* @regs: Array of registers to read from
|
||||||
|
* @val: Pointer to store read value, in native register size for device
|
||||||
|
* @val_count: Number of registers to read
|
||||||
|
*
|
||||||
|
* A value of zero will be returned on success, a negative errno will
|
||||||
|
* be returned in error cases.
|
||||||
|
*/
|
||||||
|
int regmap_multi_reg_read(struct regmap *map, unsigned int *regs, void *val,
|
||||||
|
size_t val_count)
|
||||||
|
{
|
||||||
|
if (val_count == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return _regmap_bulk_read(map, 0, regs, val, val_count);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regmap_multi_reg_read);
|
||||||
|
|
||||||
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change, bool force_write)
|
bool *change, bool force_write)
|
||||||
|
@ -1237,6 +1237,8 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
|
|||||||
void *val, size_t val_len);
|
void *val, size_t val_len);
|
||||||
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
size_t val_count);
|
size_t val_count);
|
||||||
|
int regmap_multi_reg_read(struct regmap *map, unsigned int *reg, void *val,
|
||||||
|
size_t val_count);
|
||||||
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
|
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change, bool async, bool force);
|
bool *change, bool async, bool force);
|
||||||
@ -1607,7 +1609,7 @@ struct regmap_irq_chip {
|
|||||||
|
|
||||||
unsigned int main_status;
|
unsigned int main_status;
|
||||||
unsigned int num_main_status_bits;
|
unsigned int num_main_status_bits;
|
||||||
struct regmap_irq_sub_irq_map *sub_reg_offsets;
|
const struct regmap_irq_sub_irq_map *sub_reg_offsets;
|
||||||
int num_main_regs;
|
int num_main_regs;
|
||||||
|
|
||||||
unsigned int status_base;
|
unsigned int status_base;
|
||||||
|
@ -64,7 +64,17 @@ platform_suspend_ops
|
|||||||
proc_ops
|
proc_ops
|
||||||
proto_ops
|
proto_ops
|
||||||
pwm_ops
|
pwm_ops
|
||||||
|
reg_default
|
||||||
|
reg_field
|
||||||
|
reg_sequence
|
||||||
regmap_access_table
|
regmap_access_table
|
||||||
|
regmap_bus
|
||||||
|
regmap_config
|
||||||
|
regmap_irq
|
||||||
|
regmap_irq_chip
|
||||||
|
regmap_irq_sub_irq_map
|
||||||
|
regmap_range
|
||||||
|
regmap_range_cfg
|
||||||
regulator_ops
|
regulator_ops
|
||||||
reset_control_ops
|
reset_control_ops
|
||||||
rpc_pipe_ops
|
rpc_pipe_ops
|
||||||
|
Loading…
Reference in New Issue
Block a user