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