diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-03-02 15:05:46 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-03-05 05:21:46 -0500 |
commit | 0e3db173e2b9fd3b82246516e72c17763eb5f98d (patch) | |
tree | ce00c29c56332c925766f7f793d388b9670d802f /drivers/pinctrl/pinmux.c | |
parent | 7ecdb16fe63e5b356335ebdc236adfb48cef31e1 (diff) |
pinctrl: add usecount to pins for muxing
Multiple mapping table entries could reference the same pin, and hence
"own" it. This would be unusual now that pinctrl_get() represents a single
state for a client device, but in the future when it represents all known
states for a device, this is quite likely. Implement reference counting
for pin ownership to handle this.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Dong Aisheng <dong.aisheng@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
-rw-r--r-- | drivers/pinctrl/pinmux.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f0fb98d252e8..56ca42e6a6ec 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -83,11 +83,16 @@ static int pin_request(struct pinctrl_dev *pctldev, | |||
83 | goto out; | 83 | goto out; |
84 | } | 84 | } |
85 | 85 | ||
86 | if (desc->owner && strcmp(desc->owner, owner)) { | 86 | if (desc->usecount && strcmp(desc->owner, owner)) { |
87 | dev_err(pctldev->dev, | 87 | dev_err(pctldev->dev, |
88 | "pin already requested\n"); | 88 | "pin already requested\n"); |
89 | goto out; | 89 | goto out; |
90 | } | 90 | } |
91 | |||
92 | desc->usecount++; | ||
93 | if (desc->usecount > 1) | ||
94 | return 0; | ||
95 | |||
91 | desc->owner = owner; | 96 | desc->owner = owner; |
92 | 97 | ||
93 | /* Let each pin increase references to this module */ | 98 | /* Let each pin increase references to this module */ |
@@ -111,12 +116,18 @@ static int pin_request(struct pinctrl_dev *pctldev, | |||
111 | else | 116 | else |
112 | status = 0; | 117 | status = 0; |
113 | 118 | ||
114 | if (status) | 119 | if (status) { |
115 | dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", | 120 | dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", |
116 | pctldev->desc->name, pin); | 121 | pctldev->desc->name, pin); |
122 | module_put(pctldev->owner); | ||
123 | } | ||
124 | |||
117 | out_free_pin: | 125 | out_free_pin: |
118 | if (status) | 126 | if (status) { |
119 | desc->owner = NULL; | 127 | desc->usecount--; |
128 | if (!desc->usecount) | ||
129 | desc->owner = NULL; | ||
130 | } | ||
120 | out: | 131 | out: |
121 | if (status) | 132 | if (status) |
122 | dev_err(pctldev->dev, "pin-%d (%s) status %d\n", | 133 | dev_err(pctldev->dev, "pin-%d (%s) status %d\n", |
@@ -150,6 +161,10 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
150 | return NULL; | 161 | return NULL; |
151 | } | 162 | } |
152 | 163 | ||
164 | desc->usecount--; | ||
165 | if (desc->usecount) | ||
166 | return NULL; | ||
167 | |||
153 | /* | 168 | /* |
154 | * If there is no kind of request function for the pin we just assume | 169 | * If there is no kind of request function for the pin we just assume |
155 | * we got it by default and proceed. | 170 | * we got it by default and proceed. |