123 lines
4.4 KiB
Plaintext
123 lines
4.4 KiB
Plaintext
|
This document provides an overview of the msm_gpiomux interface, which
|
||
|
is used to provide gpio pin multiplexing and configuration on mach-msm
|
||
|
targets.
|
||
|
|
||
|
Usage
|
||
|
=====
|
||
|
|
||
|
To use gpiomux, do the following before the msmgpio gpiochips probe:
|
||
|
|
||
|
- Call msm_gpiomux_init to allocate needed resources.
|
||
|
- Install one or more sets of gpiomux configuration data via
|
||
|
msm_gpiomux_install and/or msm_gpiomux_write.
|
||
|
|
||
|
Failing to finish these steps before the probe of msmgpio can result in calls
|
||
|
from msmgpio to gpiomux to try and activate lines which have not yet
|
||
|
been configured.
|
||
|
|
||
|
A basic gpiomux setting is described by a gpiomux_setting structure.
|
||
|
A gpiomux configuration is a group of those settings (one for each power
|
||
|
state of the board) paired with a specific gpio, like so:
|
||
|
|
||
|
struct msm_gpiomux_config gpio123_config __initdata = {
|
||
|
.gpio = 123,
|
||
|
.settings = {
|
||
|
[GPIOMUX_ACTIVE] = {
|
||
|
.func = GPIOMUX_FUNC_GPIO,
|
||
|
.drv = GPIOMUX_DRV_2MA,
|
||
|
.pull = GPIOMUX_PULL_NONE,
|
||
|
.dir = GPIOMUX_OUT_HIGH,
|
||
|
},
|
||
|
[GPIOMUX_SUSPENDED] = {
|
||
|
.func = GPIOMUX_FUNC_3,
|
||
|
.drv = GPIOMUX_DRV_8MA,
|
||
|
.pull = GPIOMUX_PULL_DOWN,
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
The effect of this configuration is as follows:
|
||
|
|
||
|
- When the system boots, gpio 123 will be put into the SUSPENDED setting.
|
||
|
- When the reference count for gpio 123 rises above 0, the ACTIVE setting
|
||
|
will be applied.
|
||
|
- When the reference count falls back to 0, the SUSPENDED setting will be
|
||
|
reapplied.
|
||
|
|
||
|
The reference count rises when msm_gpiomux_get() is called and falls
|
||
|
when msm_gpiomux_put() is called. msmgpio has hooks to these functions
|
||
|
in its gpiolib implementation. This means that when you call gpio_request()
|
||
|
on an msmgpio, msm_gpiomux_get() is automatically called on your behalf.
|
||
|
Similarly, when you call gpio_free(), msm_gpiomux_put() is called for you.
|
||
|
This allows generic drivers to obtain low-level management of msmgpio lines
|
||
|
without having to be aware of the gpiomux layer.
|
||
|
|
||
|
Note that the .dir field is ignored if .func != GPIOMUX_FUNC_GPIO, since
|
||
|
software control of gpios is allowed only in GPIO mode. By selecting any
|
||
|
other .func, you assign the gpio to another piece of hardware and lose
|
||
|
control of it from gpiolib. You can still reserve such gpios with gpio_request
|
||
|
to prevent other modules from using them while they're in such a state,
|
||
|
but other gpiolib functions will not behave as you expect if .func != GPIO.
|
||
|
|
||
|
If a configuration is omitted, nothing will happen at the relevant transitions.
|
||
|
This allows for the creation of 'static configurations' which do not
|
||
|
change as the line is requested and freed.
|
||
|
|
||
|
Static Configurations
|
||
|
=====================
|
||
|
|
||
|
To install a static configuration, which is applied at boot and does
|
||
|
not change after that, install a configuration with a suspended component
|
||
|
but no active component:
|
||
|
|
||
|
.gpio = ...,
|
||
|
.settings = {
|
||
|
[GPIOMUX_SUSPENDED] = {
|
||
|
...
|
||
|
},
|
||
|
},
|
||
|
|
||
|
The suspended setting is applied during boot, and the lack of any valid
|
||
|
active setting prevents any other setting from being applied at runtime.
|
||
|
If other subsystems attempting to access the line is a concern, one could
|
||
|
*really* anchor the configuration down by calling msm_gpiomux_get on the
|
||
|
line at initialization to move the line into active mode. With the line
|
||
|
held, it will never be re-suspended, and with no valid active configuration,
|
||
|
no new configurations will be applied.
|
||
|
|
||
|
But then, if having other subsystems grabbing for the line is truly a concern,
|
||
|
it should be reserved with gpio_request instead, which carries an implicit
|
||
|
msm_gpiomux_get.
|
||
|
|
||
|
gpiomux and gpiolib
|
||
|
===================
|
||
|
|
||
|
It is expected that msm gpio_chips will call msm_gpiomux_get() and
|
||
|
msm_gpiomux_put() from their request and free hooks, like this fictional
|
||
|
example:
|
||
|
|
||
|
static int request(struct gpio_chip *chip, unsigned offset)
|
||
|
{
|
||
|
return msm_gpiomux_get(chip->base + offset);
|
||
|
}
|
||
|
|
||
|
static void free(struct gpio_chip *chip, unsigned offset)
|
||
|
{
|
||
|
msm_gpiomux_put(chip->base + offset);
|
||
|
}
|
||
|
|
||
|
...somewhere in a gpio_chip declaration...
|
||
|
.request = request,
|
||
|
.free = free,
|
||
|
|
||
|
This provides important functionality:
|
||
|
- It guarantees that a gpio line will have its 'active' config applied
|
||
|
when the line is requested, and will not be suspended while the line
|
||
|
remains requested; and
|
||
|
- It guarantees that gpio-direction settings from gpiolib behave sensibly.
|
||
|
See "About Output-Enable Settings."
|
||
|
|
||
|
This mechanism allows for "auto-request" of gpiomux lines via gpiolib
|
||
|
when it is suitable. Drivers wishing more exact control are, of course,
|
||
|
free to also use msm_gpiomux_set and msm_gpiomux_get.
|