aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorXiubo Li <lixiubo@cmss.chinamobile.com>2016-01-04 05:00:33 -0500
committerMark Brown <broonie@kernel.org>2016-02-19 11:11:23 -0500
commitca747be22fa57bbee50e34c220401160e8f2a07f (patch)
tree402e74745cc42672333891ca30232716c1b8eafe /drivers/base/regmap
parent92e963f50fc74041b5e9e744c330dca48e04f08d (diff)
regmap: core: Introduce register stride order
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>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h10
-rw-r--r--drivers/base/regmap/regmap.c19
2 files changed, 23 insertions, 6 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 3df977054781..c22b04b2ca17 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -110,6 +110,7 @@ struct regmap {
110 /* number of bits to (left) shift the reg value when formatting*/ 110 /* number of bits to (left) shift the reg value when formatting*/
111 int reg_shift; 111 int reg_shift;
112 int reg_stride; 112 int reg_stride;
113 int reg_stride_order;
113 114
114 /* regcache specific members */ 115 /* regcache specific members */
115 const struct regcache_ops *cache_ops; 116 const struct regcache_ops *cache_ops;
@@ -263,4 +264,13 @@ static inline const char *regmap_name(const struct regmap *map)
263 return map->name; 264 return map->name;
264} 265}
265 266
267static inline unsigned int regmap_get_offset(const struct regmap *map,
268 unsigned int index)
269{
270 if (map->reg_stride_order >= 0)
271 return index << map->reg_stride_order;
272 else
273 return index * map->reg_stride;
274}
275
266#endif 276#endif
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index ee54e841de4a..29d526e0fc0f 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -19,6 +19,7 @@
19#include <linux/rbtree.h> 19#include <linux/rbtree.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/log2.h>
22 23
23#define CREATE_TRACE_POINTS 24#define CREATE_TRACE_POINTS
24#include "trace.h" 25#include "trace.h"
@@ -638,6 +639,10 @@ struct regmap *__regmap_init(struct device *dev,
638 map->reg_stride = config->reg_stride; 639 map->reg_stride = config->reg_stride;
639 else 640 else
640 map->reg_stride = 1; 641 map->reg_stride = 1;
642 if (is_power_of_2(map->reg_stride))
643 map->reg_stride_order = ilog2(map->reg_stride);
644 else
645 map->reg_stride_order = -1;
641 map->use_single_read = config->use_single_rw || !bus || !bus->read; 646 map->use_single_read = config->use_single_rw || !bus || !bus->read;
642 map->use_single_write = config->use_single_rw || !bus || !bus->write; 647 map->use_single_write = config->use_single_rw || !bus || !bus->write;
643 map->can_multi_write = config->can_multi_write && bus && bus->write; 648 map->can_multi_write = config->can_multi_write && bus && bus->write;
@@ -1308,7 +1313,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
1308 if (map->writeable_reg) 1313 if (map->writeable_reg)
1309 for (i = 0; i < val_len / map->format.val_bytes; i++) 1314 for (i = 0; i < val_len / map->format.val_bytes; i++)
1310 if (!map->writeable_reg(map->dev, 1315 if (!map->writeable_reg(map->dev,
1311 reg + (i * map->reg_stride))) 1316 reg + regmap_get_offset(map, i)))
1312 return -EINVAL; 1317 return -EINVAL;
1313 1318
1314 if (!map->cache_bypass && map->format.parse_val) { 1319 if (!map->cache_bypass && map->format.parse_val) {
@@ -1316,7 +1321,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
1316 int val_bytes = map->format.val_bytes; 1321 int val_bytes = map->format.val_bytes;
1317 for (i = 0; i < val_len / val_bytes; i++) { 1322 for (i = 0; i < val_len / val_bytes; i++) {
1318 ival = map->format.parse_val(val + (i * val_bytes)); 1323 ival = map->format.parse_val(val + (i * val_bytes));
1319 ret = regcache_write(map, reg + (i * map->reg_stride), 1324 ret = regcache_write(map,
1325 reg + regmap_get_offset(map, i),
1320 ival); 1326 ival);
1321 if (ret) { 1327 if (ret) {
1322 dev_err(map->dev, 1328 dev_err(map->dev,
@@ -1846,8 +1852,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1846 goto out; 1852 goto out;
1847 } 1853 }
1848 1854
1849 ret = _regmap_write(map, reg + (i * map->reg_stride), 1855 ret = _regmap_write(map,
1850 ival); 1856 reg + regmap_get_offset(map, i),
1857 ival);
1851 if (ret != 0) 1858 if (ret != 0)
1852 goto out; 1859 goto out;
1853 } 1860 }
@@ -2416,7 +2423,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
2416 * cost as we expect to hit the cache. 2423 * cost as we expect to hit the cache.
2417 */ 2424 */
2418 for (i = 0; i < val_count; i++) { 2425 for (i = 0; i < val_count; i++) {
2419 ret = _regmap_read(map, reg + (i * map->reg_stride), 2426 ret = _regmap_read(map, reg + regmap_get_offset(map, i),
2420 &v); 2427 &v);
2421 if (ret != 0) 2428 if (ret != 0)
2422 goto out; 2429 goto out;
@@ -2568,7 +2575,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
2568 } else { 2575 } else {
2569 for (i = 0; i < val_count; i++) { 2576 for (i = 0; i < val_count; i++) {
2570 unsigned int ival; 2577 unsigned int ival;
2571 ret = regmap_read(map, reg + (i * map->reg_stride), 2578 ret = regmap_read(map, reg + regmap_get_offset(map, i),
2572 &ival); 2579 &ival);
2573 if (ret != 0) 2580 if (ret != 0)
2574 return ret; 2581 return ret;