Skip to content

Commit

Permalink
pinctrl: record a pin owner, not mux function, when requesting pins
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stephen Warren authored and Linus Walleij committed Feb 22, 2012
1 parent b1eed4e commit 3cc70ed
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 41 deletions.
2 changes: 1 addition & 1 deletion drivers/pinctrl/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down
71 changes: 31 additions & 40 deletions drivers/pinctrl/pinmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand All @@ -154,16 +148,16 @@ static int pin_request(struct pinctrl_dev *pctldev,
* @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,
struct pinctrl_gpio_range *gpio_range)
{
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) {
Expand All @@ -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;
}

/**
Expand All @@ -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;
}
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++) {
Expand All @@ -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;
Expand Down

0 comments on commit 3cc70ed

Please sign in to comment.