aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-18 05:52:25 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-20 07:15:39 -0500
commit82159ba8e6ef8c38e3e0452d90b4ff8da9e4b2c1 (patch)
tree2f488ebc125b24d6790afad633ec8be1e933be18 /drivers/base/regmap/regmap.c
parentdcd6c92267155e70a94b3927bce681ce74b80d1f (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>
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 be10a4ff660..e9c2ac0174c 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -160,7 +160,9 @@ struct regmap *regmap_init(struct device *dev,
160 mutex_init(&map->lock); 160 mutex_init(&map->lock);
161 map->format.buf_size = (config->reg_bits + config->val_bits) / 8; 161 map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
162 map->format.reg_bytes = config->reg_bits / 8; 162 map->format.reg_bytes = config->reg_bits / 8;
163 map->format.pad_bytes = config->pad_bits / 8;
163 map->format.val_bytes = config->val_bits / 8; 164 map->format.val_bytes = config->val_bits / 8;
165 map->format.buf_size += map->format.pad_bytes;
164 map->dev = dev; 166 map->dev = dev;
165 map->bus = bus; 167 map->bus = bus;
166 map->max_register = config->max_register; 168 map->max_register = config->max_register;
@@ -235,7 +237,7 @@ struct regmap *regmap_init(struct device *dev,
235 !(map->format.format_reg && map->format.format_val)) 237 !(map->format.format_reg && map->format.format_val))
236 goto err_map; 238 goto err_map;
237 239
238 map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); 240 map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL);
239 if (map->work_buf == NULL) { 241 if (map->work_buf == NULL) {
240 ret = -ENOMEM; 242 ret = -ENOMEM;
241 goto err_map; 243 goto err_map;
@@ -329,23 +331,28 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
329 * send the work_buf directly, otherwise try to do a gather 331 * send the work_buf directly, otherwise try to do a gather
330 * write. 332 * write.
331 */ 333 */
332 if (val == map->work_buf + map->format.reg_bytes) 334 if (val == (map->work_buf + map->format.pad_bytes +
335 map->format.reg_bytes))
333 ret = map->bus->write(map->dev, map->work_buf, 336 ret = map->bus->write(map->dev, map->work_buf,
334 map->format.reg_bytes + val_len); 337 map->format.reg_bytes +
338 map->format.pad_bytes +
339 val_len);
335 else if (map->bus->gather_write) 340 else if (map->bus->gather_write)
336 ret = map->bus->gather_write(map->dev, map->work_buf, 341 ret = map->bus->gather_write(map->dev, map->work_buf,
337 map->format.reg_bytes, 342 map->format.reg_bytes +
343 map->format.pad_bytes,
338 val, val_len); 344 val, val_len);
339 345
340 /* If that didn't work fall back on linearising by hand. */ 346 /* If that didn't work fall back on linearising by hand. */
341 if (ret == -ENOTSUPP) { 347 if (ret == -ENOTSUPP) {
342 len = map->format.reg_bytes + val_len; 348 len = map->format.reg_bytes + map->format.pad_bytes + val_len;
343 buf = kmalloc(len, GFP_KERNEL); 349 buf = kzalloc(len, GFP_KERNEL);
344 if (!buf) 350 if (!buf)
345 return -ENOMEM; 351 return -ENOMEM;
346 352
347 memcpy(buf, map->work_buf, map->format.reg_bytes); 353 memcpy(buf, map->work_buf, map->format.reg_bytes);
348 memcpy(buf + map->format.reg_bytes, val, val_len); 354 memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
355 val, val_len);
349 ret = map->bus->write(map->dev, buf, len); 356 ret = map->bus->write(map->dev, buf, len);
350 357
351 kfree(buf); 358 kfree(buf);
@@ -387,10 +394,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
387 394
388 return ret; 395 return ret;
389 } else { 396 } else {
390 map->format.format_val(map->work_buf + map->format.reg_bytes, 397 map->format.format_val(map->work_buf + map->format.reg_bytes
391 val); 398 + map->format.pad_bytes, val);
392 return _regmap_raw_write(map, reg, 399 return _regmap_raw_write(map, reg,
393 map->work_buf + map->format.reg_bytes, 400 map->work_buf +
401 map->format.reg_bytes +
402 map->format.pad_bytes,
394 map->format.val_bytes); 403 map->format.val_bytes);
395 } 404 }
396} 405}
@@ -473,7 +482,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
473 trace_regmap_hw_read_start(map->dev, reg, 482 trace_regmap_hw_read_start(map->dev, reg,
474 val_len / map->format.val_bytes); 483 val_len / map->format.val_bytes);
475 484
476 ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes, 485 ret = map->bus->read(map->dev, map->work_buf,
486 map->format.reg_bytes + map->format.pad_bytes,
477 val, val_len); 487 val, val_len);
478 488
479 trace_regmap_hw_read_done(map->dev, reg, 489 trace_regmap_hw_read_done(map->dev, reg,