regmap: Don't use format_val in regmap_bulk_read

commit 9ae27a8d1f3ebff09191fb8cb1341414547293b2 upstream.

A bulk read can be implemented either through regmap_raw_read, or
by reading each register individually using regmap_read.  Both
regmap_read and regmap_bulk_read should return values in native
endian. In the individual case the current implementation calls
format_val to put the data into the output array, which can cause
endian issues. The regmap_read will have already converted the data
into native endian, if the hosts endian differs from the device then
format_val will switch the endian back again.

Rather than using format_val simply use the code that is called if
there is no format_val function. This code supports all cases except
24-bit but there don't appear to be any users of regmap_bulk_read for
24-bit. Additionally, it would have to be a big endian host for the
old code to actually function correctly anyway.

Fixes: 15b8d2c41fe5 ("regmap: Fix regmap_bulk_read in BE mode")
Reported-by: David Rhodes <david.rhodes@cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
[bwh: Backported to 3.16:
 - 64-bit I/O is not supported
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
Charles Keepax 2018-02-12 18:15:46 +00:00 committed by syphyr
parent 5e93f562f2
commit 08c2d5a0bf
1 changed files with 17 additions and 26 deletions

View File

@ -1833,39 +1833,30 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(val + i);
} else {
u32 *u32 = val;
u16 *u16 = val;
u8 *u8 = val;
for (i = 0; i < val_count; i++) {
unsigned int ival;
ret = regmap_read(map, reg + (i * map->reg_stride),
&ival);
if (ret != 0)
return ret;
if (map->format.format_val) {
map->format.format_val(val + (i * val_bytes), ival, 0);
} else {
/* Devices providing read and write
* operations can use the bulk I/O
* functions if they define a val_bytes,
* we assume that the values are native
* endian.
*/
u32 *u32 = val;
u16 *u16 = val;
u8 *u8 = val;
switch (map->format.val_bytes) {
case 4:
u32[i] = ival;
break;
case 2:
u16[i] = ival;
break;
case 1:
u8[i] = ival;
break;
default:
return -EINVAL;
}
switch (map->format.val_bytes) {
case 4:
u32[i] = ival;
break;
case 2:
u16[i] = ival;
break;
case 1:
u8[i] = ival;
break;
default:
return -EINVAL;
}
}
}