diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-04 13:20:18 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-14 21:00:00 -0400 |
| commit | 8a2ceac6617a67d8a1ee4bd255743d577bde311a (patch) | |
| tree | 3d930e91d65fb6ccf22bc7cdfd2de168ce3eb0f1 /drivers/base | |
| parent | 0ff3e62ff119f2b65b0a8ad48fcb669f609fd904 (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')
| -rw-r--r-- | drivers/base/regmap/regmap.c | 26 |
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, ®, 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, ®, range, val_num); | ||
| 857 | if (ret != 0) | 879 | if (ret != 0) |
| 858 | return ret; | 880 | return ret; |
| 859 | } | 881 | } |
