diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-01-18 05:52:25 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-01-20 07:15:39 -0500 |
commit | 82159ba8e6ef8c38e3e0452d90b4ff8da9e4b2c1 (patch) | |
tree | 2f488ebc125b24d6790afad633ec8be1e933be18 /drivers/base/regmap | |
parent | dcd6c92267155e70a94b3927bce681ce74b80d1f (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')
-rw-r--r-- | drivers/base/regmap/internal.h | 1 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 32 |
2 files changed, 22 insertions, 11 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 1a02b7537c8b..e33f1be2b299 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -22,6 +22,7 @@ struct regcache_ops; | |||
22 | struct regmap_format { | 22 | struct regmap_format { |
23 | size_t buf_size; | 23 | size_t buf_size; |
24 | size_t reg_bytes; | 24 | size_t reg_bytes; |
25 | size_t pad_bytes; | ||
25 | size_t val_bytes; | 26 | size_t val_bytes; |
26 | void (*format_write)(struct regmap *map, | 27 | void (*format_write)(struct regmap *map, |
27 | unsigned int reg, unsigned int val); | 28 | unsigned int reg, unsigned int val); |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index be10a4ff6609..e9c2ac0174c6 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, |