pinctrl: GPIO direction support for muxing
authorLinus Walleij <linus.walleij@linaro.org>
Mon, 14 Nov 2011 09:06:22 +0000 (10:06 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 3 Jan 2012 08:10:01 +0000 (09:10 +0100)
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>
Documentation/pinctrl.txt
drivers/pinctrl/pinmux.c
include/linux/pinctrl/pinmux.h

index 43ba411..3846264 100644 (file)
@@ -645,6 +645,17 @@ All the above functions are mandatory to implement for a pinmux driver.
 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
 individual pin into a GPIO pin independent of any other pins, and then try
 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
 setting and then the device functions.
 
-For this reason there is an additional function a pinmux driver can implement
-to enable only GPIO on an individual pin: .gpio_request_enable(). The same
-.free() function as for other functions is assumed to be usable also for
-GPIO pins.
+For this reason there are two functions a pinmux driver can implement
+to enable only GPIO on an individual pin: .gpio_request_enable() and
+.gpio_disable_free().
 
 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
 operation.
 
-Alternatively 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.
+If your driver needs to have an indication from the framework of whether the
+GPIO pin shall be used for input or output you can implement the
+.gpio_set_direction() function. As described this shall be called from the
+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
index 92aa13e..f3e4f03 100644 (file)
@@ -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
  * @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)
 {
@@ -249,6 +253,10 @@ EXPORT_SYMBOL_GPL(pinmux_request_gpio);
 /**
  * pinmux_free_gpio() - free a single pin, currently used as GPIO
  * @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)
 {
@@ -270,6 +278,59 @@ void pinmux_free_gpio(unsigned 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
  * @maps: the pinmux mappings table to register
index bb7a979..937b3e2 100644 (file)
@@ -54,7 +54,13 @@ struct pinctrl_dev;
  *     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
  *     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 {
        int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
@@ -76,11 +82,17 @@ struct pinmux_ops {
        void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
                                   struct pinctrl_gpio_range *range,
                                   unsigned offset);
+       int (*gpio_set_direction) (struct pinctrl_dev *pctldev,
+                                  struct pinctrl_gpio_range *range,
+                                  unsigned offset,
+                                  bool input);
 };
 
 /* External interface to pinmux */
 extern int pinmux_request_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 void pinmux_put(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)
 {
        return NULL;