For many drivers which will support rich endianness of CPU<-->Dev need define DT properties by itself without the binding support. The value endianness using regmap-mmio, for example: Index CPU Device Endianess flag for DT property ------------------------------------------------------------ 1 LE LE - 2 LE BE 'big-endian' 3 BE BE - 4 BE LE 'little-endian' ============ Here add DT endianness binding support will define two string properties of the register and value endiannesses: 'regmap-reg-endian' and 'regmap-val-endian'. And the value of them will be: 'le' : REGMAP_ENDIAN_LITTLE 'be' : REGMAP_ENDIAN_BIG 'native' : REGMAP_ENDIAN_NATIVE Absent : REGMAP_ENDIAN_DEFAULT The value endianness for regmap-mmio, for example: Index CPU Device Endianess flag for DT property ------------------------------------------------------------ 1 LE LE 'native' or absent 2 LE BE 'be' 3 BE BE 'native' or absent 4 BE LE 'le' Please see the following documetation for detail usage: Documentation/devicetree/bindings/regmap/regmap-endianness.txt Signed-off-by: Xiubo Li <Li.Xiubo@xxxxxxxxxxxxx> --- drivers/base/regmap/regmap.c | 96 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 11 deletions(-) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 8e8cea1..cfc9302 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -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> @@ -423,6 +424,81 @@ static void regmap_range_exit(struct regmap *map) } /** + * of_regmap_endian_get_by_name() - Parse and lookup the endianness referenced + * by a device node + * @np: pointer to clock consumer node + * @name: name of consumer's endianness input + * + * This function parses the device endianness property, and uses them to + * determine the endianness of the registers and values. + */ +static int of_regmap_endian_get_by_name(struct device_node *np, + const char *endian_name, + enum regmap_endian *out_endian) +{ + const char *endianness; + int ret; + + if (!out_endian) + return -EINVAL; + + /* Set the default endianness */ + *out_endian = REGMAP_ENDIAN_DEFAULT; + + /* Absent or being to use the flag from config of the drivers */ + if (!of_find_property(np, endian_name, NULL)) + return 0; + + ret = of_property_read_string(np, endian_name, &endianness); + if (ret) + return ret; + + if (!strcmp("le", endianness)) + *out_endian = REGMAP_ENDIAN_LITTLE; + else if (!strcmp("be", endianness)) + *out_endian = REGMAP_ENDIAN_BIG; + else if (!strcmp("native", endianness)) + *out_endian = REGMAP_ENDIAN_NATIVE; + + return 0; +} + +static int of_regmap_get_endian(struct device *dev, + const struct regmap_bus *bus, + const struct regmap_config *config, + const char *endian_name, + enum regmap_endian *out_endian) +{ + int ret; + + if (!out_endian) + return -EINVAL; + + if (dev) { + ret = of_regmap_endian_get_by_name(dev->of_node, endian_name, + out_endian); + if (ret < 0) + return ret; + } + + if (*out_endian != REGMAP_ENDIAN_DEFAULT) + return 0; + + /* + * Parsing the endianness from driver's config + * or bus, this is to be compatible with the + * none DT and the old drivers. + */ + *out_endian = config->reg_format_endian; + if (*out_endian == REGMAP_ENDIAN_DEFAULT) + *out_endian = bus->reg_format_endian_default; + if (*out_endian == REGMAP_ENDIAN_DEFAULT) + *out_endian = REGMAP_ENDIAN_BIG; + + return 0; +} + +/** * regmap_init(): Initialise register map * * @dev: Device that will be interacted with @@ -518,17 +594,15 @@ 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; + ret = of_regmap_get_endian(dev, bus, config, "regmap-reg-endian", + ®_endian); + if (ret) + return ERR_PTR(ret); + + ret = of_regmap_get_endian(dev, bus, config, "regmap-val-endian", + &val_endian); + if (ret) + return ERR_PTR(ret); switch (config->reg_bits + map->reg_shift) { case 2: -- 1.8.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html