2014-07-15 04:22:20

by Xiubo Li

[permalink] [raw]
Subject: [PATCHv5 0/2] add DT endianness binding support for regmap

Changes in V5:
- remove the register's dt endianness support for it will always be BE
for now.
- only support the register values buffers dt endianness support.



Xiubo Li (2):
regmap: add DT endianness binding support.
dt/bindings: Add the DT binding documentation for endianness

.../devicetree/bindings/regmap/regmap.txt | 48 +++++++++
drivers/base/regmap/regmap-i2c.c | 2 +
drivers/base/regmap/regmap-spi.c | 2 +
drivers/base/regmap/regmap.c | 117 +++++++++++++++++++--
4 files changed, 158 insertions(+), 11 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regmap/regmap.txt

--
1.8.5


2014-07-15 04:22:28

by Xiubo Li

[permalink] [raw]
Subject: [PATCHv5 1/2] regmap: add DT endianness binding support.

For many drivers which will support rich endianness of Devices
need define DT properties by itself with the binding support.

The endianness using regmap:
Index Device Properties if needs bytes-swap,
or just ignore it
-------------------------------------------------------------
1 BE 'big-endian'
2 LE 'little-endian'

The properties include all the register values and the buffers.
And these properties are very usful for the MMIO devices:

Such as: a memory-mapped device, on one SoC is in BE mode, while
in another SoC will be in LE mode, and the CPU will always in LE
mode.

For the first case, we must use cpu_to_be32/be32_to_cpu for
32-bit registers accessing, so the 'big-endian' property is needed.

For the second case, we can just ignore the bytes-swap
functions like cpu_to_le32/le32_to_cpu, so the 'little-endian'
property could be abscent.

And vice versa...

Signed-off-by: Xiubo Li <[email protected]>
---
drivers/base/regmap/regmap-i2c.c | 2 +
drivers/base/regmap/regmap-spi.c | 2 +
drivers/base/regmap/regmap.c | 117 +++++++++++++++++++++++++++++++++++----
3 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index ca193d1..053150a 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -168,6 +168,8 @@ static struct regmap_bus regmap_i2c = {
.write = regmap_i2c_write,
.gather_write = regmap_i2c_gather_write,
.read = regmap_i2c_read,
+ .reg_format_endian_default = REGMAP_ENDIAN_BIG,
+ .val_format_endian_default = REGMAP_ENDIAN_BIG,
};

static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 0eb3097..53d1148 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -109,6 +109,8 @@ static struct regmap_bus regmap_spi = {
.async_alloc = regmap_spi_async_alloc,
.read = regmap_spi_read,
.read_flag_mask = 0x80,
+ .reg_format_endian_default = REGMAP_ENDIAN_BIG,
+ .val_format_endian_default = REGMAP_ENDIAN_BIG,
};

/**
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 74d8c06..c033766 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>

@@ -448,6 +449,102 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
}
EXPORT_SYMBOL_GPL(regmap_attach_dev);

+enum regmap_endian_type {
+ REGMAP_ENDIAN_REG,
+ REGMAP_ENDIAN_VAL,
+};
+
+static int of_regmap_get_endian(struct device *dev,
+ const struct regmap_bus *bus,
+ const struct regmap_config *config,
+ enum regmap_endian_type type,
+ enum regmap_endian *endian)
+{
+ struct device_node *np = dev->of_node;
+
+ if (!endian || !config)
+ return -EINVAL;
+
+ /*
+ * Firstly, try to parse the endianness from driver's config,
+ * this is to be compatible with the none DT or the old drivers.
+ * From the driver's config the endianness value maybe:
+ * REGMAP_ENDIAN_BIG,
+ * REGMAP_ENDIAN_LITTLE,
+ * REGMAP_ENDIAN_NATIVE,
+ * REGMAP_ENDIAN_DEFAULT.
+ */
+ switch (type) {
+ case REGMAP_ENDIAN_REG:
+ *endian = config->reg_format_endian;
+ break;
+ case REGMAP_ENDIAN_VAL:
+ *endian = config->val_format_endian;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * If the endianness parsed from driver config is
+ * REGMAP_ENDIAN_DEFAULT, that means maybe we are using the DT
+ * node to specify the endianness information.
+ */
+ if (*endian != REGMAP_ENDIAN_DEFAULT)
+ return 0;
+
+ /*
+ * Secondly, try to parse the endianness from DT node if the
+ * driver config does not specify it.
+ * From the DT node the endianness value maybe:
+ * REGMAP_ENDIAN_BIG,
+ * REGMAP_ENDIAN_LITTLE,
+ * REGMAP_ENDIAN_NATIVE,
+ */
+ switch (type) {
+ case REGMAP_ENDIAN_VAL:
+ 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;
+ else
+ *endian = REGMAP_ENDIAN_NATIVE;
+ break;
+ case REGMAP_ENDIAN_REG:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * If the endianness parsed from DT node is REGMAP_ENDIAN_NATIVE, that
+ * maybe means the DT does not care the endianness or it should use
+ * the regmap bus's default endianness, then we should try to check
+ * whether the regmap bus has specified the default endianness.
+ */
+ if (*endian != REGMAP_ENDIAN_NATIVE)
+ return 0;
+
+ /*
+ * Finally, try to parse the endianness from regmap bus config
+ * if in device's DT node the endianness property is absent.
+ */
+ switch (type) {
+ case REGMAP_ENDIAN_REG:
+ if (bus && bus->reg_format_endian_default)
+ *endian = bus->reg_format_endian_default;
+ break;
+ case REGMAP_ENDIAN_VAL:
+ if (bus && bus->val_format_endian_default)
+ *endian = bus->val_format_endian_default;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* regmap_init(): Initialise register map
*
@@ -551,17 +648,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_ENDIAN_REG,
+ &reg_endian);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = of_regmap_get_endian(dev, bus, config, REGMAP_ENDIAN_VAL,
+ &val_endian);
+ if (ret)
+ return ERR_PTR(ret);

switch (config->reg_bits + map->reg_shift) {
case 2:
--
1.8.5

2014-07-15 04:29:22

by Xiubo Li

[permalink] [raw]
Subject: RE: [PATCHv5 2/2] dt/bindings: Add the DT binding documentation for endianness

Hi,

Please ignore this V5 patch series.

Thanks,

BRs




> -----Original Message-----
> From: Xiubo Li [mailto:[email protected]]
> Sent: Tuesday, July 15, 2014 12:18 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; Xiubo Li-B47053
> Subject: [PATCHv5 2/2] dt/bindings: Add the DT binding documentation for
> endianness
>
> Device-Tree binding for device endianness
> Index Device Endianness properties
> ---------------------------------------------------
> 1 BE 'big-endian'
> 2 LE 'little-endian'
>
> For one device driver, which will run in different scenarios above
> on different SoCs using the devicetree, we need one way to simplify
> this.
>
> Signed-off-by: Xiubo Li <[email protected]>
> ---
> .../devicetree/bindings/regmap/regmap.txt | 48
> ++++++++++++++++++++++
> 1 file changed, 48 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regmap/regmap.txt
>
> diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt
> b/Documentation/devicetree/bindings/regmap/regmap.txt
> new file mode 100644
> index 0000000..cc5f7f8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regmap/regmap.txt
> @@ -0,0 +1,48 @@
> +Device-Tree binding for device endianness
> +
> +The endianness mode of CPU & Device scenarios:
> +Index CPU Device Endianness properties
> +------------------------------------------------------------
> +1 LE LE -
> +2 LE BE 'big-endian{,-*}'
> +3 BE BE -
> +4 BE LE 'little-endian{,-*}'
> +
> +For one device driver, which will run in different scenarios above
> +on different SoCs using the devicetree, we need one way to simplify
> +this.
> +
> +Required properties:
> +- {big,little}-endian{,-*}: these are boolean properties, if absent
> + meaning that the CPU and the Device are in the same endianness mode.
> +
> +Examples:
> +Scenario 1 : CPU in LE mode & device in LE mode.
> +dev: dev@40031000 {
> + compatible = "name";
> + reg = <0x40031000 0x1000>;
> + ...
> +};
> +
> +Scenario 2 : CPU in LE mode & device in BE mode.
> +dev: dev@40031000 {
> + compatible = "name";
> + reg = <0x40031000 0x1000>;
> + ...
> + big-endian{,-*};
> +};
> +
> +Scenario 3 : CPU in BE mode & device in BE mode.
> +dev: dev@40031000 {
> + compatible = "name";
> + reg = <0x40031000 0x1000>;
> + ...
> +};
> +
> +Scenario 4 : CPU in BE mode & device in LE mode.
> +dev: dev@40031000 {
> + compatible = "name";
> + reg = <0x40031000 0x1000>;
> + ...
> + little-endian{,-*};
> +};
> --
> 1.8.5

2014-07-15 04:36:50

by Xiubo Li

[permalink] [raw]
Subject: [PATCHv5 2/2] dt/bindings: Add the DT binding documentation for endianness

Device-Tree binding for device endianness
Index Device Endianness properties
---------------------------------------------------
1 BE 'big-endian'
2 LE 'little-endian'

For one device driver, which will run in different scenarios above
on different SoCs using the devicetree, we need one way to simplify
this.

Signed-off-by: Xiubo Li <[email protected]>
---
.../devicetree/bindings/regmap/regmap.txt | 48 ++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regmap/regmap.txt

diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt
new file mode 100644
index 0000000..cc5f7f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/regmap/regmap.txt
@@ -0,0 +1,48 @@
+Device-Tree binding for device endianness
+
+The endianness mode of CPU & Device scenarios:
+Index CPU Device Endianness properties
+------------------------------------------------------------
+1 LE LE -
+2 LE BE 'big-endian{,-*}'
+3 BE BE -
+4 BE LE 'little-endian{,-*}'
+
+For one device driver, which will run in different scenarios above
+on different SoCs using the devicetree, we need one way to simplify
+this.
+
+Required properties:
+- {big,little}-endian{,-*}: these are boolean properties, if absent
+ meaning that the CPU and the Device are in the same endianness mode.
+
+Examples:
+Scenario 1 : CPU in LE mode & device in LE mode.
+dev: dev@40031000 {
+ compatible = "name";
+ reg = <0x40031000 0x1000>;
+ ...
+};
+
+Scenario 2 : CPU in LE mode & device in BE mode.
+dev: dev@40031000 {
+ compatible = "name";
+ reg = <0x40031000 0x1000>;
+ ...
+ big-endian{,-*};
+};
+
+Scenario 3 : CPU in BE mode & device in BE mode.
+dev: dev@40031000 {
+ compatible = "name";
+ reg = <0x40031000 0x1000>;
+ ...
+};
+
+Scenario 4 : CPU in BE mode & device in LE mode.
+dev: dev@40031000 {
+ compatible = "name";
+ reg = <0x40031000 0x1000>;
+ ...
+ little-endian{,-*};
+};
--
1.8.5