diff options
| author | Stephen Warren <swarren@nvidia.com> | 2012-04-16 12:51:00 -0400 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2012-04-18 07:53:13 -0400 |
| commit | 6d4ca1fb467932773da7b808c52f3d7ef4461ba0 (patch) | |
| tree | 6e2055564dc75b2c44a3a41daf6ebfcfce326617 | |
| parent | 2aeefe0233174015aef19dc06aac02a1119a44be (diff) | |
pinctrl: implement devm_pinctrl_get()/put()
These functions allow the driver core to automatically clean up any
allocations made by drivers, thus leading to simplified drivers.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
| -rw-r--r-- | Documentation/driver-model/devres.txt | 4 | ||||
| -rw-r--r-- | Documentation/pinctrl.txt | 48 | ||||
| -rw-r--r-- | drivers/pinctrl/core.c | 56 | ||||
| -rw-r--r-- | include/linux/pinctrl/consumer.h | 44 |
4 files changed, 133 insertions, 19 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 2a596a4fc23e..ef4fa7b423d2 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
| @@ -276,3 +276,7 @@ REGULATOR | |||
| 276 | devm_regulator_get() | 276 | devm_regulator_get() |
| 277 | devm_regulator_put() | 277 | devm_regulator_put() |
| 278 | devm_regulator_bulk_get() | 278 | devm_regulator_bulk_get() |
| 279 | |||
| 280 | PINCTRL | ||
| 281 | devm_pinctrl_get() | ||
| 282 | devm_pinctrl_put() | ||
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 4431c3e727ba..e40f4b4e1977 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt | |||
| @@ -945,13 +945,13 @@ case), we define a mapping like this: | |||
| 945 | The result of grabbing this mapping from the device with something like | 945 | The result of grabbing this mapping from the device with something like |
| 946 | this (see next paragraph): | 946 | this (see next paragraph): |
| 947 | 947 | ||
| 948 | p = pinctrl_get(dev); | 948 | p = devm_pinctrl_get(dev); |
| 949 | s = pinctrl_lookup_state(p, "8bit"); | 949 | s = pinctrl_lookup_state(p, "8bit"); |
| 950 | ret = pinctrl_select_state(p, s); | 950 | ret = pinctrl_select_state(p, s); |
| 951 | 951 | ||
| 952 | or more simply: | 952 | or more simply: |
| 953 | 953 | ||
| 954 | p = pinctrl_get_select(dev, "8bit"); | 954 | p = devm_pinctrl_get_select(dev, "8bit"); |
| 955 | 955 | ||
| 956 | Will be that you activate all the three bottom records in the mapping at | 956 | Will be that you activate all the three bottom records in the mapping at |
| 957 | once. Since they share the same name, pin controller device, function and | 957 | once. Since they share the same name, pin controller device, function and |
| @@ -985,7 +985,7 @@ foo_probe() | |||
| 985 | /* Allocate a state holder named "foo" etc */ | 985 | /* Allocate a state holder named "foo" etc */ |
| 986 | struct foo_state *foo = ...; | 986 | struct foo_state *foo = ...; |
| 987 | 987 | ||
| 988 | foo->p = pinctrl_get(&device); | 988 | foo->p = devm_pinctrl_get(&device); |
| 989 | if (IS_ERR(foo->p)) { | 989 | if (IS_ERR(foo->p)) { |
| 990 | /* FIXME: clean up "foo" here */ | 990 | /* FIXME: clean up "foo" here */ |
| 991 | return PTR_ERR(foo->p); | 991 | return PTR_ERR(foo->p); |
| @@ -993,24 +993,17 @@ foo_probe() | |||
| 993 | 993 | ||
| 994 | foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT); | 994 | foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT); |
| 995 | if (IS_ERR(foo->s)) { | 995 | if (IS_ERR(foo->s)) { |
| 996 | pinctrl_put(foo->p); | ||
| 997 | /* FIXME: clean up "foo" here */ | 996 | /* FIXME: clean up "foo" here */ |
| 998 | return PTR_ERR(s); | 997 | return PTR_ERR(s); |
| 999 | } | 998 | } |
| 1000 | 999 | ||
| 1001 | ret = pinctrl_select_state(foo->s); | 1000 | ret = pinctrl_select_state(foo->s); |
| 1002 | if (ret < 0) { | 1001 | if (ret < 0) { |
| 1003 | pinctrl_put(foo->p); | ||
| 1004 | /* FIXME: clean up "foo" here */ | 1002 | /* FIXME: clean up "foo" here */ |
| 1005 | return ret; | 1003 | return ret; |
| 1006 | } | 1004 | } |
| 1007 | } | 1005 | } |
| 1008 | 1006 | ||
| 1009 | foo_remove() | ||
| 1010 | { | ||
| 1011 | pinctrl_put(state->p); | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | This get/lookup/select/put sequence can just as well be handled by bus drivers | 1007 | This get/lookup/select/put sequence can just as well be handled by bus drivers |
| 1015 | if you don't want each and every driver to handle it and you know the | 1008 | if you don't want each and every driver to handle it and you know the |
| 1016 | arrangement on your bus. | 1009 | arrangement on your bus. |
| @@ -1022,6 +1015,11 @@ The semantics of the pinctrl APIs are: | |||
| 1022 | kernel memory to hold the pinmux state. All mapping table parsing or similar | 1015 | kernel memory to hold the pinmux state. All mapping table parsing or similar |
| 1023 | slow operations take place within this API. | 1016 | slow operations take place within this API. |
| 1024 | 1017 | ||
| 1018 | - devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put() | ||
| 1019 | to be called automatically on the retrieved pointer when the associated | ||
| 1020 | device is removed. It is recommended to use this function over plain | ||
| 1021 | pinctrl_get(). | ||
| 1022 | |||
| 1025 | - pinctrl_lookup_state() is called in process context to obtain a handle to a | 1023 | - pinctrl_lookup_state() is called in process context to obtain a handle to a |
| 1026 | specific state for a the client device. This operation may be slow too. | 1024 | specific state for a the client device. This operation may be slow too. |
| 1027 | 1025 | ||
| @@ -1034,14 +1032,25 @@ The semantics of the pinctrl APIs are: | |||
| 1034 | 1032 | ||
| 1035 | - pinctrl_put() frees all information associated with a pinctrl handle. | 1033 | - pinctrl_put() frees all information associated with a pinctrl handle. |
| 1036 | 1034 | ||
| 1035 | - devm_pinctrl_put() is a variant of pinctrl_put() that may be used to | ||
| 1036 | explicitly destroy a pinctrl object returned by devm_pinctrl_get(). | ||
| 1037 | However, use of this function will be rare, due to the automatic cleanup | ||
| 1038 | that will occur even without calling it. | ||
| 1039 | |||
| 1040 | pinctrl_get() must be paired with a plain pinctrl_put(). | ||
| 1041 | pinctrl_get() may not be paired with devm_pinctrl_put(). | ||
| 1042 | devm_pinctrl_get() can optionally be paired with devm_pinctrl_put(). | ||
| 1043 | devm_pinctrl_get() may not be paired with plain pinctrl_put(). | ||
| 1044 | |||
| 1037 | Usually the pin control core handled the get/put pair and call out to the | 1045 | Usually the pin control core handled the get/put pair and call out to the |
| 1038 | device drivers bookkeeping operations, like checking available functions and | 1046 | device drivers bookkeeping operations, like checking available functions and |
| 1039 | the associated pins, whereas the enable/disable pass on to the pin controller | 1047 | the associated pins, whereas the enable/disable pass on to the pin controller |
| 1040 | driver which takes care of activating and/or deactivating the mux setting by | 1048 | driver which takes care of activating and/or deactivating the mux setting by |
| 1041 | quickly poking some registers. | 1049 | quickly poking some registers. |
| 1042 | 1050 | ||
| 1043 | The pins are allocated for your device when you issue the pinctrl_get() call, | 1051 | The pins are allocated for your device when you issue the devm_pinctrl_get() |
| 1044 | after this you should be able to see this in the debugfs listing of all pins. | 1052 | call, after this you should be able to see this in the debugfs listing of all |
| 1053 | pins. | ||
| 1045 | 1054 | ||
| 1046 | NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the | 1055 | NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the |
| 1047 | requested pinctrl handles, for example if the pinctrl driver has not yet | 1056 | requested pinctrl handles, for example if the pinctrl driver has not yet |
| @@ -1092,13 +1101,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B: | |||
| 1092 | 1101 | ||
| 1093 | #include <linux/pinctrl/consumer.h> | 1102 | #include <linux/pinctrl/consumer.h> |
| 1094 | 1103 | ||
| 1095 | foo_switch() | 1104 | struct pinctrl *p; |
| 1096 | { | 1105 | struct pinctrl_state *s1, *s2; |
| 1097 | struct pinctrl *p; | ||
| 1098 | struct pinctrl_state *s1, *s2; | ||
| 1099 | 1106 | ||
| 1107 | foo_probe() | ||
| 1108 | { | ||
| 1100 | /* Setup */ | 1109 | /* Setup */ |
| 1101 | p = pinctrl_get(&device); | 1110 | p = devm_pinctrl_get(&device); |
| 1102 | if (IS_ERR(p)) | 1111 | if (IS_ERR(p)) |
| 1103 | ... | 1112 | ... |
| 1104 | 1113 | ||
| @@ -1109,7 +1118,10 @@ foo_switch() | |||
| 1109 | s2 = pinctrl_lookup_state(foo->p, "pos-B"); | 1118 | s2 = pinctrl_lookup_state(foo->p, "pos-B"); |
| 1110 | if (IS_ERR(s2)) | 1119 | if (IS_ERR(s2)) |
| 1111 | ... | 1120 | ... |
| 1121 | } | ||
| 1112 | 1122 | ||
| 1123 | foo_switch() | ||
| 1124 | { | ||
| 1113 | /* Enable on position A */ | 1125 | /* Enable on position A */ |
| 1114 | ret = pinctrl_select_state(s1); | 1126 | ret = pinctrl_select_state(s1); |
| 1115 | if (ret < 0) | 1127 | if (ret < 0) |
| @@ -1123,8 +1135,6 @@ foo_switch() | |||
| 1123 | ... | 1135 | ... |
| 1124 | 1136 | ||
| 1125 | ... | 1137 | ... |
| 1126 | |||
| 1127 | pinctrl_put(p); | ||
| 1128 | } | 1138 | } |
| 1129 | 1139 | ||
| 1130 | The above has to be done from process context. | 1140 | The above has to be done from process context. |
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 59027ab8347a..2eaa1876534b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/sysfs.h> | 23 | #include <linux/sysfs.h> |
| 24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
| 25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
| 26 | #include <linux/pinctrl/consumer.h> | ||
| 26 | #include <linux/pinctrl/pinctrl.h> | 27 | #include <linux/pinctrl/pinctrl.h> |
| 27 | #include <linux/pinctrl/machine.h> | 28 | #include <linux/pinctrl/machine.h> |
| 28 | #include "core.h" | 29 | #include "core.h" |
| @@ -801,6 +802,61 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state) | |||
| 801 | } | 802 | } |
| 802 | EXPORT_SYMBOL_GPL(pinctrl_select_state); | 803 | EXPORT_SYMBOL_GPL(pinctrl_select_state); |
| 803 | 804 | ||
| 805 | static void devm_pinctrl_release(struct device *dev, void *res) | ||
| 806 | { | ||
| 807 | pinctrl_put(*(struct pinctrl **)res); | ||
| 808 | } | ||
| 809 | |||
| 810 | /** | ||
| 811 | * struct devm_pinctrl_get() - Resource managed pinctrl_get() | ||
| 812 | * @dev: the device to obtain the handle for | ||
| 813 | * | ||
| 814 | * If there is a need to explicitly destroy the returned struct pinctrl, | ||
| 815 | * devm_pinctrl_put() should be used, rather than plain pinctrl_put(). | ||
| 816 | */ | ||
| 817 | struct pinctrl *devm_pinctrl_get(struct device *dev) | ||
| 818 | { | ||
| 819 | struct pinctrl **ptr, *p; | ||
| 820 | |||
| 821 | ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL); | ||
| 822 | if (!ptr) | ||
| 823 | return ERR_PTR(-ENOMEM); | ||
| 824 | |||
| 825 | p = pinctrl_get(dev); | ||
| 826 | if (!IS_ERR(p)) { | ||
| 827 | *ptr = p; | ||
| 828 | devres_add(dev, ptr); | ||
| 829 | } else { | ||
| 830 | devres_free(ptr); | ||
| 831 | } | ||
| 832 | |||
| 833 | return p; | ||
| 834 | } | ||
| 835 | EXPORT_SYMBOL_GPL(devm_pinctrl_get); | ||
| 836 | |||
| 837 | static int devm_pinctrl_match(struct device *dev, void *res, void *data) | ||
| 838 | { | ||
| 839 | struct pinctrl **p = res; | ||
| 840 | |||
| 841 | return *p == data; | ||
| 842 | } | ||
| 843 | |||
| 844 | /** | ||
| 845 | * devm_pinctrl_put() - Resource managed pinctrl_put() | ||
| 846 | * @p: the pinctrl handle to release | ||
| 847 | * | ||
| 848 | * Deallocate a struct pinctrl obtained via devm_pinctrl_get(). Normally | ||
| 849 | * this function will not need to be called and the resource management | ||
| 850 | * code will ensure that the resource is freed. | ||
| 851 | */ | ||
| 852 | void devm_pinctrl_put(struct pinctrl *p) | ||
| 853 | { | ||
| 854 | WARN_ON(devres_destroy(p->dev, devm_pinctrl_release, | ||
| 855 | devm_pinctrl_match, p)); | ||
| 856 | pinctrl_put(p); | ||
| 857 | } | ||
| 858 | EXPORT_SYMBOL_GPL(devm_pinctrl_put); | ||
| 859 | |||
| 804 | int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, | 860 | int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, |
| 805 | bool dup, bool locked) | 861 | bool dup, bool locked) |
| 806 | { | 862 | { |
diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 191e72688481..6dd96fb45482 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h | |||
| @@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state( | |||
| 36 | const char *name); | 36 | const char *name); |
| 37 | extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s); | 37 | extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s); |
| 38 | 38 | ||
| 39 | extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev); | ||
| 40 | extern void devm_pinctrl_put(struct pinctrl *p); | ||
| 41 | |||
| 39 | #else /* !CONFIG_PINCTRL */ | 42 | #else /* !CONFIG_PINCTRL */ |
| 40 | 43 | ||
| 41 | static inline int pinctrl_request_gpio(unsigned gpio) | 44 | static inline int pinctrl_request_gpio(unsigned gpio) |
| @@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p, | |||
| 79 | return 0; | 82 | return 0; |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 85 | static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev) | ||
| 86 | { | ||
| 87 | return NULL; | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline void devm_pinctrl_put(struct pinctrl *p) | ||
| 91 | { | ||
| 92 | } | ||
| 93 | |||
| 82 | #endif /* CONFIG_PINCTRL */ | 94 | #endif /* CONFIG_PINCTRL */ |
| 83 | 95 | ||
| 84 | static inline struct pinctrl * __must_check pinctrl_get_select( | 96 | static inline struct pinctrl * __must_check pinctrl_get_select( |
| @@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default( | |||
| 113 | return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT); | 125 | return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT); |
| 114 | } | 126 | } |
| 115 | 127 | ||
| 128 | static inline struct pinctrl * __must_check devm_pinctrl_get_select( | ||
| 129 | struct device *dev, const char *name) | ||
| 130 | { | ||
| 131 | struct pinctrl *p; | ||
| 132 | struct pinctrl_state *s; | ||
| 133 | int ret; | ||
| 134 | |||
| 135 | p = devm_pinctrl_get(dev); | ||
| 136 | if (IS_ERR(p)) | ||
| 137 | return p; | ||
| 138 | |||
| 139 | s = pinctrl_lookup_state(p, name); | ||
| 140 | if (IS_ERR(s)) { | ||
| 141 | devm_pinctrl_put(p); | ||
| 142 | return ERR_PTR(PTR_ERR(s)); | ||
| 143 | } | ||
| 144 | |||
| 145 | ret = pinctrl_select_state(p, s); | ||
| 146 | if (ret < 0) { | ||
| 147 | devm_pinctrl_put(p); | ||
| 148 | return ERR_PTR(ret); | ||
| 149 | } | ||
| 150 | |||
| 151 | return p; | ||
| 152 | } | ||
| 153 | |||
| 154 | static inline struct pinctrl * __must_check devm_pinctrl_get_select_default( | ||
| 155 | struct device *dev) | ||
| 156 | { | ||
| 157 | return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT); | ||
| 158 | } | ||
| 159 | |||
| 116 | #ifdef CONFIG_PINCONF | 160 | #ifdef CONFIG_PINCONF |
| 117 | 161 | ||
| 118 | extern int pin_config_get(const char *dev_name, const char *name, | 162 | extern int pin_config_get(const char *dev_name, const char *name, |
