Skip to content
Libre Computer
Platform

Module 9 · Lab 6

Device tree and pin multiplexing

A PC's buses announce what is plugged into them. Most peripherals on an Arm system-on-chip cannot, so the board ships a description of its hardware, and the header's pins can each be switched between several jobs.

Key ideas

  • The device tree is a tree of nodes, one per device. Each says what the device is (compatible), where its registers are (reg), and which interrupts, clocks and regulators it uses. status turns it on or off.
  • Pin multiplexing: one pad of the system-on-chip can be a GPIO, or an I2C, SPI, UART or PWM signal. A function-select register picks which, and the kernel's pin-control driver writes it from the device tree's pin-control nodes. Only one function owns a pad at a time, so enabling a bus on two pins takes them away from GPIO. ldto conflicts checks whether two overlays claim the same pin; gpioinfo shows whether a line is already held by a bus, a driver or a program.
  • An overlay is a patch to the board's device tree, applied live to the running kernel or merged so the bootloader loads it at boot, that enables a bus on header pins or adds a part on it, without rebuilding the kernel or the base tree.
  • When an overlay adds a part with an in-kernel driver, the kernel probes it and the part appears in /sys and /dev with no code written.

Pin multiplexing

Pin multiplexing: one pad, several possible functionsWhich functions a pad offers depends on the pad; the GPIO pinout lists every header pin's.GPIO controllera line in libgpiodI2C controllerSDA or SCLUART controllerTX or RXPWM controllera PWM outputmuxPadon the chipHeader pinwhat you wire toFunction-select registerone field per padWritten by the kernel's pin-control driver,from the device tree or an overlay.Only one function owns a pad at a time: enablingI2C on two pins takes them away from GPIO.
Several controllers can reach one pad; a register field connects one of them. Here an I2C overlay has selected the I2C function. lgpio pinmux 7J1 <pin> lists the functions a pin's pad can carry on your board; gpioinfo shows what holds the pin now.

Device tree or ACPI

A PC learns its hardware differently. Its firmware hands the operating system ACPI tables, and those tables can contain small programs the OS runs to switch devices on and off. Arm boards like the course boards use a device tree: a plain description, with no code in it. The same Linux kernel understands both, and 64-bit Arm servers often use ACPI. What decides it is what the firmware provides.

Device treeACPI
What it isData only: nodes and properties, compiled from .dts source into a binary .dtbTables from the firmware, including AML bytecode that the OS interprets to run firmware-defined methods
Who writes itBoard and kernel developers, in the open with the kernelThe firmware vendor, built into the firmware
How the OS gets itThe bootloader passes it in memory; through UEFI it arrives as a configuration tableThe firmware publishes the tables; the OS finds them through UEFI
Power and device controlThe kernel's drivers do it, using the clocks, regulators and resets the tree namesOften firmware methods the OS calls, so the firmware keeps control
Adding a part on a headerAn overlay patches the treeAn extra table, or a firmware update
Where you meet itMost Arm and embedded boards, including both course boardsx86 PCs and laptops, and many Arm servers

On the course boards, U-Boot hands Linux a device tree through UEFI (module 7); there are no ACPI tables to read. The kernel log says which it found in its first lines.

The wiring tool

libretech-wiring-tool is Libre Computer's catalogue of ready-made overlays for each board's 40-pin header, and the commands that use them. Each board has its own set: one overlay per bus or part, a pin map of the header, and slot names that mean the same header pins on every board, so the same command works on Das Frite and on Solitude:

SlotHeader pinsOverlay on both course boards
H40P_I2C_127 (SDA), 28 (SCL)I2C bus
H40P_I2C_1_SSD1306_128x6427, 28The I2C bus with the SSD1306 128 × 64 OLED bound to the kernel's driver
H40P_SPI_0_1CS19 (MOSI), 21 (MISO), 23 (SCLK), 24 (CS0)SPI bus with one chip select
H40P_SPI_0_1CS_DEV19, 21, 23, 24The same bus with a spidev device for user-space access

Das Frite's console uses header pins 3 and 5, which other boards use for I2C; that is why the course uses the slot on pins 27 and 28 on both boards.

Overlays with ldto

ldto is the wiring tool's overlay command. Run the changing ones with sudo.

CommandWhat it does
ldto listEvery overlay for this board, with its slot name and a one-line summary
ldto info H40P_I2C_1The pins an overlay claims, what it needs first and what needs it
ldto conflicts A BWhether two overlays want the same pin or bus
ldto enable --dry-run AThe plan: which overlays would be applied, in which order, on which pins
ldto enable A / ldto disable AApply to the running kernel now, or take it off; gone at the next boot
ldto merge AMake it permanent: merge it into the device tree the bootloader loads from the EFI system partition
ldto statusWhat is applied now, what is merged, and what the next boot will use
ldto resetRemove the merged tree, so the next boot uses the firmware's own
lgpio pinmux 7J1 27The companion GPIO tool: a header pin's pad and every function it can carry (7J1 is the 40-pin header)

ldto applies its catalogue's overlays through the kernel's configfs overlay interface, and you can use the same interface for an overlay you wrote: compile it with dtc -@ -I dts -O dtb -o my.dtbo my.dts, then sudo mkdir /sys/kernel/config/device-tree/overlays/my, write the file into it with sudo sh -c 'cat my.dtbo > /sys/kernel/config/device-tree/overlays/my/dtbo', and check that status in that directory reads applied. sudo rmdir of the directory takes it off again.

Where the running tree comes from

Which tree Linux boots with is decided in this order, and knowing it explains most surprises:

SourceWhen it appliesKept across a reboot?
The tree built into the bootloader, plus overlays the firmware applies from SPI flashWhen nothing overrides itYes
A tree on the EFI system partition, written by ldto mergeWhenever that file is present; it replaces the built-in treeYes, until ldto reset or until a kernel update overwrites the file (re-merge then; ldto status says so)
Overlays applied live with ldto enableOn top of whichever tree bootedNo

Try an overlay live first; merge it only once it works, so a bad overlay cannot stop the board from booting.

On the bench

In short, what you do in lab 6, where the steps are given in full:

  1. Read the live tree under /proc/device-tree, decompile it with dtc, and find the first kernel log lines that say it booted from a device tree.
  2. Run lgpio pinmux 7J1 27 (7J1 is the wiring tool's name for the 40-pin header) and compare it with the same pin in the GPIO pinout: every function its pad can carry, and the register write that selects each.
  3. With ldto list and ldto info H40P_I2C_1, find the I2C overlay and the pins it claims; apply it with sudo ldto enable H40P_I2C_1 and check that a new /dev/i2c-* appears.
  4. Write your own overlay that binds the kernel's DS3231 real-time clock driver on that bus and apply it live through the kernel's configfs overlay interface. Check that a second /dev/rtc appears, then remove your overlay and take the bus off with sudo ldto disable H40P_I2C_1.

Resources

ResourceUse in this module
GPIO pinout: Das Frite · SolitudeEvery header pin's functions, libgpiod line, pad and mux register
libretech-wiring-toolReady-made overlays for the 40-pin header, and the tool that applies them
ldto documentationEvery ldto command, and the header slot table
GPIO pin header maps and wiring toolHow to use the wiring tool
Kernel devicetree documentationThe format and its bindings
Kernel ACPI documentationHow Linux uses ACPI, for comparison