Skip to content

Commit

Permalink
regmap: Converts group operation into single read write operations
Browse files Browse the repository at this point in the history
Some devices does not support bulk read and write operations, for them
we have series of single write and read operations.

Signed-off-by: Anthony Olech <Anthony.Olech@diasemi.com>
Signed-off-by: Ashish Jangam <ashish.jangam@kpitcummins.com>
[Fixed coding style, don't check use_single_rw before assign --broonie ]
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Ashish Jangam authored and Mark Brown committed Apr 30, 2012
1 parent 5680655 commit 2e33caf
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
3 changes: 3 additions & 0 deletions drivers/base/regmap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ struct regmap {

struct reg_default *patch;
int patch_regs;

/* if set, converts bulk rw to single rw */
bool use_single_rw;
};

struct regcache_ops {
Expand Down
40 changes: 36 additions & 4 deletions drivers/base/regmap/regmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ struct regmap *regmap_init(struct device *dev,
map->reg_stride = config->reg_stride;
else
map->reg_stride = 1;
map->use_single_rw = config->use_single_rw;
map->dev = dev;
map->bus = bus;
map->bus_context = bus_context;
Expand Down Expand Up @@ -686,7 +687,22 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_val(wval + i);
}
ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
/*
* Some devices does not support bulk write, for
* them we have a series of single write operations.
*/
if (map->use_single_rw) {
for (i = 0; i < val_count; i++) {
ret = regmap_raw_write(map,
reg + (i * map->reg_stride),
val + (i * val_bytes),
val_bytes);
if (ret != 0)
return ret;
}
} else {
ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
}

if (val_bytes != 1)
kfree(wval);
Expand Down Expand Up @@ -855,9 +871,25 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
return -EINVAL;

if (vol || map->cache_type == REGCACHE_NONE) {
ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
if (ret != 0)
return ret;
/*
* Some devices does not support bulk read, for
* them we have a series of single read operations.
*/
if (map->use_single_rw) {
for (i = 0; i < val_count; i++) {
ret = regmap_raw_read(map,
reg + (i * map->reg_stride),
val + (i * val_bytes),
val_bytes);
if (ret != 0)
return ret;
}
} else {
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);
Expand Down
5 changes: 5 additions & 0 deletions include/linux/regmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ struct reg_default {
* @write_flag_mask: Mask to be set in the top byte of the register when doing
* a write. If both read_flag_mask and write_flag_mask are
* empty the regmap_bus default masks are used.
* @use_single_rw: If set, converts the bulk read and write operations into
* a series of single read and write operations. This is useful
* for device that does not support bulk read and write.
*
* @cache_type: The actual cache type.
* @reg_defaults_raw: Power on reset values for registers (for use with
Expand Down Expand Up @@ -104,6 +107,8 @@ struct regmap_config {

u8 read_flag_mask;
u8 write_flag_mask;

bool use_single_rw;
};

typedef int (*regmap_hw_write)(void *context, const void *data,
Expand Down

0 comments on commit 2e33caf

Please sign in to comment.