aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-04 13:20:18 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-14 21:00:00 -0400
commit8a2ceac6617a67d8a1ee4bd255743d577bde311a (patch)
tree3d930e91d65fb6ccf22bc7cdfd2de168ce3eb0f1 /drivers/base/regmap
parent0ff3e62ff119f2b65b0a8ad48fcb669f609fd904 (diff)
regmap: Split raw writes that cross window boundaries
If a block write covers a paged memory region and crosses a window boundary then rather than failing the write split the transfer up into multiple writes, making the whole process more transparent for drivers. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/regmap.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index baf9586b4fd8..96253cd949e9 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -852,8 +852,30 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
852 852
853 range = _regmap_range_lookup(map, reg); 853 range = _regmap_range_lookup(map, reg);
854 if (range) { 854 if (range) {
855 ret = _regmap_select_page(map, &reg, range, 855 int val_num = val_len / map->format.val_bytes;
856 val_len / map->format.val_bytes); 856 int win_offset = (reg - range->range_min) % range->window_len;
857 int win_residue = range->window_len - win_offset;
858
859 /* If the write goes beyond the end of the window split it */
860 while (val_num > win_residue) {
861 dev_dbg(map->dev, "Writing window %d/%d\n",
862 win_residue, val_len / map->format.val_bytes);
863 ret = _regmap_raw_write(map, reg, val, win_residue *
864 map->format.val_bytes);
865 if (ret != 0)
866 return ret;
867
868 reg += win_residue;
869 val_num -= win_residue;
870 val += win_residue * map->format.val_bytes;
871 val_len -= win_residue * map->format.val_bytes;
872
873 win_offset = (reg - range->range_min) %
874 range->window_len;
875 win_residue = range->window_len - win_offset;
876 }
877
878 ret = _regmap_select_page(map, &reg, range, val_num);
857 if (ret != 0) 879 if (ret != 0)
858 return ret; 880 return ret;
859 } 881 }