]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/base/regmap/regmap.c
Merge remote-tracking branches 'spi/topic/fsl-dspi', 'spi/topic/imx', 'spi/topic...
[karo-tx-linux.git] / drivers / base / regmap / regmap.c
index 78f43fb2fe84647d5e97d5c9f6468cf6c8704187..f2281af24ec6d944fe52154544f8f86b160532fd 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/rbtree.h>
 #include <linux/sched.h>
 
@@ -109,7 +110,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
 
 bool regmap_volatile(struct regmap *map, unsigned int reg)
 {
-       if (!regmap_readable(map, reg))
+       if (!map->format.format_write && !regmap_readable(map, reg))
                return false;
 
        if (map->volatile_reg)
@@ -448,6 +449,66 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
 }
 EXPORT_SYMBOL_GPL(regmap_attach_dev);
 
+static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
+                                       const struct regmap_config *config)
+{
+       enum regmap_endian endian;
+
+       /* Retrieve the endianness specification from the regmap config */
+       endian = config->reg_format_endian;
+
+       /* If the regmap config specified a non-default value, use that */
+       if (endian != REGMAP_ENDIAN_DEFAULT)
+               return endian;
+
+       /* Retrieve the endianness specification from the bus config */
+       if (bus && bus->reg_format_endian_default)
+               endian = bus->reg_format_endian_default;
+
+       /* If the bus specified a non-default value, use that */
+       if (endian != REGMAP_ENDIAN_DEFAULT)
+               return endian;
+
+       /* Use this if no other value was found */
+       return REGMAP_ENDIAN_BIG;
+}
+
+static enum regmap_endian regmap_get_val_endian(struct device *dev,
+                                       const struct regmap_bus *bus,
+                                       const struct regmap_config *config)
+{
+       struct device_node *np = dev->of_node;
+       enum regmap_endian endian;
+
+       /* Retrieve the endianness specification from the regmap config */
+       endian = config->val_format_endian;
+
+       /* If the regmap config specified a non-default value, use that */
+       if (endian != REGMAP_ENDIAN_DEFAULT)
+               return endian;
+
+       /* Parse the device's DT node for an endianness specification */
+       if (of_property_read_bool(np, "big-endian"))
+               endian = REGMAP_ENDIAN_BIG;
+       else if (of_property_read_bool(np, "little-endian"))
+               endian = REGMAP_ENDIAN_LITTLE;
+
+       /* If the endianness was specified in DT, use that */
+       if (endian != REGMAP_ENDIAN_DEFAULT)
+               return endian;
+
+       /* Retrieve the endianness specification from the bus config */
+       if (bus && bus->val_format_endian_default)
+               endian = bus->val_format_endian_default;
+
+       /* If the bus specified a non-default value, use that */
+       if (endian != REGMAP_ENDIAN_DEFAULT)
+               return endian;
+
+       /* Use this if no other value was found */
+       return REGMAP_ENDIAN_BIG;
+}
+
 /**
  * regmap_init(): Initialise register map
  *
@@ -551,17 +612,8 @@ struct regmap *regmap_init(struct device *dev,
                map->reg_read  = _regmap_bus_read;
        }
 
-       reg_endian = config->reg_format_endian;
-       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
-               reg_endian = bus->reg_format_endian_default;
-       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
-               reg_endian = REGMAP_ENDIAN_BIG;
-
-       val_endian = config->val_format_endian;
-       if (val_endian == REGMAP_ENDIAN_DEFAULT)
-               val_endian = bus->val_format_endian_default;
-       if (val_endian == REGMAP_ENDIAN_DEFAULT)
-               val_endian = REGMAP_ENDIAN_BIG;
+       reg_endian = regmap_get_reg_endian(bus, config);
+       val_endian = regmap_get_val_endian(dev, bus, config);
 
        switch (config->reg_bits + map->reg_shift) {
        case 2: