aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-04-09 13:40:24 -0600
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-10 11:01:18 +0100
commitf01ee60fffa4dc6c77122121233a793f7f696e67 (patch)
tree5072955487b9e4c80f5c6f6454358d80e8f23a48 /drivers/base/regmap/regmap.c
parentMerge branches 'regmap-core', 'regmap-mmio' and 'regmap-naming' into regmap-stride (diff)
downloadlinux-dev-f01ee60fffa4dc6c77122121233a793f7f696e67.tar.xz
linux-dev-f01ee60fffa4dc6c77122121233a793f7f696e67.zip
regmap: implement register striding
regmap_config.reg_stride is introduced. All extant register addresses are a multiple of this value. Users of serial-oriented regmap busses will typically set this to 1. Users of the MMIO regmap bus will typically set this based on the value size of their registers, in bytes, so 4 for a 32-bit register. Throughout the regmap code, actual register addresses are used. Wherever the register address is used to index some array of values, the address is divided by the stride to determine the index, or vice-versa. Error- checking is added to all entry-points for register address data to ensure that register addresses actually satisfy the specified stride. The MMIO bus ensures that the specified stride is large enough for the register size. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 40f910162781..8a25006b2a4d 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -243,6 +243,10 @@ struct regmap *regmap_init(struct device *dev,
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
map->format.buf_size += map->format.pad_bytes;
map->reg_shift = config->pad_bits % 8;
+ if (config->reg_stride)
+ map->reg_stride = config->reg_stride;
+ else
+ map->reg_stride = 1;
map->dev = dev;
map->bus = bus;
map->bus_context = bus_context;
@@ -469,7 +473,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
/* Check for unwritable registers before we start */
if (map->writeable_reg)
for (i = 0; i < val_len / map->format.val_bytes; i++)
- if (!map->writeable_reg(map->dev, reg + i))
+ if (!map->writeable_reg(map->dev,
+ reg + (i * map->reg_stride)))
return -EINVAL;
if (!map->cache_bypass && map->format.parse_val) {
@@ -478,7 +483,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
for (i = 0; i < val_len / val_bytes; i++) {
memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
ival = map->format.parse_val(map->work_buf);
- ret = regcache_write(map, reg + i, ival);
+ ret = regcache_write(map, reg + (i * map->reg_stride),
+ ival);
if (ret) {
dev_err(map->dev,
"Error in caching of register: %u ret: %d\n",
@@ -590,6 +596,9 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
{
int ret;
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
map->lock(map);
ret = _regmap_write(map, reg, val);
@@ -623,6 +632,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
if (val_len % map->format.val_bytes)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
map->lock(map);
@@ -657,6 +668,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
if (!map->format.parse_val)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
map->lock(map);
@@ -753,6 +766,9 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
map->lock(map);
ret = _regmap_read(map, reg, val);
@@ -784,6 +800,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
if (val_len % map->format.val_bytes)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
map->lock(map);
@@ -797,7 +815,8 @@ 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, &v);
+ ret = _regmap_read(map, reg + (i * map->reg_stride),
+ &v);
if (ret != 0)
goto out;
@@ -832,6 +851,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (!map->format.parse_val)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
if (vol || map->cache_type == REGCACHE_NONE) {
ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
@@ -842,7 +863,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
map->format.parse_val(val + i);
} else {
for (i = 0; i < val_count; i++) {
- ret = regmap_read(map, reg + i, val + (i * val_bytes));
+ ret = regmap_read(map, reg + (i * map->reg_stride),
+ val + (i * val_bytes));
if (ret != 0)
return ret;
}