Skip to content

Commit

Permalink
regmap: core: Introduce register stride order
Browse files Browse the repository at this point in the history
Since the register stride should always equal to 2^N, and bit rotation is
much faster than multiplication and division. So introducing the stride
order and using bit rotation to get the offset of the register from the
index to improve the performance.

Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Xiubo Li authored and Mark Brown committed Feb 19, 2016
1 parent 92e963f commit ca747be
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 6 deletions.
10 changes: 10 additions & 0 deletions drivers/base/regmap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ struct regmap {
/* number of bits to (left) shift the reg value when formatting*/
int reg_shift;
int reg_stride;
int reg_stride_order;

/* regcache specific members */
const struct regcache_ops *cache_ops;
Expand Down Expand Up @@ -263,4 +264,13 @@ static inline const char *regmap_name(const struct regmap *map)
return map->name;
}

static inline unsigned int regmap_get_offset(const struct regmap *map,
unsigned int index)
{
if (map->reg_stride_order >= 0)
return index << map->reg_stride_order;
else
return index * map->reg_stride;
}

#endif
19 changes: 13 additions & 6 deletions drivers/base/regmap/regmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/rbtree.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/log2.h>

#define CREATE_TRACE_POINTS
#include "trace.h"
Expand Down Expand Up @@ -638,6 +639,10 @@ struct regmap *__regmap_init(struct device *dev,
map->reg_stride = config->reg_stride;
else
map->reg_stride = 1;
if (is_power_of_2(map->reg_stride))
map->reg_stride_order = ilog2(map->reg_stride);
else
map->reg_stride_order = -1;
map->use_single_read = config->use_single_rw || !bus || !bus->read;
map->use_single_write = config->use_single_rw || !bus || !bus->write;
map->can_multi_write = config->can_multi_write && bus && bus->write;
Expand Down Expand Up @@ -1308,15 +1313,16 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
if (map->writeable_reg)
for (i = 0; i < val_len / map->format.val_bytes; i++)
if (!map->writeable_reg(map->dev,
reg + (i * map->reg_stride)))
reg + regmap_get_offset(map, i)))
return -EINVAL;

if (!map->cache_bypass && map->format.parse_val) {
unsigned int ival;
int val_bytes = map->format.val_bytes;
for (i = 0; i < val_len / val_bytes; i++) {
ival = map->format.parse_val(val + (i * val_bytes));
ret = regcache_write(map, reg + (i * map->reg_stride),
ret = regcache_write(map,
reg + regmap_get_offset(map, i),
ival);
if (ret) {
dev_err(map->dev,
Expand Down Expand Up @@ -1846,8 +1852,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
goto out;
}

ret = _regmap_write(map, reg + (i * map->reg_stride),
ival);
ret = _regmap_write(map,
reg + regmap_get_offset(map, i),
ival);
if (ret != 0)
goto out;
}
Expand Down Expand Up @@ -2416,7 +2423,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
* cost as we expect to hit the cache.
*/
for (i = 0; i < val_count; i++) {
ret = _regmap_read(map, reg + (i * map->reg_stride),
ret = _regmap_read(map, reg + regmap_get_offset(map, i),
&v);
if (ret != 0)
goto out;
Expand Down Expand Up @@ -2568,7 +2575,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
} else {
for (i = 0; i < val_count; i++) {
unsigned int ival;
ret = regmap_read(map, reg + (i * map->reg_stride),
ret = regmap_read(map, reg + regmap_get_offset(map, i),
&ival);
if (ret != 0)
return ret;
Expand Down

0 comments on commit ca747be

Please sign in to comment.