Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (31 commits) pinctrl: remove unnecessary max pin number pinctrl: correct a offset while enumerating pins pinctrl: some typo fixes pinctrl: rename U300 and SIRF pin controllers pinctrl: pass name instead of device to pin_config_* pinctrl: add "struct seq_file;" to pinconf.h pinctrl: conjure names for unnamed pins pinctrl: add a group-specific hog macro pinctrl: don't create a device for each pin controller arm/u300: don't use PINMUX_MAP_PRIMARY* pinctrl: implement PINMUX_MAP_SYS_HOG pinctrl: add a pin config interface pinctrl/coh901: driver to request its pins pinctrl: u300-pinmux: register proper GPIO ranges pinctrl: move the U300 GPIO driver to pinctrl ARM: u300: localize GPIO assignments pinctrl: make it possible to add multiple maps pinctrl: make a copy of pinmux map pinctrl: GPIO direction support for muxing pinctrl: print pin range in GPIO range debugs ...
This commit is contained in:
commit
d52739c62e
|
@ -7,12 +7,9 @@ This subsystem deals with:
|
||||||
|
|
||||||
- Multiplexing of pins, pads, fingers (etc) see below for details
|
- Multiplexing of pins, pads, fingers (etc) see below for details
|
||||||
|
|
||||||
The intention is to also deal with:
|
- Configuration of pins, pads, fingers (etc), such as software-controlled
|
||||||
|
biasing and driving mode specific pins, such as pull-up/down, open drain,
|
||||||
- Software-controlled biasing and driving mode specific pins, such as
|
load capacitance etc.
|
||||||
pull-up/down, open drain etc, load capacitance configuration when controlled
|
|
||||||
by software, etc.
|
|
||||||
|
|
||||||
|
|
||||||
Top-level interface
|
Top-level interface
|
||||||
===================
|
===================
|
||||||
|
@ -32,7 +29,7 @@ Definition of PIN:
|
||||||
be sparse - i.e. there may be gaps in the space with numbers where no
|
be sparse - i.e. there may be gaps in the space with numbers where no
|
||||||
pin exists.
|
pin exists.
|
||||||
|
|
||||||
When a PIN CONTROLLER is instatiated, it will register a descriptor to the
|
When a PIN CONTROLLER is instantiated, it will register a descriptor to the
|
||||||
pin control framework, and this descriptor contains an array of pin descriptors
|
pin control framework, and this descriptor contains an array of pin descriptors
|
||||||
describing the pins handled by this specific pin controller.
|
describing the pins handled by this specific pin controller.
|
||||||
|
|
||||||
|
@ -61,14 +58,14 @@ this in our driver:
|
||||||
|
|
||||||
#include <linux/pinctrl/pinctrl.h>
|
#include <linux/pinctrl/pinctrl.h>
|
||||||
|
|
||||||
const struct pinctrl_pin_desc __refdata foo_pins[] = {
|
const struct pinctrl_pin_desc foo_pins[] = {
|
||||||
PINCTRL_PIN(0, "A1"),
|
PINCTRL_PIN(0, "A8"),
|
||||||
PINCTRL_PIN(1, "A2"),
|
PINCTRL_PIN(1, "B8"),
|
||||||
PINCTRL_PIN(2, "A3"),
|
PINCTRL_PIN(2, "C8"),
|
||||||
...
|
...
|
||||||
PINCTRL_PIN(61, "H6"),
|
PINCTRL_PIN(61, "F1"),
|
||||||
PINCTRL_PIN(62, "H7"),
|
PINCTRL_PIN(62, "G1"),
|
||||||
PINCTRL_PIN(63, "H8"),
|
PINCTRL_PIN(63, "H1"),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pinctrl_desc foo_desc = {
|
static struct pinctrl_desc foo_desc = {
|
||||||
|
@ -88,11 +85,16 @@ int __init foo_probe(void)
|
||||||
pr_err("could not register foo pin driver\n");
|
pr_err("could not register foo pin driver\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and
|
||||||
|
selected drivers, you need to select them from your machine's Kconfig entry,
|
||||||
|
since these are so tightly integrated with the machines they are used on.
|
||||||
|
See for example arch/arm/mach-u300/Kconfig for an example.
|
||||||
|
|
||||||
Pins usually have fancier names than this. You can find these in the dataheet
|
Pins usually have fancier names than this. You can find these in the dataheet
|
||||||
for your chip. Notice that the core pinctrl.h file provides a fancy macro
|
for your chip. Notice that the core pinctrl.h file provides a fancy macro
|
||||||
called PINCTRL_PIN() to create the struct entries. As you can see I enumerated
|
called PINCTRL_PIN() to create the struct entries. As you can see I enumerated
|
||||||
the pins from 0 in the upper left corner to 63 in the lower right corner,
|
the pins from 0 in the upper left corner to 63 in the lower right corner.
|
||||||
this enumeration was arbitrarily chosen, in practice you need to think
|
This enumeration was arbitrarily chosen, in practice you need to think
|
||||||
through your numbering system so that it matches the layout of registers
|
through your numbering system so that it matches the layout of registers
|
||||||
and such things in your driver, or the code may become complicated. You must
|
and such things in your driver, or the code may become complicated. You must
|
||||||
also consider matching of offsets to the GPIO ranges that may be handled by
|
also consider matching of offsets to the GPIO ranges that may be handled by
|
||||||
|
@ -133,8 +135,8 @@ struct foo_group {
|
||||||
const unsigned num_pins;
|
const unsigned num_pins;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int spi0_pins[] = { 0, 8, 16, 24 };
|
static const unsigned int spi0_pins[] = { 0, 8, 16, 24 };
|
||||||
static unsigned int i2c0_pins[] = { 24, 25 };
|
static const unsigned int i2c0_pins[] = { 24, 25 };
|
||||||
|
|
||||||
static const struct foo_group foo_groups[] = {
|
static const struct foo_group foo_groups[] = {
|
||||||
{
|
{
|
||||||
|
@ -193,6 +195,88 @@ structure, for example specific register ranges associated with each group
|
||||||
and so on.
|
and so on.
|
||||||
|
|
||||||
|
|
||||||
|
Pin configuration
|
||||||
|
=================
|
||||||
|
|
||||||
|
Pins can sometimes be software-configured in an various ways, mostly related
|
||||||
|
to their electronic properties when used as inputs or outputs. For example you
|
||||||
|
may be able to make an output pin high impedance, or "tristate" meaning it is
|
||||||
|
effectively disconnected. You may be able to connect an input pin to VDD or GND
|
||||||
|
using a certain resistor value - pull up and pull down - so that the pin has a
|
||||||
|
stable value when nothing is driving the rail it is connected to, or when it's
|
||||||
|
unconnected.
|
||||||
|
|
||||||
|
For example, a platform may do this:
|
||||||
|
|
||||||
|
ret = pin_config_set("foo-dev", "FOO_GPIO_PIN", PLATFORM_X_PULL_UP);
|
||||||
|
|
||||||
|
To pull up a pin to VDD. The pin configuration driver implements callbacks for
|
||||||
|
changing pin configuration in the pin controller ops like this:
|
||||||
|
|
||||||
|
#include <linux/pinctrl/pinctrl.h>
|
||||||
|
#include <linux/pinctrl/pinconf.h>
|
||||||
|
#include "platform_x_pindefs.h"
|
||||||
|
|
||||||
|
static int foo_pin_config_get(struct pinctrl_dev *pctldev,
|
||||||
|
unsigned offset,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
struct my_conftype conf;
|
||||||
|
|
||||||
|
... Find setting for pin @ offset ...
|
||||||
|
|
||||||
|
*config = (unsigned long) conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int foo_pin_config_set(struct pinctrl_dev *pctldev,
|
||||||
|
unsigned offset,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
struct my_conftype *conf = (struct my_conftype *) config;
|
||||||
|
|
||||||
|
switch (conf) {
|
||||||
|
case PLATFORM_X_PULL_UP:
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int foo_pin_config_group_get (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned selector,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
static int foo_pin_config_group_set (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned selector,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pinconf_ops foo_pconf_ops = {
|
||||||
|
.pin_config_get = foo_pin_config_get,
|
||||||
|
.pin_config_set = foo_pin_config_set,
|
||||||
|
.pin_config_group_get = foo_pin_config_group_get,
|
||||||
|
.pin_config_group_set = foo_pin_config_group_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pin config operations are handled by some pin controller */
|
||||||
|
static struct pinctrl_desc foo_desc = {
|
||||||
|
...
|
||||||
|
.confops = &foo_pconf_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
Since some controllers have special logic for handling entire groups of pins
|
||||||
|
they can exploit the special whole-group pin control function. The
|
||||||
|
pin_config_group_set() callback is allowed to return the error code -EAGAIN,
|
||||||
|
for groups it does not want to handle, or if it just wants to do some
|
||||||
|
group-level handling and then fall through to iterate over all pins, in which
|
||||||
|
case each individual pin will be treated by separate pin_config_set() calls as
|
||||||
|
well.
|
||||||
|
|
||||||
|
|
||||||
Interaction with the GPIO subsystem
|
Interaction with the GPIO subsystem
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
@ -214,19 +298,20 @@ static struct pinctrl_gpio_range gpio_range_a = {
|
||||||
.name = "chip a",
|
.name = "chip a",
|
||||||
.id = 0,
|
.id = 0,
|
||||||
.base = 32,
|
.base = 32,
|
||||||
|
.pin_base = 32,
|
||||||
.npins = 16,
|
.npins = 16,
|
||||||
.gc = &chip_a;
|
.gc = &chip_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pinctrl_gpio_range gpio_range_a = {
|
static struct pinctrl_gpio_range gpio_range_b = {
|
||||||
.name = "chip b",
|
.name = "chip b",
|
||||||
.id = 0,
|
.id = 0,
|
||||||
.base = 48,
|
.base = 48,
|
||||||
|
.pin_base = 64,
|
||||||
.npins = 8,
|
.npins = 8,
|
||||||
.gc = &chip_b;
|
.gc = &chip_b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
struct pinctrl_dev *pctl;
|
struct pinctrl_dev *pctl;
|
||||||
...
|
...
|
||||||
|
@ -235,42 +320,39 @@ static struct pinctrl_gpio_range gpio_range_a = {
|
||||||
}
|
}
|
||||||
|
|
||||||
So this complex system has one pin controller handling two different
|
So this complex system has one pin controller handling two different
|
||||||
GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in
|
GPIO chips. "chip a" has 16 pins and "chip b" has 8 pins. The "chip a" and
|
||||||
the global GPIO pin space at:
|
"chip b" have different .pin_base, which means a start pin number of the
|
||||||
|
GPIO range.
|
||||||
|
|
||||||
chip a: [32 .. 47]
|
The GPIO range of "chip a" starts from the GPIO base of 32 and actual
|
||||||
chip b: [48 .. 55]
|
pin range also starts from 32. However "chip b" has different starting
|
||||||
|
offset for the GPIO range and pin range. The GPIO range of "chip b" starts
|
||||||
|
from GPIO number 48, while the pin range of "chip b" starts from 64.
|
||||||
|
|
||||||
|
We can convert a gpio number to actual pin number using this "pin_base".
|
||||||
|
They are mapped in the global GPIO pin space at:
|
||||||
|
|
||||||
|
chip a:
|
||||||
|
- GPIO range : [32 .. 47]
|
||||||
|
- pin range : [32 .. 47]
|
||||||
|
chip b:
|
||||||
|
- GPIO range : [48 .. 55]
|
||||||
|
- pin range : [64 .. 71]
|
||||||
|
|
||||||
When GPIO-specific functions in the pin control subsystem are called, these
|
When GPIO-specific functions in the pin control subsystem are called, these
|
||||||
ranges will be used to look up the apropriate pin controller by inspecting
|
ranges will be used to look up the appropriate pin controller by inspecting
|
||||||
and matching the pin to the pin ranges across all controllers. When a
|
and matching the pin to the pin ranges across all controllers. When a
|
||||||
pin controller handling the matching range is found, GPIO-specific functions
|
pin controller handling the matching range is found, GPIO-specific functions
|
||||||
will be called on that specific pin controller.
|
will be called on that specific pin controller.
|
||||||
|
|
||||||
For all functionalities dealing with pin biasing, pin muxing etc, the pin
|
For all functionalities dealing with pin biasing, pin muxing etc, the pin
|
||||||
controller subsystem will subtract the range's .base offset from the passed
|
controller subsystem will subtract the range's .base offset from the passed
|
||||||
in gpio pin number, and pass that on to the pin control driver, so the driver
|
in gpio number, and add the ranges's .pin_base offset to retrive a pin number.
|
||||||
will get an offset into its handled number range. Further it is also passed
|
After that, the subsystem passes it on to the pin control driver, so the driver
|
||||||
|
will get an pin number into its handled number range. Further it is also passed
|
||||||
the range ID value, so that the pin controller knows which range it should
|
the range ID value, so that the pin controller knows which range it should
|
||||||
deal with.
|
deal with.
|
||||||
|
|
||||||
For example: if a user issues pinctrl_gpio_set_foo(50), the pin control
|
|
||||||
subsystem will find that the second range on this pin controller matches,
|
|
||||||
subtract the base 48 and call the
|
|
||||||
pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has
|
|
||||||
this signature:
|
|
||||||
|
|
||||||
int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev,
|
|
||||||
struct pinctrl_gpio_range *rangeid,
|
|
||||||
unsigned offset);
|
|
||||||
|
|
||||||
Now the driver knows that we want to do some GPIO-specific operation on the
|
|
||||||
second GPIO range handled by "chip b", at offset 2 in that specific range.
|
|
||||||
|
|
||||||
(If the GPIO subsystem is ever refactored to use a local per-GPIO controller
|
|
||||||
pin space, this mapping will need to be augmented accordingly.)
|
|
||||||
|
|
||||||
|
|
||||||
PINMUX interfaces
|
PINMUX interfaces
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
@ -438,7 +520,7 @@ you. Define enumerators only for the pins you can control if that makes sense.
|
||||||
|
|
||||||
Assumptions:
|
Assumptions:
|
||||||
|
|
||||||
We assume that the number possible function maps to pin groups is limited by
|
We assume that the number of possible function maps to pin groups is limited by
|
||||||
the hardware. I.e. we assume that there is no system where any function can be
|
the hardware. I.e. we assume that there is no system where any function can be
|
||||||
mapped to any pin, like in a phone exchange. So the available pins groups for
|
mapped to any pin, like in a phone exchange. So the available pins groups for
|
||||||
a certain function will be limited to a few choices (say up to eight or so),
|
a certain function will be limited to a few choices (say up to eight or so),
|
||||||
|
@ -585,7 +667,7 @@ int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
|
||||||
|
|
||||||
const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
|
const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
|
||||||
{
|
{
|
||||||
return myfuncs[selector].name;
|
return foo_functions[selector].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
|
@ -600,16 +682,16 @@ static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
int foo_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
int foo_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
unsigned group)
|
unsigned group)
|
||||||
{
|
{
|
||||||
u8 regbit = (1 << group);
|
u8 regbit = (1 << selector + group);
|
||||||
|
|
||||||
writeb((readb(MUX)|regbit), MUX)
|
writeb((readb(MUX)|regbit), MUX)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
|
void foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
unsigned group)
|
unsigned group)
|
||||||
{
|
{
|
||||||
u8 regbit = (1 << group);
|
u8 regbit = (1 << selector + group);
|
||||||
|
|
||||||
writeb((readb(MUX) & ~(regbit)), MUX)
|
writeb((readb(MUX) & ~(regbit)), MUX)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -647,6 +729,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.
|
||||||
|
@ -654,19 +747,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
|
||||||
|
@ -683,19 +781,19 @@ spi on the second function mapping:
|
||||||
|
|
||||||
#include <linux/pinctrl/machine.h>
|
#include <linux/pinctrl/machine.h>
|
||||||
|
|
||||||
static struct pinmux_map pmx_mapping[] = {
|
static const struct pinmux_map __initdata pmx_mapping[] = {
|
||||||
{
|
{
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "spi0",
|
.function = "spi0",
|
||||||
.dev_name = "foo-spi.0",
|
.dev_name = "foo-spi.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "i2c0",
|
.function = "i2c0",
|
||||||
.dev_name = "foo-i2c.0",
|
.dev_name = "foo-i2c.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "mmc0",
|
.function = "mmc0",
|
||||||
.dev_name = "foo-mmc.0",
|
.dev_name = "foo-mmc.0",
|
||||||
},
|
},
|
||||||
|
@ -714,14 +812,14 @@ for example if they are not yet instantiated or cumbersome to obtain.
|
||||||
|
|
||||||
You register this pinmux mapping to the pinmux subsystem by simply:
|
You register this pinmux mapping to the pinmux subsystem by simply:
|
||||||
|
|
||||||
ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
|
ret = pinmux_register_mappings(pmx_mapping, ARRAY_SIZE(pmx_mapping));
|
||||||
|
|
||||||
Since the above construct is pretty common there is a helper macro to make
|
Since the above construct is pretty common there is a helper macro to make
|
||||||
it even more compact which assumes you want to use pinctrl.0 and position
|
it even more compact which assumes you want to use pinctrl-foo and position
|
||||||
0 for mapping, for example:
|
0 for mapping, for example:
|
||||||
|
|
||||||
static struct pinmux_map pmx_mapping[] = {
|
static struct pinmux_map __initdata pmx_mapping[] = {
|
||||||
PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"),
|
PINMUX_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -734,14 +832,14 @@ As it is possible to map a function to different groups of pins an optional
|
||||||
...
|
...
|
||||||
{
|
{
|
||||||
.name = "spi0-pos-A",
|
.name = "spi0-pos-A",
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "spi0",
|
.function = "spi0",
|
||||||
.group = "spi0_0_grp",
|
.group = "spi0_0_grp",
|
||||||
.dev_name = "foo-spi.0",
|
.dev_name = "foo-spi.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "spi0-pos-B",
|
.name = "spi0-pos-B",
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "spi0",
|
.function = "spi0",
|
||||||
.group = "spi0_1_grp",
|
.group = "spi0_1_grp",
|
||||||
.dev_name = "foo-spi.0",
|
.dev_name = "foo-spi.0",
|
||||||
|
@ -760,46 +858,46 @@ case), we define a mapping like this:
|
||||||
...
|
...
|
||||||
{
|
{
|
||||||
.name "2bit"
|
.name "2bit"
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "mmc0",
|
|
||||||
.group = "mmc0_0_grp",
|
|
||||||
.dev_name = "foo-mmc.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name "4bit"
|
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
|
||||||
.function = "mmc0",
|
|
||||||
.group = "mmc0_0_grp",
|
|
||||||
.dev_name = "foo-mmc.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name "4bit"
|
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
|
||||||
.function = "mmc0",
|
.function = "mmc0",
|
||||||
.group = "mmc0_1_grp",
|
.group = "mmc0_1_grp",
|
||||||
.dev_name = "foo-mmc.0",
|
.dev_name = "foo-mmc.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name "8bit"
|
.name "4bit"
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "mmc0",
|
|
||||||
.group = "mmc0_0_grp",
|
|
||||||
.dev_name = "foo-mmc.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name "8bit"
|
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
|
||||||
.function = "mmc0",
|
.function = "mmc0",
|
||||||
.group = "mmc0_1_grp",
|
.group = "mmc0_1_grp",
|
||||||
.dev_name = "foo-mmc.0",
|
.dev_name = "foo-mmc.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name "8bit"
|
.name "4bit"
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "mmc0",
|
.function = "mmc0",
|
||||||
.group = "mmc0_2_grp",
|
.group = "mmc0_2_grp",
|
||||||
.dev_name = "foo-mmc.0",
|
.dev_name = "foo-mmc.0",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name "8bit"
|
||||||
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
|
.function = "mmc0",
|
||||||
|
.group = "mmc0_1_grp",
|
||||||
|
.dev_name = "foo-mmc.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name "8bit"
|
||||||
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
|
.function = "mmc0",
|
||||||
|
.group = "mmc0_2_grp",
|
||||||
|
.dev_name = "foo-mmc.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name "8bit"
|
||||||
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
|
.function = "mmc0",
|
||||||
|
.group = "mmc0_3_grp",
|
||||||
|
.dev_name = "foo-mmc.0",
|
||||||
|
},
|
||||||
...
|
...
|
||||||
|
|
||||||
The result of grabbing this mapping from the device with something like
|
The result of grabbing this mapping from the device with something like
|
||||||
|
@ -898,7 +996,7 @@ like this:
|
||||||
|
|
||||||
{
|
{
|
||||||
.name "POWERMAP"
|
.name "POWERMAP"
|
||||||
.ctrl_dev_name = "pinctrl.0",
|
.ctrl_dev_name = "pinctrl-foo",
|
||||||
.function = "power_func",
|
.function = "power_func",
|
||||||
.hog_on_boot = true,
|
.hog_on_boot = true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -5123,7 +5123,7 @@ F: drivers/*/*/picoxcell*
|
||||||
PIN CONTROL SUBSYSTEM
|
PIN CONTROL SUBSYSTEM
|
||||||
M: Linus Walleij <linus.walleij@linaro.org>
|
M: Linus Walleij <linus.walleij@linaro.org>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/pinmux/
|
F: drivers/pinctrl/
|
||||||
|
|
||||||
PKTCDVD DRIVER
|
PKTCDVD DRIVER
|
||||||
M: Peter Osterlund <petero2@telia.com>
|
M: Peter Osterlund <petero2@telia.com>
|
||||||
|
|
|
@ -7,8 +7,8 @@ comment "ST-Ericsson Mobile Platform Products"
|
||||||
config MACH_U300
|
config MACH_U300
|
||||||
bool "U300"
|
bool "U300"
|
||||||
select PINCTRL
|
select PINCTRL
|
||||||
select PINMUX_U300
|
select PINCTRL_U300
|
||||||
select GPIO_U300
|
select PINCTRL_COH901
|
||||||
|
|
||||||
comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
|
comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
|
||||||
|
|
||||||
|
|
|
@ -1605,15 +1605,15 @@ static struct platform_device pinmux_device = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Pinmux settings */
|
/* Pinmux settings */
|
||||||
static struct pinmux_map u300_pinmux_map[] = {
|
static struct pinmux_map __initdata u300_pinmux_map[] = {
|
||||||
/* anonymous maps for chip power and EMIFs */
|
/* anonymous maps for chip power and EMIFs */
|
||||||
PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
|
PINMUX_MAP_SYS_HOG("POWER", "pinmux-u300", "power"),
|
||||||
PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
|
PINMUX_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"),
|
||||||
PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"),
|
PINMUX_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"),
|
||||||
/* per-device maps for MMC/SD, SPI and UART */
|
/* per-device maps for MMC/SD, SPI and UART */
|
||||||
PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"),
|
PINMUX_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"),
|
||||||
PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"),
|
PINMUX_MAP("SPI", "pinmux-u300", "spi0", "pl022"),
|
||||||
PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"),
|
PINMUX_MAP("UART0", "pinmux-u300", "uart0", "uart0"),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct u300_mux_hog {
|
struct u300_mux_hog {
|
||||||
|
|
|
@ -9,121 +9,6 @@
|
||||||
#ifndef __MACH_U300_GPIO_U300_H
|
#ifndef __MACH_U300_GPIO_U300_H
|
||||||
#define __MACH_U300_GPIO_U300_H
|
#define __MACH_U300_GPIO_U300_H
|
||||||
|
|
||||||
/*
|
|
||||||
* Individual pin assignments for the B26/S26. Notice that the
|
|
||||||
* actual usage of these pins depends on the PAD MUX settings, that
|
|
||||||
* is why the same number can potentially appear several times.
|
|
||||||
* In the reference design each pin is only used for one purpose.
|
|
||||||
* These were determined by inspecting the B26/S26 schematic:
|
|
||||||
* 2/1911-ROA 128 1603
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_MACH_U300_BS2X
|
|
||||||
#define U300_GPIO_PIN_UART_RX 0
|
|
||||||
#define U300_GPIO_PIN_UART_TX 1
|
|
||||||
#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_CAM_SLEEP 4
|
|
||||||
#define U300_GPIO_PIN_CAM_REG_EN 5
|
|
||||||
#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
|
|
||||||
#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
|
|
||||||
#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
|
|
||||||
#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
|
|
||||||
#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
|
|
||||||
#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
|
|
||||||
#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
|
|
||||||
#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Individual pin assignments for the B330/S330 and B365/S365.
|
|
||||||
* Notice that the actual usage of these pins depends on the
|
|
||||||
* PAD MUX settings, that is why the same number can potentially
|
|
||||||
* appear several times. In the reference design each pin is only
|
|
||||||
* used for one purpose. These were determined by inspecting the
|
|
||||||
* S365 schematic.
|
|
||||||
*/
|
|
||||||
#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
|
|
||||||
defined(CONFIG_MACH_U300_BS335)
|
|
||||||
#define U300_GPIO_PIN_UART_RX 0
|
|
||||||
#define U300_GPIO_PIN_UART_TX 1
|
|
||||||
#define U300_GPIO_PIN_UART_CTS 2
|
|
||||||
#define U300_GPIO_PIN_UART_RTS 3
|
|
||||||
#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
|
|
||||||
#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
|
|
||||||
#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
|
|
||||||
#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
|
|
||||||
#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
|
|
||||||
#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
|
|
||||||
#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
|
|
||||||
#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
|
|
||||||
#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
|
|
||||||
#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
|
|
||||||
#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
|
|
||||||
#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
|
|
||||||
#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
|
|
||||||
#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
|
|
||||||
|
|
||||||
#ifdef CONFIG_MACH_U300_BS335
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
|
|
||||||
|
|
||||||
#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
|
|
||||||
#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum u300_gpio_variant - the type of U300 GPIO employed
|
* enum u300_gpio_variant - the type of U300 GPIO employed
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -110,7 +110,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Maximum 8*7 GPIO lines */
|
/* Maximum 8*7 GPIO lines */
|
||||||
#ifdef CONFIG_GPIO_U300
|
#ifdef CONFIG_PINCTRL_COH901
|
||||||
#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END)
|
#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END)
|
||||||
#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56)
|
#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <mach/coh901318.h>
|
#include <mach/coh901318.h>
|
||||||
#include <mach/dma_channels.h>
|
#include <mach/dma_channels.h>
|
||||||
#include <mach/gpio-u300.h>
|
|
||||||
|
|
||||||
|
#include "u300-gpio.h"
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
|
|
||||||
static struct mmci_platform_data mmc0_plat_data = {
|
static struct mmci_platform_data mmc0_plat_data = {
|
||||||
|
|
114
arch/arm/mach-u300/u300-gpio.h
Normal file
114
arch/arm/mach-u300/u300-gpio.h
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Individual pin assignments for the B26/S26. Notice that the
|
||||||
|
* actual usage of these pins depends on the PAD MUX settings, that
|
||||||
|
* is why the same number can potentially appear several times.
|
||||||
|
* In the reference design each pin is only used for one purpose.
|
||||||
|
* These were determined by inspecting the B26/S26 schematic:
|
||||||
|
* 2/1911-ROA 128 1603
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_MACH_U300_BS2X
|
||||||
|
#define U300_GPIO_PIN_UART_RX 0
|
||||||
|
#define U300_GPIO_PIN_UART_TX 1
|
||||||
|
#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_CAM_SLEEP 4
|
||||||
|
#define U300_GPIO_PIN_CAM_REG_EN 5
|
||||||
|
#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
|
||||||
|
#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
|
||||||
|
#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
|
||||||
|
#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
|
||||||
|
#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
|
||||||
|
#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
|
||||||
|
#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
|
||||||
|
#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Individual pin assignments for the B330/S330 and B365/S365.
|
||||||
|
* Notice that the actual usage of these pins depends on the
|
||||||
|
* PAD MUX settings, that is why the same number can potentially
|
||||||
|
* appear several times. In the reference design each pin is only
|
||||||
|
* used for one purpose. These were determined by inspecting the
|
||||||
|
* S365 schematic.
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
|
||||||
|
defined(CONFIG_MACH_U300_BS335)
|
||||||
|
#define U300_GPIO_PIN_UART_RX 0
|
||||||
|
#define U300_GPIO_PIN_UART_TX 1
|
||||||
|
#define U300_GPIO_PIN_UART_CTS 2
|
||||||
|
#define U300_GPIO_PIN_UART_RTS 3
|
||||||
|
#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
|
||||||
|
#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
|
||||||
|
#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
|
||||||
|
#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
|
||||||
|
#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
|
||||||
|
#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
|
||||||
|
#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
|
||||||
|
#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
|
||||||
|
#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
|
||||||
|
#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
|
||||||
|
#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
|
||||||
|
#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
|
||||||
|
#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
|
||||||
|
#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MACH_U300_BS335
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
|
||||||
|
|
||||||
|
#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
|
||||||
|
#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -176,15 +176,6 @@ config GPIO_SCH
|
||||||
The Intel Tunnel Creek processor has 5 GPIOs powered by the
|
The Intel Tunnel Creek processor has 5 GPIOs powered by the
|
||||||
core power rail and 9 from suspend power supply.
|
core power rail and 9 from suspend power supply.
|
||||||
|
|
||||||
config GPIO_U300
|
|
||||||
bool "ST-Ericsson U300 COH 901 335/571 GPIO"
|
|
||||||
depends on GPIOLIB && ARCH_U300
|
|
||||||
help
|
|
||||||
Say yes here to support GPIO interface on ST-Ericsson U300.
|
|
||||||
The names of the two IP block variants supported are
|
|
||||||
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
|
|
||||||
ports of 8 GPIO pins each.
|
|
||||||
|
|
||||||
config GPIO_VX855
|
config GPIO_VX855
|
||||||
tristate "VIA VX855/VX875 GPIO"
|
tristate "VIA VX855/VX875 GPIO"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
|
|
@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
|
||||||
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
|
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
|
||||||
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
|
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
|
||||||
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
|
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
|
||||||
obj-$(CONFIG_MACH_U300) += gpio-u300.o
|
|
||||||
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
|
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
|
||||||
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
|
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
|
||||||
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
|
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
|
||||||
|
|
|
@ -12,7 +12,10 @@ menu "Pin controllers"
|
||||||
depends on PINCTRL
|
depends on PINCTRL
|
||||||
|
|
||||||
config PINMUX
|
config PINMUX
|
||||||
bool "Support pinmux controllers"
|
bool "Support pin multiplexing controllers"
|
||||||
|
|
||||||
|
config PINCONF
|
||||||
|
bool "Support pin configuration controllers"
|
||||||
|
|
||||||
config DEBUG_PINCTRL
|
config DEBUG_PINCTRL
|
||||||
bool "Debug PINCTRL calls"
|
bool "Debug PINCTRL calls"
|
||||||
|
@ -20,16 +23,25 @@ config DEBUG_PINCTRL
|
||||||
help
|
help
|
||||||
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
|
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
|
||||||
|
|
||||||
config PINMUX_SIRF
|
config PINCTRL_SIRF
|
||||||
bool "CSR SiRFprimaII pinmux driver"
|
bool "CSR SiRFprimaII pin controller driver"
|
||||||
depends on ARCH_PRIMA2
|
depends on ARCH_PRIMA2
|
||||||
select PINMUX
|
select PINMUX
|
||||||
|
|
||||||
config PINMUX_U300
|
config PINCTRL_U300
|
||||||
bool "U300 pinmux driver"
|
bool "U300 pin controller driver"
|
||||||
depends on ARCH_U300
|
depends on ARCH_U300
|
||||||
select PINMUX
|
select PINMUX
|
||||||
|
|
||||||
|
config PINCTRL_COH901
|
||||||
|
bool "ST-Ericsson U300 COH 901 335/571 GPIO"
|
||||||
|
depends on GPIOLIB && ARCH_U300 && PINMUX_U300
|
||||||
|
help
|
||||||
|
Say yes here to support GPIO interface on ST-Ericsson U300.
|
||||||
|
The names of the two IP block variants supported are
|
||||||
|
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
|
||||||
|
ports of 8 GPIO pins each.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# generic pinmux support
|
# generic pinmux support
|
||||||
|
|
||||||
ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG
|
ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
|
||||||
|
|
||||||
obj-$(CONFIG_PINCTRL) += core.o
|
obj-$(CONFIG_PINCTRL) += core.o
|
||||||
obj-$(CONFIG_PINMUX) += pinmux.o
|
obj-$(CONFIG_PINMUX) += pinmux.o
|
||||||
obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o
|
obj-$(CONFIG_PINCONF) += pinconf.o
|
||||||
obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
|
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
|
||||||
|
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
|
||||||
|
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
|
||||||
|
|
|
@ -28,17 +28,12 @@
|
||||||
#include <linux/pinctrl/machine.h>
|
#include <linux/pinctrl/machine.h>
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "pinmux.h"
|
#include "pinmux.h"
|
||||||
|
#include "pinconf.h"
|
||||||
|
|
||||||
/* Global list of pin control devices */
|
/* Global list of pin control devices */
|
||||||
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||||
static LIST_HEAD(pinctrldev_list);
|
static LIST_HEAD(pinctrldev_list);
|
||||||
|
|
||||||
static void pinctrl_dev_release(struct device *dev)
|
|
||||||
{
|
|
||||||
struct pinctrl_dev *pctldev = dev_get_drvdata(dev);
|
|
||||||
kfree(pctldev);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
|
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
|
||||||
{
|
{
|
||||||
/* We're not allowed to register devices without name */
|
/* We're not allowed to register devices without name */
|
||||||
|
@ -70,14 +65,14 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
|
||||||
|
|
||||||
mutex_lock(&pinctrldev_list_mutex);
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||||
if (dev && &pctldev->dev == dev) {
|
if (dev && pctldev->dev == dev) {
|
||||||
/* Matched on device pointer */
|
/* Matched on device pointer */
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devname &&
|
if (devname &&
|
||||||
!strcmp(dev_name(&pctldev->dev), devname)) {
|
!strcmp(dev_name(pctldev->dev), devname)) {
|
||||||
/* Matched on device name */
|
/* Matched on device name */
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -88,7 +83,7 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
|
||||||
return found ? pctldev : NULL;
|
return found ? pctldev : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin)
|
struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin)
|
||||||
{
|
{
|
||||||
struct pin_desc *pindesc;
|
struct pin_desc *pindesc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -100,6 +95,31 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin)
|
||||||
return pindesc;
|
return pindesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pin_get_from_name() - look up a pin number from a name
|
||||||
|
* @pctldev: the pin control device to lookup the pin on
|
||||||
|
* @name: the name of the pin to look up
|
||||||
|
*/
|
||||||
|
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
|
||||||
|
{
|
||||||
|
unsigned i, pin;
|
||||||
|
|
||||||
|
/* The pin number can be retrived from the pin controller descriptor */
|
||||||
|
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||||
|
struct pin_desc *desc;
|
||||||
|
|
||||||
|
pin = pctldev->desc->pins[i].number;
|
||||||
|
desc = pin_desc_get(pctldev, pin);
|
||||||
|
/* Pin space may be sparse */
|
||||||
|
if (desc == NULL)
|
||||||
|
continue;
|
||||||
|
if (desc->name && !strcmp(name, desc->name))
|
||||||
|
return pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pin_is_valid() - check if pin exists on controller
|
* pin_is_valid() - check if pin exists on controller
|
||||||
* @pctldev: the pin control device to check the pin on
|
* @pctldev: the pin control device to check the pin on
|
||||||
|
@ -139,6 +159,8 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
|
||||||
if (pindesc != NULL) {
|
if (pindesc != NULL) {
|
||||||
radix_tree_delete(&pctldev->pin_desc_tree,
|
radix_tree_delete(&pctldev->pin_desc_tree,
|
||||||
pins[i].number);
|
pins[i].number);
|
||||||
|
if (pindesc->dynamic_name)
|
||||||
|
kfree(pindesc->name);
|
||||||
}
|
}
|
||||||
kfree(pindesc);
|
kfree(pindesc);
|
||||||
}
|
}
|
||||||
|
@ -160,19 +182,27 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
|
||||||
pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
|
pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
|
||||||
if (pindesc == NULL)
|
if (pindesc == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
spin_lock_init(&pindesc->lock);
|
spin_lock_init(&pindesc->lock);
|
||||||
|
|
||||||
/* Set owner */
|
/* Set owner */
|
||||||
pindesc->pctldev = pctldev;
|
pindesc->pctldev = pctldev;
|
||||||
|
|
||||||
/* Copy basic pin info */
|
/* Copy basic pin info */
|
||||||
pindesc->name = name;
|
if (pindesc->name) {
|
||||||
|
pindesc->name = name;
|
||||||
|
} else {
|
||||||
|
pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
|
||||||
|
if (pindesc->name == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
pindesc->dynamic_name = true;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock(&pctldev->pin_desc_tree_lock);
|
spin_lock(&pctldev->pin_desc_tree_lock);
|
||||||
radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
|
radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
|
||||||
spin_unlock(&pctldev->pin_desc_tree_lock);
|
spin_unlock(&pctldev->pin_desc_tree_lock);
|
||||||
pr_debug("registered pin %d (%s) on %s\n",
|
pr_debug("registered pin %d (%s) on %s\n",
|
||||||
number, name ? name : "(unnamed)", pctldev->desc->name);
|
number, pindesc->name, pctldev->desc->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,21 +314,52 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
|
||||||
mutex_unlock(&pctldev->gpio_ranges_lock);
|
mutex_unlock(&pctldev->gpio_ranges_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pinctrl_get_group_selector() - returns the group selector for a group
|
||||||
|
* @pctldev: the pin controller handling the group
|
||||||
|
* @pin_group: the pin group to look up
|
||||||
|
*/
|
||||||
|
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
|
||||||
|
const char *pin_group)
|
||||||
|
{
|
||||||
|
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
|
||||||
|
unsigned group_selector = 0;
|
||||||
|
|
||||||
|
while (pctlops->list_groups(pctldev, group_selector) >= 0) {
|
||||||
|
const char *gname = pctlops->get_group_name(pctldev,
|
||||||
|
group_selector);
|
||||||
|
if (!strcmp(gname, pin_group)) {
|
||||||
|
dev_dbg(pctldev->dev,
|
||||||
|
"found group selector %u for %s\n",
|
||||||
|
group_selector,
|
||||||
|
pin_group);
|
||||||
|
return group_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
group_selector++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_err(pctldev->dev, "does not have pin group %s\n",
|
||||||
|
pin_group);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||||
{
|
{
|
||||||
struct pinctrl_dev *pctldev = s->private;
|
struct pinctrl_dev *pctldev = s->private;
|
||||||
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
|
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
|
||||||
unsigned pin;
|
unsigned i, pin;
|
||||||
|
|
||||||
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
|
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
|
||||||
seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin);
|
|
||||||
|
|
||||||
/* The highest pin number need to be included in the loop, thus <= */
|
/* The pin number can be retrived from the pin controller descriptor */
|
||||||
for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
|
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||||
struct pin_desc *desc;
|
struct pin_desc *desc;
|
||||||
|
|
||||||
|
pin = pctldev->desc->pins[i].number;
|
||||||
desc = pin_desc_get(pctldev, pin);
|
desc = pin_desc_get(pctldev, pin);
|
||||||
/* Pin space may be sparse */
|
/* Pin space may be sparse */
|
||||||
if (desc == NULL)
|
if (desc == NULL)
|
||||||
|
@ -363,8 +424,11 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
||||||
/* Loop over the ranges */
|
/* Loop over the ranges */
|
||||||
mutex_lock(&pctldev->gpio_ranges_lock);
|
mutex_lock(&pctldev->gpio_ranges_lock);
|
||||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||||
seq_printf(s, "%u: %s [%u - %u]\n", range->id, range->name,
|
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
||||||
range->base, (range->base + range->npins - 1));
|
range->id, range->name,
|
||||||
|
range->base, (range->base + range->npins - 1),
|
||||||
|
range->pin_base,
|
||||||
|
(range->pin_base + range->npins - 1));
|
||||||
}
|
}
|
||||||
mutex_unlock(&pctldev->gpio_ranges_lock);
|
mutex_unlock(&pctldev->gpio_ranges_lock);
|
||||||
|
|
||||||
|
@ -375,11 +439,15 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
|
||||||
{
|
{
|
||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
|
|
||||||
seq_puts(s, "name [pinmux]\n");
|
seq_puts(s, "name [pinmux] [pinconf]\n");
|
||||||
mutex_lock(&pinctrldev_list_mutex);
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||||
seq_printf(s, "%s ", pctldev->desc->name);
|
seq_printf(s, "%s ", pctldev->desc->name);
|
||||||
if (pctldev->desc->pmxops)
|
if (pctldev->desc->pmxops)
|
||||||
|
seq_puts(s, "yes ");
|
||||||
|
else
|
||||||
|
seq_puts(s, "no ");
|
||||||
|
if (pctldev->desc->confops)
|
||||||
seq_puts(s, "yes");
|
seq_puts(s, "yes");
|
||||||
else
|
else
|
||||||
seq_puts(s, "no");
|
seq_puts(s, "no");
|
||||||
|
@ -444,11 +512,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
|
||||||
{
|
{
|
||||||
static struct dentry *device_root;
|
static struct dentry *device_root;
|
||||||
|
|
||||||
device_root = debugfs_create_dir(dev_name(&pctldev->dev),
|
device_root = debugfs_create_dir(dev_name(pctldev->dev),
|
||||||
debugfs_root);
|
debugfs_root);
|
||||||
if (IS_ERR(device_root) || !device_root) {
|
if (IS_ERR(device_root) || !device_root) {
|
||||||
pr_warn("failed to create debugfs directory for %s\n",
|
pr_warn("failed to create debugfs directory for %s\n",
|
||||||
dev_name(&pctldev->dev));
|
dev_name(pctldev->dev));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debugfs_create_file("pins", S_IFREG | S_IRUGO,
|
debugfs_create_file("pins", S_IFREG | S_IRUGO,
|
||||||
|
@ -458,6 +526,7 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
|
||||||
debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
|
debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
|
||||||
device_root, pctldev, &pinctrl_gpioranges_ops);
|
device_root, pctldev, &pinctrl_gpioranges_ops);
|
||||||
pinmux_init_device_debugfs(device_root, pctldev);
|
pinmux_init_device_debugfs(device_root, pctldev);
|
||||||
|
pinconf_init_device_debugfs(device_root, pctldev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pinctrl_init_debugfs(void)
|
static void pinctrl_init_debugfs(void)
|
||||||
|
@ -495,7 +564,6 @@ static void pinctrl_init_debugfs(void)
|
||||||
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
struct device *dev, void *driver_data)
|
struct device *dev, void *driver_data)
|
||||||
{
|
{
|
||||||
static atomic_t pinmux_no = ATOMIC_INIT(0);
|
|
||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -514,6 +582,16 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're implementing pinconfig, check the ops for sanity */
|
||||||
|
if (pctldesc->confops) {
|
||||||
|
ret = pinconf_check_ops(pctldesc->confops);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s pin config ops lacks necessary functions\n",
|
||||||
|
pctldesc->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
|
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
|
||||||
if (pctldev == NULL)
|
if (pctldev == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -526,18 +604,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
spin_lock_init(&pctldev->pin_desc_tree_lock);
|
spin_lock_init(&pctldev->pin_desc_tree_lock);
|
||||||
INIT_LIST_HEAD(&pctldev->gpio_ranges);
|
INIT_LIST_HEAD(&pctldev->gpio_ranges);
|
||||||
mutex_init(&pctldev->gpio_ranges_lock);
|
mutex_init(&pctldev->gpio_ranges_lock);
|
||||||
|
pctldev->dev = dev;
|
||||||
/* Register device */
|
|
||||||
pctldev->dev.parent = dev;
|
|
||||||
dev_set_name(&pctldev->dev, "pinctrl.%d",
|
|
||||||
atomic_inc_return(&pinmux_no) - 1);
|
|
||||||
pctldev->dev.release = pinctrl_dev_release;
|
|
||||||
ret = device_register(&pctldev->dev);
|
|
||||||
if (ret != 0) {
|
|
||||||
pr_err("error in device registration\n");
|
|
||||||
goto out_reg_dev_err;
|
|
||||||
}
|
|
||||||
dev_set_drvdata(&pctldev->dev, pctldev);
|
|
||||||
|
|
||||||
/* Register all the pins */
|
/* Register all the pins */
|
||||||
pr_debug("try to register %d pins on %s...\n",
|
pr_debug("try to register %d pins on %s...\n",
|
||||||
|
@ -547,7 +614,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
pr_err("error during pin registration\n");
|
pr_err("error during pin registration\n");
|
||||||
pinctrl_free_pindescs(pctldev, pctldesc->pins,
|
pinctrl_free_pindescs(pctldev, pctldesc->pins,
|
||||||
pctldesc->npins);
|
pctldesc->npins);
|
||||||
goto out_reg_pins_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinctrl_init_device_debugfs(pctldev);
|
pinctrl_init_device_debugfs(pctldev);
|
||||||
|
@ -557,10 +624,8 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
pinmux_hog_maps(pctldev);
|
pinmux_hog_maps(pctldev);
|
||||||
return pctldev;
|
return pctldev;
|
||||||
|
|
||||||
out_reg_pins_err:
|
out_err:
|
||||||
device_del(&pctldev->dev);
|
kfree(pctldev);
|
||||||
out_reg_dev_err:
|
|
||||||
put_device(&pctldev->dev);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pinctrl_register);
|
EXPORT_SYMBOL_GPL(pinctrl_register);
|
||||||
|
@ -584,7 +649,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
||||||
/* Destroy descriptor tree */
|
/* Destroy descriptor tree */
|
||||||
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
|
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
|
||||||
pctldev->desc->npins);
|
pctldev->desc->npins);
|
||||||
device_unregister(&pctldev->dev);
|
kfree(pctldev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pinctrl_unregister);
|
EXPORT_SYMBOL_GPL(pinctrl_unregister);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
* License terms: GNU General Public License (GPL) version 2
|
* License terms: GNU General Public License (GPL) version 2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/pinctrl/pinconf.h>
|
||||||
|
|
||||||
|
struct pinctrl_gpio_range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct pinctrl_dev - pin control class device
|
* struct pinctrl_dev - pin control class device
|
||||||
* @node: node to include this pin controller in the global pin controller list
|
* @node: node to include this pin controller in the global pin controller list
|
||||||
|
@ -34,7 +38,7 @@ struct pinctrl_dev {
|
||||||
spinlock_t pin_desc_tree_lock;
|
spinlock_t pin_desc_tree_lock;
|
||||||
struct list_head gpio_ranges;
|
struct list_head gpio_ranges;
|
||||||
struct mutex gpio_ranges_lock;
|
struct mutex gpio_ranges_lock;
|
||||||
struct device dev;
|
struct device *dev;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
void *driver_data;
|
void *driver_data;
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
|
@ -48,6 +52,7 @@ struct pinctrl_dev {
|
||||||
* @pctldev: corresponding pin control device
|
* @pctldev: corresponding pin control device
|
||||||
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a
|
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a
|
||||||
* datasheet or such
|
* datasheet or such
|
||||||
|
* @dynamic_name: if the name of this pin was dynamically allocated
|
||||||
* @lock: a lock to protect the descriptor structure
|
* @lock: a lock to protect the descriptor structure
|
||||||
* @mux_requested: whether the pin is already requested by pinmux or not
|
* @mux_requested: whether the pin is already requested by pinmux or not
|
||||||
* @mux_function: a named muxing function for the pin that will be passed to
|
* @mux_function: a named muxing function for the pin that will be passed to
|
||||||
|
@ -56,6 +61,7 @@ struct pinctrl_dev {
|
||||||
struct pin_desc {
|
struct pin_desc {
|
||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
bool dynamic_name;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
/* These fields only added when supporting pinmux drivers */
|
/* These fields only added when supporting pinmux drivers */
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
|
@ -65,7 +71,10 @@ struct pin_desc {
|
||||||
|
|
||||||
struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
|
struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
|
||||||
const char *dev_name);
|
const char *dev_name);
|
||||||
struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin);
|
struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin);
|
||||||
|
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
|
||||||
int pinctrl_get_device_gpio_range(unsigned gpio,
|
int pinctrl_get_device_gpio_range(unsigned gpio,
|
||||||
struct pinctrl_dev **outdev,
|
struct pinctrl_dev **outdev,
|
||||||
struct pinctrl_gpio_range **outrange);
|
struct pinctrl_gpio_range **outrange);
|
||||||
|
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
|
||||||
|
const char *pin_group);
|
||||||
|
|
326
drivers/pinctrl/pinconf.c
Normal file
326
drivers/pinctrl/pinconf.c
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* Core driver for the pin config portions of the pin control subsystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 ST-Ericsson SA
|
||||||
|
* Written on behalf of Linaro for ST-Ericsson
|
||||||
|
*
|
||||||
|
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||||
|
*
|
||||||
|
* License terms: GNU General Public License (GPL) version 2
|
||||||
|
*/
|
||||||
|
#define pr_fmt(fmt) "pinconfig core: " fmt
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/pinctrl/machine.h>
|
||||||
|
#include <linux/pinctrl/pinctrl.h>
|
||||||
|
#include <linux/pinctrl/pinconf.h>
|
||||||
|
#include "core.h"
|
||||||
|
#include "pinconf.h"
|
||||||
|
|
||||||
|
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||||
|
|
||||||
|
if (!ops || !ops->pin_config_get) {
|
||||||
|
dev_err(pctldev->dev, "cannot get pin configuration, missing "
|
||||||
|
"pin_config_get() function in driver\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ops->pin_config_get(pctldev, pin, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pin_config_get() - get the configuration of a single pin parameter
|
||||||
|
* @dev_name: name of the pin controller device for this pin
|
||||||
|
* @name: name of the pin to get the config for
|
||||||
|
* @config: the config pointed to by this argument will be filled in with the
|
||||||
|
* current pin state, it can be used directly by drivers as a numeral, or
|
||||||
|
* it can be dereferenced to any struct.
|
||||||
|
*/
|
||||||
|
int pin_config_get(const char *dev_name, const char *name,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev;
|
||||||
|
int pin;
|
||||||
|
|
||||||
|
pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
|
||||||
|
if (!pctldev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pin = pin_get_from_name(pctldev, name);
|
||||||
|
if (pin < 0)
|
||||||
|
return pin;
|
||||||
|
|
||||||
|
return pin_config_get_for_pin(pctldev, pin, config);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pin_config_get);
|
||||||
|
|
||||||
|
int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ops || !ops->pin_config_set) {
|
||||||
|
dev_err(pctldev->dev, "cannot configure pin, missing "
|
||||||
|
"config function in driver\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ops->pin_config_set(pctldev, pin, config);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(pctldev->dev,
|
||||||
|
"unable to set pin configuration on pin %d\n", pin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pin_config_set() - set the configuration of a single pin parameter
|
||||||
|
* @dev_name: name of pin controller device for this pin
|
||||||
|
* @name: name of the pin to set the config for
|
||||||
|
* @config: the config in this argument will contain the desired pin state, it
|
||||||
|
* can be used directly by drivers as a numeral, or it can be dereferenced
|
||||||
|
* to any struct.
|
||||||
|
*/
|
||||||
|
int pin_config_set(const char *dev_name, const char *name,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev;
|
||||||
|
int pin;
|
||||||
|
|
||||||
|
pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
|
||||||
|
if (!pctldev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pin = pin_get_from_name(pctldev, name);
|
||||||
|
if (pin < 0)
|
||||||
|
return pin;
|
||||||
|
|
||||||
|
return pin_config_set_for_pin(pctldev, pin, config);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pin_config_set);
|
||||||
|
|
||||||
|
int pin_config_group_get(const char *dev_name, const char *pin_group,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev;
|
||||||
|
const struct pinconf_ops *ops;
|
||||||
|
int selector;
|
||||||
|
|
||||||
|
pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
|
||||||
|
if (!pctldev)
|
||||||
|
return -EINVAL;
|
||||||
|
ops = pctldev->desc->confops;
|
||||||
|
|
||||||
|
if (!ops || !ops->pin_config_group_get) {
|
||||||
|
dev_err(pctldev->dev, "cannot get configuration for pin "
|
||||||
|
"group, missing group config get function in "
|
||||||
|
"driver\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
selector = pinctrl_get_group_selector(pctldev, pin_group);
|
||||||
|
if (selector < 0)
|
||||||
|
return selector;
|
||||||
|
|
||||||
|
return ops->pin_config_group_get(pctldev, selector, config);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pin_config_group_get);
|
||||||
|
|
||||||
|
|
||||||
|
int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev;
|
||||||
|
const struct pinconf_ops *ops;
|
||||||
|
const struct pinctrl_ops *pctlops;
|
||||||
|
int selector;
|
||||||
|
const unsigned *pins;
|
||||||
|
unsigned num_pins;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
|
||||||
|
if (!pctldev)
|
||||||
|
return -EINVAL;
|
||||||
|
ops = pctldev->desc->confops;
|
||||||
|
pctlops = pctldev->desc->pctlops;
|
||||||
|
|
||||||
|
if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
|
||||||
|
dev_err(pctldev->dev, "cannot configure pin group, missing "
|
||||||
|
"config function in driver\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
selector = pinctrl_get_group_selector(pctldev, pin_group);
|
||||||
|
if (selector < 0)
|
||||||
|
return selector;
|
||||||
|
|
||||||
|
ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(pctldev->dev, "cannot configure pin group, error "
|
||||||
|
"getting pins\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the pin controller supports handling entire groups we use that
|
||||||
|
* capability.
|
||||||
|
*/
|
||||||
|
if (ops->pin_config_group_set) {
|
||||||
|
ret = ops->pin_config_group_set(pctldev, selector, config);
|
||||||
|
/*
|
||||||
|
* If the pin controller prefer that a certain group be handled
|
||||||
|
* pin-by-pin as well, it returns -EAGAIN.
|
||||||
|
*/
|
||||||
|
if (ret != -EAGAIN)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the controller cannot handle entire groups, we configure each pin
|
||||||
|
* individually.
|
||||||
|
*/
|
||||||
|
if (!ops->pin_config_set)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < num_pins; i++) {
|
||||||
|
ret = ops->pin_config_set(pctldev, pins[i], config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pin_config_group_set);
|
||||||
|
|
||||||
|
int pinconf_check_ops(const struct pinconf_ops *ops)
|
||||||
|
{
|
||||||
|
/* We must be able to read out pin status */
|
||||||
|
if (!ops->pin_config_get && !ops->pin_config_group_get)
|
||||||
|
return -EINVAL;
|
||||||
|
/* We have to be able to config the pins in SOME way */
|
||||||
|
if (!ops->pin_config_set && !ops->pin_config_group_set)
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
|
static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
|
||||||
|
struct seq_file *s, int pin)
|
||||||
|
{
|
||||||
|
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||||
|
|
||||||
|
if (ops && ops->pin_config_dbg_show)
|
||||||
|
ops->pin_config_dbg_show(pctldev, s, pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pinconf_pins_show(struct seq_file *s, void *what)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev = s->private;
|
||||||
|
unsigned i, pin;
|
||||||
|
|
||||||
|
seq_puts(s, "Pin config settings per pin\n");
|
||||||
|
seq_puts(s, "Format: pin (name): pinmux setting array\n");
|
||||||
|
|
||||||
|
/* The pin number can be retrived from the pin controller descriptor */
|
||||||
|
for (i = 0; pin < pctldev->desc->npins; i++) {
|
||||||
|
struct pin_desc *desc;
|
||||||
|
|
||||||
|
pin = pctldev->desc->pins[i].number;
|
||||||
|
desc = pin_desc_get(pctldev, pin);
|
||||||
|
/* Skip if we cannot search the pin */
|
||||||
|
if (desc == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
seq_printf(s, "pin %d (%s):", pin,
|
||||||
|
desc->name ? desc->name : "unnamed");
|
||||||
|
|
||||||
|
pinconf_dump_pin(pctldev, s, pin);
|
||||||
|
|
||||||
|
seq_printf(s, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pinconf_dump_group(struct pinctrl_dev *pctldev,
|
||||||
|
struct seq_file *s, unsigned selector,
|
||||||
|
const char *gname)
|
||||||
|
{
|
||||||
|
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||||
|
|
||||||
|
if (ops && ops->pin_config_group_dbg_show)
|
||||||
|
ops->pin_config_group_dbg_show(pctldev, s, selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pinconf_groups_show(struct seq_file *s, void *what)
|
||||||
|
{
|
||||||
|
struct pinctrl_dev *pctldev = s->private;
|
||||||
|
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
|
||||||
|
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||||
|
unsigned selector = 0;
|
||||||
|
|
||||||
|
if (!ops || !ops->pin_config_group_get)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
seq_puts(s, "Pin config settings per pin group\n");
|
||||||
|
seq_puts(s, "Format: group (name): pinmux setting array\n");
|
||||||
|
|
||||||
|
while (pctlops->list_groups(pctldev, selector) >= 0) {
|
||||||
|
const char *gname = pctlops->get_group_name(pctldev, selector);
|
||||||
|
|
||||||
|
seq_printf(s, "%u (%s):", selector, gname);
|
||||||
|
pinconf_dump_group(pctldev, s, selector, gname);
|
||||||
|
selector++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pinconf_pins_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, pinconf_pins_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pinconf_groups_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, pinconf_groups_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations pinconf_pins_ops = {
|
||||||
|
.open = pinconf_pins_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct file_operations pinconf_groups_ops = {
|
||||||
|
.open = pinconf_groups_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
void pinconf_init_device_debugfs(struct dentry *devroot,
|
||||||
|
struct pinctrl_dev *pctldev)
|
||||||
|
{
|
||||||
|
debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
|
||||||
|
devroot, pctldev, &pinconf_pins_ops);
|
||||||
|
debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
|
||||||
|
devroot, pctldev, &pinconf_groups_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
36
drivers/pinctrl/pinconf.h
Normal file
36
drivers/pinctrl/pinconf.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Internal interface between the core pin control system and the
|
||||||
|
* pin config portions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 ST-Ericsson SA
|
||||||
|
* Written on behalf of Linaro for ST-Ericsson
|
||||||
|
* Based on bits of regulator core, gpio core and clk core
|
||||||
|
*
|
||||||
|
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||||
|
*
|
||||||
|
* License terms: GNU General Public License (GPL) version 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PINCONF
|
||||||
|
|
||||||
|
int pinconf_check_ops(const struct pinconf_ops *ops);
|
||||||
|
void pinconf_init_device_debugfs(struct dentry *devroot,
|
||||||
|
struct pinctrl_dev *pctldev);
|
||||||
|
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
|
unsigned long *config);
|
||||||
|
int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||||
|
unsigned long config);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline int pinconf_check_ops(const struct pinconf_ops *ops)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pinconf_init_device_debugfs(struct dentry *devroot,
|
||||||
|
struct pinctrl_dev *pctldev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/pinctrl/pinmux.h>
|
||||||
#include <mach/gpio-u300.h>
|
#include <mach/gpio-u300.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -351,6 +352,24 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
|
||||||
return container_of(chip, struct u300_gpio, chip);
|
return container_of(chip, struct u300_gpio, chip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int u300_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Map back to global GPIO space and request muxing, the direction
|
||||||
|
* parameter does not matter for this controller.
|
||||||
|
*/
|
||||||
|
int gpio = chip->base + offset;
|
||||||
|
|
||||||
|
return pinmux_request_gpio(gpio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void u300_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
int gpio = chip->base + offset;
|
||||||
|
|
||||||
|
pinmux_free_gpio(gpio);
|
||||||
|
}
|
||||||
|
|
||||||
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
|
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
{
|
{
|
||||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||||
|
@ -483,6 +502,8 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
|
||||||
static struct gpio_chip u300_gpio_chip = {
|
static struct gpio_chip u300_gpio_chip = {
|
||||||
.label = "u300-gpio-chip",
|
.label = "u300-gpio-chip",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.request = u300_gpio_request,
|
||||||
|
.free = u300_gpio_free,
|
||||||
.get = u300_gpio_get,
|
.get = u300_gpio_get,
|
||||||
.set = u300_gpio_set,
|
.set = u300_gpio_set,
|
||||||
.direction_input = u300_gpio_direction_input,
|
.direction_input = u300_gpio_direction_input,
|
|
@ -463,7 +463,7 @@ static const struct sirfsoc_padmux spi1_padmux = {
|
||||||
.funcval = BIT(8),
|
.funcval = BIT(8),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned spi1_pins[] = { 33, 34, 35, 36 };
|
static const unsigned spi1_pins[] = { 43, 44, 45, 46 };
|
||||||
|
|
||||||
static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
|
static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
|
||||||
{
|
{
|
||||||
|
@ -1067,7 +1067,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||||
|
|
||||||
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||||
muxval = muxval | (1 << offset);
|
muxval = muxval | (1 << (offset - range->pin_base));
|
||||||
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1086,7 +1086,6 @@ static struct pinctrl_desc sirfsoc_pinmux_desc = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.pins = sirfsoc_pads,
|
.pins = sirfsoc_pads,
|
||||||
.npins = ARRAY_SIZE(sirfsoc_pads),
|
.npins = ARRAY_SIZE(sirfsoc_pads),
|
||||||
.maxpin = SIRFSOC_NUM_PADS - 1,
|
|
||||||
.pctlops = &sirfsoc_pctrl_ops,
|
.pctlops = &sirfsoc_pctrl_ops,
|
||||||
.pmxops = &sirfsoc_pinmux_ops,
|
.pmxops = &sirfsoc_pinmux_ops,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -1100,21 +1099,25 @@ static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
|
||||||
.name = "sirfsoc-gpio*",
|
.name = "sirfsoc-gpio*",
|
||||||
.id = 0,
|
.id = 0,
|
||||||
.base = 0,
|
.base = 0,
|
||||||
|
.pin_base = 0,
|
||||||
.npins = 32,
|
.npins = 32,
|
||||||
}, {
|
}, {
|
||||||
.name = "sirfsoc-gpio*",
|
.name = "sirfsoc-gpio*",
|
||||||
.id = 1,
|
.id = 1,
|
||||||
.base = 32,
|
.base = 32,
|
||||||
|
.pin_base = 32,
|
||||||
.npins = 32,
|
.npins = 32,
|
||||||
}, {
|
}, {
|
||||||
.name = "sirfsoc-gpio*",
|
.name = "sirfsoc-gpio*",
|
||||||
.id = 2,
|
.id = 2,
|
||||||
.base = 64,
|
.base = 64,
|
||||||
|
.pin_base = 64,
|
||||||
.npins = 32,
|
.npins = 32,
|
||||||
}, {
|
}, {
|
||||||
.name = "sirfsoc-gpio*",
|
.name = "sirfsoc-gpio*",
|
||||||
.id = 3,
|
.id = 3,
|
||||||
.base = 96,
|
.base = 96,
|
||||||
|
.pin_base = 96,
|
||||||
.npins = 19,
|
.npins = 19,
|
||||||
},
|
},
|
||||||
};
|
};
|
|
@ -940,20 +940,23 @@ static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector,
|
||||||
{
|
{
|
||||||
u16 regval, val, mask;
|
u16 regval, val, mask;
|
||||||
int i;
|
int i;
|
||||||
|
const struct u300_pmx_mask *upmx_mask;
|
||||||
|
|
||||||
|
upmx_mask = u300_pmx_functions[selector].mask;
|
||||||
for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
|
for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
|
||||||
if (enable)
|
if (enable)
|
||||||
val = u300_pmx_functions[selector].mask->bits;
|
val = upmx_mask->bits;
|
||||||
else
|
else
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|
||||||
mask = u300_pmx_functions[selector].mask->mask;
|
mask = upmx_mask->mask;
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
regval = readw(upmx->virtbase + u300_pmx_registers[i]);
|
regval = readw(upmx->virtbase + u300_pmx_registers[i]);
|
||||||
regval &= ~mask;
|
regval &= ~mask;
|
||||||
regval |= val;
|
regval |= val;
|
||||||
writew(regval, upmx->virtbase + u300_pmx_registers[i]);
|
writew(regval, upmx->virtbase + u300_pmx_registers[i]);
|
||||||
}
|
}
|
||||||
|
upmx_mask++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,21 +1019,35 @@ static struct pinmux_ops u300_pmx_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: this will be set to sane values as this driver engulfs
|
* GPIO ranges handled by the application-side COH901XXX GPIO controller
|
||||||
* drivers/gpio/gpio-u300.c and we really know this stuff.
|
* Very many pins can be converted into GPIO pins, but we only list those
|
||||||
|
* that are useful in practice to cut down on tables.
|
||||||
*/
|
*/
|
||||||
static struct pinctrl_gpio_range u300_gpio_range = {
|
#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \
|
||||||
.name = "COH901*",
|
.pin_base = b, .npins = c }
|
||||||
.id = 0,
|
|
||||||
.base = 0,
|
static struct pinctrl_gpio_range u300_gpio_ranges[] = {
|
||||||
.npins = 64,
|
U300_GPIO_RANGE(10, 426, 1),
|
||||||
|
U300_GPIO_RANGE(11, 180, 1),
|
||||||
|
U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */
|
||||||
|
U300_GPIO_RANGE(13, 179, 1),
|
||||||
|
U300_GPIO_RANGE(14, 178, 1),
|
||||||
|
U300_GPIO_RANGE(16, 194, 1),
|
||||||
|
U300_GPIO_RANGE(17, 193, 1),
|
||||||
|
U300_GPIO_RANGE(18, 192, 1),
|
||||||
|
U300_GPIO_RANGE(19, 191, 1),
|
||||||
|
U300_GPIO_RANGE(20, 186, 1),
|
||||||
|
U300_GPIO_RANGE(21, 185, 1),
|
||||||
|
U300_GPIO_RANGE(22, 184, 1),
|
||||||
|
U300_GPIO_RANGE(23, 183, 1),
|
||||||
|
U300_GPIO_RANGE(24, 182, 1),
|
||||||
|
U300_GPIO_RANGE(25, 181, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pinctrl_desc u300_pmx_desc = {
|
static struct pinctrl_desc u300_pmx_desc = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.pins = u300_pads,
|
.pins = u300_pads,
|
||||||
.npins = ARRAY_SIZE(u300_pads),
|
.npins = ARRAY_SIZE(u300_pads),
|
||||||
.maxpin = U300_NUM_PADS-1,
|
|
||||||
.pctlops = &u300_pctrl_ops,
|
.pctlops = &u300_pctrl_ops,
|
||||||
.pmxops = &u300_pmx_ops,
|
.pmxops = &u300_pmx_ops,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -1038,9 +1055,10 @@ static struct pinctrl_desc u300_pmx_desc = {
|
||||||
|
|
||||||
static int __init u300_pmx_probe(struct platform_device *pdev)
|
static int __init u300_pmx_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct u300_pmx *upmx;
|
struct u300_pmx *upmx;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Create state holders etc for this driver */
|
/* Create state holders etc for this driver */
|
||||||
upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
|
upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
|
||||||
|
@ -1077,7 +1095,8 @@ static int __init u300_pmx_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We will handle a range of GPIO pins */
|
/* We will handle a range of GPIO pins */
|
||||||
pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range);
|
for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
|
||||||
|
pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, upmx);
|
platform_set_drvdata(pdev, upmx);
|
||||||
|
|
||||||
|
@ -1099,8 +1118,10 @@ out_no_resource:
|
||||||
static int __exit u300_pmx_remove(struct platform_device *pdev)
|
static int __exit u300_pmx_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct u300_pmx *upmx = platform_get_drvdata(pdev);
|
struct u300_pmx *upmx = platform_get_drvdata(pdev);
|
||||||
|
int i;
|
||||||
|
|
||||||
pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range);
|
for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
|
||||||
|
pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
|
||||||
pinctrl_unregister(upmx->pctl);
|
pinctrl_unregister(upmx->pctl);
|
||||||
iounmap(upmx->virtbase);
|
iounmap(upmx->virtbase);
|
||||||
release_mem_region(upmx->phybase, upmx->physize);
|
release_mem_region(upmx->phybase, upmx->physize);
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/string.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
@ -32,12 +33,8 @@
|
||||||
static DEFINE_MUTEX(pinmux_list_mutex);
|
static DEFINE_MUTEX(pinmux_list_mutex);
|
||||||
static LIST_HEAD(pinmux_list);
|
static LIST_HEAD(pinmux_list);
|
||||||
|
|
||||||
/* List of pinmux hogs */
|
/* Global pinmux maps */
|
||||||
static DEFINE_MUTEX(pinmux_hoglist_mutex);
|
static struct pinmux_map *pinmux_maps;
|
||||||
static LIST_HEAD(pinmux_hoglist);
|
|
||||||
|
|
||||||
/* Global pinmux maps, we allow one set only */
|
|
||||||
static struct pinmux_map const *pinmux_maps;
|
|
||||||
static unsigned pinmux_maps_num;
|
static unsigned pinmux_maps_num;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,41 +95,35 @@ struct pinmux_hog {
|
||||||
* @function: a functional name to give to this pin, passed to the driver
|
* @function: a functional name to give to this pin, passed to the driver
|
||||||
* so it knows what function to mux in, e.g. the string "gpioNN"
|
* so it knows what function to mux in, e.g. the string "gpioNN"
|
||||||
* means that you want to mux in the pin for use as GPIO number NN
|
* means that you want to mux in the pin for use as GPIO number NN
|
||||||
* @gpio: if this request concerns a single GPIO pin
|
|
||||||
* @gpio_range: the range matching the GPIO pin if this is a request for a
|
* @gpio_range: the range matching the GPIO pin if this is a request for a
|
||||||
* single GPIO pin
|
* single GPIO pin
|
||||||
*/
|
*/
|
||||||
static int pin_request(struct pinctrl_dev *pctldev,
|
static int pin_request(struct pinctrl_dev *pctldev,
|
||||||
int pin, const char *function, bool gpio,
|
int pin, const char *function,
|
||||||
struct pinctrl_gpio_range *gpio_range)
|
struct pinctrl_gpio_range *gpio_range)
|
||||||
{
|
{
|
||||||
struct pin_desc *desc;
|
struct pin_desc *desc;
|
||||||
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
||||||
int status = -EINVAL;
|
int status = -EINVAL;
|
||||||
|
|
||||||
dev_dbg(&pctldev->dev, "request pin %d for %s\n", pin, function);
|
dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, function);
|
||||||
|
|
||||||
if (!pin_is_valid(pctldev, pin)) {
|
|
||||||
dev_err(&pctldev->dev, "pin is invalid\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function) {
|
|
||||||
dev_err(&pctldev->dev, "no function name given\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc = pin_desc_get(pctldev, pin);
|
desc = pin_desc_get(pctldev, pin);
|
||||||
if (desc == NULL) {
|
if (desc == NULL) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"pin is not registered so it cannot be requested\n");
|
"pin is not registered so it cannot be requested\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!function) {
|
||||||
|
dev_err(pctldev->dev, "no function name given\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
if (desc->mux_function) {
|
if (desc->mux_function) {
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"pin already requested\n");
|
"pin already requested\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +132,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
||||||
|
|
||||||
/* Let each pin increase references to this module */
|
/* Let each pin increase references to this module */
|
||||||
if (!try_module_get(pctldev->owner)) {
|
if (!try_module_get(pctldev->owner)) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"could not increase module refcount for pin %d\n",
|
"could not increase module refcount for pin %d\n",
|
||||||
pin);
|
pin);
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
|
@ -152,7 +143,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
||||||
* If there is no kind of request function for the pin we just assume
|
* If there is no kind of request function for the pin we just assume
|
||||||
* we got it by default and proceed.
|
* we got it by default and proceed.
|
||||||
*/
|
*/
|
||||||
if (gpio && ops->gpio_request_enable)
|
if (gpio_range && ops->gpio_request_enable)
|
||||||
/* This requests and enables a single GPIO pin */
|
/* This requests and enables a single GPIO pin */
|
||||||
status = ops->gpio_request_enable(pctldev, gpio_range, pin);
|
status = ops->gpio_request_enable(pctldev, gpio_range, pin);
|
||||||
else if (ops->request)
|
else if (ops->request)
|
||||||
|
@ -161,7 +152,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
dev_err(&pctldev->dev, "->request on device %s failed "
|
dev_err(pctldev->dev, "->request on device %s failed "
|
||||||
"for pin %d\n",
|
"for pin %d\n",
|
||||||
pctldev->desc->name, pin);
|
pctldev->desc->name, pin);
|
||||||
out_free_pin:
|
out_free_pin:
|
||||||
|
@ -172,7 +163,7 @@ out_free_pin:
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (status)
|
if (status)
|
||||||
dev_err(&pctldev->dev, "pin-%d (%s) status %d\n",
|
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
|
||||||
pin, function ? : "?", status);
|
pin, function ? : "?", status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -182,34 +173,52 @@ out:
|
||||||
* pin_free() - release a single muxed in pin so something else can be muxed
|
* pin_free() - release a single muxed in pin so something else can be muxed
|
||||||
* @pctldev: pin controller device handling this pin
|
* @pctldev: pin controller device handling this pin
|
||||||
* @pin: the pin to free
|
* @pin: the pin to free
|
||||||
* @free_func: whether to free the pin's assigned function name string
|
* @gpio_range: the range matching the GPIO pin if this is a request for a
|
||||||
|
* single GPIO pin
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the function name in use. This is used
|
||||||
|
* for callers that dynamically allocate a function name so it can be freed
|
||||||
|
* once the pin is free. This is done for GPIO request functions.
|
||||||
*/
|
*/
|
||||||
static void pin_free(struct pinctrl_dev *pctldev, int pin, int free_func)
|
static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
|
||||||
|
struct pinctrl_gpio_range *gpio_range)
|
||||||
{
|
{
|
||||||
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
const struct pinmux_ops *ops = pctldev->desc->pmxops;
|
||||||
struct pin_desc *desc;
|
struct pin_desc *desc;
|
||||||
|
const char *func;
|
||||||
|
|
||||||
desc = pin_desc_get(pctldev, pin);
|
desc = pin_desc_get(pctldev, pin);
|
||||||
if (desc == NULL) {
|
if (desc == NULL) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"pin is not registered so it cannot be freed\n");
|
"pin is not registered so it cannot be freed\n");
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ops->free)
|
/*
|
||||||
|
* If there is no kind of request function for the pin we just assume
|
||||||
|
* we got it by default and proceed.
|
||||||
|
*/
|
||||||
|
if (gpio_range && ops->gpio_disable_free)
|
||||||
|
ops->gpio_disable_free(pctldev, gpio_range, pin);
|
||||||
|
else if (ops->free)
|
||||||
ops->free(pctldev, pin);
|
ops->free(pctldev, pin);
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
if (free_func)
|
func = desc->mux_function;
|
||||||
kfree(desc->mux_function);
|
|
||||||
desc->mux_function = NULL;
|
desc->mux_function = NULL;
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
module_put(pctldev->owner);
|
module_put(pctldev->owner);
|
||||||
|
|
||||||
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +234,7 @@ int pinmux_request_gpio(unsigned gpio)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Convert to the pin controllers number space */
|
/* Convert to the pin controllers number space */
|
||||||
pin = gpio - range->base;
|
pin = gpio - range->base + range->pin_base;
|
||||||
|
|
||||||
/* Conjure some name stating what chip and pin this is taken by */
|
/* Conjure some name stating what chip and pin this is taken by */
|
||||||
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
|
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
|
||||||
|
@ -234,7 +243,7 @@ int pinmux_request_gpio(unsigned gpio)
|
||||||
if (!function)
|
if (!function)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = pin_request(pctldev, pin, function, true, range);
|
ret = pin_request(pctldev, pin, function, range);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
kfree(function);
|
kfree(function);
|
||||||
|
|
||||||
|
@ -245,6 +254,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)
|
||||||
{
|
{
|
||||||
|
@ -252,53 +265,108 @@ void pinmux_free_gpio(unsigned gpio)
|
||||||
struct pinctrl_gpio_range *range;
|
struct pinctrl_gpio_range *range;
|
||||||
int ret;
|
int ret;
|
||||||
int pin;
|
int pin;
|
||||||
|
const char *func;
|
||||||
|
|
||||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Convert to the pin controllers number space */
|
/* Convert to the pin controllers number space */
|
||||||
pin = gpio - range->base;
|
pin = gpio - range->base + range->pin_base;
|
||||||
|
|
||||||
pin_free(pctldev, pin, true);
|
func = pin_free(pctldev, pin, range);
|
||||||
|
kfree(func);
|
||||||
}
|
}
|
||||||
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, this should be marked with
|
||||||
|
* __initdata so it can be discarded after boot, this function will
|
||||||
|
* perform a shallow copy for the mapping entries.
|
||||||
* @num_maps: the number of maps in the mapping table
|
* @num_maps: the number of maps in the mapping table
|
||||||
*
|
*
|
||||||
* Only call this once during initialization of your machine, the function is
|
* Only call this once during initialization of your machine, the function is
|
||||||
* tagged as __init and won't be callable after init has completed. The map
|
* tagged as __init and won't be callable after init has completed. The map
|
||||||
* passed into this function will be owned by the pinmux core and cannot be
|
* passed into this function will be owned by the pinmux core and cannot be
|
||||||
* free:d.
|
* freed.
|
||||||
*/
|
*/
|
||||||
int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||||
unsigned num_maps)
|
unsigned num_maps)
|
||||||
{
|
{
|
||||||
|
void *tmp_maps;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pinmux_maps != NULL) {
|
|
||||||
pr_err("pinmux mappings already registered, you can only "
|
|
||||||
"register one set of maps\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("add %d pinmux maps\n", num_maps);
|
pr_debug("add %d pinmux maps\n", num_maps);
|
||||||
|
|
||||||
|
/* First sanity check the new mapping */
|
||||||
for (i = 0; i < num_maps; i++) {
|
for (i = 0; i < num_maps; i++) {
|
||||||
/* Sanity check the mapping */
|
|
||||||
if (!maps[i].name) {
|
if (!maps[i].name) {
|
||||||
pr_err("failed to register map %d: "
|
pr_err("failed to register map %d: "
|
||||||
"no map name given\n", i);
|
"no map name given\n", i);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
|
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
|
||||||
pr_err("failed to register map %s (%d): "
|
pr_err("failed to register map %s (%d): "
|
||||||
"no pin control device given\n",
|
"no pin control device given\n",
|
||||||
maps[i].name, i);
|
maps[i].name, i);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!maps[i].function) {
|
if (!maps[i].function) {
|
||||||
pr_err("failed to register map %s (%d): "
|
pr_err("failed to register map %s (%d): "
|
||||||
"no function ID given\n", maps[i].name, i);
|
"no function ID given\n", maps[i].name, i);
|
||||||
|
@ -315,9 +383,30 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
|
||||||
maps[i].function);
|
maps[i].function);
|
||||||
}
|
}
|
||||||
|
|
||||||
pinmux_maps = maps;
|
/*
|
||||||
pinmux_maps_num = num_maps;
|
* Make a copy of the map array - string pointers will end up in the
|
||||||
|
* kernel const section anyway so these do not need to be deep copied.
|
||||||
|
*/
|
||||||
|
if (!pinmux_maps_num) {
|
||||||
|
/* On first call, just copy them */
|
||||||
|
tmp_maps = kmemdup(maps,
|
||||||
|
sizeof(struct pinmux_map) * num_maps,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!tmp_maps)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
/* Subsequent calls, reallocate array to new size */
|
||||||
|
size_t oldsize = sizeof(struct pinmux_map) * pinmux_maps_num;
|
||||||
|
size_t newsize = sizeof(struct pinmux_map) * num_maps;
|
||||||
|
|
||||||
|
tmp_maps = krealloc(pinmux_maps, oldsize + newsize, GFP_KERNEL);
|
||||||
|
if (!tmp_maps)
|
||||||
|
return -ENOMEM;
|
||||||
|
memcpy((tmp_maps + oldsize), maps, newsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
pinmux_maps = tmp_maps;
|
||||||
|
pinmux_maps_num += num_maps;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,14 +434,14 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
dev_dbg(&pctldev->dev, "requesting the %u pins from group %u\n",
|
dev_dbg(pctldev->dev, "requesting the %u pins from group %u\n",
|
||||||
num_pins, group_selector);
|
num_pins, group_selector);
|
||||||
|
|
||||||
/* Try to allocate all pins in this group, one by one */
|
/* Try to allocate all pins in this group, one by one */
|
||||||
for (i = 0; i < num_pins; i++) {
|
for (i = 0; i < num_pins; i++) {
|
||||||
ret = pin_request(pctldev, pins[i], func, false, NULL);
|
ret = pin_request(pctldev, pins[i], func, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"could not get pin %d for function %s "
|
"could not get pin %d for function %s "
|
||||||
"on device %s - conflicting mux mappings?\n",
|
"on device %s - conflicting mux mappings?\n",
|
||||||
pins[i], func ? : "(undefined)",
|
pins[i], func ? : "(undefined)",
|
||||||
|
@ -360,7 +449,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
|
||||||
/* On error release all taken pins */
|
/* On error release all taken pins */
|
||||||
i--; /* this pin just failed */
|
i--; /* this pin just failed */
|
||||||
for (; i >= 0; i--)
|
for (; i >= 0; i--)
|
||||||
pin_free(pctldev, pins[i], false);
|
pin_free(pctldev, pins[i], NULL);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,44 +473,13 @@ static void release_pins(struct pinctrl_dev *pctldev,
|
||||||
ret = pctlops->get_group_pins(pctldev, group_selector,
|
ret = pctlops->get_group_pins(pctldev, group_selector,
|
||||||
&pins, &num_pins);
|
&pins, &num_pins);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pctldev->dev, "could not get pins to release for "
|
dev_err(pctldev->dev, "could not get pins to release for "
|
||||||
"group selector %d\n",
|
"group selector %d\n",
|
||||||
group_selector);
|
group_selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (i = 0; i < num_pins; i++)
|
for (i = 0; i < num_pins; i++)
|
||||||
pin_free(pctldev, pins[i], false);
|
pin_free(pctldev, pins[i], NULL);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pinmux_get_group_selector() - returns the group selector for a group
|
|
||||||
* @pctldev: the pin controller handling the group
|
|
||||||
* @pin_group: the pin group to look up
|
|
||||||
*/
|
|
||||||
static int pinmux_get_group_selector(struct pinctrl_dev *pctldev,
|
|
||||||
const char *pin_group)
|
|
||||||
{
|
|
||||||
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
|
|
||||||
unsigned group_selector = 0;
|
|
||||||
|
|
||||||
while (pctlops->list_groups(pctldev, group_selector) >= 0) {
|
|
||||||
const char *gname = pctlops->get_group_name(pctldev,
|
|
||||||
group_selector);
|
|
||||||
if (!strcmp(gname, pin_group)) {
|
|
||||||
dev_dbg(&pctldev->dev,
|
|
||||||
"found group selector %u for %s\n",
|
|
||||||
group_selector,
|
|
||||||
pin_group);
|
|
||||||
return group_selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
group_selector++;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_err(&pctldev->dev, "does not have pin group %s\n",
|
|
||||||
pin_group);
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -465,9 +523,9 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
|
||||||
return ret;
|
return ret;
|
||||||
if (num_groups < 1)
|
if (num_groups < 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
ret = pinmux_get_group_selector(pctldev, groups[0]);
|
ret = pinctrl_get_group_selector(pctldev, groups[0]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"function %s wants group %s but the pin "
|
"function %s wants group %s but the pin "
|
||||||
"controller does not seem to have that group\n",
|
"controller does not seem to have that group\n",
|
||||||
pmxops->get_function_name(pctldev, func_selector),
|
pmxops->get_function_name(pctldev, func_selector),
|
||||||
|
@ -476,7 +534,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_groups > 1)
|
if (num_groups > 1)
|
||||||
dev_dbg(&pctldev->dev,
|
dev_dbg(pctldev->dev,
|
||||||
"function %s support more than one group, "
|
"function %s support more than one group, "
|
||||||
"default-selecting first group %s (%d)\n",
|
"default-selecting first group %s (%d)\n",
|
||||||
pmxops->get_function_name(pctldev, func_selector),
|
pmxops->get_function_name(pctldev, func_selector),
|
||||||
|
@ -486,13 +544,13 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&pctldev->dev,
|
dev_dbg(pctldev->dev,
|
||||||
"check if we have pin group %s on controller %s\n",
|
"check if we have pin group %s on controller %s\n",
|
||||||
pin_group, pinctrl_dev_get_name(pctldev));
|
pin_group, pinctrl_dev_get_name(pctldev));
|
||||||
|
|
||||||
ret = pinmux_get_group_selector(pctldev, pin_group);
|
ret = pinctrl_get_group_selector(pctldev, pin_group);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_dbg(&pctldev->dev,
|
dev_dbg(pctldev->dev,
|
||||||
"%s does not support pin group %s with function %s\n",
|
"%s does not support pin group %s with function %s\n",
|
||||||
pinctrl_dev_get_name(pctldev),
|
pinctrl_dev_get_name(pctldev),
|
||||||
pin_group,
|
pin_group,
|
||||||
|
@ -569,7 +627,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pmx->pctldev && pmx->pctldev != pctldev) {
|
if (pmx->pctldev && pmx->pctldev != pctldev) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"different pin control devices given for device %s, "
|
"different pin control devices given for device %s, "
|
||||||
"function %s\n",
|
"function %s\n",
|
||||||
devname,
|
devname,
|
||||||
|
@ -592,7 +650,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
|
||||||
*/
|
*/
|
||||||
if (pmx->func_selector != UINT_MAX &&
|
if (pmx->func_selector != UINT_MAX &&
|
||||||
pmx->func_selector != func_selector) {
|
pmx->func_selector != func_selector) {
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"dual function defines in the map for device %s\n",
|
"dual function defines in the map for device %s\n",
|
||||||
devname);
|
devname);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -698,7 +756,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("in map, found pctldev %s to handle function %s",
|
pr_debug("in map, found pctldev %s to handle function %s",
|
||||||
dev_name(&pctldev->dev), map->function);
|
dev_name(pctldev->dev), map->function);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -874,7 +932,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||||
* without any problems, so then we can hog pinmuxes for
|
* without any problems, so then we can hog pinmuxes for
|
||||||
* all devices that just want a static pin mux at this point.
|
* all devices that just want a static pin mux at this point.
|
||||||
*/
|
*/
|
||||||
dev_err(&pctldev->dev, "map %s wants to hog a non-system "
|
dev_err(pctldev->dev, "map %s wants to hog a non-system "
|
||||||
"pinmux, this is not going to work\n", map->name);
|
"pinmux, this is not going to work\n", map->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -886,7 +944,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||||
pmx = pinmux_get(NULL, map->name);
|
pmx = pinmux_get(NULL, map->name);
|
||||||
if (IS_ERR(pmx)) {
|
if (IS_ERR(pmx)) {
|
||||||
kfree(hog);
|
kfree(hog);
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"could not get the %s pinmux mapping for hogging\n",
|
"could not get the %s pinmux mapping for hogging\n",
|
||||||
map->name);
|
map->name);
|
||||||
return PTR_ERR(pmx);
|
return PTR_ERR(pmx);
|
||||||
|
@ -896,7 +954,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pinmux_put(pmx);
|
pinmux_put(pmx);
|
||||||
kfree(hog);
|
kfree(hog);
|
||||||
dev_err(&pctldev->dev,
|
dev_err(pctldev->dev,
|
||||||
"could not enable the %s pinmux mapping for hogging\n",
|
"could not enable the %s pinmux mapping for hogging\n",
|
||||||
map->name);
|
map->name);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -905,7 +963,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||||
hog->map = map;
|
hog->map = map;
|
||||||
hog->pmx = pmx;
|
hog->pmx = pmx;
|
||||||
|
|
||||||
dev_info(&pctldev->dev, "hogged map %s, function %s\n", map->name,
|
dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
|
||||||
map->function);
|
map->function);
|
||||||
mutex_lock(&pctldev->pinmux_hogs_lock);
|
mutex_lock(&pctldev->pinmux_hogs_lock);
|
||||||
list_add(&hog->node, &pctldev->pinmux_hogs);
|
list_add(&hog->node, &pctldev->pinmux_hogs);
|
||||||
|
@ -924,7 +982,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
|
||||||
*/
|
*/
|
||||||
int pinmux_hog_maps(struct pinctrl_dev *pctldev)
|
int pinmux_hog_maps(struct pinctrl_dev *pctldev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pctldev->dev;
|
struct device *dev = pctldev->dev;
|
||||||
const char *devname = dev_name(dev);
|
const char *devname = dev_name(dev);
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
@ -948,7 +1006,7 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pinmux_hog_maps() - unhog specific map entries on controller device
|
* pinmux_unhog_maps() - unhog specific map entries on controller device
|
||||||
* @pctldev: the pin control device to unhog entries on
|
* @pctldev: the pin control device to unhog entries on
|
||||||
*/
|
*/
|
||||||
void pinmux_unhog_maps(struct pinctrl_dev *pctldev)
|
void pinmux_unhog_maps(struct pinctrl_dev *pctldev)
|
||||||
|
@ -1005,18 +1063,19 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
|
||||||
static int pinmux_pins_show(struct seq_file *s, void *what)
|
static int pinmux_pins_show(struct seq_file *s, void *what)
|
||||||
{
|
{
|
||||||
struct pinctrl_dev *pctldev = s->private;
|
struct pinctrl_dev *pctldev = s->private;
|
||||||
unsigned pin;
|
unsigned i, pin;
|
||||||
|
|
||||||
seq_puts(s, "Pinmux settings per pin\n");
|
seq_puts(s, "Pinmux settings per pin\n");
|
||||||
seq_puts(s, "Format: pin (name): pinmuxfunction\n");
|
seq_puts(s, "Format: pin (name): pinmuxfunction\n");
|
||||||
|
|
||||||
/* The highest pin number need to be included in the loop, thus <= */
|
/* The pin number can be retrived from the pin controller descriptor */
|
||||||
for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
|
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||||
|
|
||||||
struct pin_desc *desc;
|
struct pin_desc *desc;
|
||||||
|
|
||||||
|
pin = pctldev->desc->pins[i].number;
|
||||||
desc = pin_desc_get(pctldev, pin);
|
desc = pin_desc_get(pctldev, pin);
|
||||||
/* Pin space may be sparse */
|
/* Skip if we cannot search the pin */
|
||||||
if (desc == NULL)
|
if (desc == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct pinmux_map {
|
||||||
const char *group;
|
const char *group;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
const char *dev_name;
|
const char *dev_name;
|
||||||
const bool hog_on_boot;
|
bool hog_on_boot;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,29 +66,21 @@ struct pinmux_map {
|
||||||
{ .name = a, .ctrl_dev_name = b, .function = c }
|
{ .name = a, .ctrl_dev_name = b, .function = c }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convenience macro to map a function onto the primary device pinctrl device
|
* Convenience macro to map a system function onto a certain pinctrl device,
|
||||||
* this is especially helpful on systems that have only one pin controller
|
|
||||||
* or need to set up a lot of mappings on the primary controller.
|
|
||||||
*/
|
|
||||||
#define PINMUX_MAP_PRIMARY(a, b, c) \
|
|
||||||
{ .name = a, .ctrl_dev_name = "pinctrl.0", .function = b, \
|
|
||||||
.dev_name = c }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convenience macro to map a system function onto the primary pinctrl device.
|
|
||||||
* System functions are not assigned to a particular device.
|
|
||||||
*/
|
|
||||||
#define PINMUX_MAP_PRIMARY_SYS(a, b) \
|
|
||||||
{ .name = a, .ctrl_dev_name = "pinctrl.0", .function = b }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convenience macro to map a system function onto the primary pinctrl device,
|
|
||||||
* to be hogged by the pinmux core until the system shuts down.
|
* to be hogged by the pinmux core until the system shuts down.
|
||||||
*/
|
*/
|
||||||
#define PINMUX_MAP_PRIMARY_SYS_HOG(a, b) \
|
#define PINMUX_MAP_SYS_HOG(a, b, c) \
|
||||||
{ .name = a, .ctrl_dev_name = "pinctrl.0", .function = b, \
|
{ .name = a, .ctrl_dev_name = b, .function = c, \
|
||||||
.hog_on_boot = true }
|
.hog_on_boot = true }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convenience macro to map a system function onto a certain pinctrl device
|
||||||
|
* using a specified group, to be hogged by the pinmux core until the system
|
||||||
|
* shuts down.
|
||||||
|
*/
|
||||||
|
#define PINMUX_MAP_SYS_HOG_GROUP(a, b, c, d) \
|
||||||
|
{ .name = a, .ctrl_dev_name = b, .function = c, .group = d, \
|
||||||
|
.hog_on_boot = true }
|
||||||
|
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
|
|
||||||
|
|
97
include/linux/pinctrl/pinconf.h
Normal file
97
include/linux/pinctrl/pinconf.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Interface the pinconfig portions of the pinctrl subsystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 ST-Ericsson SA
|
||||||
|
* Written on behalf of Linaro for ST-Ericsson
|
||||||
|
* This interface is used in the core to keep track of pins.
|
||||||
|
*
|
||||||
|
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||||
|
*
|
||||||
|
* License terms: GNU General Public License (GPL) version 2
|
||||||
|
*/
|
||||||
|
#ifndef __LINUX_PINCTRL_PINCONF_H
|
||||||
|
#define __LINUX_PINCTRL_PINCONF_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_PINCONF
|
||||||
|
|
||||||
|
struct pinctrl_dev;
|
||||||
|
struct seq_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pinconf_ops - pin config operations, to be implemented by
|
||||||
|
* pin configuration capable drivers.
|
||||||
|
* @pin_config_get: get the config of a certain pin, if the requested config
|
||||||
|
* is not available on this controller this should return -ENOTSUPP
|
||||||
|
* and if it is available but disabled it should return -EINVAL
|
||||||
|
* @pin_config_get: get the config of a certain pin
|
||||||
|
* @pin_config_set: configure an individual pin
|
||||||
|
* @pin_config_group_get: get configurations for an entire pin group
|
||||||
|
* @pin_config_group_set: configure all pins in a group
|
||||||
|
* @pin_config_dbg_show: optional debugfs display hook that will provide
|
||||||
|
* per-device info for a certain pin in debugfs
|
||||||
|
* @pin_config_group_dbg_show: optional debugfs display hook that will provide
|
||||||
|
* per-device info for a certain group in debugfs
|
||||||
|
*/
|
||||||
|
struct pinconf_ops {
|
||||||
|
int (*pin_config_get) (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned pin,
|
||||||
|
unsigned long *config);
|
||||||
|
int (*pin_config_set) (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned pin,
|
||||||
|
unsigned long config);
|
||||||
|
int (*pin_config_group_get) (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned selector,
|
||||||
|
unsigned long *config);
|
||||||
|
int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
|
||||||
|
unsigned selector,
|
||||||
|
unsigned long config);
|
||||||
|
void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev,
|
||||||
|
struct seq_file *s,
|
||||||
|
unsigned offset);
|
||||||
|
void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,
|
||||||
|
struct seq_file *s,
|
||||||
|
unsigned selector);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int pin_config_get(const char *dev_name, const char *name,
|
||||||
|
unsigned long *config);
|
||||||
|
extern int pin_config_set(const char *dev_name, const char *name,
|
||||||
|
unsigned long config);
|
||||||
|
extern int pin_config_group_get(const char *dev_name,
|
||||||
|
const char *pin_group,
|
||||||
|
unsigned long *config);
|
||||||
|
extern int pin_config_group_set(const char *dev_name,
|
||||||
|
const char *pin_group,
|
||||||
|
unsigned long config);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline int pin_config_get(const char *dev_name, const char *name,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pin_config_set(const char *dev_name, const char *name,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pin_config_group_get(const char *dev_name,
|
||||||
|
const char *pin_group,
|
||||||
|
unsigned long *config)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pin_config_group_set(const char *dev_name,
|
||||||
|
const char *pin_group,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LINUX_PINCTRL_PINCONF_H */
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
struct pinctrl_dev;
|
struct pinctrl_dev;
|
||||||
struct pinmux_ops;
|
struct pinmux_ops;
|
||||||
|
struct pinconf_ops;
|
||||||
struct gpio_chip;
|
struct gpio_chip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +46,7 @@ struct pinctrl_pin_desc {
|
||||||
* @name: a name for the chip in this range
|
* @name: a name for the chip in this range
|
||||||
* @id: an ID number for the chip in this range
|
* @id: an ID number for the chip in this range
|
||||||
* @base: base offset of the GPIO range
|
* @base: base offset of the GPIO range
|
||||||
|
* @pin_base: base pin number of the GPIO range
|
||||||
* @npins: number of pins in the GPIO range, including the base number
|
* @npins: number of pins in the GPIO range, including the base number
|
||||||
* @gc: an optional pointer to a gpio_chip
|
* @gc: an optional pointer to a gpio_chip
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +55,7 @@ struct pinctrl_gpio_range {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
unsigned int base;
|
unsigned int base;
|
||||||
|
unsigned int pin_base;
|
||||||
unsigned int npins;
|
unsigned int npins;
|
||||||
struct gpio_chip *gc;
|
struct gpio_chip *gc;
|
||||||
};
|
};
|
||||||
|
@ -89,22 +92,20 @@ struct pinctrl_ops {
|
||||||
* this pin controller
|
* this pin controller
|
||||||
* @npins: number of descriptors in the array, usually just ARRAY_SIZE()
|
* @npins: number of descriptors in the array, usually just ARRAY_SIZE()
|
||||||
* of the pins field above
|
* of the pins field above
|
||||||
* @maxpin: since pin spaces may be sparse, there can he "holes" in the
|
|
||||||
* pin range, this attribute gives the maximum pin number in the
|
|
||||||
* total range. This should not be lower than npins for example,
|
|
||||||
* but may be equal to npins if you have no holes in the pin range.
|
|
||||||
* @pctlops: pin control operation vtable, to support global concepts like
|
* @pctlops: pin control operation vtable, to support global concepts like
|
||||||
* grouping of pins, this is optional.
|
* grouping of pins, this is optional.
|
||||||
* @pmxops: pinmux operation vtable, if you support pinmuxing in your driver
|
* @pmxops: pinmux operations vtable, if you support pinmuxing in your driver
|
||||||
|
* @confops: pin config operations vtable, if you support pin configuration in
|
||||||
|
* your driver
|
||||||
* @owner: module providing the pin controller, used for refcounting
|
* @owner: module providing the pin controller, used for refcounting
|
||||||
*/
|
*/
|
||||||
struct pinctrl_desc {
|
struct pinctrl_desc {
|
||||||
const char *name;
|
const char *name;
|
||||||
struct pinctrl_pin_desc const *pins;
|
struct pinctrl_pin_desc const *pins;
|
||||||
unsigned int npins;
|
unsigned int npins;
|
||||||
unsigned int maxpin;
|
|
||||||
struct pinctrl_ops *pctlops;
|
struct pinctrl_ops *pctlops;
|
||||||
struct pinmux_ops *pmxops;
|
struct pinmux_ops *pmxops;
|
||||||
|
struct pinconf_ops *confops;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,7 +124,7 @@ extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
|
||||||
|
|
||||||
struct pinctrl_dev;
|
struct pinctrl_dev;
|
||||||
|
|
||||||
/* Sufficiently stupid default function when pinctrl is not in use */
|
/* Sufficiently stupid default functions when pinctrl is not in use */
|
||||||
static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
|
static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
|
||||||
{
|
{
|
||||||
return pin >= 0;
|
return pin >= 0;
|
||||||
|
|
|
@ -52,9 +52,15 @@ struct pinctrl_dev;
|
||||||
* @disable: disable a certain muxing selector with a certain pin group
|
* @disable: disable a certain muxing selector with a certain pin group
|
||||||
* @gpio_request_enable: requests and enables GPIO on a certain pin.
|
* @gpio_request_enable: requests and enables GPIO on a certain pin.
|
||||||
* 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 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);
|
||||||
|
@ -73,11 +79,20 @@ struct pinmux_ops {
|
||||||
int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
|
int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
|
||||||
struct pinctrl_gpio_range *range,
|
struct pinctrl_gpio_range *range,
|
||||||
unsigned offset);
|
unsigned offset);
|
||||||
|
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 */
|
/* 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);
|
||||||
|
@ -94,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;
|
||||||
|
|
Loading…
Reference in a new issue