mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
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:
parent
7928b2cbe5
commit
9ae27a8d1f
1 changed files with 23 additions and 32 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue