aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2014-09-29 15:49:42 -0400
committerMark Brown <broonie@kernel.org>2014-09-29 15:49:42 -0400
commit45942c310da8eadc603e7d2332897909c1da4b70 (patch)
tree40ef6d2a4ac4d1a676d3c8e4b7a91460896bd7e2
parent88507a2ba8b453a38b950f3ccb2cae6cc4d82e7a (diff)
parent6e64b6ccc1e46932768e3bb8974fc2e5589bca7a (diff)
Merge remote-tracking branch 'regmap/topic/dt-endian' into regmap-next
-rw-r--r--Documentation/devicetree/bindings/regmap/regmap.txt47
-rw-r--r--drivers/base/regmap/regmap-i2c.c2
-rw-r--r--drivers/base/regmap/regmap-spi.c2
-rw-r--r--drivers/base/regmap/regmap.c79
4 files changed, 119 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt
new file mode 100644
index 000000000000..b494f8b8ef72
--- /dev/null
+++ b/Documentation/devicetree/bindings/regmap/regmap.txt
@@ -0,0 +1,47 @@
1Device-Tree binding for regmap
2
3The endianness mode of CPU & Device scenarios:
4Index Device Endianness properties
5---------------------------------------------------
61 BE 'big-endian'
72 LE 'little-endian'
8
9For one device driver, which will run in different scenarios above
10on different SoCs using the devicetree, we need one way to simplify
11this.
12
13Required properties:
14- {big,little}-endian: these are boolean properties, if absent
15 meaning that the CPU and the Device are in the same endianness mode,
16 these properties are for register values and all the buffers only.
17
18Examples:
19Scenario 1 : CPU in LE mode & device in LE mode.
20dev: dev@40031000 {
21 compatible = "name";
22 reg = <0x40031000 0x1000>;
23 ...
24};
25
26Scenario 2 : CPU in LE mode & device in BE mode.
27dev: dev@40031000 {
28 compatible = "name";
29 reg = <0x40031000 0x1000>;
30 ...
31 big-endian;
32};
33
34Scenario 3 : CPU in BE mode & device in BE mode.
35dev: dev@40031000 {
36 compatible = "name";
37 reg = <0x40031000 0x1000>;
38 ...
39};
40
41Scenario 4 : CPU in BE mode & device in LE mode.
42dev: dev@40031000 {
43 compatible = "name";
44 reg = <0x40031000 0x1000>;
45 ...
46 little-endian;
47};
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index ca193d1ef47c..053150a7f9f2 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 = {
168 .write = regmap_i2c_write, 168 .write = regmap_i2c_write,
169 .gather_write = regmap_i2c_gather_write, 169 .gather_write = regmap_i2c_gather_write,
170 .read = regmap_i2c_read, 170 .read = regmap_i2c_read,
171 .reg_format_endian_default = REGMAP_ENDIAN_BIG,
172 .val_format_endian_default = REGMAP_ENDIAN_BIG,
171}; 173};
172 174
173static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, 175static 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 0eb3097c0d76..53d1148e80a0 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 = {
109 .async_alloc = regmap_spi_async_alloc, 109 .async_alloc = regmap_spi_async_alloc,
110 .read = regmap_spi_read, 110 .read = regmap_spi_read,
111 .read_flag_mask = 0x80, 111 .read_flag_mask = 0x80,
112 .reg_format_endian_default = REGMAP_ENDIAN_BIG,
113 .val_format_endian_default = REGMAP_ENDIAN_BIG,
112}; 114};
113 115
114/** 116/**
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3a785a4f4ff6..d2f8a818d200 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -15,6 +15,7 @@
15#include <linux/export.h> 15#include <linux/export.h>
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/of.h>
18#include <linux/rbtree.h> 19#include <linux/rbtree.h>
19#include <linux/sched.h> 20#include <linux/sched.h>
20 21
@@ -448,6 +449,71 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
448} 449}
449EXPORT_SYMBOL_GPL(regmap_attach_dev); 450EXPORT_SYMBOL_GPL(regmap_attach_dev);
450 451
452static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
453 const struct regmap_config *config)
454{
455 enum regmap_endian endian;
456
457 /* Retrieve the endianness specification from the regmap config */
458 endian = config->reg_format_endian;
459
460 /* If the regmap config specified a non-default value, use that */
461 if (endian != REGMAP_ENDIAN_DEFAULT)
462 return endian;
463
464 /* Retrieve the endianness specification from the bus config */
465 if (bus && bus->reg_format_endian_default)
466 endian = bus->reg_format_endian_default;
467
468 /* If the bus specified a non-default value, use that */
469 if (endian != REGMAP_ENDIAN_DEFAULT)
470 return endian;
471
472 /* Use this if no other value was found */
473 return REGMAP_ENDIAN_BIG;
474}
475
476static enum regmap_endian regmap_get_val_endian(struct device *dev,
477 const struct regmap_bus *bus,
478 const struct regmap_config *config)
479{
480 struct device_node *np;
481 enum regmap_endian endian;
482
483 /* Retrieve the endianness specification from the regmap config */
484 endian = config->val_format_endian;
485
486 /* If the regmap config specified a non-default value, use that */
487 if (endian != REGMAP_ENDIAN_DEFAULT)
488 return endian;
489
490 /* If the dev and dev->of_node exist try to get endianness from DT */
491 if (dev && dev->of_node) {
492 np = dev->of_node;
493
494 /* Parse the device's DT node for an endianness specification */
495 if (of_property_read_bool(np, "big-endian"))
496 endian = REGMAP_ENDIAN_BIG;
497 else if (of_property_read_bool(np, "little-endian"))
498 endian = REGMAP_ENDIAN_LITTLE;
499
500 /* If the endianness was specified in DT, use that */
501 if (endian != REGMAP_ENDIAN_DEFAULT)
502 return endian;
503 }
504
505 /* Retrieve the endianness specification from the bus config */
506 if (bus && bus->val_format_endian_default)
507 endian = bus->val_format_endian_default;
508
509 /* If the bus specified a non-default value, use that */
510 if (endian != REGMAP_ENDIAN_DEFAULT)
511 return endian;
512
513 /* Use this if no other value was found */
514 return REGMAP_ENDIAN_BIG;
515}
516
451/** 517/**
452 * regmap_init(): Initialise register map 518 * regmap_init(): Initialise register map
453 * 519 *
@@ -551,17 +617,8 @@ struct regmap *regmap_init(struct device *dev,
551 map->reg_read = _regmap_bus_read; 617 map->reg_read = _regmap_bus_read;
552 } 618 }
553 619
554 reg_endian = config->reg_format_endian; 620 reg_endian = regmap_get_reg_endian(bus, config);
555 if (reg_endian == REGMAP_ENDIAN_DEFAULT) 621 val_endian = regmap_get_val_endian(dev, bus, config);
556 reg_endian = bus->reg_format_endian_default;
557 if (reg_endian == REGMAP_ENDIAN_DEFAULT)
558 reg_endian = REGMAP_ENDIAN_BIG;
559
560 val_endian = config->val_format_endian;
561 if (val_endian == REGMAP_ENDIAN_DEFAULT)
562 val_endian = bus->val_format_endian_default;
563 if (val_endian == REGMAP_ENDIAN_DEFAULT)
564 val_endian = REGMAP_ENDIAN_BIG;
565 622
566 switch (config->reg_bits + map->reg_shift) { 623 switch (config->reg_bits + map->reg_shift) {
567 case 2: 624 case 2: