summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-02-19 23:45:44 -0700
committerLinus Walleij <linus.walleij@linaro.org>2012-02-22 17:59:35 +0100
commit3cc70ed32cd6c5cb57de17bde615148ed7eda88f (patch)
treef9eb9c82c9b5862617cf2bf18a1cb3c96fddc968 /drivers
parentb1eed4ece7064c361d6e03f6706d90e4e9dd7e96 (diff)
pinctrl: record a pin owner, not mux function, when requesting pins
When pins are requested/acquired/got, some device becomes the owner of their mux setting. At this point, it isn't certain which mux function will be selected for the pin, since this may vary between each of the device's states in the pinctrl mapping table. As such, we should record the owning device, not what we think the initial mux setting will be, when requesting pins. This doesn't make a lot of difference right now since pinctrl_get gets only one single device/state combination, but this will make a difference when pinctrl_get gets all states, and pinctrl_select_state can switch between states. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pinctrl/core.h2
-rw-r--r--drivers/pinctrl/pinmux.c71
2 files changed, 32 insertions, 41 deletions
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 7c305672919e..061c57d0e8f9 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -94,7 +94,7 @@ struct pin_desc {
spinlock_t lock;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
- const char *mux_function;
+ const char *owner;
#endif
};
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index ea31c4655667..288789750f96 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -71,21 +71,20 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)
/**
* pin_request() - request a single pin to be muxed in, typically for GPIO
* @pin: the pin number in the global pin space
- * @function: a functional name to give to this pin, passed to the driver
- * so it knows what function to mux in, e.g. the string "gpioNN"
- * means that you want to mux in the pin for use as GPIO number NN
+ * @owner: a representation of the owner of this pin; typically the device
+ * name that controls its mux function, or the requested GPIO name
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*/
static int pin_request(struct pinctrl_dev *pctldev,
- int pin, const char *function,
+ int pin, const char *owner,
struct pinctrl_gpio_range *gpio_range)
{
struct pin_desc *desc;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
- dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, function);
+ dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
@@ -94,19 +93,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out;
}
- if (!function) {
- dev_err(pctldev->dev, "no function name given\n");
- return -EINVAL;
- }
-
spin_lock(&desc->lock);
- if (desc->mux_function) {
+ if (desc->owner && strcmp(desc->owner, owner)) {
spin_unlock(&desc->lock);
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}
- desc->mux_function = function;
+ desc->owner = owner;
spin_unlock(&desc->lock);
/* Let each pin increase references to this module */
@@ -136,13 +130,13 @@ static int pin_request(struct pinctrl_dev *pctldev,
out_free_pin:
if (status) {
spin_lock(&desc->lock);
- desc->mux_function = NULL;
+ desc->owner = NULL;
spin_unlock(&desc->lock);
}
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
- pin, function ? : "?", status);
+ pin, owner, status);
return status;
}
@@ -154,8 +148,8 @@ out:
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*
- * This function returns a pointer to the function name in use. This is used
- * for callers that dynamically allocate a function name so it can be freed
+ * This function returns a pointer to the previous owner. This is used
+ * for callers that dynamically allocate an owner name so it can be freed
* once the pin is free. This is done for GPIO request functions.
*/
static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
@@ -163,7 +157,7 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
struct pin_desc *desc;
- const char *func;
+ const char *owner;
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
@@ -182,12 +176,12 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
ops->free(pctldev, pin);
spin_lock(&desc->lock);
- func = desc->mux_function;
- desc->mux_function = NULL;
+ owner = desc->owner;
+ desc->owner = NULL;
spin_unlock(&desc->lock);
module_put(pctldev->owner);
- return func;
+ return owner;
}
/**
@@ -201,19 +195,19 @@ int pinmux_request_gpio(struct pinctrl_dev *pctldev,
unsigned pin, unsigned gpio)
{
char gpiostr[16];
- const char *function;
+ const char *owner;
int ret;
/* Conjure some name stating what chip and pin this is taken by */
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
- function = kstrdup(gpiostr, GFP_KERNEL);
- if (!function)
+ owner = kstrdup(gpiostr, GFP_KERNEL);
+ if (!owner)
return -EINVAL;
- ret = pin_request(pctldev, pin, function, range);
+ ret = pin_request(pctldev, pin, owner, range);
if (ret < 0)
- kfree(function);
+ kfree(owner);
return ret;
}
@@ -227,10 +221,10 @@ int pinmux_request_gpio(struct pinctrl_dev *pctldev,
void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
struct pinctrl_gpio_range *range)
{
- const char *func;
+ const char *owner;
- func = pin_free(pctldev, pin, range);
- kfree(func);
+ owner = pin_free(pctldev, pin, range);
+ kfree(owner);
}
/**
@@ -260,17 +254,15 @@ int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
/**
* acquire_pins() - acquire all the pins for a certain function on a pinmux
* @pctldev: the device to take the pins on
- * @func_selector: the function selector to acquire the pins for
+ * @owner: a representation of the owner of this pin; typically the device
+ * name that controls its mux function
* @group_selector: the group selector containing the pins to acquire
*/
static int acquire_pins(struct pinctrl_dev *pctldev,
- unsigned func_selector,
+ const char *owner,
unsigned group_selector)
{
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- const char *func = pmxops->get_function_name(pctldev,
- func_selector);
const unsigned *pins;
unsigned num_pins;
int ret;
@@ -286,11 +278,11 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
/* Try to allocate all pins in this group, one by one */
for (i = 0; i < num_pins; i++) {
- ret = pin_request(pctldev, pins[i], func, NULL);
+ ret = pin_request(pctldev, pins[i], owner, NULL);
if (ret) {
dev_err(pctldev->dev,
- "could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
- pins[i], func ? : "(undefined)",
+ "could not get request pin %d on device %s - conflicting mux mappings?\n",
+ pins[i],
pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */
@@ -503,7 +495,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
if (!grp)
return -ENOMEM;
grp->group_selector = group_selector;
- ret = acquire_pins(pctldev, func_selector, group_selector);
+ ret = acquire_pins(pctldev, devname, group_selector);
if (ret) {
kfree(grp);
return ret;
@@ -630,7 +622,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
unsigned i, pin;
seq_puts(s, "Pinmux settings per pin\n");
- seq_puts(s, "Format: pin (name): pinmuxfunction\n");
+ seq_puts(s, "Format: pin (name): owner\n");
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
@@ -645,8 +637,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
seq_printf(s, "pin %d (%s): %s\n", pin,
desc->name ? desc->name : "unnamed",
- desc->mux_function ? desc->mux_function
- : "UNCLAIMED");
+ desc->owner ? desc->owner : "UNCLAIMED");
}
return 0;