The pin control subsystem
A typical system-on-chip (SOC) will have hundreds of pins (electrical connectors) on it. Many of those pins have a well-defined purpose: supplying power or clocks to the processor, video output, memory control, and so on. But many of these pins - again, possibly hundreds of them - will have no single defined purpose. Most of them can be used as general-purpose I/O (GPIO) pins that can drive an LED, read the state of a pushbutton, perform serial input or output, or activate an integrated pepper spray dispenser. Some subsets of those pins can be organized into groups to serve as an I2C port, an I2S port, or to perform any of a number of other types of multi-signal communications. Many of the pins can be configured with a number of different electrical characteristics.
Without a proper configuration of its pins, an SOC will not function properly - if at all. But the right pin configuration is entirely dependent on the board the SOC is a part of; a processor running in one vendor's handset will be wired quite differently than the same processor in another vendor's cow-milking machine. Pin configuration is typically done as part of the board-specific startup code; the system-specific nature of that code prevents a kernel built for one device from running on another even if the same processor is in use. Pin configuration also tends to involve a lot of cut-and-pasted, duplicated code; that, of course, is the type of code that the embedded developers (and the ARM developers in particular) are trying to get rid of.
The idea behind the pin control subsystem is to create a centralized mechanism for the management and configuration of multi-function pins, replacing a lot of board-specific code. This subsystem is quite thoroughly documented in Documentation/pinctrl.txt. A core developer would use the pin control code to describe a processor's multi-function pins and the uses to which each can be put. Developers enabling a specific board can then use that configuration to set up the pins as needed for their deployment.
The first step is to tell the subsystem which pins the processor provides; that is a simple matter of enumerating their names and associating each with an integer pin number. A call to pinctrl_register() will make those pins known to the system as a whole. The mapping of numbers to pins is up to the developer, but it makes sense to, for example, keep a bank of GPIO pins together to simplify coding later on.
One of the interesting things about multi-function pins is that many of them can be assigned as a group to an internal functional unit. As a simple example, one could imagine that pins 122 and 123 can be routed to an internal I2C controller. Other types of ports may take more pins; an I2S port to talk to a codec needs at least three, while SPI ports need four. It is not generally possible to connect an arbitrary set of pins to any controller; usually an internal controller has a very small number of possible routings. These routings can also conflict with each other; pin 77, say, could be either an I2C SCL line or an SPI SCLK line, but it cannot serve both purposes at the same time.
The pin controller allows the developer to define "pin groups," essentially named arrays of pins that can be assigned as a group to a controller. Groups can (and often will) overlap each other; the pin controller will ensure that overlapping groups cannot be selected at the same time. Groups can be associated with "functions" describing the controllers to which they can be attached. Some functions may have a single pin group that can be used; others will have multiple groups.
There are some other bits and pieces (some glue to make the pin controller work easily with the GPIO subsystem, for example), but the above describes most of the functionality found in the 3.1 version of the pin controller. Using this structure, board developers can register one or more pinmux_map structures describing how the pins are actually wired on the target system. That work can be done in a board file, or, presumably, be generated from a device tree file. The pin controller will use the mapping to ensure that no pins have been assigned to more than one function; it will then instruct the low-level pinmux driver to configure the pins as described. All of that work is now done in common code.
The pin multiplexer on a typical SOC can do a lot more than just assign a pin to a specific function, though. There is typically a wealth of options for each pin. Different pins can be driven to different voltages, for example; they can also be connected to pull-up or pull-down resistors to bias a line to a specific value. Some pins can be configured to detect input signal changes and generate an interrupt or a wakeup event. Others may be able to perform debouncing. It adds up to a fair amount of complexity which is often reflected in the board-specific setup code.
The generic pin configuration interface, currently in its third revision, attempts to bring the details of pin configuration into the pin controller core. To that end, it defines 17 (at last count) parameters that might be settable on a given pin; they vary from the value of the pullup resistor to be used through slew rates for rising or falling signals and whether the pin can be a source of wakeup events. With this code in place, it should become possible to describe the complete configuration of complex pin multiplexors entirely within the pin controller.
The number of pin controller users in the 3.1 kernel is relatively small,
but there are a number of patches circulating to expand its usage. With
the addition of the configuration interface (in the 3.2 kernel, probably),
there will be even more reason to make use of it. One of the more
complicated bits of board-level configuration will be supported almost
entirely in common code, with all of the usual code quality and
maintainability benefits. It is hard to stick a pin into an improvement
like that.
Index entries for this article | |
---|---|
Kernel | Device drivers |
Kernel | Pin controller |
Posted Nov 24, 2011 6:52 UTC (Thu)
by linusw (subscriber, #40300)
[Link]
I have found that the biggest confusion around pin controllers is terminology, I currently think of pin control (pinctrl) as a superset of pin multiplex (pinmux) and pin configuration (pinconf).
- pinctrl does enumeration of pins, groups of pins and GPIO range cross-referencing.
- pinmux multiplexes across different uses of pins.
- pinconf configures electrical characteristics (etc) of pins.
Posted Nov 24, 2011 14:04 UTC (Thu)
by dougg (guest, #1894)
[Link] (2 responses)
Posted Nov 24, 2011 14:43 UTC (Thu)
by linusw (subscriber, #40300)
[Link]
Actually pin control is partitioned apart from users of the pins, say GPIO or I2C or SPI, it just does pin control. As for gpiolib, it's designed to only handle single-bit GPIOs. I think a new MMIO-port abstraction is needed to handle a register range as a memory-mapped parallel port of some kind, if one does not already exist, I haven't seen one.
Posted Dec 1, 2011 13:06 UTC (Thu)
by jpfrancois (subscriber, #65948)
[Link]
Having a common pin multiplexing scheme doesn't mean all your pin will be declared as GPIO.
Now, regarding your GPIO, the gpiolib code is not pefect, but I think there was an attempt to do gpio gouping, so that they can act as a parallel bus.
In many cases, the gpiolib is a clear win, and when using SoC from different vendor, playing with individual gpio is now the same, wether you are playing with an atmel or a texas chip. I don't miss old days when you add to figure out what code to use to move a particular gpio.
Posted Nov 24, 2011 23:04 UTC (Thu)
by djm (subscriber, #11651)
[Link]
The pin control subsystem
Parallel Input Output Controller (PIO)
Now the kernel's existing approach based on gpiolib is a sick joke, as it is based on abstracting all the complexity (explained in your article) out of the gpio architecture, so what is left is lame.
So the bit I wanted to stress in this post is that gpio lines in the same controller bank (i.e. 32 lines) can be used as a parallel bus. In the hardware I use PC16-PC31 are used as the top 16 bits of the data bus. Now not many users should be fiddling with the data bus but there are other uses of the parallel nature of some gpio lines. A step too far for a pin control system?
If so then mmap() is your friend. As the SCSI storage subsystem has taught me: the kernel isn't necessarily the way, it often is in the way.
Parallel Input Output Controller (PIO)
So the bit I wanted to stress in this post is that gpio lines in the same controller bank (i.e. 32 lines) can be used as a parallel bus. In the hardware I use PC16-PC31 are used as the top 16 bits of the data bus. Now not many users should be fiddling with the data bus but there are other uses of the parallel nature of some gpio lines.
Parallel Input Output Controller (PIO)
OpenBSD has had something like this for a few years in its gpio(4) device and associated gpioctl(8) utility. These allow configuration of device pins in various I/O modes and runtime attachment of I2C and Onewire drivers (iic(4) and onewire(4) respectively. The available I2C drivers are pretty skewed towards sensors one would find on a motherboard, but the kernel API is trivial to write drivers to (hell, even I wrote a couple).
The pin control subsystem