summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-10-10 13:24:52 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-10-13 11:41:54 +0100
commitde2d808f4de091321978d05a85ef0819e8f3561a (patch)
treed2b3d27de79f9cd7d7092a886c8a9479588a5428 /drivers/base
parent8528bdd450d34687b380c0f87992d105bdf54ca3 (diff)
regmap: Support some block operations on cached devices
Support raw reads if all the registers being read are volatile, the cache will have no impact for tem. Support bulk reads either directly (if all the registers are volatile) or by falling back to iterating over single register reads otherwise. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regmap.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 85bffddda530..bf441db1ee90 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -482,8 +482,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t val_len)
{
int ret;
+ int i;
+ bool vol = true;
- WARN_ON(map->cache_type != REGCACHE_NONE);
+ for (i = 0; i < val_len / map->format.val_bytes; i++)
+ if (!regmap_volatile(map, reg + i))
+ vol = false;
+
+ WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
mutex_lock(&map->lock);
@@ -511,18 +517,30 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
{
int ret, i;
size_t val_bytes = map->format.val_bytes;
-
- WARN_ON(map->cache_type != REGCACHE_NONE);
+ bool vol = true;
if (!map->format.parse_val)
return -EINVAL;
- ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
- if (ret != 0)
- return ret;
+ /* Is this a block of volatile registers? */
+ for (i = 0; i < val_count; i++)
+ if (!regmap_volatile(map, reg + i))
+ vol = false;
- for (i = 0; i < val_count * val_bytes; i += val_bytes)
- map->format.parse_val(val + i);
+ if (vol || map->cache_type == REGCACHE_NONE) {
+ ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+ if (ret != 0)
+ return ret;
+
+ for (i = 0; i < val_count * val_bytes; i += val_bytes)
+ map->format.parse_val(val + i);
+ } else {
+ for (i = 0; i < val_count; i++) {
+ ret = regmap_read(map, reg + i, val + (i * val_bytes));
+ if (ret != 0)
+ return ret;
+ }
+ }
return 0;
}