From 813f6f1d964eedb7f60fd78b4fdaf50953eb0b73 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Sat, 29 Aug 2015 09:03:56 +0530 Subject: [PATCH] regmap: call regmap_raw_multi_reg_write from regcache sync Call regmap_raw_multi_reg_write API from regcache sync to sync multiple registers to the hardware if bus interface supports multi register write. This change will help in reducing the latency for syncing the registers to the hardware. Change-Id: I94d19434dc7465434f10db9f7bd62fcc8246d845 Signed-off-by: Sudheer Papothi --- drivers/base/regmap/regcache.c | 54 +++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4c07802986b2..673938f972a8 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -682,6 +682,53 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, return ret; } +static int regcache_sync_block_raw_multi_reg(struct regmap *map, void *block, + unsigned long *cache_present, + unsigned int block_base, + unsigned int start, + unsigned int end) +{ + unsigned int i, val; + unsigned int regtmp = 0; + int ret = 0; + struct reg_sequence *regs; + size_t num_regs = ((end - start) + 1); + + regs = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL); + if (!regs) + return -ENOMEM; + + num_regs = 0; + for (i = start; i < end; i++) { + regtmp = block_base + (i * map->reg_stride); + + /* skip registers that are not defined/available */ + if (!regcache_reg_present(cache_present, i)) + continue; + + val = regcache_get_val(map, block, i); + + /* Is this the hardware default? If so skip. */ + ret = regcache_lookup_reg(map, regtmp); + if (ret >= 0 && val == map->reg_defaults[ret].def) { + continue; + } else { + regs[num_regs].reg = regtmp; + regs[num_regs].def = val; + regs[num_regs].delay_us = 0; + num_regs += 1; + } + } + ret = 0; + if (num_regs) { + dev_dbg(map->dev, "%s: start: 0x%x - end: 0x%x\n", + __func__, regs[0].reg, regs[num_regs-1].reg); + ret = _regmap_raw_multi_reg_write(map, regs, num_regs); + } + kfree(regs); + return ret; +} + static int regcache_sync_block_raw(struct regmap *map, void *block, unsigned long *cache_present, unsigned int block_base, unsigned int start, @@ -729,7 +776,12 @@ int regcache_sync_block(struct regmap *map, void *block, unsigned int block_base, unsigned int start, unsigned int end) { - if (regmap_can_raw_write(map) && !map->use_single_write) + if (regmap_can_raw_write(map) && map->can_multi_write) + return regcache_sync_block_raw_multi_reg(map, block, + cache_present, + block_base, start, + end); + else if (regmap_can_raw_write(map) && !map->use_single_write) return regcache_sync_block_raw(map, block, cache_present, block_base, start, end); else