diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-03-05 19:22:15 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-03-12 17:43:09 -0400 |
commit | 652162d469a73450a66b6c8049b16c2b7828fa24 (patch) | |
tree | 4df09c6e5e370a4bd73569503d1a124599871db5 /drivers/pinctrl | |
parent | a6c3b33f02c799db69a3cd82545e45e9df3d69ca (diff) |
pinctrl: allow concurrent gpio and mux function ownership of pins
Per recent updates to Documentation/gpio.txt, gpiolib drivers should
inform pinctrl when a GPIO is requested. pinctrl then marks that pin as
in-use for that GPIO function.
When an SoC muxes pins in a group, it's quite possible for the group to
contain e.g. 6 pins, but only 4 of them actually be needed by the HW
module that's mux'd to them. In this case, the other 2 pins could be
used as GPIOs. However, pinctrl marks all the pins within the group as
in-use by the selected mux function. To allow the expected gpiolib
interaction, separate the concepts of pin ownership into two parts: One
for the mux function and one for GPIO usage. Finally, allow those two
ownerships to exist in parallel.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/core.h | 13 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.c | 72 |
2 files changed, 56 insertions, 29 deletions
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index efbfb62ab147..17ecf651b123 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -119,15 +119,15 @@ struct pinctrl_setting { | |||
119 | * @name: a name for the pin, e.g. the name of the pin/pad/finger on a | 119 | * @name: a name for the pin, e.g. the name of the pin/pad/finger on a |
120 | * datasheet or such | 120 | * datasheet or such |
121 | * @dynamic_name: if the name of this pin was dynamically allocated | 121 | * @dynamic_name: if the name of this pin was dynamically allocated |
122 | * @usecount: If zero, the pin is not claimed, and @owner should be NULL. | 122 | * @mux_usecount: If zero, the pin is not claimed, and @owner should be NULL. |
123 | * If non-zero, this pin is claimed by @owner. This field is an integer | 123 | * If non-zero, this pin is claimed by @owner. This field is an integer |
124 | * rather than a boolean, since pinctrl_get() might process multiple | 124 | * rather than a boolean, since pinctrl_get() might process multiple |
125 | * mapping table entries that refer to, and hence claim, the same group | 125 | * mapping table entries that refer to, and hence claim, the same group |
126 | * or pin, and each of these will increment the @usecount. | 126 | * or pin, and each of these will increment the @usecount. |
127 | * @owner: The name of the entity owning the pin. Typically, this is the name | 127 | * @mux_owner: The name of device that called pinctrl_get(). |
128 | * of the device that called pinctrl_get(). Alternatively, it may be the | ||
129 | * name of the GPIO passed to pinctrl_request_gpio(). | ||
130 | * @mux_setting: The most recent selected mux setting for this pin, if any. | 128 | * @mux_setting: The most recent selected mux setting for this pin, if any. |
129 | * @gpio_owner: If pinctrl_request_gpio() was called for this pin, this is | ||
130 | * the name of the GPIO that "owns" this pin. | ||
131 | */ | 131 | */ |
132 | struct pin_desc { | 132 | struct pin_desc { |
133 | struct pinctrl_dev *pctldev; | 133 | struct pinctrl_dev *pctldev; |
@@ -135,9 +135,10 @@ struct pin_desc { | |||
135 | bool dynamic_name; | 135 | bool dynamic_name; |
136 | /* These fields only added when supporting pinmux drivers */ | 136 | /* These fields only added when supporting pinmux drivers */ |
137 | #ifdef CONFIG_PINMUX | 137 | #ifdef CONFIG_PINMUX |
138 | unsigned usecount; | 138 | unsigned mux_usecount; |
139 | const char *owner; | 139 | const char *mux_owner; |
140 | const struct pinctrl_setting_mux *mux_setting; | 140 | const struct pinctrl_setting_mux *mux_setting; |
141 | const char *gpio_owner; | ||
141 | #endif | 142 | #endif |
142 | }; | 143 | }; |
143 | 144 | ||
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 86e401754116..4e62783a573a 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -94,17 +94,28 @@ static int pin_request(struct pinctrl_dev *pctldev, | |||
94 | goto out; | 94 | goto out; |
95 | } | 95 | } |
96 | 96 | ||
97 | if (desc->usecount && strcmp(desc->owner, owner)) { | 97 | if (gpio_range) { |
98 | dev_err(pctldev->dev, | 98 | /* There's no need to support multiple GPIO requests */ |
99 | "pin already requested\n"); | 99 | if (desc->gpio_owner) { |
100 | goto out; | 100 | dev_err(pctldev->dev, |
101 | } | 101 | "pin already requested\n"); |
102 | goto out; | ||
103 | } | ||
102 | 104 | ||
103 | desc->usecount++; | 105 | desc->gpio_owner = owner; |
104 | if (desc->usecount > 1) | 106 | } else { |
105 | return 0; | 107 | if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) { |
108 | dev_err(pctldev->dev, | ||
109 | "pin already requested\n"); | ||
110 | goto out; | ||
111 | } | ||
106 | 112 | ||
107 | desc->owner = owner; | 113 | desc->mux_usecount++; |
114 | if (desc->mux_usecount > 1) | ||
115 | return 0; | ||
116 | |||
117 | desc->mux_owner = owner; | ||
118 | } | ||
108 | 119 | ||
109 | /* Let each pin increase references to this module */ | 120 | /* Let each pin increase references to this module */ |
110 | if (!try_module_get(pctldev->owner)) { | 121 | if (!try_module_get(pctldev->owner)) { |
@@ -135,9 +146,13 @@ static int pin_request(struct pinctrl_dev *pctldev, | |||
135 | 146 | ||
136 | out_free_pin: | 147 | out_free_pin: |
137 | if (status) { | 148 | if (status) { |
138 | desc->usecount--; | 149 | if (gpio_range) { |
139 | if (!desc->usecount) | 150 | desc->gpio_owner = NULL; |
140 | desc->owner = NULL; | 151 | } else { |
152 | desc->mux_usecount--; | ||
153 | if (!desc->mux_usecount) | ||
154 | desc->mux_owner = NULL; | ||
155 | } | ||
141 | } | 156 | } |
142 | out: | 157 | out: |
143 | if (status) | 158 | if (status) |
@@ -172,9 +187,11 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
172 | return NULL; | 187 | return NULL; |
173 | } | 188 | } |
174 | 189 | ||
175 | desc->usecount--; | 190 | if (!gpio_range) { |
176 | if (desc->usecount) | 191 | desc->mux_usecount--; |
177 | return NULL; | 192 | if (desc->mux_usecount) |
193 | return NULL; | ||
194 | } | ||
178 | 195 | ||
179 | /* | 196 | /* |
180 | * If there is no kind of request function for the pin we just assume | 197 | * If there is no kind of request function for the pin we just assume |
@@ -185,9 +202,15 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
185 | else if (ops->free) | 202 | else if (ops->free) |
186 | ops->free(pctldev, pin); | 203 | ops->free(pctldev, pin); |
187 | 204 | ||
188 | owner = desc->owner; | 205 | if (gpio_range) { |
189 | desc->owner = NULL; | 206 | owner = desc->gpio_owner; |
190 | desc->mux_setting = NULL; | 207 | desc->gpio_owner = NULL; |
208 | } else { | ||
209 | owner = desc->mux_owner; | ||
210 | desc->mux_owner = NULL; | ||
211 | desc->mux_setting = NULL; | ||
212 | } | ||
213 | |||
191 | module_put(pctldev->owner); | 214 | module_put(pctldev->owner); |
192 | 215 | ||
193 | return owner; | 216 | return owner; |
@@ -493,7 +516,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what) | |||
493 | unsigned i, pin; | 516 | unsigned i, pin; |
494 | 517 | ||
495 | seq_puts(s, "Pinmux settings per pin\n"); | 518 | seq_puts(s, "Pinmux settings per pin\n"); |
496 | seq_puts(s, "Format: pin (name): owner\n"); | 519 | seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n"); |
497 | 520 | ||
498 | mutex_lock(&pinctrl_mutex); | 521 | mutex_lock(&pinctrl_mutex); |
499 | 522 | ||
@@ -508,13 +531,16 @@ static int pinmux_pins_show(struct seq_file *s, void *what) | |||
508 | if (desc == NULL) | 531 | if (desc == NULL) |
509 | continue; | 532 | continue; |
510 | 533 | ||
511 | if (desc->owner && | 534 | if (desc->mux_owner && |
512 | !strcmp(desc->owner, pinctrl_dev_get_name(pctldev))) | 535 | !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev))) |
513 | is_hog = true; | 536 | is_hog = true; |
514 | 537 | ||
515 | seq_printf(s, "pin %d (%s): %s%s", pin, | 538 | seq_printf(s, "pin %d (%s): %s %s%s", pin, |
516 | desc->name ? desc->name : "unnamed", | 539 | desc->name ? desc->name : "unnamed", |
517 | desc->owner ? desc->owner : "UNCLAIMED", | 540 | desc->mux_owner ? desc->mux_owner |
541 | : "(MUX UNCLAIMED)", | ||
542 | desc->gpio_owner ? desc->gpio_owner | ||
543 | : "(GPIO UNCLAIMED)", | ||
518 | is_hog ? " (HOG)" : ""); | 544 | is_hog ? " (HOG)" : ""); |
519 | 545 | ||
520 | if (desc->mux_setting) | 546 | if (desc->mux_setting) |