Message ID | 1363345636-2006-1-git-send-email-linus.walleij@stericsson.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 03/15/2013 05:07 AM, Linus Walleij wrote: > From: Linus Walleij <linus.walleij@linaro.org> > > Recently as adoption of the pinctrl framework is reaching > niches where the pins are reconfigured during system sleep > and datasheets often talk about something called "GPIO mode", > some engineers become confused by this, thinking that since > it is named "GPIO (something something)" it must be modeled > in the kernel using <linux/gpio.h>. > +static struct pinctrl_map __initdata pinmap[] = { > + PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_DEFAULT", "pinctrl-foo", Extra trailing " after PINCTRL_STATE_DEFAULT there. Otherwise, this sounds plausible, so, Reviewed-by: Stephen Warren <swarren@nvidia.com>
Hi Linus, On Friday 15 March 2013 12:07:16 Linus Walleij wrote: > From: Linus Walleij <linus.walleij@linaro.org> > > Recently as adoption of the pinctrl framework is reaching > niches where the pins are reconfigured during system sleep > and datasheets often talk about something called "GPIO mode", > some engineers become confused by this, thinking that since > it is named "GPIO (something something)" it must be modeled > in the kernel using <linux/gpio.h>. > > To clarify things, let's put in this piece of documentation, > or just start off the discussion here. > > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Cc: Pankaj Dev <pankaj.dev@st.com> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > Documentation/pinctrl.txt | 112 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 112 insertions(+) > > diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt > index a2b57e0..3e41545 100644 > --- a/Documentation/pinctrl.txt > +++ b/Documentation/pinctrl.txt > @@ -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 > @@ -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), > +}; I'm having a bit of trouble with PIN_CONFIG_DRIVE_PUSH_PULL and PIN_CONFIG_OUTPUT. Strictly speaking, when configured in output mode, the pin will be in a push-pull configuration. Could you clarify the exact scope of the two configuration parameters ? > +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 > ==================================
On Tue, Apr 23, 2013 at 3:33 PM, Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: >> +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), >> +}; > > I'm having a bit of trouble with PIN_CONFIG_DRIVE_PUSH_PULL and > PIN_CONFIG_OUTPUT. Strictly speaking, when configured in output mode, the pin > will be in a push-pull configuration. For your system or for any system? Open drain, open source are also output modes, and none of them are push-pull. > Could you clarify the exact scope of the > two configuration parameters ? PIN_CONFIG_OUTPUT is left a bit unspecified, but here the idea was a passive drive, like just connecting the pin to VDD or GND without any driver stage at all. Maybe I should patch the documentation since we seem to be the only user? In the above case (which is derived from the ABx500) I think what is happening is that the pin is connected to ground during sleep, without any enabled driver stages, which saves a lot of power, since you do not need to bias the totempole during sleep in that way. Yours, Linus Walleij
Hi Linus, On Thursday 25 April 2013 23:39:18 Linus Walleij wrote: > On Tue, Apr 23, 2013 at 3:33 PM, Laurent Pinchart wrote: > >> +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), > >> +}; > > > > I'm having a bit of trouble with PIN_CONFIG_DRIVE_PUSH_PULL and > > PIN_CONFIG_OUTPUT. Strictly speaking, when configured in output mode, the > > pin will be in a push-pull configuration. > > For your system or for any system? Open drain, open source are also > output modes, and none of them are push-pull. Indeed. I was actually thinking about the opposite, push-pull is output. > > Could you clarify the exact scope of the two configuration parameters ? > > PIN_CONFIG_OUTPUT is left a bit unspecified, but here the idea was a passive > drive, like just connecting the pin to VDD or GND without any driver stage > at all. Isn't that a driver stage ? :-) > Maybe I should patch the documentation since we seem to be the only user? > > In the above case (which is derived from the ABx500) I think what is > happening is that the pin is connected to ground during sleep, without any > enabled driver stages, which saves a lot of power, since you do not need to > bias the totempole during sleep in that way. Right. What is unclear to me is the interaction between OUTPUT and DRIVE_*. That's the part I would like to see clarified. Does DRIVE_* imply that the pin is driven by the selected function, and OUTPUT imply that the pin is driven to a fixed level ? If so, how do you configure the drive type of a pin that will be used through the GPIO API ? What about cases where I want to drive the pin to a fixed level in a non low-power output mode (for instance because I need more current that what the low-power output mode provides) ?
On Fri, Apr 26, 2013 at 1:15 AM, Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: > On Thursday 25 April 2013 23:39:18 Linus Walleij wrote: >> On Tue, Apr 23, 2013 at 3:33 PM, Laurent Pinchart wrote: >> > Could you clarify the exact scope of the two configuration parameters ? >> >> PIN_CONFIG_OUTPUT is left a bit unspecified, but here the idea was a passive >> drive, like just connecting the pin to VDD or GND without any driver stage >> at all. > > Isn't that a driver stage ? :-) OK something that is not a totempole type drive ... push/pull surely implies a totempole type design. > What is unclear to me is the interaction between OUTPUT and DRIVE_*. > That's the part I would like to see clarified. I sent some patch now, check it ... hm reported-by still doesn't add you to CC :-/ better patch git-send-email... > Does DRIVE_* imply that the pin > is driven by the selected function, and OUTPUT imply that the pin is driven to > a fixed level ? That is unclear, but I suggest DRIVE* implies that everything on the pin is driven according to that configuration. (Else it is getting ignored...) OUTPUT would be used when you don't know the particulars or when the driving cannot be controlled in a fine-grained manner like with the DRIVE* configs. Does this make sense? > If so, how do you configure the drive type of a pin that will > be used through the GPIO API ? It is possible to use the pinctrl and GPIO APIs orthogonally. For example the pinctrl can use hogs to reconfigure the pins during sleep without intervention from the GPIO API. So they will be fingering on the same pins registers. Maybe even the same register (if access can be protected properly) from different APIs. > What about cases where I want to drive the pin > to a fixed level in a non low-power output mode (for instance because I need > more current that what the low-power output mode provides) ? Just use pinconfig for that? Is the usecase something like a power-supplying GPIO pin and then sometimes you want to provide more power from it? Then use pinconfig to shunt in the driver stages, and GPIO API to enable/disable it. Yours, Linus Walleij
Hi Linus, On Friday 26 April 2013 10:49:12 Linus Walleij wrote: > On Fri, Apr 26, 2013 at 1:15 AM, Laurent Pinchart wrote: > > On Thursday 25 April 2013 23:39:18 Linus Walleij wrote: > >> On Tue, Apr 23, 2013 at 3:33 PM, Laurent Pinchart wrote: > >> > Could you clarify the exact scope of the two configuration parameters ? > >> > >> PIN_CONFIG_OUTPUT is left a bit unspecified, but here the idea was a > >> passive drive, like just connecting the pin to VDD or GND without any > >> driver stage at all. > > > > Isn't that a driver stage ? :-) > > OK something that is not a totempole type drive ... > push/pull surely implies a totempole type design. > > > What is unclear to me is the interaction between OUTPUT and DRIVE_*. > > That's the part I would like to see clarified. > > I sent some patch now, check it ... hm reported-by still doesn't add > you to CC :-/ better patch git-send-email... > > > Does DRIVE_* imply that the pin is driven by the selected function, and > > OUTPUT imply that the pin is driven to a fixed level ? > > That is unclear, but I suggest DRIVE* implies that everything on the pin > is driven according to that configuration. (Else it is getting ignored...) > > OUTPUT would be used when you don't know the particulars or when > the driving cannot be controlled in a fine-grained manner like with the > DRIVE* configs. > > Does this make sense? Kinda, but it's still unclear to me. While the options are (briefly) documented, how they interact isn't. > > If so, how do you configure the drive type of a pin that will be used > > through the GPIO API ? > > It is possible to use the pinctrl and GPIO APIs orthogonally. > > For example the pinctrl can use hogs to reconfigure the pins during sleep > without intervention from the GPIO API. > > So they will be fingering on the same pins registers. Maybe even the same > register (if access can be protected properly) from different APIs. > > > What about cases where I want to drive the pin to a fixed level in a non > > low-power output mode (for instance because I need more current that what > > the low-power output mode provides) ? > > Just use pinconfig for that? How would you do so ? Only OUTPUT allows setting the output level explictly, the other DRIVE_* options don't specify the output level. > Is the usecase something like a power-supplying GPIO pin and then sometimes > you want to provide more power from it? > > Then use pinconfig to shunt in the driver stages, and GPIO API to > enable/disable it.
On Sat, Apr 27, 2013 at 3:16 AM, Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: > On Friday 26 April 2013 10:49:12 Linus Walleij wrote: >> > Does DRIVE_* imply that the pin is driven by the selected function, and >> > OUTPUT imply that the pin is driven to a fixed level ? >> >> That is unclear, but I suggest DRIVE* implies that everything on the pin >> is driven according to that configuration. (Else it is getting ignored...) >> >> OUTPUT would be used when you don't know the particulars or when >> the driving cannot be controlled in a fine-grained manner like with the >> DRIVE* configs. >> >> Does this make sense? > > Kinda, but it's still unclear to me. While the options are (briefly) > documented, how they interact isn't. Do you think the sematics need to be etched in stone or do you think it could be left as driver-specific, like if I write in the defintion that the interaction of different config arguments is up to the driver? >> > What about cases where I want to drive the pin to a fixed level in a non >> > low-power output mode (for instance because I need more current that what >> > the low-power output mode provides) ? >> >> Just use pinconfig for that? > > How would you do so ? Only OUTPUT allows setting the output level explictly, > the other DRIVE_* options don't specify the output level. The PIN_CONFIG_DRIVE_STRENGTH argument is in mA. Is this what you're after or something else? Yours, Linus Walleij
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index a2b57e0..3e41545 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -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 @@ -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 ==================================