diff options
| -rw-r--r-- | drivers/base/regmap/regmap-i2c.c | 2 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-spi.c | 2 | ||||
| -rw-r--r-- | 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 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 | ||
| 173 | static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, | 175 | 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 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 | } |
| 449 | EXPORT_SYMBOL_GPL(regmap_attach_dev); | 450 | EXPORT_SYMBOL_GPL(regmap_attach_dev); |
| 450 | 451 | ||
| 452 | enum regmap_endian_type { | ||
| 453 | REGMAP_ENDIAN_REG, | ||
| 454 | REGMAP_ENDIAN_VAL, | ||
| 455 | }; | ||
| 456 | |||
| 457 | static 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 | ®_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: |
