Merge branches 'regmap-linus' and 'regmap-interface' into regmap-next
[firefly-linux-kernel-4.4.55.git] / drivers / base / regmap / regmap.c
index 0eef4da1ac61f1deb274e56fb5601cfc6275c193..02ed1546da21d405893aef17933528bcf72fd71c 100644 (file)
@@ -37,6 +37,11 @@ struct regmap {
        void *work_buf;     /* Scratch buffer used to format I/O */
        struct regmap_format format;  /* Buffer format */
        const struct regmap_bus *bus;
+
+       unsigned int max_register;
+       bool (*writeable_reg)(struct device *dev, unsigned int reg);
+       bool (*readable_reg)(struct device *dev, unsigned int reg);
+       bool (*volatile_reg)(struct device *dev, unsigned int reg);
 };
 
 static void regmap_format_4_12_write(struct regmap *map,
@@ -116,6 +121,10 @@ struct regmap *regmap_init(struct device *dev,
        map->format.val_bytes = config->val_bits / 8;
        map->dev = dev;
        map->bus = bus;
+       map->max_register = config->max_register;
+       map->writeable_reg = config->writeable_reg;
+       map->readable_reg = config->readable_reg;
+       map->volatile_reg = config->volatile_reg;
 
        switch (config->reg_bits) {
        case 4:
@@ -202,13 +211,19 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        map->format.format_reg(map->work_buf, reg);
 
-       /* Try to do a gather write if we can */
-       if (map->bus->gather_write)
+       /* If we're doing a single register write we can probably just
+        * send the work_buf directly, otherwise try to do a gather
+        * write.
+        */
+       if (val == map->work_buf + map->format.reg_bytes)
+               ret = map->bus->write(map->dev, map->work_buf,
+                                     map->format.reg_bytes + val_len);
+       else if (map->bus->gather_write)
                ret = map->bus->gather_write(map->dev, map->work_buf,
                                             map->format.reg_bytes,
                                             val, val_len);
 
-       /* Otherwise fall back on linearising by hand. */
+       /* If that didn't work fall back on linearising by hand. */
        if (ret == -ENOTSUPP) {
                len = map->format.reg_bytes + val_len;
                buf = kmalloc(len, GFP_KERNEL);