summaryrefslogtreecommitdiff
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-18 10:52:25 +0000
committerLokesh Pathak <lpathak@nvidia.com>2012-03-05 07:56:32 -0800
commitfa17671aae4c6891ad008c0f4cb8ad2b21b41858 (patch)
tree2de3cf15f343c7663be5bfa9fb27aebb06c3e5e6 /drivers/base/regmap/regmap.c
parent5cbf2fb24232034d211dbcd1c6719bea3930d38f (diff)
regmap: Add support for padding between register and address
Some devices, especially those with high speed control interfaces, require padding between the register and the data. Support this in the regmap API by providing a pad_bits configuration parameter. Only devices with integer byte counts are supported. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> (cherry picked from commit 82159ba8e6ef8c38e3e0452d90b4ff8da9e4b2c1) Change-Id: Id9710b92e08ac905f3291715aa457842e60fed3d Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/87575
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index e9970bafb435..94e808ba7514 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -160,7 +160,9 @@ struct regmap *regmap_init(struct device *dev,
mutex_init(&map->lock);
map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
map->format.reg_bytes = config->reg_bits / 8;
+ map->format.pad_bytes = config->pad_bits / 8;
map->format.val_bytes = config->val_bits / 8;
+ map->format.buf_size += map->format.pad_bytes;
map->dev = dev;
map->bus = bus;
map->max_register = config->max_register;
@@ -235,7 +237,7 @@ struct regmap *regmap_init(struct device *dev,
!(map->format.format_reg && map->format.format_val))
goto err_map;
- map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
+ map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL);
if (map->work_buf == NULL) {
ret = -ENOMEM;
goto err_map;
@@ -329,23 +331,28 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
* send the work_buf directly, otherwise try to do a gather
* write.
*/
- if (val == map->work_buf + map->format.reg_bytes)
+ if (val == (map->work_buf + map->format.pad_bytes +
+ map->format.reg_bytes))
ret = map->bus->write(map->dev, map->work_buf,
- map->format.reg_bytes + val_len);
+ map->format.reg_bytes +
+ map->format.pad_bytes +
+ val_len);
else if (map->bus->gather_write)
ret = map->bus->gather_write(map->dev, map->work_buf,
- map->format.reg_bytes,
+ map->format.reg_bytes +
+ map->format.pad_bytes,
val, val_len);
/* If that didn't work fall back on linearising by hand. */
if (ret == -ENOTSUPP) {
- len = map->format.reg_bytes + val_len;
- buf = kmalloc(len, GFP_KERNEL);
+ len = map->format.reg_bytes + map->format.pad_bytes + val_len;
+ buf = kzalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, map->work_buf, map->format.reg_bytes);
- memcpy(buf + map->format.reg_bytes, val, val_len);
+ memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
+ val, val_len);
ret = map->bus->write(map->dev, buf, len);
kfree(buf);
@@ -387,10 +394,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
return ret;
} else {
- map->format.format_val(map->work_buf + map->format.reg_bytes,
- val);
+ map->format.format_val(map->work_buf + map->format.reg_bytes
+ + map->format.pad_bytes, val);
return _regmap_raw_write(map, reg,
- map->work_buf + map->format.reg_bytes,
+ map->work_buf +
+ map->format.reg_bytes +
+ map->format.pad_bytes,
map->format.val_bytes);
}
}
@@ -473,7 +482,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
trace_regmap_hw_read_start(map->dev, reg,
val_len / map->format.val_bytes);
- ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
+ ret = map->bus->read(map->dev, map->work_buf,
+ map->format.reg_bytes + map->format.pad_bytes,
val, val_len);
trace_regmap_hw_read_done(map->dev, reg,