pinctrl: add usecount to pins for muxing
authorStephen Warren <swarren@nvidia.com>
Fri, 2 Mar 2012 20:05:46 +0000 (13:05 -0700)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 5 Mar 2012 10:21:46 +0000 (11:21 +0100)
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>
drivers/pinctrl/core.h
drivers/pinctrl/pinmux.c

index 5f258b7..0bc52ec 100644 (file)
@@ -82,7 +82,14 @@ 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;
@@ -90,6 +97,7 @@ struct pin_desc {
        bool dynamic_name;
        /* These fields only added when supporting pinmux drivers */
 #ifdef CONFIG_PINMUX
+       unsigned usecount;
        const char *owner;
 #endif
 };
index f0fb98d..56ca42e 100644 (file)
@@ -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 */
@@ -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",
@@ -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.