diff options
| author | Mark Brown <broonie@kernel.org> | 2014-09-29 15:49:42 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2014-09-29 15:49:42 -0400 |
| commit | 45942c310da8eadc603e7d2332897909c1da4b70 (patch) | |
| tree | 40ef6d2a4ac4d1a676d3c8e4b7a91460896bd7e2 | |
| parent | 88507a2ba8b453a38b950f3ccb2cae6cc4d82e7a (diff) | |
| parent | 6e64b6ccc1e46932768e3bb8974fc2e5589bca7a (diff) | |
Merge remote-tracking branch 'regmap/topic/dt-endian' into regmap-next
| -rw-r--r-- | Documentation/devicetree/bindings/regmap/regmap.txt | 47 | ||||
| -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 | 79 |
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 @@ | |||
| 1 | Device-Tree binding for regmap | ||
| 2 | |||
| 3 | The endianness mode of CPU & Device scenarios: | ||
| 4 | Index Device Endianness properties | ||
| 5 | --------------------------------------------------- | ||
| 6 | 1 BE 'big-endian' | ||
| 7 | 2 LE 'little-endian' | ||
| 8 | |||
| 9 | For one device driver, which will run in different scenarios above | ||
| 10 | on different SoCs using the devicetree, we need one way to simplify | ||
| 11 | this. | ||
| 12 | |||
| 13 | Required 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 | |||
| 18 | Examples: | ||
| 19 | Scenario 1 : CPU in LE mode & device in LE mode. | ||
| 20 | dev: dev@40031000 { | ||
| 21 | compatible = "name"; | ||
| 22 | reg = <0x40031000 0x1000>; | ||
| 23 | ... | ||
| 24 | }; | ||
| 25 | |||
| 26 | Scenario 2 : CPU in LE mode & device in BE mode. | ||
| 27 | dev: dev@40031000 { | ||
| 28 | compatible = "name"; | ||
| 29 | reg = <0x40031000 0x1000>; | ||
| 30 | ... | ||
| 31 | big-endian; | ||
| 32 | }; | ||
| 33 | |||
| 34 | Scenario 3 : CPU in BE mode & device in BE mode. | ||
| 35 | dev: dev@40031000 { | ||
| 36 | compatible = "name"; | ||
| 37 | reg = <0x40031000 0x1000>; | ||
| 38 | ... | ||
| 39 | }; | ||
| 40 | |||
| 41 | Scenario 4 : CPU in BE mode & device in LE mode. | ||
| 42 | dev: 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 | ||
| 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 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 | } |
| 449 | EXPORT_SYMBOL_GPL(regmap_attach_dev); | 450 | EXPORT_SYMBOL_GPL(regmap_attach_dev); |
| 450 | 451 | ||
| 452 | static 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 | |||
| 476 | static 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: |
