aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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: