aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-14 09:15:48 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-14 09:15:48 -0400
commitaddfd8a09e1f434a73b3d87d36ef050c73511d2b (patch)
tree22dd5a1f108dcd123797dbe9f5aa45e8d3faa492
parenteae4b51b21f7452b0b53a9848f48c02cb0fac336 (diff)
parentdf00c79f78d8b0ad788daf689ea461ace9d0811f (diff)
Merge remote-tracking branch 'regmap/topic/bulk' into regmap-next
-rw-r--r--drivers/base/regmap/regcache.c5
-rw-r--r--drivers/base/regmap/regmap.c76
-rw-r--r--include/linux/regmap.h2
3 files changed, 78 insertions, 5 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index fb84d711fbb4..938cb1d2ea26 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -35,12 +35,17 @@ static int regcache_hw_init(struct regmap *map)
35 return -EINVAL; 35 return -EINVAL;
36 36
37 if (!map->reg_defaults_raw) { 37 if (!map->reg_defaults_raw) {
38 u32 cache_bypass = map->cache_bypass;
38 dev_warn(map->dev, "No cache defaults, reading back from HW\n"); 39 dev_warn(map->dev, "No cache defaults, reading back from HW\n");
40
41 /* Bypass the cache access till data read from HW*/
42 map->cache_bypass = 1;
39 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); 43 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
40 if (!tmp_buf) 44 if (!tmp_buf)
41 return -EINVAL; 45 return -EINVAL;
42 ret = regmap_bulk_read(map, 0, tmp_buf, 46 ret = regmap_bulk_read(map, 0, tmp_buf,
43 map->num_reg_defaults_raw); 47 map->num_reg_defaults_raw);
48 map->cache_bypass = cache_bypass;
44 if (ret < 0) { 49 if (ret < 0) {
45 kfree(tmp_buf); 50 kfree(tmp_buf);
46 return ret; 51 return ret;
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 2f7c25c68c9e..7a3f535e481c 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -411,6 +411,26 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
411 if (!map->writeable_reg(map->dev, reg + i)) 411 if (!map->writeable_reg(map->dev, reg + i))
412 return -EINVAL; 412 return -EINVAL;
413 413
414 if (!map->cache_bypass && map->format.parse_val) {
415 unsigned int ival;
416 int val_bytes = map->format.val_bytes;
417 for (i = 0; i < val_len / val_bytes; i++) {
418 memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
419 ival = map->format.parse_val(map->work_buf);
420 ret = regcache_write(map, reg + i, ival);
421 if (ret) {
422 dev_err(map->dev,
423 "Error in caching of register: %u ret: %d\n",
424 reg + i, ret);
425 return ret;
426 }
427 }
428 if (map->cache_only) {
429 map->cache_dirty = true;
430 return 0;
431 }
432 }
433
414 map->format.format_reg(map->work_buf, reg); 434 map->format.format_reg(map->work_buf, reg);
415 435
416 u8[0] |= map->write_flag_mask; 436 u8[0] |= map->write_flag_mask;
@@ -461,7 +481,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
461 int ret; 481 int ret;
462 BUG_ON(!map->format.format_write && !map->format.format_val); 482 BUG_ON(!map->format.format_write && !map->format.format_val);
463 483
464 if (!map->cache_bypass) { 484 if (!map->cache_bypass && map->format.format_write) {
465 ret = regcache_write(map, reg, val); 485 ret = regcache_write(map, reg, val);
466 if (ret != 0) 486 if (ret != 0)
467 return ret; 487 return ret;
@@ -538,12 +558,8 @@ EXPORT_SYMBOL_GPL(regmap_write);
538int regmap_raw_write(struct regmap *map, unsigned int reg, 558int regmap_raw_write(struct regmap *map, unsigned int reg,
539 const void *val, size_t val_len) 559 const void *val, size_t val_len)
540{ 560{
541 size_t val_count = val_len / map->format.val_bytes;
542 int ret; 561 int ret;
543 562
544 WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
545 map->cache_type != REGCACHE_NONE);
546
547 mutex_lock(&map->lock); 563 mutex_lock(&map->lock);
548 564
549 ret = _regmap_raw_write(map, reg, val, val_len); 565 ret = _regmap_raw_write(map, reg, val, val_len);
@@ -554,6 +570,56 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
554} 570}
555EXPORT_SYMBOL_GPL(regmap_raw_write); 571EXPORT_SYMBOL_GPL(regmap_raw_write);
556 572
573/*
574 * regmap_bulk_write(): Write multiple registers to the device
575 *
576 * @map: Register map to write to
577 * @reg: First register to be write from
578 * @val: Block of data to be written, in native register size for device
579 * @val_count: Number of registers to write
580 *
581 * This function is intended to be used for writing a large block of
582 * data to be device either in single transfer or multiple transfer.
583 *
584 * A value of zero will be returned on success, a negative errno will
585 * be returned in error cases.
586 */
587int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
588 size_t val_count)
589{
590 int ret = 0, i;
591 size_t val_bytes = map->format.val_bytes;
592 void *wval;
593
594 if (!map->format.parse_val)
595 return -EINVAL;
596
597 mutex_lock(&map->lock);
598
599 /* No formatting is require if val_byte is 1 */
600 if (val_bytes == 1) {
601 wval = (void *)val;
602 } else {
603 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
604 if (!wval) {
605 ret = -ENOMEM;
606 dev_err(map->dev, "Error in memory allocation\n");
607 goto out;
608 }
609 for (i = 0; i < val_count * val_bytes; i += val_bytes)
610 map->format.parse_val(wval + i);
611 }
612 ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
613
614 if (val_bytes != 1)
615 kfree(wval);
616
617out:
618 mutex_unlock(&map->lock);
619 return ret;
620}
621EXPORT_SYMBOL_GPL(regmap_bulk_write);
622
557static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 623static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
558 unsigned int val_len) 624 unsigned int val_len)
559{ 625{
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 398377d89332..5d7e6add0084 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -146,6 +146,8 @@ int regmap_reinit_cache(struct regmap *map,
146int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); 146int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
147int regmap_raw_write(struct regmap *map, unsigned int reg, 147int regmap_raw_write(struct regmap *map, unsigned int reg,
148 const void *val, size_t val_len); 148 const void *val, size_t val_len);
149int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
150 size_t val_count);
149int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); 151int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
150int regmap_raw_read(struct regmap *map, unsigned int reg, 152int regmap_raw_read(struct regmap *map, unsigned int reg,
151 void *val, size_t val_len); 153 void *val, size_t val_len);