regmap: Support bulk writes for devices without raw formatting
[deliverable/linux.git] / drivers / base / regmap / regmap.c
index df2d2ef5d6b38bf374ab8ed3158d80e301a92852..51fa7d66a393bf5bee6818c1432211dfd76582ce 100644 (file)
@@ -1777,8 +1777,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
        size_t val_bytes = map->format.val_bytes;
        size_t total_size = val_bytes * val_count;
 
-       if (map->bus && !map->format.parse_inplace)
-               return -EINVAL;
        if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
 
@@ -1789,7 +1787,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
         *
         * The first if block is used for memory mapped io. It does not allow
         * val_bytes of 3 for example.
-        * The second one is used for busses which do not have this limitation
+        * The second one is for busses that do not provide raw I/O.
+        * The third one is used for busses which do not have these limitations
         * and can write arbitrary value lengths.
         */
        if (!map->bus) {
@@ -1825,6 +1824,32 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
                }
 out:
                map->unlock(map->lock_arg);
+       } else if (map->bus && !map->format.parse_inplace) {
+               const u8 *u8 = val;
+               const u16 *u16 = val;
+               const u32 *u32 = val;
+               unsigned int ival;
+
+               for (i = 0; i < val_count; i++) {
+                       switch (map->format.val_bytes) {
+                       case 4:
+                               ival = u32[i];
+                               break;
+                       case 2:
+                               ival = u16[i];
+                               break;
+                       case 1:
+                               ival = u8[i];
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+
+                       ret = regmap_write(map, reg + (i * map->reg_stride),
+                                          ival);
+                       if (ret)
+                               return ret;
+               }
        } else if (map->use_single_write ||
                   (map->max_raw_write && map->max_raw_write < total_size)) {
                int chunk_stride = map->reg_stride;
This page took 0.038558 seconds and 5 git commands to generate.