Commit fa76a3db authored by Sonic Zhang's avatar Sonic Zhang Committed by Linus Walleij

pinctrl: allow exlusive GPIO/mux pin allocation

Disallow simultaneous use of the the GPIO and peripheral mux
functions by setting a flag "strict" in struct pinctrl_desc.

The blackfin pinmux and gpio controller doesn't allow user to
set up a pin for both GPIO and peripheral function. So, add flag
strict in struct pinctrl_desc to check both gpio_owner and
mux_owner before approving the pin request.

v2-changes:
- if strict flag is set, check gpio_owner and mux_onwer in if and
  else clause

v3-changes:
- add kerneldoc for this struct
- augment Documentation/pinctrl.txt
Signed-off-by: default avatarSonic Zhang <sonic.zhang@analog.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent c30024a6
...@@ -73,6 +73,7 @@ static struct pinctrl_desc foo_desc = { ...@@ -73,6 +73,7 @@ static struct pinctrl_desc foo_desc = {
.pins = foo_pins, .pins = foo_pins,
.npins = ARRAY_SIZE(foo_pins), .npins = ARRAY_SIZE(foo_pins),
.owner = THIS_MODULE, .owner = THIS_MODULE,
.strict = true,
}; };
int __init foo_probe(void) int __init foo_probe(void)
...@@ -830,6 +831,11 @@ separate memory range only intended for GPIO driving, and the register ...@@ -830,6 +831,11 @@ separate memory range only intended for GPIO driving, and the register
range dealing with pin config and pin multiplexing get placed into a range dealing with pin config and pin multiplexing get placed into a
different memory range and a separate section of the data sheet. different memory range and a separate section of the data sheet.
A flag "strict" in struct pinctrl_desc is available to check and deny
simultaneous access to the same pin from GPIO and pin multiplexing
consumers on hardware of this type. The pinctrl driver should set this flag
accordingly.
(B) (B)
pin config pin config
...@@ -850,6 +856,11 @@ possible that the GPIO, pin config and pin multiplex registers are placed into ...@@ -850,6 +856,11 @@ possible that the GPIO, pin config and pin multiplex registers are placed into
the same memory range and the same section of the data sheet, although that the same memory range and the same section of the data sheet, although that
need not be the case. need not be the case.
In some pin controllers, although the physical pins are designed in the same
way as (B), the GPIO function still can't be enabled at the same time as the
peripheral functions. So again the "strict" flag should be set, denying
simultaneous activation by GPIO and other muxed in devices.
From a kernel point of view, however, these are different aspects of the From a kernel point of view, however, these are different aspects of the
hardware and shall be put into different subsystems: hardware and shall be put into different subsystems:
......
...@@ -710,6 +710,7 @@ static struct pinctrl_desc adi_pinmux_desc = { ...@@ -710,6 +710,7 @@ static struct pinctrl_desc adi_pinmux_desc = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pctlops = &adi_pctrl_ops, .pctlops = &adi_pctrl_ops,
.pmxops = &adi_pinmux_ops, .pmxops = &adi_pinmux_ops,
.strict = true,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -107,6 +107,13 @@ static int pin_request(struct pinctrl_dev *pctldev, ...@@ -107,6 +107,13 @@ static int pin_request(struct pinctrl_dev *pctldev,
desc->name, desc->gpio_owner, owner); desc->name, desc->gpio_owner, owner);
goto out; goto out;
} }
if (pctldev->desc->strict && desc->mux_usecount &&
strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
desc->gpio_owner = owner; desc->gpio_owner = owner;
} else { } else {
...@@ -116,6 +123,12 @@ static int pin_request(struct pinctrl_dev *pctldev, ...@@ -116,6 +123,12 @@ static int pin_request(struct pinctrl_dev *pctldev,
desc->name, desc->mux_owner, owner); desc->name, desc->mux_owner, owner);
goto out; goto out;
} }
if (pctldev->desc->strict && desc->gpio_owner) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->gpio_owner, owner);
goto out;
}
desc->mux_usecount++; desc->mux_usecount++;
if (desc->mux_usecount > 1) if (desc->mux_usecount > 1)
......
...@@ -114,6 +114,8 @@ struct pinctrl_ops { ...@@ -114,6 +114,8 @@ struct pinctrl_ops {
* of the pins field above * of the pins field above
* @pctlops: pin control operation vtable, to support global concepts like * @pctlops: pin control operation vtable, to support global concepts like
* grouping of pins, this is optional. * grouping of pins, this is optional.
* @strict: check both gpio_owner and mux_owner strictly before approving
the pin request
* @pmxops: pinmux operations vtable, if you support pinmuxing in your driver * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver
* @confops: pin config operations vtable, if you support pin configuration in * @confops: pin config operations vtable, if you support pin configuration in
* your driver * your driver
...@@ -132,6 +134,7 @@ struct pinctrl_desc { ...@@ -132,6 +134,7 @@ struct pinctrl_desc {
const struct pinctrl_ops *pctlops; const struct pinctrl_ops *pctlops;
const struct pinmux_ops *pmxops; const struct pinmux_ops *pmxops;
const struct pinconf_ops *confops; const struct pinconf_ops *confops;
bool strict;
struct module *owner; struct module *owner;
#ifdef CONFIG_GENERIC_PINCONF #ifdef CONFIG_GENERIC_PINCONF
unsigned int num_custom_params; unsigned int num_custom_params;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment