Skip to content

Linux GPIO Controller Architecture

Linux GPIO support is built on top of GPIO controller drivers that expose hardware GPIO lines through a common abstraction layer.

Understanding the GPIO subsystem requires separating three different concepts:

GPIO Controller
GPIO Line
GPIO Consumer

GPIO Controller

A GPIO controller is a hardware peripheral responsible for controlling a group of GPIO lines.

From a hardware perspective, a GPIO controller is usually implemented as a MMIO register block.

Typical registers include:

DIR
IN
OUT
SET
CLR

Example:

GPIO Controller

DIR Register
IN Register
OUT Register
SET Register
CLR Register

Linux represents a GPIO controller through:

struct gpio_chip

GPIO Line

A GPIO line represents a single GPIO signal managed by a GPIO controller.

Conceptually:

GPIO Line
    =
Register Bit

Example:

DIR bit 5
OUT bit 5
IN bit 5

represent:

GPIO Line 5

A GPIO controller typically manages multiple GPIO lines.

Example:

GPIO Controller
    ├── GPIO Line 0
    ├── GPIO Line 1
    ├── GPIO Line 2
    └── ...

GPIO Consumer

A GPIO consumer is a device driver that owns and uses a GPIO line.

Examples:

Ethernet PHY Reset
Wi-Fi Enable
Bluetooth Enable
LED Control
Power Enable

Debug information can be observed through:

cat /sys/kernel/debug/gpio

Example:

gpio-601 (ETH_RST_N | phy-reset)

Where:

ETH_RST_N
    GPIO line name

phy-reset
    GPIO consumer

Linux GPIO Architecture

The GPIO subsystem is layered as follows:

Driver
gpiolib
gpio_chip
GPIO Controller Driver
MMIO Registers

Hardware-specific register operations remain inside the controller driver.

Generic GPIO APIs are provided by gpiolib.


GPIO Controller and gpio_chip

Linux uses:

struct gpio_chip

to represent a GPIO controller.

A simplified model looks like:

struct gpio_chip {
    int (*direction_input)(...);
    int (*direction_output)(...);

    int (*get)(...);
    int (*set)(...);
};

The callbacks provide hardware-specific implementations.

Example:

gpiolib
chip->set()
GPIO Controller Driver
writel()

GPIO Numbering

Historically Linux exposed global GPIO numbers.

Example:

gpiochip569
line 17

Global GPIO number:

569 + 17 = 586

Modern GPIO drivers should avoid relying on global GPIO numbers.

Preferred models are:

gpiochip + line offset

or

GPIO descriptors

Raspberry Pi 5 Example

Observed GPIO hierarchy:

Device Tree
platform device
platform driver
gpiochip
GPIO lines

Example controllers:

107d508500.gpio
107d517c00.gpio
1f000d0000.gpio

Example GPIO chip:

gpiochip0
label = pinctrl-rp1
ngpio = 54

Relationship to MMIO

GPIO controllers are implemented on top of MMIO register blocks.

Typical operation flow:

Driver
gpiod_set_value()
gpio_chip callback
writel()
GPIO register

This abstraction allows Linux GPIO APIs to remain independent of hardware-specific register layouts.

  • MMIO Register Access
  • Platform Driver
  • Linux Driver Model
  • gpiolib
  • GPIO Descriptor
  • Device Tree GPIO Binding