aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-08-27 17:07:01 -0400
committerMark Brown <broonie@linaro.org>2014-08-27 17:07:01 -0400
commit6ba42ba608df1e243d594a682073e783a57c95f5 (patch)
tree5b52ddf4d71f57d366af5f69ef2761164d355b68
parentc99428d035908b9c0b8be452f9b091bc5e090256 (diff)
parentcf673fbc6342b1c2310cdfdc4ed99f18f866b8e4 (diff)
Merge tag 'dt-endian' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into spi-fsl-dspi
regmap: Device tree endianness support This adds generic support for specifying endianess for register map in the DT.
-rw-r--r--drivers/base/regmap/regmap.c143
1 files changed, 50 insertions, 93 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index e4e567e82b84..01ae4b829360 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -449,100 +449,64 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
449} 449}
450EXPORT_SYMBOL_GPL(regmap_attach_dev); 450EXPORT_SYMBOL_GPL(regmap_attach_dev);
451 451
452enum regmap_endian_type { 452static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
453 REGMAP_ENDIAN_REG, 453 const struct regmap_config *config)
454 REGMAP_ENDIAN_VAL, 454{
455}; 455 enum regmap_endian endian;
456 456
457static int of_regmap_get_endian(struct device *dev, 457 /* Retrieve the endianness specification from the regmap config */
458 const struct regmap_bus *bus, 458 endian = config->reg_format_endian;
459 const struct regmap_config *config, 459
460 enum regmap_endian_type type, 460 /* If the regmap config specified a non-default value, use that */
461 enum regmap_endian *endian) 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)
462{ 479{
463 struct device_node *np = dev->of_node; 480 struct device_node *np = dev->of_node;
481 enum regmap_endian endian;
464 482
465 if (!endian || !config) 483 /* Retrieve the endianness specification from the regmap config */
466 return -EINVAL; 484 endian = config->val_format_endian;
467 485
468 /* 486 /* If the regmap config specified a non-default value, use that */
469 * Firstly, try to parse the endianness from driver's config, 487 if (endian != REGMAP_ENDIAN_DEFAULT)
470 * this is to be compatible with the none DT or the old drivers. 488 return endian;
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 489
488 /* 490 /* Parse the device's DT node for an endianness specification */
489 * If the endianness parsed from driver config is 491 if (of_property_read_bool(np, "big-endian"))
490 * REGMAP_ENDIAN_DEFAULT, that means maybe we are using the DT 492 endian = REGMAP_ENDIAN_BIG;
491 * node to specify the endianness information. 493 else if (of_property_read_bool(np, "little-endian"))
492 */ 494 endian = REGMAP_ENDIAN_LITTLE;
493 if (*endian != REGMAP_ENDIAN_DEFAULT)
494 return 0;
495 495
496 /* 496 /* If the endianness was specified in DT, use that */
497 * Secondly, try to parse the endianness from DT node if the 497 if (endian != REGMAP_ENDIAN_DEFAULT)
498 * driver config does not specify it. 498 return endian;
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 499
519 /* 500 /* Retrieve the endianness specification from the bus config */
520 * If the endianness parsed from DT node is REGMAP_ENDIAN_NATIVE, that 501 if (bus && bus->val_format_endian_default)
521 * maybe means the DT does not care the endianness or it should use 502 endian = bus->val_format_endian_default;
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 503
528 /* 504 /* If the bus specified a non-default value, use that */
529 * Finally, try to parse the endianness from regmap bus config 505 if (endian != REGMAP_ENDIAN_DEFAULT)
530 * if in device's DT node the endianness property is absent. 506 return endian;
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 507
545 return 0; 508 /* Use this if no other value was found */
509 return REGMAP_ENDIAN_BIG;
546} 510}
547 511
548/** 512/**
@@ -648,15 +612,8 @@ struct regmap *regmap_init(struct device *dev,
648 map->reg_read = _regmap_bus_read; 612 map->reg_read = _regmap_bus_read;
649 } 613 }
650 614
651 ret = of_regmap_get_endian(dev, bus, config, REGMAP_ENDIAN_REG, 615 reg_endian = regmap_get_reg_endian(bus, config);
652 &reg_endian); 616 val_endian = regmap_get_val_endian(dev, bus, config);
653 if (ret)
654 return ERR_PTR(ret);
655
656 ret = of_regmap_get_endian(dev, bus, config, REGMAP_ENDIAN_VAL,
657 &val_endian);
658 if (ret)
659 return ERR_PTR(ret);
660 617
661 switch (config->reg_bits + map->reg_shift) { 618 switch (config->reg_bits + map->reg_shift) {
662 case 2: 619 case 2: