Commit 5ab4909d authored by Linus Walleij's avatar Linus Walleij

Merge tag 'intel-pinctrl-v6.3-1' of...

Merge tag 'intel-pinctrl-v6.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel into devel

intel-pinctrl for v6.3-1

* Add ~4kOhm bias support to Intel pin control drivers
* Convert Intel pin control drivers to use INTEL_COMMUNITY_*()
* Add struct pinfunction and use it in Intel pin control drivers
* Make pin control documentation up to date
* Miscellaneous cleanups

The following is an automated git shortlog grouped by driver:

pinctrl:
 - Proofreading and updating the documentation accordingly
 - Proofreading and updating the documentation (part 2)

alderlake:
 -  Replace ADL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

baytrail:
 -  Convert to use new memeber in struct intel_function

broxton:
 -  Replace BXT_COMMUNITY() by INTEL_COMMUNITY_SIZE()

cannonlake:
 -  Replace CNL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

cedarfork:
 -  Replace CDF_COMMUNITY() by INTEL_COMMUNITY_GPPS()

cherryview:
 -  Convert to use new memeber in struct intel_function

denverton:
 -  Replace DNV_COMMUNITY() by INTEL_COMMUNITY_GPPS()

elkhartlake:
 -  Replace EHL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

emmitsburg:
 -  Replace EBG_COMMUNITY() by INTEL_COMMUNITY_GPPS()

geminilake:
 -  Replace GLK_COMMUNITY() by INTEL_COMMUNITY_SIZE()

icelake:
 -  Replace ICL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

intel:
 -  Get rid of unused members in struct intel_function
 -  Make use of struct pinfunction and PINCTRL_PINFUNCTION()
 -  Define maximum pad number in the group
 -  Use same order of bit fields for PADCFG2
 -  Add ~4k bias support
 -  Add definitions to all possible biases
 -  Deduplicate some code in intel_config_set_pull()
 -  Add default case to intel_config_set_pull()
 -  Convert to generic_handle_domain_irq()
 -  Always use gpp_num_padown_regs in the main driver
 -  Introduce INTEL_COMMUNITY_*() to unify community macros

Introduce struct pinfunction and PINCTRL_PINFUNCTION() macro:
 - Introduce struct pinfunction and PINCTRL_PINFUNCTION() macro

jasperlake:
 -  Replace JSL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

lakefield:
 -  Replace LKF_COMMUNITY() by INTEL_COMMUNITY_GPPS()

lewisburg:
 -  Replace LBG_COMMUNITY() by INTEL_COMMUNITY_SIZE()

lynxpoint:
 -  Convert to use new memeber in struct intel_function

merrifield:
 -  Convert to use new memeber in struct intel_function

meteorlake:
 -  Replace MTL_COMMUNITY() by INTEL_COMMUNITY_GPPS()

moorefield:
 -  Convert to use new memeber in struct intel_function

sunrisepoint:
 -  Replace SPT_COMMUNITY() by INTEL_COMMUNITY_*()

tigerlake:
 -  Replace TGL_COMMUNITY() by INTEL_COMMUNITY_GPPS()
