aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiubo Li <Li.Xiubo@freescale.com>2014-07-15 00:23:02 -0400
committerMark Brown <broonie@linaro.org>2014-08-16 17:56:23 -0400
commitd647c199510c2c126ac03ecbea51086e10126a40 (patch)
tree5eb1dbbd005c41474dc15d3482d48bc854e0d2f2
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
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 <Li.Xiubo@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-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.c117
3 files changed, 110 insertions, 11 deletions
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 78f43fb2fe84..e4e567e82b84 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,102 @@ 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
452enum regmap_endian_type {
453 REGMAP_ENDIAN_REG,
454 REGMAP_ENDIAN_VAL,
455};
456
457static int of_regmap_get_endian(struct device *dev,
458 const struct regmap_bus *bus,
459 const struct regmap_config *config,
460 enum regmap_endian_type type,
461 enum regmap_endian *endian)
462{
463 struct device_node *np = dev->of_node;
464
465 if (!endian || !config)
466 return -EINVAL;
467
468 /*
469 * Firstly, try to parse the endianness from driver's config,
470 * this is to be compatible with the none DT or the old drivers.
471 * From the driver's config the endianness value maybe:
472 * REGMAP_ENDIAN_BIG,
473 * REGMAP_ENDIAN_LITTLE,
474 * REGMAP_ENDIAN_NATIVE,
475 * REGMAP_ENDIAN_DEFAULT.
476 */
477 switch (type) {
478 case REGMAP_ENDIAN_REG:
479 *endian = config->reg_format_endian;
480 break;
481 case REGMAP_ENDIAN_VAL:
482 *endian = config->val_format_endian;
483 break;
484 default:
485 return -EINVAL;
486 }
487
488 /*
489 * If the endianness parsed from driver config is
490 * REGMAP_ENDIAN_DEFAULT, that means maybe we are using the DT
491 * node to specify the endianness information.
492 */
493 if (*endian != REGMAP_ENDIAN_DEFAULT)
494 return 0;
495
496 /*
497 * Secondly, try to parse the endianness from DT node if the
498 * driver config does not specify it.
499 * From the DT node the endianness value maybe:
500 * REGMAP_ENDIAN_BIG,
501 * REGMAP_ENDIAN_LITTLE,
502 * REGMAP_ENDIAN_NATIVE,
503 */
504 switch (type) {
505 case REGMAP_ENDIAN_VAL:
506 if (of_property_read_bool(np, "big-endian"))
507 *endian = REGMAP_ENDIAN_BIG;
508 else if (of_property_read_bool(np, "little-endian"))
509 *endian = REGMAP_ENDIAN_LITTLE;
510 else
511 *endian = REGMAP_ENDIAN_NATIVE;
512 break;
513 case REGMAP_ENDIAN_REG:
514 break;
515 default:
516 return -EINVAL;
517 }
518
519 /*
520 * If the endianness parsed from DT node is REGMAP_ENDIAN_NATIVE, that
521 * maybe means the DT does not care the endianness or it should use
522 * the regmap bus's default endianness, then we should try to check
523 * whether the regmap bus has specified the default endianness.
524 */
525 if (*endian != REGMAP_ENDIAN_NATIVE)
526 return 0;
527
528 /*
529 * Finally, try to parse the endianness from regmap bus config
530 * if in device's DT node the endianness property is absent.
531 */
532 switch (type) {
533 case REGMAP_ENDIAN_REG:
534 if (bus && bus->reg_format_endian_default)
535 *endian = bus->reg_format_endian_default;
536 break;
537 case REGMAP_ENDIAN_VAL:
538 if (bus && bus->val_format_endian_default)
539 *endian = bus->val_format_endian_default;
540 break;
541 default:
542 return -EINVAL;
543 }
544
545 return 0;
546}
547
451/** 548/**
452 * regmap_init(): Initialise register map 549 * regmap_init(): Initialise register map
453 * 550 *
@@ -551,17 +648,15 @@ struct regmap *regmap_init(struct device *dev,
551 map->reg_read = _regmap_bus_read; 648 map->reg_read = _regmap_bus_read;
552 } 649 }
553 650
554 reg_endian = config->reg_format_endian; 651 ret = of_regmap_get_endian(dev, bus, config, REGMAP_ENDIAN_REG,
555 if (reg_endian == REGMAP_ENDIAN_DEFAULT) 652 &reg_endian);
556 reg_endian = bus->reg_format_endian_default; 653 if (ret)
557 if (reg_endian == REGMAP_ENDIAN_DEFAULT) 654 return ERR_PTR(ret);
558 reg_endian = REGMAP_ENDIAN_BIG; 655
559 656 ret = of_regmap_get_endian(dev, bus, config, REGMAP_ENDIAN_VAL,
560 val_endian = config->val_format_endian; 657 &val_endian);
561 if (val_endian == REGMAP_ENDIAN_DEFAULT) 658 if (ret)
562 val_endian = bus->val_format_endian_default; 659 return ERR_PTR(ret);
563 if (val_endian == REGMAP_ENDIAN_DEFAULT)
564 val_endian = REGMAP_ENDIAN_BIG;
565 660
566 switch (config->reg_bits + map->reg_shift) { 661 switch (config->reg_bits + map->reg_shift) {
567 case 2: 662 case 2: