===============================
PINCTRL (PIN CONTROL) subsystem
===============================
This document outlines the pin control subsystem in Linux
This subsystem deals with:
- Enumerating and naming controllable pins
- Multiplexing of pins, pads, fingers (etc) see below for details
- Configuration of pins, pads, fingers (etc), such as software-controlled
biasing and driving mode specific pins, such as pull-up, pull-down, open drain,
load capacitance etc.
Top-level interface
===================
Definitions:
- 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,
set drive strength, etc. for individual pins or groups of pins.
- 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
in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so
there may be several such number spaces in a system. This pin space may
be sparse - i.e. there may be gaps in the space with numbers where no
pin exists.
When a PIN CONTROLLER is instantiated, it will register a descriptor to the
pin control framework, and this descriptor contains an array of pin descriptors
describing the pins handled by this specific pin controller.
Here is an example of a PGA (Pin Grid Array) chip seen from underneath::
A B C D E F G H
8 o o o o o o o o
7 o o o o o o o o
6 o o o o o o o o
5 o o o o o o o o
4 o o o o o o o o
3 o o o o o o o o
2 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
this in our driver:
.. code-block:: c
#include <linux/pinctrl/pinctrl.h>
const struct pinctrl_pin_desc foo_pins[] = {
PINCTRL_PIN(0, "A8"),
PINCTRL_PIN(1, "B8"),
PINCTRL_PIN(2, "C8"),
...
PINCTRL_PIN(61, "F1"),
PINCTRL_PIN(62, "G1"),
PINCTRL_PIN(63, "H1"),
};
static struct pinctrl_desc foo_desc = {
.name = "foo",
.pins = foo_pins,
.npins = ARRAY_SIZE(foo_pins),
.owner = THIS_MODULE,
};
int __init foo_init(void)
{
int error;
struct pinctrl_dev *pctl;
error = pinctrl_register_and_init(&foo_desc, <PARENT>, NULL, &pctl);
if (error)
return error