parents 19a2c394 88f8ac47
...@@ -11,20 +11,18 @@ This subsystem deals with: ...@@ -11,20 +11,18 @@ This subsystem deals with:
- Multiplexing of pins, pads, fingers (etc) see below for details - Multiplexing of pins, pads, fingers (etc) see below for details
- Configuration of pins, pads, fingers (etc), such as software-controlled - Configuration of pins, pads, fingers (etc), such as software-controlled
biasing and driving mode specific pins, such as pull-up/down, open drain, biasing and driving mode specific pins, such as pull-up, pull-down, open drain,
load capacitance etc. load capacitance etc.
Top-level interface Top-level interface
=================== ===================
Definition of PIN CONTROLLER: Definitions:
- A pin controller is a piece of hardware, usually a set of registers, that - A PIN CONTROLLER is a piece of hardware, usually a set of registers, that
can control PINs. It may be able to multiplex, bias, set load capacitance, can control PINs. It may be able to multiplex, bias, set load capacitance,
set drive strength, etc. for individual pins or groups of pins. set drive strength, etc. for individual pins or groups of pins.
Definition of PIN:
- PINS are equal to pads, fingers, balls or whatever packaging input or - PINS are equal to pads, fingers, balls or whatever packaging input or
output line you want to control and these are denoted by unsigned integers output line you want to control and these are denoted by unsigned integers
in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so
...@@ -57,7 +55,9 @@ Here is an example of a PGA (Pin Grid Array) chip seen from underneath:: ...@@ -57,7 +55,9 @@ Here is an example of a PGA (Pin Grid Array) chip seen from underneath::
1 o o o o o o o o 1 o o o o o o o o
To register a pin controller and name all the pins on this package we can do To register a pin controller and name all the pins on this package we can do
this in our driver:: this in our driver:
.. code-block:: c
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
...@@ -78,14 +78,13 @@ this in our driver:: ...@@ -78,14 +78,13 @@ this in our driver::
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
int __init foo_probe(void) int __init foo_init(void)
{ {
int error; int error;
struct pinctrl_dev *pctl; struct pinctrl_dev *pctl;
error = pinctrl_register_and_init(&foo_desc, <PARENT>, error = pinctrl_register_and_init(&foo_desc, <PARENT>, NULL, &pctl);
NULL, &pctl);
if (error) if (error)
return error; return error;
...@@ -95,20 +94,20 @@ this in our driver:: ...@@ -95,20 +94,20 @@ this in our driver::
To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and 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, 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. since these are so tightly integrated with the machines they are used on.
See for example arch/arm/mach-ux500/Kconfig for an example. See ``arch/arm/mach-ux500/Kconfig`` for an example.
Pins usually have fancier names than this. You can find these in the datasheet Pins usually have fancier names than this. You can find these in the datasheet
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 the pins are
the pins from 0 in the upper left corner to 63 in the lower right corner. enumerated 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
the pin controller. the pin controller.
For a padring with 467 pads, as opposed to actual pins, I used an enumeration For a padding with 467 pads, as opposed to actual pins, the enumeration will
like this, walking around the edge of the chip, which seems to be industry be like this, walking around the edge of the chip, which seems to be industry
standard too (all these pads had names, too):: standard too (all these pads had names, too)::
...@@ -132,50 +131,38 @@ on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins ...@@ -132,50 +131,38 @@ on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins
on { 24, 25 }. on { 24, 25 }.
These two groups are presented to the pin control subsystem by implementing These two groups are presented to the pin control subsystem by implementing
some generic pinctrl_ops like this:: some generic ``pinctrl_ops`` like this:
#include <linux/pinctrl/pinctrl.h> .. code-block:: c
struct foo_group { #include <linux/pinctrl/pinctrl.h>
const char *name;
const unsigned int *pins;
const unsigned num_pins;
};
static const unsigned int spi0_pins[] = { 0, 8, 16, 24 }; static const unsigned int spi0_pins[] = { 0, 8, 16, 24 };
static const unsigned int i2c0_pins[] = { 24, 25 }; static const unsigned int i2c0_pins[] = { 24, 25 };
static const struct foo_group foo_groups[] = { static const struct pingroup foo_groups[] = {
{ PINCTRL_PINGROUP("spi0_grp", spi0_pins, ARRAY_SIZE(spi0_pins)),
.name = "spi0_grp", PINCTRL_PINGROUP("i2c0_grp", i2c0_pins, ARRAY_SIZE(i2c0_pins)),
.pins = spi0_pins,
.num_pins = ARRAY_SIZE(spi0_pins),
},
{
.name = "i2c0_grp",
.pins = i2c0_pins,
.num_pins = ARRAY_SIZE(i2c0_pins),
},
}; };
static int foo_get_groups_count(struct pinctrl_dev *pctldev) static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{ {
return ARRAY_SIZE(foo_groups); return ARRAY_SIZE(foo_groups);
} }
static const char *foo_get_group_name(struct pinctrl_dev *pctldev, static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector) unsigned int selector)
{ {
return foo_groups[selector].name; return foo_groups[selector].name;
} }
static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, static int foo_get_group_pins(struct pinctrl_dev *pctldev,
const unsigned **pins, unsigned int selector,
unsigned *num_pins) const unsigned int **pins,
unsigned int *npins)
{ {
*pins = (unsigned *) foo_groups[selector].pins; *pins = foo_groups[selector].pins;
*num_pins = foo_groups[selector].num_pins; *npins = foo_groups[selector].npins;
return 0; return 0;
} }
...@@ -185,13 +172,12 @@ some generic pinctrl_ops like this:: ...@@ -185,13 +172,12 @@ some generic pinctrl_ops like this::
.get_group_pins = foo_get_group_pins, .get_group_pins = foo_get_group_pins,
}; };
static struct pinctrl_desc foo_desc = { static struct pinctrl_desc foo_desc = {
... ...
.pctlops = &foo_pctrl_ops, .pctlops = &foo_pctrl_ops,
}; };
The pin control subsystem will call the .get_groups_count() function to The pin control subsystem will call the ``.get_groups_count()`` function to
determine the total number of legal selectors, then it will call the other functions determine the total number of legal selectors, then it will call the other functions
to retrieve the name and pins of the group. Maintaining the data structure of to retrieve the name and pins of the group. Maintaining the data structure of
the groups is up to the driver, this is just a simple example - in practice you the groups is up to the driver, this is just a simple example - in practice you
...@@ -204,38 +190,41 @@ Pin configuration ...@@ -204,38 +190,41 @@ Pin configuration
Pins can sometimes be software-configured in various ways, mostly related Pins can sometimes be software-configured in various ways, mostly related
to their electronic properties when used as inputs or outputs. For example you 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 may be able to make an output pin high impedance (Hi-Z), or "tristate" meaning it is
effectively disconnected. You may be able to connect an input pin to VDD or GND 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 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 stable value when nothing is driving the rail it is connected to, or when it's
unconnected. unconnected.
Pin configuration can be programmed by adding configuration entries into the Pin configuration can be programmed by adding configuration entries into the
mapping table; see section "Board/machine configuration" below. mapping table; see section `Board/machine configuration`_ below.
The format and meaning of the configuration parameter, PLATFORM_X_PULL_UP The format and meaning of the configuration parameter, PLATFORM_X_PULL_UP
above, is entirely defined by the pin controller driver. above, is entirely defined by the pin controller driver.
The pin configuration driver implements callbacks for changing pin The pin configuration driver implements callbacks for changing pin
configuration in the pin controller ops like this:: configuration in the pin controller ops like this:
.. code-block:: c
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include "platform_x_pindefs.h" #include "platform_x_pindefs.h"
static int foo_pin_config_get(struct pinctrl_dev *pctldev, static int foo_pin_config_get(struct pinctrl_dev *pctldev,
unsigned offset, unsigned int offset,
unsigned long *config) unsigned long *config)
{ {
struct my_conftype conf; struct my_conftype conf;
... Find setting for pin @ offset ... /* ... Find setting for pin @ offset ... */
*config = (unsigned long) conf; *config = (unsigned long) conf;
} }
static int foo_pin_config_set(struct pinctrl_dev *pctldev, static int foo_pin_config_set(struct pinctrl_dev *pctldev,
unsigned offset, unsigned int offset,
unsigned long config) unsigned long config)
{ {
struct my_conftype *conf = (struct my_conftype *) config; struct my_conftype *conf = (struct my_conftype *) config;
...@@ -243,18 +232,18 @@ configuration in the pin controller ops like this:: ...@@ -243,18 +232,18 @@ configuration in the pin controller ops like this::
switch (conf) { switch (conf) {
case PLATFORM_X_PULL_UP: case PLATFORM_X_PULL_UP:
... ...
} break;
} }
} }
static int foo_pin_config_group_get (struct pinctrl_dev *pctldev, static int foo_pin_config_group_get(struct pinctrl_dev *pctldev,
unsigned selector, unsigned selector,
unsigned long *config) unsigned long *config)
{ {
... ...
} }
static int foo_pin_config_group_set (struct pinctrl_dev *pctldev, static int foo_pin_config_group_set(struct pinctrl_dev *pctldev,
unsigned selector, unsigned selector,
unsigned long config) unsigned long config)
{ {
...@@ -281,8 +270,8 @@ The GPIO drivers may want to perform operations of various types on the same ...@@ -281,8 +270,8 @@ The GPIO drivers may want to perform operations of various types on the same
physical pins that are also registered as pin controller pins. physical pins that are also registered as pin controller pins.
First and foremost, the two subsystems can be used as completely orthogonal, First and foremost, the two subsystems can be used as completely orthogonal,
see the section named "pin control requests from drivers" and see the section named `Pin control requests from drivers`_ and
"drivers needing both pin control and GPIOs" below for details. But in some `Drivers needing both pin control and GPIOs`_ below for details. But in some
situations a cross-subsystem mapping between pins and GPIOs is needed. situations a cross-subsystem mapping between pins and GPIOs is needed.
Since the pin controller subsystem has its pinspace local to the pin controller Since the pin controller subsystem has its pinspace local to the pin controller
...@@ -291,7 +280,13 @@ controller handles control of a certain GPIO pin. Since a single pin controller ...@@ -291,7 +280,13 @@ controller handles control of a certain GPIO pin. Since a single pin controller
may be muxing several GPIO ranges (typically SoCs that have one set of pins, may be muxing several GPIO ranges (typically SoCs that have one set of pins,
but internally several GPIO silicon blocks, each modelled as a struct but internally several GPIO silicon blocks, each modelled as a struct
gpio_chip) any number of GPIO ranges can be added to a pin controller instance gpio_chip) any number of GPIO ranges can be added to a pin controller instance
like this:: like this:
.. code-block:: c
#include <linux/gpio/driver.h>
#include <linux/pinctrl/pinctrl.h>
struct gpio_chip chip_a; struct gpio_chip chip_a;
struct gpio_chip chip_b; struct gpio_chip chip_b;
...@@ -302,7 +297,7 @@ like this:: ...@@ -302,7 +297,7 @@ like this::
.base = 32, .base = 32,
.pin_base = 32, .pin_base = 32,
.npins = 16, .npins = 16,
.gc = &chip_a; .gc = &chip_a,
}; };
static struct pinctrl_gpio_range gpio_range_b = { static struct pinctrl_gpio_range gpio_range_b = {
...@@ -314,16 +309,18 @@ like this:: ...@@ -314,16 +309,18 @@ like this::
.gc = &chip_b; .gc = &chip_b;
}; };
int __init foo_init(void)
{ {
struct pinctrl_dev *pctl; struct pinctrl_dev *pctl;
... ...
pinctrl_add_gpio_range(pctl, &gpio_range_a); pinctrl_add_gpio_range(pctl, &gpio_range_a);
pinctrl_add_gpio_range(pctl, &gpio_range_b); pinctrl_add_gpio_range(pctl, &gpio_range_b);
...
} }
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. The "chip a" and GPIO chips. "chip a" has 16 pins and "chip b" has 8 pins. The "chip a" and
"chip b" have different .pin_base, which means a start pin number of the "chip b" have different ``pin_base``, which means a start pin number of the
GPIO range. GPIO range.
The GPIO range of "chip a" starts from the GPIO base of 32 and actual The GPIO range of "chip a" starts from the GPIO base of 32 and actual
...@@ -331,7 +328,7 @@ pin range also starts from 32. However "chip b" has different starting ...@@ -331,7 +328,7 @@ 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 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. 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". We can convert a gpio number to actual pin number using this ``pin_base``.
They are mapped in the global GPIO pin space at: They are mapped in the global GPIO pin space at:
chip a: chip a:
...@@ -343,9 +340,11 @@ chip b: ...@@ -343,9 +340,11 @@ chip b:
The above examples assume the mapping between the GPIOs and pins is The above examples assume the mapping between the GPIOs and pins is
linear. If the mapping is sparse or haphazard, an array of arbitrary pin linear. If the mapping is sparse or haphazard, an array of arbitrary pin
numbers can be encoded in the range like this:: numbers can be encoded in the range like this:
static const unsigned range_pins[] = { 14, 1, 22, 17, 10, 8, 6, 2 }; .. code-block:: c
static const unsigned int range_pins[] = { 14, 1, 22, 17, 10, 8, 6, 2 };
static struct pinctrl_gpio_range gpio_range = { static struct pinctrl_gpio_range gpio_range = {
.name = "chip", .name = "chip",
...@@ -353,16 +352,17 @@ numbers can be encoded in the range like this:: ...@@ -353,16 +352,17 @@ numbers can be encoded in the range like this::
.base = 32, .base = 32,
.pins = &range_pins, .pins = &range_pins,
.npins = ARRAY_SIZE(range_pins), .npins = ARRAY_SIZE(range_pins),
.gc = &chip; .gc = &chip,
}; };
In this case the pin_base property will be ignored. If the name of a pin In this case the ``pin_base`` property will be ignored. If the name of a pin
group is known, the pins and npins elements of the above structure can be group is known, the pins and npins elements of the above structure can be
initialised using the function pinctrl_get_group_pins(), e.g. for pin initialised using the function ``pinctrl_get_group_pins()``, e.g. for pin
group "foo":: group "foo":
.. code-block:: c
pinctrl_get_group_pins(pctl, "foo", &gpio_range.pins, pinctrl_get_group_pins(pctl, "foo", &gpio_range.pins, &gpio_range.npins);
&gpio_range.npins);
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 appropriate pin controller by inspecting ranges will be used to look up the appropriate pin controller by inspecting
...@@ -378,8 +378,8 @@ will get a pin number into its handled number range. Further it is also passed ...@@ -378,8 +378,8 @@ will get a 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.
Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see Calling ``pinctrl_add_gpio_range()`` from pinctrl driver is DEPRECATED. Please see
section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind section 2.1 of ``Documentation/devicetree/bindings/gpio/gpio.txt`` on how to bind
pinctrl and gpio drivers. pinctrl and gpio drivers.
...@@ -466,10 +466,10 @@ in your machine configuration. It is inspired by the clk, GPIO and regulator ...@@ -466,10 +466,10 @@ in your machine configuration. It is inspired by the clk, GPIO and regulator
subsystems, so devices will request their mux setting, but it's also possible subsystems, so devices will request their mux setting, but it's also possible
to request a single pin for e.g. GPIO. to request a single pin for e.g. GPIO.
Definitions: The conventions are:
- FUNCTIONS can be switched in and out by a driver residing with the pin - FUNCTIONS can be switched in and out by a driver residing with the pin
control subsystem in the drivers/pinctrl/* directory of the kernel. The control subsystem in the ``drivers/pinctrl`` directory of the kernel. The
pin control driver knows the possible functions. In the example above you can pin control driver knows the possible functions. In the example above you can
identify three pinmux functions, one for spi, one for i2c and one for mmc. identify three pinmux functions, one for spi, one for i2c and one for mmc.
...@@ -515,11 +515,13 @@ Definitions: ...@@ -515,11 +515,13 @@ Definitions:
In the example case we can define that this particular machine shall In the example case we can define that this particular machine shall
use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function
fi2c0 group gi2c0, on the primary pin controller, we get mappings fi2c0 group gi2c0, on the primary pin controller, we get mappings
like these:: like these:
.. code-block:: c
{ {
{"map-spi0", spi0, pinctrl0, fspi0, gspi0}, {"map-spi0", spi0, pinctrl0, fspi0, gspi0},
{"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0} {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0},
} }
Every map must be assigned a state name, pin controller, device and Every map must be assigned a state name, pin controller, device and
...@@ -569,80 +571,51 @@ is possible to perform the requested mux setting, poke the hardware so that ...@@ -569,80 +571,51 @@ is possible to perform the requested mux setting, poke the hardware so that
this happens. this happens.
Pinmux drivers are required to supply a few callback functions, some are Pinmux drivers are required to supply a few callback functions, some are
optional. Usually the set_mux() function is implemented, writing values into optional. Usually the ``.set_mux()`` function is implemented, writing values into
some certain registers to activate a certain mux setting for a certain pin. some certain registers to activate a certain mux setting for a certain pin.
A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4 A simple driver for the above example will work by setting bits 0, 1, 2, 3, 4, or 5
into some register named MUX to select a certain function with a certain into some register named MUX to select a certain function with a certain
group of pins would work something like this:: group of pins would work something like this:
.. code-block:: c
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
struct foo_group { static const unsigned int spi0_0_pins[] = { 0, 8, 16, 24 };
const char *name; static const unsigned int spi0_1_pins[] = { 38, 46, 54, 62 };
const unsigned int *pins; static const unsigned int i2c0_pins[] = { 24, 25 };
const unsigned num_pins; static const unsigned int mmc0_1_pins[] = { 56, 57 };
}; static const unsigned int mmc0_2_pins[] = { 58, 59 };
static const unsigned int mmc0_3_pins[] = { 60, 61, 62, 63 };
static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 };
static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 }; static const struct pingroup foo_groups[] = {
static const unsigned i2c0_pins[] = { 24, 25 }; PINCTRL_PINGROUP("spi0_0_grp", spi0_0_pins, ARRAY_SIZE(spi0_0_pins)),
static const unsigned mmc0_1_pins[] = { 56, 57 }; PINCTRL_PINGROUP("spi0_1_grp", spi0_1_pins, ARRAY_SIZE(spi0_1_pins)),
static const unsigned mmc0_2_pins[] = { 58, 59 }; PINCTRL_PINGROUP("i2c0_grp", i2c0_pins, ARRAY_SIZE(i2c0_pins)),
static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 }; PINCTRL_PINGROUP("mmc0_1_grp", mmc0_1_pins, ARRAY_SIZE(mmc0_1_pins)),
PINCTRL_PINGROUP("mmc0_2_grp", mmc0_2_pins, ARRAY_SIZE(mmc0_2_pins)),
static const struct foo_group foo_groups[] = { PINCTRL_PINGROUP("mmc0_3_grp", mmc0_3_pins, ARRAY_SIZE(mmc0_3_pins)),
{
.name = "spi0_0_grp",
.pins = spi0_0_pins,
.num_pins = ARRAY_SIZE(spi0_0_pins),
},
{
.name = "spi0_1_grp",
.pins = spi0_1_pins,
.num_pins = ARRAY_SIZE(spi0_1_pins),
},
{
.name = "i2c0_grp",
.pins = i2c0_pins,
.num_pins = ARRAY_SIZE(i2c0_pins),
},
{
.name = "mmc0_1_grp",
.pins = mmc0_1_pins,
.num_pins = ARRAY_SIZE(mmc0_1_pins),
},
{
.name = "mmc0_2_grp",
.pins = mmc0_2_pins,
.num_pins = ARRAY_SIZE(mmc0_2_pins),
},
{
.name = "mmc0_3_grp",
.pins = mmc0_3_pins,
.num_pins = ARRAY_SIZE(mmc0_3_pins),
},
}; };
static int foo_get_groups_count(struct pinctrl_dev *pctldev) static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{ {
return ARRAY_SIZE(foo_groups); return ARRAY_SIZE(foo_groups);
} }
static const char *foo_get_group_name(struct pinctrl_dev *pctldev, static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector) unsigned int selector)
{ {
return foo_groups[selector].name; return foo_groups[selector].name;
} }
static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
const unsigned ** pins, const unsigned int **pins,
unsigned * num_pins) unsigned int *npins)
{ {
*pins = (unsigned *) foo_groups[selector].pins; *pins = foo_groups[selector].pins;
*num_pins = foo_groups[selector].num_pins; *npins = foo_groups[selector].npins;
return 0; return 0;
} }
...@@ -652,33 +625,14 @@ group of pins would work something like this:: ...@@ -652,33 +625,14 @@ group of pins would work something like this::
.get_group_pins = foo_get_group_pins, .get_group_pins = foo_get_group_pins,
}; };
struct foo_pmx_func {
const char *name;
const char * const *groups;
const unsigned num_groups;
};
static const char * const spi0_groups[] = { "spi0_0_grp", "spi0_1_grp" }; static const char * const spi0_groups[] = { "spi0_0_grp", "spi0_1_grp" };
static const char * const i2c0_groups[] = { "i2c0_grp" }; static const char * const i2c0_groups[] = { "i2c0_grp" };
static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp", static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp", "mmc0_3_grp" };
"mmc0_3_grp" };
static const struct foo_pmx_func foo_functions[] = { static const struct pinfunction foo_functions[] = {
{ PINCTRL_PINFUNCTION("spi0", spi0_groups, ARRAY_SIZE(spi0_groups)),
.name = "spi0", PINCTRL_PINFUNCTION("i2c0", i2c0_groups, ARRAY_SIZE(i2c0_groups)),
.groups = spi0_groups, PINCTRL_PINFUNCTION("mmc0", mmc0_groups, ARRAY_SIZE(mmc0_groups)),
.num_groups = ARRAY_SIZE(spi0_groups),
},
{
.name = "i2c0",
.groups = i2c0_groups,
.num_groups = ARRAY_SIZE(i2c0_groups),
},
{
.name = "mmc0",
.groups = mmc0_groups,
.num_groups = ARRAY_SIZE(mmc0_groups),
},
}; };
static int foo_get_functions_count(struct pinctrl_dev *pctldev) static int foo_get_functions_count(struct pinctrl_dev *pctldev)
...@@ -686,26 +640,26 @@ group of pins would work something like this:: ...@@ -686,26 +640,26 @@ group of pins would work something like this::
return ARRAY_SIZE(foo_functions); return ARRAY_SIZE(foo_functions);
} }
static const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector) static const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned int selector)
{ {
return foo_functions[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 int selector,
const char * const **groups, const char * const **groups,
unsigned * const num_groups) unsigned int * const ngroups)
{ {
*groups = foo_functions[selector].groups; *groups = foo_functions[selector].groups;
*num_groups = foo_functions[selector].num_groups; *ngroups = foo_functions[selector].ngroups;
return 0; return 0;
} }
static int foo_set_mux(struct pinctrl_dev *pctldev, unsigned selector, static int foo_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
unsigned group) unsigned int group)
{ {
u8 regbit = (1 << selector + group); u8 regbit = BIT(group);
writeb((readb(MUX)|regbit), MUX); writeb((readb(MUX) | regbit), MUX);
return 0; return 0;
} }
...@@ -724,16 +678,17 @@ group of pins would work something like this:: ...@@ -724,16 +678,17 @@ group of pins would work something like this::
.pmxops = &foo_pmxops, .pmxops = &foo_pmxops,
}; };
In the example activating muxing 0 and 1 at the same time setting bits In the example activating muxing 0 and 2 at the same time setting bits
0 and 1, uses one pin in common so they would collide. 0 and 2, uses pin 24 in common so they would collide. All the same for
the muxes 1 and 5, which have pin 62 in common.
The beauty of the pinmux subsystem is that since it keeps track of all The beauty of the pinmux subsystem is that since it keeps track of all
pins and who is using them, it will already have denied an impossible pins and who is using them, it will already have denied an impossible
request like that, so the driver does not need to worry about such request like that, so the driver does not need to worry about such
things - when it gets a selector passed in, the pinmux subsystem makes things - when it gets a selector passed in, the pinmux subsystem makes
sure no other device or GPIO assignment is already using the selected sure no other device or GPIO assignment is already using the selected
pins. Thus bits 0 and 1 in the control register will never be set at the pins. Thus bits 0 and 2, or 1 and 5 in the control register will never
same time. be set at the same time.
All the above functions are mandatory to implement for a pinmux driver. All the above functions are mandatory to implement for a pinmux driver.
...@@ -742,18 +697,18 @@ Pin control interaction with the GPIO subsystem ...@@ -742,18 +697,18 @@ Pin control interaction with the GPIO subsystem
=============================================== ===============================================
Note that the following implies that the use case is to use a certain pin Note that the following implies that the use case is to use a certain pin
from the Linux kernel using the API in <linux/gpio.h> with gpio_request() from the Linux kernel using the API in ``<linux/gpio/consumer.h>`` with gpiod_get()
and similar functions. There are cases where you may be using something and similar functions. There are cases where you may be using something
that your datasheet calls "GPIO mode", but actually is just an electrical that your datasheet calls "GPIO mode", but actually is just an electrical
configuration for a certain device. See the section below named configuration for a certain device. See the section below named
"GPIO mode pitfalls" for more details on this scenario. `GPIO mode pitfalls`_ for more details on this scenario.
The public pinmux API contains two functions named pinctrl_gpio_request() The public pinmux API contains two functions named ``pinctrl_gpio_request()``
and pinctrl_gpio_free(). These two functions shall *ONLY* be called from and ``pinctrl_gpio_free()``. These two functions shall *ONLY* be called from
gpiolib-based drivers as part of their gpio_request() and gpiolib-based drivers as part of their ``.request()`` and ``.free()`` semantics.
gpio_free() semantics. Likewise the pinctrl_gpio_direction_[input|output] Likewise the ``pinctrl_gpio_direction_input()`` / ``pinctrl_gpio_direction_output()``
shall only be called from within respective gpio_direction_[input|output] shall only be called from within respective ``.direction_input()`` /
gpiolib implementation. ``.direction_output()`` gpiolib implementation.
NOTE that platforms and individual drivers shall *NOT* request GPIO pins to be NOTE that platforms and individual drivers shall *NOT* request GPIO pins to be
controlled e.g. muxed in. Instead, implement a proper gpiolib driver and have controlled e.g. muxed in. Instead, implement a proper gpiolib driver and have
...@@ -767,8 +722,8 @@ In this case, the function array would become 64 entries for each GPIO ...@@ -767,8 +722,8 @@ 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 are two functions a pin control driver can implement For this reason there are two functions a pin control driver can implement
to enable only GPIO on an individual pin: .gpio_request_enable() and to enable only GPIO on an individual pin: ``.gpio_request_enable()`` and
.gpio_disable_free(). ``.gpio_disable_free()``.
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
...@@ -776,12 +731,12 @@ operation. ...@@ -776,12 +731,12 @@ operation.
If your driver needs to have an indication from the framework of whether the If your driver needs to have an indication from the framework of whether the
GPIO pin shall be used for input or output you can implement the GPIO pin shall be used for input or output you can implement the
.gpio_set_direction() function. As described this shall be called from the ``.gpio_set_direction()`` function. As described this shall be called from the
gpiolib driver and the affected GPIO range, pin offset and desired direction gpiolib driver and the affected GPIO range, pin offset and desired direction
will be passed along to this function. will be passed along to this function.
Alternatively to using these special functions, it is fully allowed to use Alternatively to using these special functions, it is fully allowed to use
named functions for each GPIO pin, the pinctrl_gpio_request() will attempt to named functions for each GPIO pin, the ``pinctrl_gpio_request()`` will attempt to
obtain the function "gpioN" where "N" is the global GPIO pin number if no obtain the function "gpioN" where "N" is the global GPIO pin number if no
special GPIO-handler is registered. special GPIO-handler is registered.
...@@ -794,7 +749,7 @@ is taken to mean different things than what the kernel does, the developer ...@@ -794,7 +749,7 @@ is taken to mean different things than what the kernel does, the developer
may be confused by a datasheet talking about a pin being possible to set may be confused by a datasheet talking about a pin being possible to set
into "GPIO mode". It appears that what hardware engineers mean with into "GPIO mode". It appears that what hardware engineers mean with
"GPIO mode" is not necessarily the use case that is implied in the kernel "GPIO mode" is not necessarily the use case that is implied in the kernel
interface <linux/gpio.h>: a pin that you grab from kernel code and then interface ``<linux/gpio/consumer.h>``: a pin that you grab from kernel code and then
either listen for input or drive high/low to assert/deassert some either listen for input or drive high/low to assert/deassert some
external line. external line.
...@@ -805,9 +760,10 @@ for a device. ...@@ -805,9 +760,10 @@ for a device.
The GPIO portions of a pin and its relation to a certain pin controller The GPIO portions of a pin and its relation to a certain pin controller
configuration and muxing logic can be constructed in several ways. Here configuration and muxing logic can be constructed in several ways. Here
are two examples:: are two examples.
Example **(A)**::
(A)
pin config pin config
logic regs logic regs
| +- SPI | +- SPI
...@@ -836,9 +792,7 @@ simultaneous access to the same pin from GPIO and pin multiplexing ...@@ -836,9 +792,7 @@ simultaneous access to the same pin from GPIO and pin multiplexing
consumers on hardware of this type. The pinctrl driver should set this flag consumers on hardware of this type. The pinctrl driver should set this flag
accordingly. accordingly.
:: Example **(B)**::
(B)
pin config pin config
logic regs logic regs
...@@ -899,14 +853,14 @@ If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start ...@@ -899,14 +853,14 @@ If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start
to think that you need to come up with something really complex, that the to think that you need to come up with something really complex, that the
pin shall be used for UART TX and GPIO at the same time, that you will grab pin shall be used for UART TX and GPIO at the same time, that you will grab
a pin control handle and set it to a certain state to enable UART TX to be a pin control handle and set it to a certain state to enable UART TX to be
muxed in, then twist it over to GPIO mode and use gpio_direction_output() muxed in, then twist it over to GPIO mode and use gpiod_direction_output()
to drive it low during sleep, then mux it over to UART TX again when you to drive it low during sleep, then mux it over to UART TX again when you
wake up and maybe even gpio_request/gpio_free as part of this cycle. This wake up and maybe even gpiod_get() / gpiod_put() as part of this cycle. This
all gets very complicated. all gets very complicated.
The solution is to not think that what the datasheet calls "GPIO mode" The solution is to not think that what the datasheet calls "GPIO mode"
has to be handled by the <linux/gpio.h> interface. Instead view this as has to be handled by the ``<linux/gpio/consumer.h>`` interface. Instead view this as
a certain pin config setting. Look in e.g. <linux/pinctrl/pinconf-generic.h> a certain pin config setting. Look in e.g. ``<linux/pinctrl/pinconf-generic.h>``
and you find this in the documentation: and you find this in the documentation:
PIN_CONFIG_OUTPUT: PIN_CONFIG_OUTPUT:
...@@ -915,7 +869,9 @@ and you find this in the documentation: ...@@ -915,7 +869,9 @@ and you find this in the documentation:
So it is perfectly possible to push a pin into "GPIO mode" and drive the So it is perfectly possible to push a pin into "GPIO mode" and drive the
line low as part of the usual pin control map. So for example your UART line low as part of the usual pin control map. So for example your UART
driver may look like this:: driver may look like this:
.. code-block:: c
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -928,13 +884,13 @@ driver may look like this:: ...@@ -928,13 +884,13 @@ driver may look like this::
/* Normal mode */ /* Normal mode */
retval = pinctrl_select_state(pinctrl, pins_default); retval = pinctrl_select_state(pinctrl, pins_default);
/* Sleep mode */ /* Sleep mode */
retval = pinctrl_select_state(pinctrl, pins_sleep); retval = pinctrl_select_state(pinctrl, pins_sleep);
And your machine configuration may look like this: And your machine configuration may look like this:
--------------------------------------------------
:: .. code-block:: c
static unsigned long uart_default_mode[] = { static unsigned long uart_default_mode[] = {
PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0), PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
...@@ -955,7 +911,8 @@ And your machine configuration may look like this: ...@@ -955,7 +911,8 @@ And your machine configuration may look like this:
"UART_TX_PIN", uart_sleep_mode), "UART_TX_PIN", uart_sleep_mode),
}; };
foo_init(void) { foo_init(void)
{
pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap)); pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap));
} }
...@@ -995,7 +952,9 @@ part of this. ...@@ -995,7 +952,9 @@ part of this.
A pin controller configuration for a machine looks pretty much like a simple A pin controller configuration for a machine looks pretty much like a simple
regulator configuration, so for the example array above we want to enable i2c regulator configuration, so for the example array above we want to enable i2c
and spi on the second function mapping:: and spi on the second function mapping:
.. code-block:: c
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
...@@ -1030,13 +989,17 @@ must match a function provided by the pinmux driver handling this pin range. ...@@ -1030,13 +989,17 @@ must match a function provided by the pinmux driver handling this pin range.
As you can see we may have several pin controllers on the system and thus As you can see we may have several pin controllers on the system and thus
we need to specify which one of them contains the functions we wish to map. we need to specify which one of them contains the functions we wish to map.
You register this pinmux mapping to the pinmux subsystem by simply:: You register this pinmux mapping to the pinmux subsystem by simply:
.. code-block:: c
ret = pinctrl_register_mappings(mapping, ARRAY_SIZE(mapping)); ret = pinctrl_register_mappings(mapping, ARRAY_SIZE(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-foo 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:
.. code-block:: c
static struct pinctrl_map mapping[] __initdata = { static struct pinctrl_map mapping[] __initdata = {
PIN_MAP_MUX_GROUP("foo-i2c.o", PINCTRL_STATE_DEFAULT, PIN_MAP_MUX_GROUP("foo-i2c.o", PINCTRL_STATE_DEFAULT,
...@@ -1046,7 +1009,9 @@ it even more compact which assumes you want to use pinctrl-foo and position ...@@ -1046,7 +1009,9 @@ it even more compact which assumes you want to use pinctrl-foo and position
The mapping table may also contain pin configuration entries. It's common for The mapping table may also contain pin configuration entries. It's common for
each pin/group to have a number of configuration entries that affect it, so each pin/group to have a number of configuration entries that affect it, so
the table entries for configuration reference an array of config parameters the table entries for configuration reference an array of config parameters
and values. An example using the convenience macros is shown below:: and values. An example using the convenience macros is shown below:
.. code-block:: c
static unsigned long i2c_grp_configs[] = { static unsigned long i2c_grp_configs[] = {
FOO_PIN_DRIVEN, FOO_PIN_DRIVEN,
...@@ -1073,8 +1038,10 @@ Finally, some devices expect the mapping table to contain certain specific ...@@ -1073,8 +1038,10 @@ Finally, some devices expect the mapping table to contain certain specific
named states. When running on hardware that doesn't need any pin controller named states. When running on hardware that doesn't need any pin controller
configuration, the mapping table must still contain those named states, in configuration, the mapping table must still contain those named states, in
order to explicitly indicate that the states were provided and intended to order to explicitly indicate that the states were provided and intended to
be empty. Table entry macro PIN_MAP_DUMMY_STATE serves the purpose of defining be empty. Table entry macro ``PIN_MAP_DUMMY_STATE()`` serves the purpose of defining
a named state without causing any pin controller to be programmed:: a named state without causing any pin controller to be programmed:
.. code-block:: c
static struct pinctrl_map mapping[] __initdata = { static struct pinctrl_map mapping[] __initdata = {
PIN_MAP_DUMMY_STATE("foo-i2c.0", PINCTRL_STATE_DEFAULT), PIN_MAP_DUMMY_STATE("foo-i2c.0", PINCTRL_STATE_DEFAULT),
...@@ -1085,7 +1052,9 @@ Complex mappings ...@@ -1085,7 +1052,9 @@ Complex mappings
================ ================
As it is possible to map a function to different groups of pins an optional As it is possible to map a function to different groups of pins an optional
.group can be specified like this:: .group can be specified like this:
.. code-block:: c
... ...
{ {
...@@ -1107,13 +1076,15 @@ As it is possible to map a function to different groups of pins an optional ...@@ -1107,13 +1076,15 @@ As it is possible to map a function to different groups of pins an optional
... ...
This example mapping is used to switch between two positions for spi0 at This example mapping is used to switch between two positions for spi0 at
runtime, as described further below under the heading "Runtime pinmuxing". runtime, as described further below under the heading `Runtime pinmuxing`_.
Further it is possible for one named state to affect the muxing of several Further it is possible for one named state to affect the muxing of several
groups of pins, say for example in the mmc0 example above, where you can groups of pins, say for example in the mmc0 example above, where you can
additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all
three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the three groups for a total of 2 + 2 + 4 = 8 pins (for an 8-bit MMC bus as is the
case), we define a mapping like this:: case), we define a mapping like this:
.. code-block:: c
... ...
{ {
...@@ -1167,13 +1138,17 @@ case), we define a mapping like this:: ...@@ -1167,13 +1138,17 @@ case), we define a mapping like this::
... ...
The result of grabbing this mapping from the device with something like The result of grabbing this mapping from the device with something like
this (see next paragraph):: this (see next paragraph):
.. code-block:: c
p = devm_pinctrl_get(dev); p = devm_pinctrl_get(dev);
s = pinctrl_lookup_state(p, "8bit"); s = pinctrl_lookup_state(p, "8bit");
ret = pinctrl_select_state(p, s); ret = pinctrl_select_state(p, s);
or more simply:: or more simply:
.. code-block:: c
p = devm_pinctrl_get_select(dev, "8bit"); p = devm_pinctrl_get_select(dev, "8bit");
...@@ -1188,7 +1163,7 @@ Pin control requests from drivers ...@@ -1188,7 +1163,7 @@ Pin control requests from drivers
================================= =================================
When a device driver is about to probe the device core will automatically When a device driver is about to probe the device core will automatically
attempt to issue pinctrl_get_select_default() on these devices. attempt to issue ``pinctrl_get_select_default()`` on these devices.
This way driver writers do not need to add any of the boilerplate code This way driver writers do not need to add any of the boilerplate code
of the type found below. However when doing fine-grained state selection of the type found below. However when doing fine-grained state selection
and not using the "default" state, you may have to do some device driver and not using the "default" state, you may have to do some device driver
...@@ -1206,12 +1181,14 @@ some cases where a driver needs to e.g. switch between different mux mappings ...@@ -1206,12 +1181,14 @@ some cases where a driver needs to e.g. switch between different mux mappings
at runtime this is not possible. at runtime this is not possible.
A typical case is if a driver needs to switch bias of pins from normal A typical case is if a driver needs to switch bias of pins from normal
operation and going to sleep, moving from the PINCTRL_STATE_DEFAULT to operation and going to sleep, moving from the ``PINCTRL_STATE_DEFAULT`` to
PINCTRL_STATE_SLEEP at runtime, re-biasing or even re-muxing pins to save ``PINCTRL_STATE_SLEEP`` at runtime, re-biasing or even re-muxing pins to save
current in sleep mode. current in sleep mode.
A driver may request a certain control state to be activated, usually just the A driver may request a certain control state to be activated, usually just the
default state like this:: default state like this:
.. code-block:: c
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -1251,49 +1228,49 @@ arrangement on your bus. ...@@ -1251,49 +1228,49 @@ arrangement on your bus.
The semantics of the pinctrl APIs are: The semantics of the pinctrl APIs are:
- pinctrl_get() is called in process context to obtain a handle to all pinctrl - ``pinctrl_get()`` is called in process context to obtain a handle to all pinctrl
information for a given client device. It will allocate a struct from the information for a given client device. It will allocate a struct from the
kernel memory to hold the pinmux state. All mapping table parsing or similar kernel memory to hold the pinmux state. All mapping table parsing or similar
slow operations take place within this API. slow operations take place within this API.
- devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put() - ``devm_pinctrl_get()`` is a variant of pinctrl_get() that causes ``pinctrl_put()``
to be called automatically on the retrieved pointer when the associated to be called automatically on the retrieved pointer when the associated
device is removed. It is recommended to use this function over plain device is removed. It is recommended to use this function over plain
pinctrl_get(). ``pinctrl_get()``.
- pinctrl_lookup_state() is called in process context to obtain a handle to a - ``pinctrl_lookup_state()`` is called in process context to obtain a handle to a
specific state for a client device. This operation may be slow, too. specific state for a client device. This operation may be slow, too.
- pinctrl_select_state() programs pin controller hardware according to the - ``pinctrl_select_state()`` programs pin controller hardware according to the
definition of the state as given by the mapping table. In theory, this is a definition of the state as given by the mapping table. In theory, this is a
fast-path operation, since it only involved blasting some register settings fast-path operation, since it only involved blasting some register settings
into hardware. However, note that some pin controllers may have their into hardware. However, note that some pin controllers may have their
registers on a slow/IRQ-based bus, so client devices should not assume they registers on a slow/IRQ-based bus, so client devices should not assume they
can call pinctrl_select_state() from non-blocking contexts. can call ``pinctrl_select_state()`` from non-blocking contexts.
- pinctrl_put() frees all information associated with a pinctrl handle. - ``pinctrl_put()`` frees all information associated with a pinctrl handle.
- devm_pinctrl_put() is a variant of pinctrl_put() that may be used to - ``devm_pinctrl_put()`` is a variant of ``pinctrl_put()`` that may be used to
explicitly destroy a pinctrl object returned by devm_pinctrl_get(). explicitly destroy a pinctrl object returned by ``devm_pinctrl_get()``.
However, use of this function will be rare, due to the automatic cleanup However, use of this function will be rare, due to the automatic cleanup
that will occur even without calling it. that will occur even without calling it.
pinctrl_get() must be paired with a plain pinctrl_put(). ``pinctrl_get()`` must be paired with a plain ``pinctrl_put()``.
pinctrl_get() may not be paired with devm_pinctrl_put(). ``pinctrl_get()`` may not be paired with ``devm_pinctrl_put()``.
devm_pinctrl_get() can optionally be paired with devm_pinctrl_put(). ``devm_pinctrl_get()`` can optionally be paired with ``devm_pinctrl_put()``.
devm_pinctrl_get() may not be paired with plain pinctrl_put(). ``devm_pinctrl_get()`` may not be paired with plain ``pinctrl_put()``.
Usually the pin control core handled the get/put pair and call out to the Usually the pin control core handled the get/put pair and call out to the
device drivers bookkeeping operations, like checking available functions and device drivers bookkeeping operations, like checking available functions and
the associated pins, whereas select_state pass on to the pin controller the associated pins, whereas ``pinctrl_select_state()`` pass on to the pin controller
driver which takes care of activating and/or deactivating the mux setting by driver which takes care of activating and/or deactivating the mux setting by
quickly poking some registers. quickly poking some registers.
The pins are allocated for your device when you issue the devm_pinctrl_get() The pins are allocated for your device when you issue the ``devm_pinctrl_get()``
call, after this you should be able to see this in the debugfs listing of all call, after this you should be able to see this in the debugfs listing of all
pins. pins.
NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the NOTE: the pinctrl system will return ``-EPROBE_DEFER`` if it cannot find the
requested pinctrl handles, for example if the pinctrl driver has not yet requested pinctrl handles, for example if the pinctrl driver has not yet
registered. Thus make sure that the error path in your driver gracefully registered. Thus make sure that the error path in your driver gracefully
cleans up and is ready to retry the probing later in the startup process. cleans up and is ready to retry the probing later in the startup process.
...@@ -1305,18 +1282,20 @@ Drivers needing both pin control and GPIOs ...@@ -1305,18 +1282,20 @@ Drivers needing both pin control and GPIOs
Again, it is discouraged to let drivers lookup and select pin control states Again, it is discouraged to let drivers lookup and select pin control states
themselves, but again sometimes this is unavoidable. themselves, but again sometimes this is unavoidable.
So say that your driver is fetching its resources like this:: So say that your driver is fetching its resources like this:
.. code-block:: c
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
int gpio; struct gpio_desc *gpio;
pinctrl = devm_pinctrl_get_select_default(&dev); pinctrl = devm_pinctrl_get_select_default(&dev);
gpio = devm_gpio_request(&dev, 14, "foo"); gpio = devm_gpiod_get(&dev, "foo");
Here we first request a certain pin state and then request GPIO 14 to be Here we first request a certain pin state and then request GPIO "foo" to be
used. If you're using the subsystems orthogonally like this, you should used. If you're using the subsystems orthogonally like this, you should
nominally always get your pinctrl handle and select the desired pinctrl nominally always get your pinctrl handle and select the desired pinctrl
state BEFORE requesting the GPIO. This is a semantic convention to avoid state BEFORE requesting the GPIO. This is a semantic convention to avoid
...@@ -1331,9 +1310,9 @@ probing, nevertheless orthogonal to the GPIO subsystem. ...@@ -1331,9 +1310,9 @@ probing, nevertheless orthogonal to the GPIO subsystem.
But there are also situations where it makes sense for the GPIO subsystem But there are also situations where it makes sense for the GPIO subsystem
to communicate directly with the pinctrl subsystem, using the latter as a to communicate directly with the pinctrl subsystem, using the latter as a
back-end. This is when the GPIO driver may call out to the functions back-end. This is when the GPIO driver may call out to the functions
described in the section "Pin control interaction with the GPIO subsystem" described in the section `Pin control interaction with the GPIO subsystem`_
above. This only involves per-pin multiplexing, and will be completely above. This only involves per-pin multiplexing, and will be completely
hidden behind the gpio_*() function namespace. In this case, the driver hidden behind the gpiod_*() function namespace. In this case, the driver
need not interact with the pin control subsystem at all. need not interact with the pin control subsystem at all.
If a pin control driver and a GPIO driver is dealing with the same pins If a pin control driver and a GPIO driver is dealing with the same pins
...@@ -1348,12 +1327,14 @@ System pin control hogging ...@@ -1348,12 +1327,14 @@ System pin control hogging
========================== ==========================
Pin control map entries can be hogged by the core when the pin controller Pin control map entries can be hogged by the core when the pin controller
is registered. This means that the core will attempt to call pinctrl_get(), is registered. This means that the core will attempt to call ``pinctrl_get()``,
lookup_state() and select_state() on it immediately after the pin control ``pinctrl_lookup_state()`` and ``pinctrl_select_state()`` on it immediately after
device has been registered. the pin control device has been registered.
This occurs for mapping table entries where the client device name is equal This occurs for mapping table entries where the client device name is equal
to the pin controller device name, and the state name is PINCTRL_STATE_DEFAULT:: to the pin controller device name, and the state name is ``PINCTRL_STATE_DEFAULT``:
.. code-block:: c
{ {
.dev_name = "pinctrl-foo", .dev_name = "pinctrl-foo",
...@@ -1365,7 +1346,9 @@ to the pin controller device name, and the state name is PINCTRL_STATE_DEFAULT:: ...@@ -1365,7 +1346,9 @@ to the pin controller device name, and the state name is PINCTRL_STATE_DEFAULT::
Since it may be common to request the core to hog a few always-applicable Since it may be common to request the core to hog a few always-applicable
mux settings on the primary pin controller, there is a convenience macro for mux settings on the primary pin controller, there is a convenience macro for
this:: this:
.. code-block:: c
PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-foo", NULL /* group */, PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-foo", NULL /* group */,
"power_func") "power_func")
...@@ -1385,7 +1368,9 @@ function, but with different named in the mapping as described under ...@@ -1385,7 +1368,9 @@ function, but with different named in the mapping as described under
This snippet first initializes a state object for both groups (in foo_probe()), This snippet first initializes a state object for both groups (in foo_probe()),
then muxes the function in the pins defined by group A, and finally muxes it in then muxes the function in the pins defined by group A, and finally muxes it in
on the pins defined by group B:: on the pins defined by group B:
.. code-block:: c
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -1432,6 +1417,7 @@ can be used by different functions at different times on a running system. ...@@ -1432,6 +1417,7 @@ can be used by different functions at different times on a running system.
Debugfs files Debugfs files
============= =============
These files are created in ``/sys/kernel/debug/pinctrl``: These files are created in ``/sys/kernel/debug/pinctrl``:
- ``pinctrl-devices``: prints each pin controller device along with columns to - ``pinctrl-devices``: prints each pin controller device along with columns to
...@@ -1440,7 +1426,7 @@ These files are created in ``/sys/kernel/debug/pinctrl``: ...@@ -1440,7 +1426,7 @@ These files are created in ``/sys/kernel/debug/pinctrl``:
- ``pinctrl-handles``: prints each configured pin controller handle and the - ``pinctrl-handles``: prints each configured pin controller handle and the
corresponding pinmux maps corresponding pinmux maps
- ``pinctrl-maps``: print all pinctrl maps - ``pinctrl-maps``: prints all pinctrl maps
A sub-directory is created inside of ``/sys/kernel/debug/pinctrl`` for each pin A sub-directory is created inside of ``/sys/kernel/debug/pinctrl`` for each pin
controller device containing these files: controller device containing these files:
...@@ -1448,20 +1434,22 @@ controller device containing these files: ...@@ -1448,20 +1434,22 @@ controller device containing these files:
- ``pins``: prints a line for each pin registered on the pin controller. The - ``pins``: prints a line for each pin registered on the pin controller. The
pinctrl driver may add additional information such as register contents. pinctrl driver may add additional information such as register contents.
- ``gpio-ranges``: print ranges that map gpio lines to pins on the controller - ``gpio-ranges``: prints ranges that map gpio lines to pins on the controller
- ``pingroups``: print all pin groups registered on the pin controller - ``pingroups``: prints all pin groups registered on the pin controller
- ``pinconf-pins``: print pin config settings for each pin - ``pinconf-pins``: prints pin config settings for each pin
- ``pinconf-groups``: print pin config settings per pin group - ``pinconf-groups``: prints pin config settings per pin group
- ``pinmux-functions``: print each pin function along with the pin groups that - ``pinmux-functions``: prints each pin function along with the pin groups that
map to the pin function map to the pin function
- ``pinmux-pins``: iterate through all pins and print mux owner, gpio owner - ``pinmux-pins``: iterates through all pins and prints mux owner, gpio owner
and if the pin is a hog and if the pin is a hog
- ``pinmux-select``: write to this file to activate a pin function for a group:: - ``pinmux-select``: write to this file to activate a pin function for a group:
.. code-block:: sh
echo "<group-name function-name>" > pinmux-select echo "<group-name function-name>" > pinmux-select
...@@ -34,25 +34,11 @@ ...@@ -34,25 +34,11 @@
.gpio_base = (g), \ .gpio_base = (g), \
} }
#define ADL_COMMUNITY(b, s, e, g, v) \
{ \
.barno = (b), \
.padown_offset = ADL_##v##_PAD_OWN, \
.padcfglock_offset = ADL_##v##_PADCFGLOCK, \
.hostown_offset = ADL_##v##_HOSTSW_OWN, \
.is_offset = ADL_##v##_GPI_IS, \
.ie_offset = ADL_##v##_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
#define ADL_N_COMMUNITY(b, s, e, g) \ #define ADL_N_COMMUNITY(b, s, e, g) \
ADL_COMMUNITY(b, s, e, g, N) INTEL_COMMUNITY_GPPS(b, s, e, g, ADL_N)
#define ADL_S_COMMUNITY(b, s, e, g) \ #define ADL_S_COMMUNITY(b, s, e, g) \
ADL_COMMUNITY(b, s, e, g, S) INTEL_COMMUNITY_GPPS(b, s, e, g, ADL_S)
/* Alder Lake-N */ /* Alder Lake-N */
static const struct pinctrl_pin_desc adln_pins[] = { static const struct pinctrl_pin_desc adln_pins[] = {
......
...@@ -637,18 +637,18 @@ static const char *byt_get_function_name(struct pinctrl_dev *pctldev, ...@@ -637,18 +637,18 @@ static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc->functions[selector].name; return vg->soc->functions[selector].func.name;
} }
static int byt_get_function_groups(struct pinctrl_dev *pctldev, static int byt_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned int selector,
const char * const **groups, const char * const **groups,
unsigned int *num_groups) unsigned int *ngroups)
{ {
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
*groups = vg->soc->functions[selector].groups; *groups = vg->soc->functions[selector].func.groups;
*num_groups = vg->soc->functions[selector].ngroups; *ngroups = vg->soc->functions[selector].func.ngroups;
return 0; return 0;
} }
...@@ -722,7 +722,7 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, ...@@ -722,7 +722,7 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
if (group.modes) if (group.modes)
byt_set_group_mixed_mux(vg, group, group.modes); byt_set_group_mixed_mux(vg, group, group.modes);
else if (!strcmp(func.name, "gpio")) else if (!strcmp(func.func.name, "gpio"))
byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX); byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
else else
byt_set_group_simple_mux(vg, group, group.mode); byt_set_group_simple_mux(vg, group, group.mode);
......
...@@ -20,17 +20,8 @@ ...@@ -20,17 +20,8 @@
#define BXT_GPI_IS 0x100 #define BXT_GPI_IS 0x100
#define BXT_GPI_IE 0x110 #define BXT_GPI_IE 0x110
#define BXT_COMMUNITY(s, e) \ #define BXT_COMMUNITY(b, s, e) \
{ \ INTEL_COMMUNITY_SIZE(b, s, e, 32, 4, BXT)
.padown_offset = BXT_PAD_OWN, \
.padcfglock_offset = BXT_PADCFGLOCK, \
.hostown_offset = BXT_HOSTSW_OWN, \
.is_offset = BXT_GPI_IS, \
.ie_offset = BXT_GPI_IE, \
.gpp_size = 32, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
}
/* BXT */ /* BXT */
static const struct pinctrl_pin_desc bxt_north_pins[] = { static const struct pinctrl_pin_desc bxt_north_pins[] = {
...@@ -172,7 +163,7 @@ static const struct intel_function bxt_north_functions[] = { ...@@ -172,7 +163,7 @@ static const struct intel_function bxt_north_functions[] = {
}; };
static const struct intel_community bxt_north_communities[] = { static const struct intel_community bxt_north_communities[] = {
BXT_COMMUNITY(0, 82), BXT_COMMUNITY(0, 0, 82),
}; };
static const struct intel_pinctrl_soc_data bxt_north_soc_data = { static const struct intel_pinctrl_soc_data bxt_north_soc_data = {
...@@ -289,7 +280,7 @@ static const struct intel_function bxt_northwest_functions[] = { ...@@ -289,7 +280,7 @@ static const struct intel_function bxt_northwest_functions[] = {
}; };
static const struct intel_community bxt_northwest_communities[] = { static const struct intel_community bxt_northwest_communities[] = {
BXT_COMMUNITY(0, 71), BXT_COMMUNITY(0, 0, 71),
}; };
static const struct intel_pinctrl_soc_data bxt_northwest_soc_data = { static const struct intel_pinctrl_soc_data bxt_northwest_soc_data = {
...@@ -396,7 +387,7 @@ static const struct intel_function bxt_west_functions[] = { ...@@ -396,7 +387,7 @@ static const struct intel_function bxt_west_functions[] = {
}; };
static const struct intel_community bxt_west_communities[] = { static const struct intel_community bxt_west_communities[] = {
BXT_COMMUNITY(0, 41), BXT_COMMUNITY(0, 0, 41),
}; };
static const struct intel_pinctrl_soc_data bxt_west_soc_data = { static const struct intel_pinctrl_soc_data bxt_west_soc_data = {
...@@ -472,7 +463,7 @@ static const struct intel_function bxt_southwest_functions[] = { ...@@ -472,7 +463,7 @@ static const struct intel_function bxt_southwest_functions[] = {
}; };
static const struct intel_community bxt_southwest_communities[] = { static const struct intel_community bxt_southwest_communities[] = {
BXT_COMMUNITY(0, 30), BXT_COMMUNITY(0, 0, 30),
}; };
static const struct intel_pinctrl_soc_data bxt_southwest_soc_data = { static const struct intel_pinctrl_soc_data bxt_southwest_soc_data = {
...@@ -511,7 +502,7 @@ static const struct pinctrl_pin_desc bxt_south_pins[] = { ...@@ -511,7 +502,7 @@ static const struct pinctrl_pin_desc bxt_south_pins[] = {
}; };
static const struct intel_community bxt_south_communities[] = { static const struct intel_community bxt_south_communities[] = {
BXT_COMMUNITY(0, 19), BXT_COMMUNITY(0, 0, 19),
}; };
static const struct intel_pinctrl_soc_data bxt_south_soc_data = { static const struct intel_pinctrl_soc_data bxt_south_soc_data = {
...@@ -650,7 +641,7 @@ static const struct intel_function apl_north_functions[] = { ...@@ -650,7 +641,7 @@ static const struct intel_function apl_north_functions[] = {
}; };
static const struct intel_community apl_north_communities[] = { static const struct intel_community apl_north_communities[] = {
BXT_COMMUNITY(0, 77), BXT_COMMUNITY(0, 0, 77),
}; };
static const struct intel_pinctrl_soc_data apl_north_soc_data = { static const struct intel_pinctrl_soc_data apl_north_soc_data = {
...@@ -770,7 +761,7 @@ static const struct intel_function apl_northwest_functions[] = { ...@@ -770,7 +761,7 @@ static const struct intel_function apl_northwest_functions[] = {
}; };
static const struct intel_community apl_northwest_communities[] = { static const struct intel_community apl_northwest_communities[] = {
BXT_COMMUNITY(0, 76), BXT_COMMUNITY(0, 0, 76),
}; };
static const struct intel_pinctrl_soc_data apl_northwest_soc_data = { static const struct intel_pinctrl_soc_data apl_northwest_soc_data = {
...@@ -880,7 +871,7 @@ static const struct intel_function apl_west_functions[] = { ...@@ -880,7 +871,7 @@ static const struct intel_function apl_west_functions[] = {
}; };
static const struct intel_community apl_west_communities[] = { static const struct intel_community apl_west_communities[] = {
BXT_COMMUNITY(0, 46), BXT_COMMUNITY(0, 0, 46),
}; };
static const struct intel_pinctrl_soc_data apl_west_soc_data = { static const struct intel_pinctrl_soc_data apl_west_soc_data = {
...@@ -972,7 +963,7 @@ static const struct intel_function apl_southwest_functions[] = { ...@@ -972,7 +963,7 @@ static const struct intel_function apl_southwest_functions[] = {
}; };
static const struct intel_community apl_southwest_communities[] = { static const struct intel_community apl_southwest_communities[] = {
BXT_COMMUNITY(0, 42), BXT_COMMUNITY(0, 0, 42),
}; };
static const struct intel_pinctrl_soc_data apl_southwest_soc_data = { static const struct intel_pinctrl_soc_data apl_southwest_soc_data = {
......
...@@ -15,12 +15,17 @@ ...@@ -15,12 +15,17 @@
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#define CNL_PAD_OWN 0x020 #define CNL_LP_PAD_OWN 0x020
#define CNL_PADCFGLOCK 0x080 #define CNL_LP_PADCFGLOCK 0x080
#define CNL_LP_HOSTSW_OWN 0x0b0 #define CNL_LP_HOSTSW_OWN 0x0b0
#define CNL_LP_GPI_IS 0x100
#define CNL_LP_GPI_IE 0x120
#define CNL_H_PAD_OWN 0x020
#define CNL_H_PADCFGLOCK 0x080
#define CNL_H_HOSTSW_OWN 0x0c0 #define CNL_H_HOSTSW_OWN 0x0c0
#define CNL_GPI_IS 0x100 #define CNL_H_GPI_IS 0x100
#define CNL_GPI_IE 0x120 #define CNL_H_GPI_IE 0x120
#define CNL_GPP(r, s, e, g) \ #define CNL_GPP(r, s, e, g) \
{ \ { \
...@@ -30,25 +35,11 @@ ...@@ -30,25 +35,11 @@
.gpio_base = (g), \ .gpio_base = (g), \
} }
#define CNL_COMMUNITY(b, s, e, g, v) \
{ \
.barno = (b), \
.padown_offset = CNL_PAD_OWN, \
.padcfglock_offset = CNL_PADCFGLOCK, \
.hostown_offset = CNL_##v##_HOSTSW_OWN, \
.is_offset = CNL_GPI_IS, \
.ie_offset = CNL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
#define CNL_LP_COMMUNITY(b, s, e, g) \ #define CNL_LP_COMMUNITY(b, s, e, g) \
CNL_COMMUNITY(b, s, e, g, LP) INTEL_COMMUNITY_GPPS(b, s, e, g, CNL_LP)
#define CNL_H_COMMUNITY(b, s, e, g) \ #define CNL_H_COMMUNITY(b, s, e, g) \
CNL_COMMUNITY(b, s, e, g, H) INTEL_COMMUNITY_GPPS(b, s, e, g, CNL_H)
/* Cannon Lake-H */ /* Cannon Lake-H */
static const struct pinctrl_pin_desc cnlh_pins[] = { static const struct pinctrl_pin_desc cnlh_pins[] = {
......
...@@ -28,18 +28,7 @@ ...@@ -28,18 +28,7 @@
} }
#define CDF_COMMUNITY(b, s, e, g) \ #define CDF_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, CDF)
.barno = (b), \
.padown_offset = CDF_PAD_OWN, \
.padcfglock_offset = CDF_PADCFGLOCK, \
.hostown_offset = CDF_HOSTSW_OWN, \
.is_offset = CDF_GPI_IS, \
.ie_offset = CDF_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Cedar Fork PCH */ /* Cedar Fork PCH */
static const struct pinctrl_pin_desc cdf_pins[] = { static const struct pinctrl_pin_desc cdf_pins[] = {
......
...@@ -694,7 +694,7 @@ static const char *chv_get_function_name(struct pinctrl_dev *pctldev, ...@@ -694,7 +694,7 @@ static const char *chv_get_function_name(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->functions[function].name; return pctrl->soc->functions[function].func.name;
} }
static int chv_get_function_groups(struct pinctrl_dev *pctldev, static int chv_get_function_groups(struct pinctrl_dev *pctldev,
...@@ -704,8 +704,8 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev, ...@@ -704,8 +704,8 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pctrl->soc->functions[function].groups; *groups = pctrl->soc->functions[function].func.groups;
*ngroups = pctrl->soc->functions[function].ngroups; *ngroups = pctrl->soc->functions[function].func.ngroups;
return 0; return 0;
} }
......
...@@ -28,18 +28,7 @@ ...@@ -28,18 +28,7 @@
} }
#define DNV_COMMUNITY(b, s, e, g) \ #define DNV_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, DNV)
.barno = (b), \
.padown_offset = DNV_PAD_OWN, \
.padcfglock_offset = DNV_PADCFGLOCK, \
.hostown_offset = DNV_HOSTSW_OWN, \
.is_offset = DNV_GPI_IS, \
.ie_offset = DNV_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Denverton */ /* Denverton */
static const struct pinctrl_pin_desc dnv_pins[] = { static const struct pinctrl_pin_desc dnv_pins[] = {
......
...@@ -27,18 +27,8 @@ ...@@ -27,18 +27,8 @@
.size = ((e) - (s) + 1), \ .size = ((e) - (s) + 1), \
} }
#define EHL_COMMUNITY(s, e, g) \ #define EHL_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, EHL)
.padown_offset = EHL_PAD_OWN, \
.padcfglock_offset = EHL_PADCFGLOCK, \
.hostown_offset = EHL_HOSTSW_OWN, \
.is_offset = EHL_GPI_IS, \
.ie_offset = EHL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Elkhart Lake */ /* Elkhart Lake */
static const struct pinctrl_pin_desc ehl_community0_pins[] = { static const struct pinctrl_pin_desc ehl_community0_pins[] = {
...@@ -121,7 +111,7 @@ static const struct intel_padgroup ehl_community0_gpps[] = { ...@@ -121,7 +111,7 @@ static const struct intel_padgroup ehl_community0_gpps[] = {
}; };
static const struct intel_community ehl_community0[] = { static const struct intel_community ehl_community0[] = {
EHL_COMMUNITY(0, 66, ehl_community0_gpps), EHL_COMMUNITY(0, 0, 66, ehl_community0_gpps),
}; };
static const struct intel_pinctrl_soc_data ehl_community0_soc_data = { static const struct intel_pinctrl_soc_data ehl_community0_soc_data = {
...@@ -262,7 +252,7 @@ static const struct intel_padgroup ehl_community1_gpps[] = { ...@@ -262,7 +252,7 @@ static const struct intel_padgroup ehl_community1_gpps[] = {
}; };
static const struct intel_community ehl_community1[] = { static const struct intel_community ehl_community1[] = {
EHL_COMMUNITY(0, 112, ehl_community1_gpps), EHL_COMMUNITY(0, 0, 112, ehl_community1_gpps),
}; };
static const struct intel_pinctrl_soc_data ehl_community1_soc_data = { static const struct intel_pinctrl_soc_data ehl_community1_soc_data = {
...@@ -335,7 +325,7 @@ static const struct intel_padgroup ehl_community3_gpps[] = { ...@@ -335,7 +325,7 @@ static const struct intel_padgroup ehl_community3_gpps[] = {
}; };
static const struct intel_community ehl_community3[] = { static const struct intel_community ehl_community3[] = {
EHL_COMMUNITY(0, 46, ehl_community3_gpps), EHL_COMMUNITY(0, 0, 46, ehl_community3_gpps),
}; };
static const struct intel_pinctrl_soc_data ehl_community3_soc_data = { static const struct intel_pinctrl_soc_data ehl_community3_soc_data = {
...@@ -441,7 +431,7 @@ static const struct intel_padgroup ehl_community4_gpps[] = { ...@@ -441,7 +431,7 @@ static const struct intel_padgroup ehl_community4_gpps[] = {
}; };
static const struct intel_community ehl_community4[] = { static const struct intel_community ehl_community4[] = {
EHL_COMMUNITY(0, 79, ehl_community4_gpps), EHL_COMMUNITY(0, 0, 79, ehl_community4_gpps),
}; };
static const struct intel_pinctrl_soc_data ehl_community4_soc_data = { static const struct intel_pinctrl_soc_data ehl_community4_soc_data = {
...@@ -469,7 +459,7 @@ static const struct intel_padgroup ehl_community5_gpps[] = { ...@@ -469,7 +459,7 @@ static const struct intel_padgroup ehl_community5_gpps[] = {
}; };
static const struct intel_community ehl_community5[] = { static const struct intel_community ehl_community5[] = {
EHL_COMMUNITY(0, 7, ehl_community5_gpps), EHL_COMMUNITY(0, 0, 7, ehl_community5_gpps),
}; };
static const struct intel_pinctrl_soc_data ehl_community5_soc_data = { static const struct intel_pinctrl_soc_data ehl_community5_soc_data = {
......
...@@ -28,18 +28,7 @@ ...@@ -28,18 +28,7 @@
} }
#define EBG_COMMUNITY(b, s, e, g) \ #define EBG_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, EBG)
.barno = (b), \
.padown_offset = EBG_PAD_OWN, \
.padcfglock_offset = EBG_PADCFGLOCK, \
.hostown_offset = EBG_HOSTSW_OWN, \
.is_offset = EBG_GPI_IS, \
.ie_offset = EBG_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Emmitsburg */ /* Emmitsburg */
static const struct pinctrl_pin_desc ebg_pins[] = { static const struct pinctrl_pin_desc ebg_pins[] = {
......
...@@ -20,17 +20,8 @@ ...@@ -20,17 +20,8 @@
#define GLK_GPI_IS 0x100 #define GLK_GPI_IS 0x100
#define GLK_GPI_IE 0x110 #define GLK_GPI_IE 0x110
#define GLK_COMMUNITY(s, e) \ #define GLK_COMMUNITY(b, s, e) \
{ \ INTEL_COMMUNITY_SIZE(b, s, e, 32, 4, GLK)
.padown_offset = GLK_PAD_OWN, \
.padcfglock_offset = GLK_PADCFGLOCK, \
.hostown_offset = GLK_HOSTSW_OWN, \
.is_offset = GLK_GPI_IS, \
.ie_offset = GLK_GPI_IE, \
.gpp_size = 32, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
}
/* GLK */ /* GLK */
static const struct pinctrl_pin_desc glk_northwest_pins[] = { static const struct pinctrl_pin_desc glk_northwest_pins[] = {
...@@ -173,7 +164,7 @@ static const struct intel_function glk_northwest_functions[] = { ...@@ -173,7 +164,7 @@ static const struct intel_function glk_northwest_functions[] = {
}; };
static const struct intel_community glk_northwest_communities[] = { static const struct intel_community glk_northwest_communities[] = {
GLK_COMMUNITY(0, 79), GLK_COMMUNITY(0, 0, 79),
}; };
static const struct intel_pinctrl_soc_data glk_northwest_soc_data = { static const struct intel_pinctrl_soc_data glk_northwest_soc_data = {
...@@ -306,7 +297,7 @@ static const struct intel_function glk_north_functions[] = { ...@@ -306,7 +297,7 @@ static const struct intel_function glk_north_functions[] = {
}; };
static const struct intel_community glk_north_communities[] = { static const struct intel_community glk_north_communities[] = {
GLK_COMMUNITY(0, 79), GLK_COMMUNITY(0, 0, 79),
}; };
static const struct intel_pinctrl_soc_data glk_north_soc_data = { static const struct intel_pinctrl_soc_data glk_north_soc_data = {
...@@ -345,7 +336,7 @@ static const struct pinctrl_pin_desc glk_audio_pins[] = { ...@@ -345,7 +336,7 @@ static const struct pinctrl_pin_desc glk_audio_pins[] = {
}; };
static const struct intel_community glk_audio_communities[] = { static const struct intel_community glk_audio_communities[] = {
GLK_COMMUNITY(0, 19), GLK_COMMUNITY(0, 0, 19),
}; };
static const struct intel_pinctrl_soc_data glk_audio_soc_data = { static const struct intel_pinctrl_soc_data glk_audio_soc_data = {
...@@ -427,7 +418,7 @@ static const struct intel_function glk_scc_functions[] = { ...@@ -427,7 +418,7 @@ static const struct intel_function glk_scc_functions[] = {
}; };
static const struct intel_community glk_scc_communities[] = { static const struct intel_community glk_scc_communities[] = {
GLK_COMMUNITY(0, 34), GLK_COMMUNITY(0, 0, 34),
}; };
static const struct intel_pinctrl_soc_data glk_scc_soc_data = { static const struct intel_pinctrl_soc_data glk_scc_soc_data = {
......
...@@ -15,11 +15,16 @@ ...@@ -15,11 +15,16 @@
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#define ICL_PAD_OWN 0x020 #define ICL_LP_PAD_OWN 0x020
#define ICL_PADCFGLOCK 0x080 #define ICL_LP_PADCFGLOCK 0x080
#define ICL_HOSTSW_OWN 0x0b0 #define ICL_LP_HOSTSW_OWN 0x0b0
#define ICL_GPI_IS 0x100 #define ICL_LP_GPI_IS 0x100
#define ICL_LP_GPI_IE 0x110 #define ICL_LP_GPI_IE 0x110
#define ICL_N_PAD_OWN 0x020
#define ICL_N_PADCFGLOCK 0x080
#define ICL_N_HOSTSW_OWN 0x0b0
#define ICL_N_GPI_IS 0x100
#define ICL_N_GPI_IE 0x120 #define ICL_N_GPI_IE 0x120
#define ICL_GPP(r, s, e, g) \ #define ICL_GPP(r, s, e, g) \
...@@ -30,25 +35,11 @@ ...@@ -30,25 +35,11 @@
.gpio_base = (g), \ .gpio_base = (g), \
} }
#define ICL_COMMUNITY(b, s, e, g, v) \
{ \
.barno = (b), \
.padown_offset = ICL_PAD_OWN, \
.padcfglock_offset = ICL_PADCFGLOCK, \
.hostown_offset = ICL_HOSTSW_OWN, \
.is_offset = ICL_GPI_IS, \
.ie_offset = ICL_##v##_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
#define ICL_LP_COMMUNITY(b, s, e, g) \ #define ICL_LP_COMMUNITY(b, s, e, g) \
ICL_COMMUNITY(b, s, e, g, LP) INTEL_COMMUNITY_GPPS(b, s, e, g, ICL_LP)
#define ICL_N_COMMUNITY(b, s, e, g) \ #define ICL_N_COMMUNITY(b, s, e, g) \
ICL_COMMUNITY(b, s, e, g, N) INTEL_COMMUNITY_GPPS(b, s, e, g, ICL_N)
/* Ice Lake-LP */ /* Ice Lake-LP */
static const struct pinctrl_pin_desc icllp_pins[] = { static const struct pinctrl_pin_desc icllp_pins[] = {
......
...@@ -81,13 +81,16 @@ ...@@ -81,13 +81,16 @@
#define PADCFG1_TERM_MASK GENMASK(12, 10) #define PADCFG1_TERM_MASK GENMASK(12, 10)
#define PADCFG1_TERM_20K BIT(2) #define PADCFG1_TERM_20K BIT(2)
#define PADCFG1_TERM_5K BIT(1) #define PADCFG1_TERM_5K BIT(1)
#define PADCFG1_TERM_4K (BIT(2) | BIT(1))
#define PADCFG1_TERM_1K BIT(0) #define PADCFG1_TERM_1K BIT(0)
#define PADCFG1_TERM_952 (BIT(2) | BIT(0))
#define PADCFG1_TERM_833 (BIT(1) | BIT(0)) #define PADCFG1_TERM_833 (BIT(1) | BIT(0))
#define PADCFG1_TERM_800 (BIT(2) | BIT(1) | BIT(0))
#define PADCFG2 0x008 #define PADCFG2 0x008
#define PADCFG2_DEBEN BIT(0)
#define PADCFG2_DEBOUNCE_SHIFT 1 #define PADCFG2_DEBOUNCE_SHIFT 1
#define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1) #define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1)
#define PADCFG2_DEBEN BIT(0)
#define DEBOUNCE_PERIOD_NSEC 31250 #define DEBOUNCE_PERIOD_NSEC 31250
...@@ -369,7 +372,7 @@ static const char *intel_get_function_name(struct pinctrl_dev *pctldev, ...@@ -369,7 +372,7 @@ static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->functions[function].name; return pctrl->soc->functions[function].func.name;
} }
static int intel_get_function_groups(struct pinctrl_dev *pctldev, static int intel_get_function_groups(struct pinctrl_dev *pctldev,
...@@ -379,8 +382,8 @@ static int intel_get_function_groups(struct pinctrl_dev *pctldev, ...@@ -379,8 +382,8 @@ static int intel_get_function_groups(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pctrl->soc->functions[function].groups; *groups = pctrl->soc->functions[function].func.groups;
*ngroups = pctrl->soc->functions[function].ngroups; *ngroups = pctrl->soc->functions[function].func.ngroups;
return 0; return 0;
} }
...@@ -574,6 +577,9 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -574,6 +577,9 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
case PADCFG1_TERM_1K: case PADCFG1_TERM_1K:
*arg = 1000; *arg = 1000;
break; break;
case PADCFG1_TERM_4K:
*arg = 4000;
break;
case PADCFG1_TERM_5K: case PADCFG1_TERM_5K:
*arg = 5000; *arg = 5000;
break; break;
...@@ -599,6 +605,9 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -599,6 +605,9 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
return -EINVAL; return -EINVAL;
*arg = 1000; *arg = 1000;
break; break;
case PADCFG1_TERM_4K:
*arg = 4000;
break;
case PADCFG1_TERM_5K: case PADCFG1_TERM_5K:
*arg = 5000; *arg = 5000;
break; break;
...@@ -691,21 +700,17 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -691,21 +700,17 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
raw_spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
value = readl(padcfg1); value = readl(padcfg1);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
value &= ~(PADCFG1_TERM_MASK | PADCFG1_TERM_UP); value &= ~(PADCFG1_TERM_MASK | PADCFG1_TERM_UP);
break;
case PIN_CONFIG_BIAS_PULL_UP:
value &= ~PADCFG1_TERM_MASK;
value |= PADCFG1_TERM_UP;
/* Set default strength value in case none is given */ /* Set default strength value in case none is given */
if (arg == 1) if (arg == 1)
arg = 5000; arg = 5000;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
break;
case PIN_CONFIG_BIAS_PULL_UP:
switch (arg) { switch (arg) {
case 20000: case 20000:
value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
...@@ -713,6 +718,9 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -713,6 +718,9 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
case 5000: case 5000:
value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT; value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
break; break;
case 4000:
value |= PADCFG1_TERM_4K << PADCFG1_TERM_SHIFT;
break;
case 1000: case 1000:
value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT; value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
break; break;
...@@ -721,17 +729,13 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -721,17 +729,13 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break;
} }
value |= PADCFG1_TERM_UP;
break; break;
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK);
/* Set default strength value in case none is given */
if (arg == 1)
arg = 5000;
switch (arg) { switch (arg) {
case 20000: case 20000:
value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
...@@ -739,6 +743,9 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -739,6 +743,9 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
case 5000: case 5000:
value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT; value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
break; break;
case 4000:
value |= PADCFG1_TERM_4K << PADCFG1_TERM_SHIFT;
break;
case 1000: case 1000:
if (!(community->features & PINCTRL_FEATURE_1K_PD)) { if (!(community->features & PINCTRL_FEATURE_1K_PD)) {
ret = -EINVAL; ret = -EINVAL;
...@@ -755,9 +762,14 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, ...@@ -755,9 +762,14 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break;
} }
break; break;
default:
ret = -EINVAL;
break;
} }
if (!ret) if (!ret)
...@@ -1215,13 +1227,8 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, ...@@ -1215,13 +1227,8 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
/* Only interrupts that are enabled */ /* Only interrupts that are enabled */
pending &= enabled; pending &= enabled;
for_each_set_bit(gpp_offset, &pending, padgrp->size) { for_each_set_bit(gpp_offset, &pending, padgrp->size)
unsigned int irq; generic_handle_domain_irq(gc->irq.domain, padgrp->gpio_base + gpp_offset);
irq = irq_find_mapping(gc->irq.domain,
padgrp->gpio_base + gpp_offset);
generic_handle_irq(irq);
}
ret += pending ? 1 : 0; ret += pending ? 1 : 0;
} }
...@@ -1399,7 +1406,7 @@ static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl, ...@@ -1399,7 +1406,7 @@ static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl,
for (i = 0; i < ngpps; i++) { for (i = 0; i < ngpps; i++) {
gpps[i] = community->gpps[i]; gpps[i] = community->gpps[i];
if (gpps[i].size > 32) if (gpps[i].size > INTEL_PINCTRL_MAX_GPP_SIZE)
return -EINVAL; return -EINVAL;
/* Special treatment for GPIO base */ /* Special treatment for GPIO base */
...@@ -1417,7 +1424,7 @@ static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl, ...@@ -1417,7 +1424,7 @@ static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl,
} }
gpps[i].padown_num = padown_num; gpps[i].padown_num = padown_num;
padown_num += DIV_ROUND_UP(gpps[i].size * 4, 32); padown_num += DIV_ROUND_UP(gpps[i].size * 4, INTEL_PINCTRL_MAX_GPP_SIZE);
} }
community->gpps = gpps; community->gpps = gpps;
...@@ -1433,7 +1440,7 @@ static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl, ...@@ -1433,7 +1440,7 @@ static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl,
unsigned int padown_num = 0; unsigned int padown_num = 0;
size_t i, ngpps = DIV_ROUND_UP(npins, community->gpp_size); size_t i, ngpps = DIV_ROUND_UP(npins, community->gpp_size);
if (community->gpp_size > 32) if (community->gpp_size > INTEL_PINCTRL_MAX_GPP_SIZE)
return -EINVAL; return -EINVAL;
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL); gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
...@@ -1451,14 +1458,7 @@ static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl, ...@@ -1451,14 +1458,7 @@ static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl,
gpps[i].gpio_base = gpps[i].base; gpps[i].gpio_base = gpps[i].base;
gpps[i].padown_num = padown_num; gpps[i].padown_num = padown_num;
/*
* In older hardware the number of padown registers per
* group is fixed regardless of the group size.
*/
if (community->gpp_num_padown_regs)
padown_num += community->gpp_num_padown_regs; padown_num += community->gpp_num_padown_regs;
else
padown_num += DIV_ROUND_UP(gpps[i].size * 4, 32);
} }
community->ngpps = ngpps; community->ngpps = ngpps;
......
...@@ -36,21 +36,19 @@ struct intel_pingroup { ...@@ -36,21 +36,19 @@ struct intel_pingroup {
/** /**
* struct intel_function - Description about a function * struct intel_function - Description about a function
* @name: Name of the function * @func: Generic data of the pin function (name and groups of pins)
* @groups: An array of groups for this function
* @ngroups: Number of groups in @groups
*/ */
struct intel_function { struct intel_function {
const char *name; struct pinfunction func;
const char * const *groups;
size_t ngroups;
}; };
#define INTEL_PINCTRL_MAX_GPP_SIZE 32
/** /**
* struct intel_padgroup - Hardware pad group information * struct intel_padgroup - Hardware pad group information
* @reg_num: GPI_IS register number * @reg_num: GPI_IS register number
* @base: Starting pin of this group * @base: Starting pin of this group
* @size: Size of this group (maximum is 32). * @size: Size of this group (maximum is %INTEL_PINCTRL_MAX_GPP_SIZE).
* @gpio_base: Starting GPIO base of this group * @gpio_base: Starting GPIO base of this group
* @padown_num: PAD_OWN register number (assigned by the core driver) * @padown_num: PAD_OWN register number (assigned by the core driver)
* *
...@@ -96,8 +94,7 @@ enum { ...@@ -96,8 +94,7 @@ enum {
* @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK, * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
* HOSTSW_OWN, GPI_IS, GPI_IE. Used when @gpps is %NULL. * HOSTSW_OWN, GPI_IS, GPI_IE. Used when @gpps is %NULL.
* @gpp_num_padown_regs: Number of pad registers each pad group consumes at * @gpp_num_padown_regs: Number of pad registers each pad group consumes at
* minimum. Use %0 if the number of registers can be * minimum. Used when @gpps is %NULL.
* determined by the size of the group.
* @gpps: Pad groups if the controller has variable size pad groups * @gpps: Pad groups if the controller has variable size pad groups
* @ngpps: Number of pad groups in this community * @ngpps: Number of pad groups in this community
* @pad_map: Optional non-linear mapping of the pads * @pad_map: Optional non-linear mapping of the pads
...@@ -106,11 +103,13 @@ enum { ...@@ -106,11 +103,13 @@ enum {
* @regs: Community specific common registers (reserved for core driver) * @regs: Community specific common registers (reserved for core driver)
* @pad_regs: Community specific pad registers (reserved for core driver) * @pad_regs: Community specific pad registers (reserved for core driver)
* *
* In some of Intel GPIO host controllers this driver supports each pad group * In older Intel GPIO host controllers, this driver supports, each pad group
* is of equal size (except the last one). In that case the driver can just * is of equal size (except the last one). In that case the driver can just
* fill in @gpp_size field and let the core driver to handle the rest. If * fill in @gpp_size and @gpp_num_padown_regs fields and let the core driver
* the controller has pad groups of variable size the client driver can * to handle the rest.
* pass custom @gpps and @ngpps instead. *
* In newer Intel GPIO host controllers each pad group is of variable size,
* so the client driver can pass custom @gpps and @ngpps instead.
*/ */
struct intel_community { struct intel_community {
unsigned int barno; unsigned int barno;
...@@ -143,6 +142,28 @@ struct intel_community { ...@@ -143,6 +142,28 @@ struct intel_community {
#define PINCTRL_FEATURE_BLINK BIT(4) #define PINCTRL_FEATURE_BLINK BIT(4)
#define PINCTRL_FEATURE_EXP BIT(5) #define PINCTRL_FEATURE_EXP BIT(5)
#define __INTEL_COMMUNITY(b, s, e, g, n, gs, gn, soc) \
{ \
.barno = (b), \
.padown_offset = soc ## _PAD_OWN, \
.padcfglock_offset = soc ## _PADCFGLOCK, \
.hostown_offset = soc ## _HOSTSW_OWN, \
.is_offset = soc ## _GPI_IS, \
.ie_offset = soc ## _GPI_IE, \
.gpp_size = (gs), \
.gpp_num_padown_regs = (gn), \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = (n), \
}
#define INTEL_COMMUNITY_GPPS(b, s, e, g, soc) \
__INTEL_COMMUNITY(b, s, e, g, ARRAY_SIZE(g), 0, 0, soc)
#define INTEL_COMMUNITY_SIZE(b, s, e, gs, gn, soc) \
__INTEL_COMMUNITY(b, s, e, NULL, 0, gs, gn, soc)
/** /**
* PIN_GROUP - Declare a pin group * PIN_GROUP - Declare a pin group
* @n: Name of the group * @n: Name of the group
...@@ -160,9 +181,7 @@ struct intel_community { ...@@ -160,9 +181,7 @@ struct intel_community {
#define FUNCTION(n, g) \ #define FUNCTION(n, g) \
{ \ { \
.name = (n), \ .func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)), \
.groups = (g), \
.ngroups = ARRAY_SIZE((g)), \
} }
/** /**
......
...@@ -29,18 +29,7 @@ ...@@ -29,18 +29,7 @@
} }
#define JSL_COMMUNITY(b, s, e, g) \ #define JSL_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, JSL)
.barno = (b), \
.padown_offset = JSL_PAD_OWN, \
.padcfglock_offset = JSL_PADCFGLOCK, \
.hostown_offset = JSL_HOSTSW_OWN, \
.is_offset = JSL_GPI_IS, \
.ie_offset = JSL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Jasper Lake */ /* Jasper Lake */
static const struct pinctrl_pin_desc jsl_pins[] = { static const struct pinctrl_pin_desc jsl_pins[] = {
......
...@@ -29,18 +29,7 @@ ...@@ -29,18 +29,7 @@
} }
#define LKF_COMMUNITY(b, s, e, g) \ #define LKF_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, LKF)
.barno = (b), \
.padown_offset = LKF_PAD_OWN, \
.padcfglock_offset = LKF_PADCFGLOCK, \
.hostown_offset = LKF_HOSTSW_OWN, \
.is_offset = LKF_GPI_IS, \
.ie_offset = LKF_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Lakefield */ /* Lakefield */
static const struct pinctrl_pin_desc lkf_pins[] = { static const struct pinctrl_pin_desc lkf_pins[] = {
......
...@@ -21,17 +21,7 @@ ...@@ -21,17 +21,7 @@
#define LBG_GPI_IE 0x110 #define LBG_GPI_IE 0x110
#define LBG_COMMUNITY(b, s, e) \ #define LBG_COMMUNITY(b, s, e) \
{ \ INTEL_COMMUNITY_SIZE(b, s, e, 24, 3, LBG)
.barno = (b), \
.padown_offset = LBG_PAD_OWN, \
.padcfglock_offset = LBG_PADCFGLOCK, \
.hostown_offset = LBG_HOSTSW_OWN, \
.is_offset = LBG_GPI_IS, \
.ie_offset = LBG_GPI_IE, \
.gpp_size = 24, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
}
/* Lewisburg */ /* Lewisburg */
static const struct pinctrl_pin_desc lbg_pins[] = { static const struct pinctrl_pin_desc lbg_pins[] = {
......
...@@ -341,18 +341,18 @@ static const char *lp_get_function_name(struct pinctrl_dev *pctldev, ...@@ -341,18 +341,18 @@ static const char *lp_get_function_name(struct pinctrl_dev *pctldev,
{ {
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
return lg->soc->functions[selector].name; return lg->soc->functions[selector].func.name;
} }
static int lp_get_function_groups(struct pinctrl_dev *pctldev, static int lp_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned int selector,
const char * const **groups, const char * const **groups,
unsigned int *num_groups) unsigned int *ngroups)
{ {
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
*groups = lg->soc->functions[selector].groups; *groups = lg->soc->functions[selector].func.groups;
*num_groups = lg->soc->functions[selector].ngroups; *ngroups = lg->soc->functions[selector].func.ngroups;
return 0; return 0;
} }
......
...@@ -576,7 +576,7 @@ static const char *mrfld_get_function_name(struct pinctrl_dev *pctldev, ...@@ -576,7 +576,7 @@ static const char *mrfld_get_function_name(struct pinctrl_dev *pctldev,
{ {
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->functions[function].name; return mp->functions[function].func.name;
} }
static int mrfld_get_function_groups(struct pinctrl_dev *pctldev, static int mrfld_get_function_groups(struct pinctrl_dev *pctldev,
...@@ -586,8 +586,8 @@ static int mrfld_get_function_groups(struct pinctrl_dev *pctldev, ...@@ -586,8 +586,8 @@ static int mrfld_get_function_groups(struct pinctrl_dev *pctldev,
{ {
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*groups = mp->functions[function].groups; *groups = mp->functions[function].func.groups;
*ngroups = mp->functions[function].ngroups; *ngroups = mp->functions[function].func.ngroups;
return 0; return 0;
} }
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#define MTL_PAD_OWN 0x0b0 #define MTL_P_PAD_OWN 0x0b0
#define MTL_PADCFGLOCK 0x110 #define MTL_P_PADCFGLOCK 0x110
#define MTL_HOSTSW_OWN 0x140 #define MTL_P_HOSTSW_OWN 0x140
#define MTL_GPI_IS 0x200 #define MTL_P_GPI_IS 0x200
#define MTL_GPI_IE 0x210 #define MTL_P_GPI_IE 0x210
#define MTL_GPP(r, s, e, g) \ #define MTL_GPP(r, s, e, g) \
{ \ { \
...@@ -29,18 +29,7 @@ ...@@ -29,18 +29,7 @@
} }
#define MTL_COMMUNITY(b, s, e, g) \ #define MTL_COMMUNITY(b, s, e, g) \
{ \ INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_P)
.barno = (b), \
.padown_offset = MTL_PAD_OWN, \
.padcfglock_offset = MTL_PADCFGLOCK, \
.hostown_offset = MTL_HOSTSW_OWN, \
.is_offset = MTL_GPI_IS, \
.ie_offset = MTL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
/* Meteor Lake-P */ /* Meteor Lake-P */
static const struct pinctrl_pin_desc mtlp_pins[] = { static const struct pinctrl_pin_desc mtlp_pins[] = {
......
...@@ -530,7 +530,7 @@ static const char *mofld_get_function_name(struct pinctrl_dev *pctldev, unsigned ...@@ -530,7 +530,7 @@ static const char *mofld_get_function_name(struct pinctrl_dev *pctldev, unsigned
{ {
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->functions[function].name; return mp->functions[function].func.name;
} }
static int mofld_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function, static int mofld_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
...@@ -538,8 +538,8 @@ static int mofld_get_function_groups(struct pinctrl_dev *pctldev, unsigned int f ...@@ -538,8 +538,8 @@ static int mofld_get_function_groups(struct pinctrl_dev *pctldev, unsigned int f
{ {
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*groups = mp->functions[function].groups; *groups = mp->functions[function].func.groups;
*ngroups = mp->functions[function].ngroups; *ngroups = mp->functions[function].func.ngroups;
return 0; return 0;
} }
......
...@@ -15,31 +15,17 @@ ...@@ -15,31 +15,17 @@
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#define SPT_PAD_OWN 0x020 #define SPT_H_PAD_OWN 0x020
#define SPT_H_PADCFGLOCK 0x090 #define SPT_H_PADCFGLOCK 0x090
#define SPT_LP_PADCFGLOCK 0x0a0 #define SPT_H_HOSTSW_OWN 0x0d0
#define SPT_HOSTSW_OWN 0x0d0 #define SPT_H_GPI_IS 0x100
#define SPT_GPI_IS 0x100 #define SPT_H_GPI_IE 0x120
#define SPT_GPI_IE 0x120
#define SPT_COMMUNITY(b, s, e, g, n, v, gs, gn) \
{ \
.barno = (b), \
.padown_offset = SPT_PAD_OWN, \
.padcfglock_offset = SPT_##v##_PADCFGLOCK, \
.hostown_offset = SPT_HOSTSW_OWN, \
.is_offset = SPT_GPI_IS, \
.ie_offset = SPT_GPI_IE, \
.gpp_size = (gs), \
.gpp_num_padown_regs = (gn), \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = (n), \
}
#define SPT_LP_COMMUNITY(b, s, e) \ #define SPT_LP_PAD_OWN 0x020
SPT_COMMUNITY(b, s, e, NULL, 0, LP, 24, 4) #define SPT_LP_PADCFGLOCK 0x0a0
#define SPT_LP_HOSTSW_OWN 0x0d0
#define SPT_LP_GPI_IS 0x100
#define SPT_LP_GPI_IE 0x120
#define SPT_H_GPP(r, s, e, g) \ #define SPT_H_GPP(r, s, e, g) \
{ \ { \
...@@ -50,7 +36,10 @@ ...@@ -50,7 +36,10 @@
} }
#define SPT_H_COMMUNITY(b, s, e, g) \ #define SPT_H_COMMUNITY(b, s, e, g) \
SPT_COMMUNITY(b, s, e, g, ARRAY_SIZE(g), H, 0, 0) INTEL_COMMUNITY_GPPS(b, s, e, g, SPT_H)
#define SPT_LP_COMMUNITY(b, s, e) \
INTEL_COMMUNITY_SIZE(b, s, e, 24, 4, SPT_LP)
/* Sunrisepoint-LP */ /* Sunrisepoint-LP */
static const struct pinctrl_pin_desc sptlp_pins[] = { static const struct pinctrl_pin_desc sptlp_pins[] = {
......
...@@ -15,13 +15,17 @@ ...@@ -15,13 +15,17 @@
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#define TGL_PAD_OWN 0x020 #define TGL_LP_PAD_OWN 0x020
#define TGL_LP_PADCFGLOCK 0x080 #define TGL_LP_PADCFGLOCK 0x080
#define TGL_H_PADCFGLOCK 0x090
#define TGL_LP_HOSTSW_OWN 0x0b0 #define TGL_LP_HOSTSW_OWN 0x0b0
#define TGL_LP_GPI_IS 0x100
#define TGL_LP_GPI_IE 0x120
#define TGL_H_PAD_OWN 0x020
#define TGL_H_PADCFGLOCK 0x090
#define TGL_H_HOSTSW_OWN 0x0c0 #define TGL_H_HOSTSW_OWN 0x0c0
#define TGL_GPI_IS 0x100 #define TGL_H_GPI_IS 0x100
#define TGL_GPI_IE 0x120 #define TGL_H_GPI_IE 0x120
#define TGL_GPP(r, s, e, g) \ #define TGL_GPP(r, s, e, g) \
{ \ { \
...@@ -31,25 +35,11 @@ ...@@ -31,25 +35,11 @@
.gpio_base = (g), \ .gpio_base = (g), \
} }
#define TGL_COMMUNITY(b, s, e, g, v) \
{ \
.barno = (b), \
.padown_offset = TGL_PAD_OWN, \
.padcfglock_offset = TGL_##v##_PADCFGLOCK, \
.hostown_offset = TGL_##v##_HOSTSW_OWN, \
.is_offset = TGL_GPI_IS, \
.ie_offset = TGL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
.gpps = (g), \
.ngpps = ARRAY_SIZE(g), \
}
#define TGL_LP_COMMUNITY(b, s, e, g) \ #define TGL_LP_COMMUNITY(b, s, e, g) \
TGL_COMMUNITY(b, s, e, g, LP) INTEL_COMMUNITY_GPPS(b, s, e, g, TGL_LP)
#define TGL_H_COMMUNITY(b, s, e, g) \ #define TGL_H_COMMUNITY(b, s, e, g) \
TGL_COMMUNITY(b, s, e, g, H) INTEL_COMMUNITY_GPPS(b, s, e, g, TGL_H)
/* Tiger Lake-LP */ /* Tiger Lake-LP */
static const struct pinctrl_pin_desc tgllp_pins[] = { static const struct pinctrl_pin_desc tgllp_pins[] = {
......
...@@ -206,6 +206,26 @@ extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, ...@@ -206,6 +206,26 @@ extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
const char *pin_group, const unsigned **pins, const char *pin_group, const unsigned **pins,
unsigned *num_pins); unsigned *num_pins);
/**
* struct pinfunction - Description about a function
* @name: Name of the function
* @groups: An array of groups for this function
* @ngroups: Number of groups in @groups
*/
struct pinfunction {
const char *name;
const char * const *groups;
size_t ngroups;
};
/* Convenience macro to define a single named pinfunction */
#define PINCTRL_PINFUNCTION(_name, _groups, _ngroups) \
(struct pinfunction) { \
.name = (_name), \
.groups = (_groups), \
.ngroups = (_ngroups), \
}
#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PINCTRL) #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PINCTRL)
extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment