pinctrl: GPIO direction support for muxing
When requesting a single GPIO pin to be muxed in, some controllers will need to poke a different value into the control register depending on whether the pin will be used for GPIO output or GPIO input. So create pinmux counterparts to gpio_direction_[input|output] in the pinctrl framework. ChangeLog v1->v2: - This also amends the documentation to make it clear the this function and associated machinery is *ONLY* intended as a backend to gpiolib machinery, not for everyone and his dog to start playing around with pins. ChangeLog v2->v3: - Don't pass an argument to the common request function, instead provide pinmux_* counterparts to the gpio_direction_[input|output] calls, simpler and anyone can understand it. ChangeLog v3->v4: - Fix numerous spelling mistakes and dangling text in documentation. Add Ack and Rewewed-by. Cc: Igor Grinberg <grinberg@compulab.co.il> Acked-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Thomas Abraham <thomas.abraham@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
@@ -645,6 +645,17 @@ All the above functions are mandatory to implement for a pinmux driver.
|
|||||||
Pinmux interaction with the GPIO subsystem
|
Pinmux interaction with the GPIO subsystem
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
|
The public pinmux API contains two functions named pinmux_request_gpio()
|
||||||
|
and pinmux_free_gpio(). These two functions shall *ONLY* be called from
|
||||||
|
gpiolib-based drivers as part of their gpio_request() and
|
||||||
|
gpio_free() semantics. Likewise the pinmux_gpio_direction_[input|output]
|
||||||
|
shall only be called from within respective gpio_direction_[input|output]
|
||||||
|
gpiolib implementation.
|
||||||
|
|
||||||
|
NOTE that platforms and individual drivers shall *NOT* request GPIO pins to be
|
||||||
|
muxed in. Instead, implement a proper gpiolib driver and have that driver
|
||||||
|
request proper muxing for its pins.
|
||||||
|
|
||||||
The function list could become long, especially if you can convert every
|
The function list could become long, especially if you can convert every
|
||||||
individual pin into a GPIO pin independent of any other pins, and then try
|
individual pin into a GPIO pin independent of any other pins, and then try
|
||||||
the approach to define every pin as a function.
|
the approach to define every pin as a function.
|
||||||
@@ -652,19 +663,24 @@ the approach to define every pin as a function.
|
|||||||
In this case, the function array would become 64 entries for each GPIO
|
In this case, the function array would become 64 entries for each GPIO
|
||||||
setting and then the device functions.
|
setting and then the device functions.
|
||||||
|
|
||||||
For this reason there is an additional function a pinmux driver can implement
|
For this reason there are two functions a pinmux driver can implement
|
||||||
to enable only GPIO on an individual pin: .gpio_request_enable(). The same
|
to enable only GPIO on an individual pin: .gpio_request_enable() and
|
||||||
.free() function as for other functions is assumed to be usable also for
|
.gpio_disable_free().
|
||||||
GPIO pins.
|
|
||||||
|
|
||||||
This function will pass in the affected GPIO range identified by the pin
|
This function will pass in the affected GPIO range identified by the pin
|
||||||
controller core, so you know which GPIO pins are being affected by the request
|
controller core, so you know which GPIO pins are being affected by the request
|
||||||
operation.
|
operation.
|
||||||
|
|
||||||
Alternatively it is fully allowed to use named functions for each GPIO
|
If your driver needs to have an indication from the framework of whether the
|
||||||
pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN"
|
GPIO pin shall be used for input or output you can implement the
|
||||||
where "N" is the global GPIO pin number if no special GPIO-handler is
|
.gpio_set_direction() function. As described this shall be called from the
|
||||||
registered.
|
gpiolib driver and the affected GPIO range, pin offset and desired direction
|
||||||
|
will be passed along to this function.
|
||||||
|
|
||||||
|
Alternatively to using these special functions, it is fully allowed to use
|
||||||
|
named functions for each GPIO pin, the pinmux_request_gpio() will attempt to
|
||||||
|
obtain the function "gpioN" where "N" is the global GPIO pin number if no
|
||||||
|
special GPIO-handler is registered.
|
||||||
|
|
||||||
|
|
||||||
Pinmux board/machine configuration
|
Pinmux board/machine configuration
|
||||||
|
@@ -214,6 +214,10 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
|
|||||||
/**
|
/**
|
||||||
* pinmux_request_gpio() - request a single pin to be muxed in as GPIO
|
* pinmux_request_gpio() - request a single pin to be muxed in as GPIO
|
||||||
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
||||||
|
*
|
||||||
|
* This function should *ONLY* be used from gpiolib-based GPIO drivers,
|
||||||
|
* as part of their gpio_request() semantics, platforms and individual drivers
|
||||||
|
* shall *NOT* request GPIO pins to be muxed in.
|
||||||
*/
|
*/
|
||||||
int pinmux_request_gpio(unsigned gpio)
|
int pinmux_request_gpio(unsigned gpio)
|
||||||
{
|
{
|
||||||
@@ -249,6 +253,10 @@ EXPORT_SYMBOL_GPL(pinmux_request_gpio);
|
|||||||
/**
|
/**
|
||||||
* pinmux_free_gpio() - free a single pin, currently used as GPIO
|
* pinmux_free_gpio() - free a single pin, currently used as GPIO
|
||||||
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
||||||
|
*
|
||||||
|
* This function should *ONLY* be used from gpiolib-based GPIO drivers,
|
||||||
|
* as part of their gpio_free() semantics, platforms and individual drivers
|
||||||
|
* shall *NOT* request GPIO pins to be muxed out.
|
||||||
*/
|
*/
|
||||||
void pinmux_free_gpio(unsigned gpio)
|
void pinmux_free_gpio(unsigned gpio)
|
||||||
{
|
{
|
||||||
@@ -270,6 +278,59 @@ void pinmux_free_gpio(unsigned gpio)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pinmux_free_gpio);
|
EXPORT_SYMBOL_GPL(pinmux_free_gpio);
|
||||||
|
|
||||||
|
static int pinmux_gpio_direction(unsigned gpio, bool input)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev;
|
||||||
|
struct pinctrl_gpio_range *range;
|
||||||
|
const struct pinmux_ops *ops;
|
||||||
|
int ret;
|
||||||
|
int pin;
|
||||||
|
|
||||||
|
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ops = pctldev->desc->pmxops;
|
||||||
|
|
||||||
|
/* Convert to the pin controllers number space */
|
||||||
|
pin = gpio - range->base + range->pin_base;
|
||||||
|
|
||||||
|
if (ops->gpio_set_direction)
|
||||||
|
ret = ops->gpio_set_direction(pctldev, range, pin, input);
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pinmux_gpio_direction_input() - request a GPIO pin to go into input mode
|
||||||
|
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
||||||
|
*
|
||||||
|
* This function should *ONLY* be used from gpiolib-based GPIO drivers,
|
||||||
|
* as part of their gpio_direction_input() semantics, platforms and individual
|
||||||
|
* drivers shall *NOT* touch pinmux GPIO calls.
|
||||||
|
*/
|
||||||
|
int pinmux_gpio_direction_input(unsigned gpio)
|
||||||
|
{
|
||||||
|
return pinmux_gpio_direction(gpio, true);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pinmux_gpio_direction_input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pinmux_gpio_direction_output() - request a GPIO pin to go into output mode
|
||||||
|
* @gpio: the GPIO pin number from the GPIO subsystem number space
|
||||||
|
*
|
||||||
|
* This function should *ONLY* be used from gpiolib-based GPIO drivers,
|
||||||
|
* as part of their gpio_direction_output() semantics, platforms and individual
|
||||||
|
* drivers shall *NOT* touch pinmux GPIO calls.
|
||||||
|
*/
|
||||||
|
int pinmux_gpio_direction_output(unsigned gpio)
|
||||||
|
{
|
||||||
|
return pinmux_gpio_direction(gpio, false);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pinmux_register_mappings() - register a set of pinmux mappings
|
* pinmux_register_mappings() - register a set of pinmux mappings
|
||||||
* @maps: the pinmux mappings table to register
|
* @maps: the pinmux mappings table to register
|
||||||
|
@@ -54,7 +54,13 @@ struct pinctrl_dev;
|
|||||||
* Implement this only if you can mux every pin individually as GPIO. The
|
* Implement this only if you can mux every pin individually as GPIO. The
|
||||||
* affected GPIO range is passed along with an offset(pin number) into that
|
* affected GPIO range is passed along with an offset(pin number) into that
|
||||||
* specific GPIO range - function selectors and pin groups are orthogonal
|
* specific GPIO range - function selectors and pin groups are orthogonal
|
||||||
* to this, the core will however make sure the pins do not collide
|
* to this, the core will however make sure the pins do not collide.
|
||||||
|
* @gpio_disable_free: free up GPIO muxing on a certain pin, the reverse of
|
||||||
|
* @gpio_request_enable
|
||||||
|
* @gpio_set_direction: Since controllers may need different configurations
|
||||||
|
* depending on whether the GPIO is configured as input or output,
|
||||||
|
* a direction selector function may be implemented as a backing
|
||||||
|
* to the GPIO controllers that need pin muxing.
|
||||||
*/
|
*/
|
||||||
struct pinmux_ops {
|
struct pinmux_ops {
|
||||||
int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
|
int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
|
||||||
@@ -76,11 +82,17 @@ struct pinmux_ops {
|
|||||||
void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
|
void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
|
||||||
struct pinctrl_gpio_range *range,
|
struct pinctrl_gpio_range *range,
|
||||||
unsigned offset);
|
unsigned offset);
|
||||||
|
int (*gpio_set_direction) (struct pinctrl_dev *pctldev,
|
||||||
|
struct pinctrl_gpio_range *range,
|
||||||
|
unsigned offset,
|
||||||
|
bool input);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* External interface to pinmux */
|
/* External interface to pinmux */
|
||||||
extern int pinmux_request_gpio(unsigned gpio);
|
extern int pinmux_request_gpio(unsigned gpio);
|
||||||
extern void pinmux_free_gpio(unsigned gpio);
|
extern void pinmux_free_gpio(unsigned gpio);
|
||||||
|
extern int pinmux_gpio_direction_input(unsigned gpio);
|
||||||
|
extern int pinmux_gpio_direction_output(unsigned gpio);
|
||||||
extern struct pinmux * __must_check pinmux_get(struct device *dev, const char *name);
|
extern struct pinmux * __must_check pinmux_get(struct device *dev, const char *name);
|
||||||
extern void pinmux_put(struct pinmux *pmx);
|
extern void pinmux_put(struct pinmux *pmx);
|
||||||
extern int pinmux_enable(struct pinmux *pmx);
|
extern int pinmux_enable(struct pinmux *pmx);
|
||||||
@@ -97,6 +109,16 @@ static inline void pinmux_free_gpio(unsigned gpio)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int pinmux_gpio_direction_input(unsigned gpio)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pinmux_gpio_direction_output(unsigned gpio)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct pinmux * __must_check pinmux_get(struct device *dev, const char *name)
|
static inline struct pinmux * __must_check pinmux_get(struct device *dev, const char *name)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user