regmap: Don't use format_val in regmap_bulk_read

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: 15b8d2c41f ("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>
This commit is contained in:
Charles Keepax 2018-02-12 18:15:46 +00:00 committed by Mark Brown
parent 7928b2cbe5
commit 9ae27a8d1f
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0

View file

@ -2709,47 +2709,38 @@ 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 {
#ifdef CONFIG_64BIT
u64 *u64 = val;
#endif
u32 *u32 = val;
u16 *u16 = val;
u8 *u8 = val;
for (i = 0; i < val_count; i++) {
unsigned int ival;
ret = regmap_read(map, reg + regmap_get_offset(map, i),
&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.
*/
switch (map->format.val_bytes) {
#ifdef CONFIG_64BIT
u64 *u64 = val;
case 8:
u64[i] = ival;
break;
#endif
u32 *u32 = val;
u16 *u16 = val;
u8 *u8 = val;
switch (map->format.val_bytes) {
#ifdef CONFIG_64BIT
case 8:
u64[i] = ival;
break;
#endif
case 4:
u32[i] = ival;
break;
case 2:
u16[i] = ival;
break;
case 1:
u8[i] = ival;
break;
default:
return -EINVAL;
}
case 4:
u32[i] = ival;
break;
case 2:
u16[i] = ival;
break;
case 1:
u8[i] = ival;
break;
default:
return -EINVAL;
}
}
}