Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 362975
b: refs/heads/master
c: fdba2d0
h: refs/heads/master
i:
  362973: 336841e
  362971: 8d8b553
  362967: 539cbfc
  362959: 3a15edf
  362943: 9377ea2
v: v3
  • Loading branch information
Linus Walleij committed Mar 18, 2013
1 parent d3fce1e commit 49f9a7d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9cca1173594dccc67c50f0530dc5743fa395da67
refs/heads/master: fdba2d065cb2891b3006424b50fbc6406ce66672
112 changes: 112 additions & 0 deletions trunk/Documentation/pinctrl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,13 @@ All the above functions are mandatory to implement for a pinmux driver.
Pin control interaction with the GPIO subsystem
===============================================

Note that the following implies that the use case is to use a certain pin
from the Linux kernel using the API in <linux/gpio.h> with gpio_request()
and similar functions. There are cases where you may be using something
that your datasheet calls "GPIO mode" but actually is just an electrical
configuration for a certain device. See the section below named
"GPIO mode pitfalls" for more details on this scenario.

The public pinmux API contains two functions named pinctrl_request_gpio()
and pinctrl_free_gpio(). These two functions shall *ONLY* be called from
gpiolib-based drivers as part of their gpio_request() and
Expand Down Expand Up @@ -774,6 +781,111 @@ obtain the function "gpioN" where "N" is the global GPIO pin number if no
special GPIO-handler is registered.


GPIO mode pitfalls
==================

Sometime the developer may be confused by a datasheet talking about a pin
being possible to set into "GPIO mode". It appears that what hardware
engineers mean with "GPIO mode" is not necessarily the use case that is
implied in the kernel interface <linux/gpio.h>: a pin that you grab from
kernel code and then either listen for input or drive high/low to
assert/deassert some external line.

Rather hardware engineers think that "GPIO mode" means that you can
software-control a few electrical properties of the pin that you would
not be able to control if the pin was in some other mode, such as muxed in
for a device.

Example: a pin is usually muxed in to be used as a UART TX line. But during
system sleep, we need to put this pin into "GPIO mode" and ground it.

If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start
to think that you need to come up with something real complex, that the
pin shall be used for UART TX and GPIO at the same time, that you will grab
a pin control handle and set it to a certain state to enable UART TX to be
muxed in, then twist it over to GPIO mode and use gpio_direction_output()
to drive it low during sleep, then mux it over to UART TX again when you
wake up and maybe even gpio_request/gpio_free as part of this cycle. This
all gets very complicated.

The solution is to not think that what the datasheet calls "GPIO mode"
has to be handled by the <linux/gpio.h> interface. Instead view this as
a certain pin config setting. Look in e.g. <linux/pinctrl/pinconf-generic.h>
and you find this in the documentation:

PIN_CONFIG_OUTPUT: this will configure the pin in output, use argument
1 to indicate high level, argument 0 to indicate low level.

So it is perfectly possible to push a pin into "GPIO mode" and drive the
line low as part of the usual pin control map. So for example your UART
driver may look like this:

#include <linux/pinctrl/consumer.h>

struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_sleep;

pins_default = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_DEFAULT);
pins_sleep = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_SLEEP);

/* Normal mode */
retval = pinctrl_select_state(pinctrl, pins_default);
/* Sleep mode */
retval = pinctrl_select_state(pinctrl, pins_sleep);

And your machine configuration may look like this:
--------------------------------------------------

static unsigned long uart_default_mode[] = {
PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
};

static unsigned long uart_sleep_mode[] = {
PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0),
};

static struct pinctrl_map __initdata pinmap[] = {
PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
"u0_group", "u0"),
PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
"UART_TX_PIN", uart_default_mode),
PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
"u0_group", "gpio-mode"),
PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
"UART_TX_PIN", uart_sleep_mode),
};

foo_init(void) {
pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap));
}

Here the pins we want to control are in the "u0_group" and there is some
function called "u0" that can be enabled on this group of pins, and then
everything is UART business as usual. But there is also some function
named "gpio-mode" that can be mapped onto the same pins to move them into
GPIO mode.

This will give the desired effect without any bogus interaction with the
GPIO subsystem. It is just an electrical configuration used by that device
when going to sleep, it might imply that the pin is set into something the
datasheet calls "GPIO mode" but that is not the point: it is still used
by that UART device to control the pins that pertain to that very UART
driver, putting them into modes needed by the UART. GPIO in the Linux
kernel sense are just some 1-bit line, and is a different use case.

How the registers are poked to attain the push/pull and output low
configuration and the muxing of the "u0" or "gpio-mode" group onto these
pins is a question for the driver.

Some datasheets will be more helpful and refer to the "GPIO mode" as
"low power mode" rather than anything to do with GPIO. This often means
the same thing electrically speaking, but in this latter case the
software engineers will usually quickly identify that this is some
specific muxing/configuration rather than anything related to the GPIO
API.


Board/machine configuration
==================================

Expand Down

0 comments on commit 49f9a7d

Please sign in to comment.