diff options
-rw-r--r-- | drivers/pinctrl/core.c | 120 |
1 files changed, 75 insertions, 45 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index feadf1c31133..50bcc511193e 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * | 7 | * |
8 | * Author: Linus Walleij <linus.walleij@linaro.org> | 8 | * Author: Linus Walleij <linus.walleij@linaro.org> |
9 | * | 9 | * |
10 | * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. | ||
11 | * | ||
10 | * License terms: GNU General Public License (GPL) version 2 | 12 | * License terms: GNU General Public License (GPL) version 2 |
11 | */ | 13 | */ |
12 | #define pr_fmt(fmt) "pinctrl core: " fmt | 14 | #define pr_fmt(fmt) "pinctrl core: " fmt |
@@ -31,6 +33,18 @@ | |||
31 | #include "pinconf.h" | 33 | #include "pinconf.h" |
32 | 34 | ||
33 | /** | 35 | /** |
36 | * struct pinctrl_maps - a list item containing part of the mapping table | ||
37 | * @node: mapping table list node | ||
38 | * @maps: array of mapping table entries | ||
39 | * @num_maps: the number of entries in @maps | ||
40 | */ | ||
41 | struct pinctrl_maps { | ||
42 | struct list_head node; | ||
43 | struct pinctrl_map const *maps; | ||
44 | unsigned num_maps; | ||
45 | }; | ||
46 | |||
47 | /** | ||
34 | * struct pinctrl_hog - a list item to stash control hogs | 48 | * struct pinctrl_hog - a list item to stash control hogs |
35 | * @node: pin control hog list node | 49 | * @node: pin control hog list node |
36 | * @map: map entry responsible for this hogging | 50 | * @map: map entry responsible for this hogging |
@@ -51,8 +65,14 @@ static DEFINE_MUTEX(pinctrl_list_mutex); | |||
51 | static LIST_HEAD(pinctrl_list); | 65 | static LIST_HEAD(pinctrl_list); |
52 | 66 | ||
53 | /* Global pinctrl maps */ | 67 | /* Global pinctrl maps */ |
54 | static struct pinctrl_map *pinctrl_maps; | 68 | static DEFINE_MUTEX(pinctrl_maps_mutex); |
55 | static unsigned pinctrl_maps_num; | 69 | static LIST_HEAD(pinctrl_maps); |
70 | |||
71 | #define for_each_maps(_maps_node_, _i_, _map_) \ | ||
72 | list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ | ||
73 | for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ | ||
74 | _i_ < _maps_node_->num_maps; \ | ||
75 | i++, _map_ = &_maps_node_->maps[_i_]) | ||
56 | 76 | ||
57 | const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) | 77 | const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) |
58 | { | 78 | { |
@@ -454,23 +474,17 @@ int pinctrl_gpio_direction_output(unsigned gpio) | |||
454 | } | 474 | } |
455 | EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); | 475 | EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); |
456 | 476 | ||
457 | /** | 477 | static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name) |
458 | * pinctrl_get() - retrieves the pin controller handle for a certain device | ||
459 | * @dev: the device to get the pin controller handle for | ||
460 | * @name: an optional specific control mapping name or NULL, the name is only | ||
461 | * needed if you want to have more than one mapping per device, or if you | ||
462 | * need an anonymous pin control (not tied to any specific device) | ||
463 | */ | ||
464 | struct pinctrl *pinctrl_get(struct device *dev, const char *name) | ||
465 | { | 478 | { |
466 | struct pinctrl_map const *map = NULL; | ||
467 | struct pinctrl_dev *pctldev = NULL; | 479 | struct pinctrl_dev *pctldev = NULL; |
468 | const char *devname = NULL; | 480 | const char *devname = NULL; |
469 | struct pinctrl *p; | 481 | struct pinctrl *p; |
470 | bool found_map; | 482 | bool found_map; |
471 | unsigned num_maps = 0; | 483 | unsigned num_maps = 0; |
472 | int ret = -ENODEV; | 484 | int ret = -ENODEV; |
485 | struct pinctrl_maps *maps_node; | ||
473 | int i; | 486 | int i; |
487 | struct pinctrl_map const *map; | ||
474 | 488 | ||
475 | /* We must have dev or ID or both */ | 489 | /* We must have dev or ID or both */ |
476 | if (!dev && !name) | 490 | if (!dev && !name) |
@@ -494,8 +508,7 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name) | |||
494 | pinmux_init_pinctrl_handle(p); | 508 | pinmux_init_pinctrl_handle(p); |
495 | 509 | ||
496 | /* Iterate over the pin control maps to locate the right ones */ | 510 | /* Iterate over the pin control maps to locate the right ones */ |
497 | for (i = 0; i < pinctrl_maps_num; i++) { | 511 | for_each_maps(maps_node, i, map) { |
498 | map = &pinctrl_maps[i]; | ||
499 | found_map = false; | 512 | found_map = false; |
500 | 513 | ||
501 | /* | 514 | /* |
@@ -515,7 +528,6 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name) | |||
515 | pr_debug("in map, found pctldev %s to handle function %s", | 528 | pr_debug("in map, found pctldev %s to handle function %s", |
516 | dev_name(pctldev->dev), map->function); | 529 | dev_name(pctldev->dev), map->function); |
517 | 530 | ||
518 | |||
519 | /* | 531 | /* |
520 | * If we're looking for a specific named map, this must match, | 532 | * If we're looking for a specific named map, this must match, |
521 | * else we loop and look for the next. | 533 | * else we loop and look for the next. |
@@ -574,6 +586,24 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name) | |||
574 | 586 | ||
575 | return p; | 587 | return p; |
576 | } | 588 | } |
589 | |||
590 | /** | ||
591 | * pinctrl_get() - retrieves the pin controller handle for a certain device | ||
592 | * @dev: the device to get the pin controller handle for | ||
593 | * @name: an optional specific control mapping name or NULL, the name is only | ||
594 | * needed if you want to have more than one mapping per device, or if you | ||
595 | * need an anonymous pin control (not tied to any specific device) | ||
596 | */ | ||
597 | struct pinctrl *pinctrl_get(struct device *dev, const char *name) | ||
598 | { | ||
599 | struct pinctrl *p; | ||
600 | |||
601 | mutex_lock(&pinctrl_maps_mutex); | ||
602 | p = pinctrl_get_locked(dev, name); | ||
603 | mutex_unlock(&pinctrl_maps_mutex); | ||
604 | |||
605 | return p; | ||
606 | } | ||
577 | EXPORT_SYMBOL_GPL(pinctrl_get); | 607 | EXPORT_SYMBOL_GPL(pinctrl_get); |
578 | 608 | ||
579 | /** | 609 | /** |
@@ -649,8 +679,8 @@ EXPORT_SYMBOL_GPL(pinctrl_disable); | |||
649 | int pinctrl_register_mappings(struct pinctrl_map const *maps, | 679 | int pinctrl_register_mappings(struct pinctrl_map const *maps, |
650 | unsigned num_maps) | 680 | unsigned num_maps) |
651 | { | 681 | { |
652 | void *tmp_maps; | ||
653 | int i; | 682 | int i; |
683 | struct pinctrl_maps *maps_node; | ||
654 | 684 | ||
655 | pr_debug("add %d pinmux maps\n", num_maps); | 685 | pr_debug("add %d pinmux maps\n", num_maps); |
656 | 686 | ||
@@ -684,31 +714,23 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps, | |||
684 | maps[i].function); | 714 | maps[i].function); |
685 | } | 715 | } |
686 | 716 | ||
687 | /* | 717 | maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL); |
688 | * Make a copy of the map array - string pointers will end up in the | 718 | if (!maps_node) { |
689 | * kernel const section anyway so these do not need to be deep copied. | 719 | pr_err("failed to alloc struct pinctrl_maps\n"); |
690 | */ | 720 | return -ENOMEM; |
691 | if (!pinctrl_maps_num) { | 721 | } |
692 | /* On first call, just copy them */ | ||
693 | tmp_maps = kmemdup(maps, | ||
694 | sizeof(struct pinctrl_map) * num_maps, | ||
695 | GFP_KERNEL); | ||
696 | if (!tmp_maps) | ||
697 | return -ENOMEM; | ||
698 | } else { | ||
699 | /* Subsequent calls, reallocate array to new size */ | ||
700 | size_t oldsize = sizeof(struct pinctrl_map) * pinctrl_maps_num; | ||
701 | size_t newsize = sizeof(struct pinctrl_map) * num_maps; | ||
702 | 722 | ||
703 | tmp_maps = krealloc(pinctrl_maps, | 723 | maps_node->num_maps = num_maps; |
704 | oldsize + newsize, GFP_KERNEL); | 724 | maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL); |
705 | if (!tmp_maps) | 725 | if (!maps_node->maps) { |
706 | return -ENOMEM; | 726 | kfree(maps_node); |
707 | memcpy((tmp_maps + oldsize), maps, newsize); | 727 | return -ENOMEM; |
708 | } | 728 | } |
709 | 729 | ||
710 | pinctrl_maps = tmp_maps; | 730 | mutex_lock(&pinctrl_maps_mutex); |
711 | pinctrl_maps_num += num_maps; | 731 | list_add_tail(&maps_node->node, &pinctrl_maps); |
732 | mutex_unlock(&pinctrl_maps_mutex); | ||
733 | |||
712 | return 0; | 734 | return 0; |
713 | } | 735 | } |
714 | 736 | ||
@@ -724,7 +746,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev, | |||
724 | if (!hog) | 746 | if (!hog) |
725 | return -ENOMEM; | 747 | return -ENOMEM; |
726 | 748 | ||
727 | p = pinctrl_get(pctldev->dev, map->name); | 749 | p = pinctrl_get_locked(pctldev->dev, map->name); |
728 | if (IS_ERR(p)) { | 750 | if (IS_ERR(p)) { |
729 | kfree(hog); | 751 | kfree(hog); |
730 | dev_err(pctldev->dev, | 752 | dev_err(pctldev->dev, |
@@ -768,23 +790,28 @@ int pinctrl_hog_maps(struct pinctrl_dev *pctldev) | |||
768 | struct device *dev = pctldev->dev; | 790 | struct device *dev = pctldev->dev; |
769 | const char *devname = dev_name(dev); | 791 | const char *devname = dev_name(dev); |
770 | int ret; | 792 | int ret; |
793 | struct pinctrl_maps *maps_node; | ||
771 | int i; | 794 | int i; |
795 | struct pinctrl_map const *map; | ||
772 | 796 | ||
773 | INIT_LIST_HEAD(&pctldev->pinctrl_hogs); | 797 | INIT_LIST_HEAD(&pctldev->pinctrl_hogs); |
774 | mutex_init(&pctldev->pinctrl_hogs_lock); | 798 | mutex_init(&pctldev->pinctrl_hogs_lock); |
775 | 799 | ||
776 | for (i = 0; i < pinctrl_maps_num; i++) { | 800 | mutex_lock(&pinctrl_maps_mutex); |
777 | struct pinctrl_map const *map = &pinctrl_maps[i]; | 801 | for_each_maps(maps_node, i, map) { |
778 | |||
779 | if (map->ctrl_dev_name && | 802 | if (map->ctrl_dev_name && |
780 | !strcmp(map->ctrl_dev_name, devname) && | 803 | !strcmp(map->ctrl_dev_name, devname) && |
781 | !strcmp(map->dev_name, devname)) { | 804 | !strcmp(map->dev_name, devname)) { |
782 | /* OK time to hog! */ | 805 | /* OK time to hog! */ |
783 | ret = pinctrl_hog_map(pctldev, map); | 806 | ret = pinctrl_hog_map(pctldev, map); |
784 | if (ret) | 807 | if (ret) { |
808 | mutex_unlock(&pinctrl_maps_mutex); | ||
785 | return ret; | 809 | return ret; |
810 | } | ||
786 | } | 811 | } |
787 | } | 812 | } |
813 | mutex_unlock(&pinctrl_maps_mutex); | ||
814 | |||
788 | return 0; | 815 | return 0; |
789 | } | 816 | } |
790 | 817 | ||
@@ -900,13 +927,14 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what) | |||
900 | 927 | ||
901 | static int pinctrl_maps_show(struct seq_file *s, void *what) | 928 | static int pinctrl_maps_show(struct seq_file *s, void *what) |
902 | { | 929 | { |
930 | struct pinctrl_maps *maps_node; | ||
903 | int i; | 931 | int i; |
932 | struct pinctrl_map const *map; | ||
904 | 933 | ||
905 | seq_puts(s, "Pinctrl maps:\n"); | 934 | seq_puts(s, "Pinctrl maps:\n"); |
906 | 935 | ||
907 | for (i = 0; i < pinctrl_maps_num; i++) { | 936 | mutex_lock(&pinctrl_maps_mutex); |
908 | struct pinctrl_map const *map = &pinctrl_maps[i]; | 937 | for_each_maps(maps_node, i, map) { |
909 | |||
910 | seq_printf(s, "%s:\n", map->name); | 938 | seq_printf(s, "%s:\n", map->name); |
911 | if (map->dev_name) | 939 | if (map->dev_name) |
912 | seq_printf(s, " device: %s\n", | 940 | seq_printf(s, " device: %s\n", |
@@ -919,6 +947,8 @@ static int pinctrl_maps_show(struct seq_file *s, void *what) | |||
919 | seq_printf(s, " group: %s\n", map->group ? map->group : | 947 | seq_printf(s, " group: %s\n", map->group ? map->group : |
920 | "(default)"); | 948 | "(default)"); |
921 | } | 949 | } |
950 | mutex_unlock(&pinctrl_maps_mutex); | ||
951 | |||
922 | return 0; | 952 | return 0; |
923 | } | 953 | } |
924 | 954 | ||