regmap: Don't use format_val in regmap_bulk_read
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 12 Feb 2018 18:15:46 +0000 (18:15 +0000)
committerMark Brown <broonie@kernel.org>
Tue, 13 Feb 2018 12:27:44 +0000 (12:27 +0000)
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>
drivers/base/regmap/regmap.c

index ee302ccdfbc8d366fec3f39574a4c28462b20240..4037b3782bd34c707fe9d488717f8d60ba11ed49 100644 (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.
-                                */
-#ifdef CONFIG_64BIT
-                               u64 *u64 = val;
-#endif
-                               u32 *u32 = val;
-                               u16 *u16 = val;
-                               u8 *u8 = val;
-
-                               switch (map->format.val_bytes) {
+                       switch (map->format.val_bytes) {
 #ifdef CONFIG_64BIT
-                               case 8:
-                                       u64[i] = ival;
-                                       break;
+                       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;
                        }
                }
        }