Skip to content

Commit

Permalink
pinctrl: add usecount to pins for muxing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
nvswarren authored and linusw committed Mar 5, 2012
1 parent 7ecdb16 commit 0e3db17
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 5 deletions.
10 changes: 9 additions & 1 deletion drivers/pinctrl/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,22 @@ struct pinctrl_setting {
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a
* datasheet or such
* @dynamic_name: if the name of this pin was dynamically allocated
* @owner: the device holding this pin or NULL of no device has claimed it
* @usecount: If zero, the pin is not claimed, and @owner should be NULL.
* If non-zero, this pin is claimed by @owner. This field is an integer
* rather than a boolean, since pinctrl_get() might process multiple
* mapping table entries that refer to, and hence claim, the same group
* or pin, and each of these will increment the @usecount.
* @owner: The name of the entity owning the pin. Typically, this is the name
* of the device that called pinctrl_get(). Alternatively, it may be the
* name of the GPIO passed to pinctrl_request_gpio().
*/
struct pin_desc {
struct pinctrl_dev *pctldev;
const char *name;
bool dynamic_name;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
unsigned usecount;
const char *owner;
#endif
};
Expand Down
23 changes: 19 additions & 4 deletions drivers/pinctrl/pinmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,16 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out;
}

if (desc->owner && strcmp(desc->owner, owner)) {
if (desc->usecount && strcmp(desc->owner, owner)) {
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}

desc->usecount++;
if (desc->usecount > 1)
return 0;

desc->owner = owner;

/* Let each pin increase references to this module */
Expand All @@ -111,12 +116,18 @@ static int pin_request(struct pinctrl_dev *pctldev,
else
status = 0;

if (status)
if (status) {
dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
module_put(pctldev->owner);
}

out_free_pin:
if (status)
desc->owner = NULL;
if (status) {
desc->usecount--;
if (!desc->usecount)
desc->owner = NULL;
}
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
Expand Down Expand Up @@ -150,6 +161,10 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
return NULL;
}

desc->usecount--;
if (desc->usecount)
return NULL;

/*
* If there is no kind of request function for the pin we just assume
* we got it by default and proceed.
Expand Down

0 comments on commit 0e3db17

Please sign in to comment.