diff options
author | Tony Lindgren <tony@atomide.com> | 2016-12-27 12:20:01 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-01-03 03:26:18 -0500 |
commit | a76edc89b100e4fefb2a5c00cd8cd557437659e7 (patch) | |
tree | 0131d6cad80d2ed78c97b485b0a2d9cf2a446877 /drivers/pinctrl/pinmux.c | |
parent | c033a718f615b6b3ddc83ce3e0a217c30bd09cb5 (diff) |
pinctrl: core: Add generic pinctrl functions for managing groups
We can add generic helpers for function handling for cases where the pin
controller driver does not need to use static arrays.
Signed-off-by: Tony Lindgren <tony@atomide.com>
[Renamed the Kconfig item and moved things around]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
-rw-r--r-- | drivers/pinctrl/pinmux.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 9373146f3afc..29ad3151abec 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -682,3 +682,176 @@ void pinmux_init_device_debugfs(struct dentry *devroot, | |||
682 | } | 682 | } |
683 | 683 | ||
684 | #endif /* CONFIG_DEBUG_FS */ | 684 | #endif /* CONFIG_DEBUG_FS */ |
685 | |||
686 | #ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS | ||
687 | |||
688 | /** | ||
689 | * pinmux_generic_get_function_count() - returns number of functions | ||
690 | * @pctldev: pin controller device | ||
691 | */ | ||
692 | int pinmux_generic_get_function_count(struct pinctrl_dev *pctldev) | ||
693 | { | ||
694 | return pctldev->num_functions; | ||
695 | } | ||
696 | EXPORT_SYMBOL_GPL(pinmux_generic_get_function_count); | ||
697 | |||
698 | /** | ||
699 | * pinmux_generic_get_function_name() - returns the function name | ||
700 | * @pctldev: pin controller device | ||
701 | * @selector: function number | ||
702 | */ | ||
703 | const char * | ||
704 | pinmux_generic_get_function_name(struct pinctrl_dev *pctldev, | ||
705 | unsigned int selector) | ||
706 | { | ||
707 | struct function_desc *function; | ||
708 | |||
709 | function = radix_tree_lookup(&pctldev->pin_function_tree, | ||
710 | selector); | ||
711 | if (!function) | ||
712 | return NULL; | ||
713 | |||
714 | return function->name; | ||
715 | } | ||
716 | EXPORT_SYMBOL_GPL(pinmux_generic_get_function_name); | ||
717 | |||
718 | /** | ||
719 | * pinmux_generic_get_function_groups() - gets the function groups | ||
720 | * @pctldev: pin controller device | ||
721 | * @selector: function number | ||
722 | * @groups: array of pin groups | ||
723 | * @num_groups: number of pin groups | ||
724 | */ | ||
725 | int pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev, | ||
726 | unsigned int selector, | ||
727 | const char * const **groups, | ||
728 | unsigned * const num_groups) | ||
729 | { | ||
730 | struct function_desc *function; | ||
731 | |||
732 | function = radix_tree_lookup(&pctldev->pin_function_tree, | ||
733 | selector); | ||
734 | if (!function) { | ||
735 | dev_err(pctldev->dev, "%s could not find function%i\n", | ||
736 | __func__, selector); | ||
737 | return -EINVAL; | ||
738 | } | ||
739 | *groups = function->group_names; | ||
740 | *num_groups = function->num_group_names; | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | EXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups); | ||
745 | |||
746 | /** | ||
747 | * pinmux_generic_get_function() - returns a function based on the number | ||
748 | * @pctldev: pin controller device | ||
749 | * @group_selector: function number | ||
750 | */ | ||
751 | struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev, | ||
752 | unsigned int selector) | ||
753 | { | ||
754 | struct function_desc *function; | ||
755 | |||
756 | function = radix_tree_lookup(&pctldev->pin_function_tree, | ||
757 | selector); | ||
758 | if (!function) | ||
759 | return NULL; | ||
760 | |||
761 | return function; | ||
762 | } | ||
763 | EXPORT_SYMBOL_GPL(pinmux_generic_get_function); | ||
764 | |||
765 | /** | ||
766 | * pinmux_generic_get_function_groups() - gets the function groups | ||
767 | * @pctldev: pin controller device | ||
768 | * @name: name of the function | ||
769 | * @groups: array of pin groups | ||
770 | * @num_groups: number of pin groups | ||
771 | * @data: pin controller driver specific data | ||
772 | */ | ||
773 | int pinmux_generic_add_function(struct pinctrl_dev *pctldev, | ||
774 | const char *name, | ||
775 | const char **groups, | ||
776 | const unsigned int num_groups, | ||
777 | void *data) | ||
778 | { | ||
779 | struct function_desc *function; | ||
780 | |||
781 | function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL); | ||
782 | if (!function) | ||
783 | return -ENOMEM; | ||
784 | |||
785 | function->name = name; | ||
786 | function->group_names = groups; | ||
787 | function->num_group_names = num_groups; | ||
788 | function->data = data; | ||
789 | |||
790 | radix_tree_insert(&pctldev->pin_function_tree, pctldev->num_functions, | ||
791 | function); | ||
792 | |||
793 | pctldev->num_functions++; | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | EXPORT_SYMBOL_GPL(pinmux_generic_add_function); | ||
798 | |||
799 | /** | ||
800 | * pinmux_generic_remove_function() - removes a numbered function | ||
801 | * @pctldev: pin controller device | ||
802 | * @selector: function number | ||
803 | * | ||
804 | * Note that the caller must take care of locking. | ||
805 | */ | ||
806 | int pinmux_generic_remove_function(struct pinctrl_dev *pctldev, | ||
807 | unsigned int selector) | ||
808 | { | ||
809 | struct function_desc *function; | ||
810 | |||
811 | function = radix_tree_lookup(&pctldev->pin_function_tree, | ||
812 | selector); | ||
813 | if (!function) | ||
814 | return -ENOENT; | ||
815 | |||
816 | radix_tree_delete(&pctldev->pin_function_tree, selector); | ||
817 | devm_kfree(pctldev->dev, function); | ||
818 | |||
819 | pctldev->num_functions--; | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | EXPORT_SYMBOL_GPL(pinmux_generic_remove_function); | ||
824 | |||
825 | /** | ||
826 | * pinmux_generic_free_functions() - removes all functions | ||
827 | * @pctldev: pin controller device | ||
828 | * | ||
829 | * Note that the caller must take care of locking. | ||
830 | */ | ||
831 | void pinmux_generic_free_functions(struct pinctrl_dev *pctldev) | ||
832 | { | ||
833 | struct radix_tree_iter iter; | ||
834 | struct function_desc *function; | ||
835 | unsigned long *indices; | ||
836 | void **slot; | ||
837 | int i = 0; | ||
838 | |||
839 | indices = devm_kzalloc(pctldev->dev, sizeof(*indices) * | ||
840 | pctldev->num_functions, GFP_KERNEL); | ||
841 | if (!indices) | ||
842 | return; | ||
843 | |||
844 | radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0) | ||
845 | indices[i++] = iter.index; | ||
846 | |||
847 | for (i = 0; i < pctldev->num_functions; i++) { | ||
848 | function = radix_tree_lookup(&pctldev->pin_function_tree, | ||
849 | indices[i]); | ||
850 | radix_tree_delete(&pctldev->pin_function_tree, indices[i]); | ||
851 | devm_kfree(pctldev->dev, function); | ||
852 | } | ||
853 | |||
854 | pctldev->num_functions = 0; | ||
855 | } | ||
856 | |||
857 | #endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */ | ||