Skip to content

Test: Device trees, overlays and kernel drivers

Embedded Linux & the Kernel

Device Trees, Overlays and Kernel Drivers

Why a device tree: I2C devices cannot introduce themselves

When you plug in a USB or PCIe device, the kernel reads its vendor and product IDs and loads a driver. I2C, SPI and GPIO devices have no way to do that. A DS3231 at 0x68 never says what it is, and an I2C scan only shows that something answers at 0x68 (the IMU lab’s ITG-3205 answers at the same address). So something has to tell the kernel what is wired to the board. On ARM boards that is the device tree: a description of the hardware that the firmware loads and passes to the kernel at boot. Before device trees, each ARM board had its own C “board file” compiled into the kernel. Step through the greenhouse Pi’s boot and watch when the kernel learns about each part.

Challenge: Step through the whole boot until the DS3231 is /dev/rtc0.

Discoverable buses

USB and PCIe devices report vendor and product IDs when asked; the kernel picks a driver from those.

Non-discoverable

I2C, SPI and GPIO have nothing to ask. A device answers its address, and that is all.

The device tree

A description of the hardware, loaded by the firmware and passed to the kernel at boot.

Raspberry Pi 4SoCthe kernel only knowswhat the device tree saysGPIO2 / GPIO3DS3231 RTC moduleI2C1: 0x68 (RTC) and 0x57 (EEPROM)– kernel: Linux is not running yetGPIO17Fan relay: offdriven by GPIO17– kernel: Linux is not running yetGPIO27Vent buttonGPIO27 to GND (needs a pull-up)– kernel: Linux is not running yet
  1. ▶ Power on. The boot ROM starts the bootloader. Linux is not running, and nothing has been described yet.
  2. Firmware reads config.txt. It finds dtparam=i2c_arm=on and dtoverlay=i2c-rtc,ds3231. (On a Pi 4 the firmware is start4.elf on the boot partition; on a Pi 5 it is the bootloader in the EEPROM.)
  3. Loads the base tree. bcm2711-rpi-4-b.dtb describes the SoC and what is soldered to the board: the I2C controllers, the GPIO controller, the ACT LED. Nothing about your header.
  4. Applies the overlays. i2c-rtc.dtbo adds a ds3231@68 node under I2C1 and the dtparam sets the controller’s status to "okay". The merged tree is handed to the kernel.
  5. Kernel reads the tree. It creates a device for every enabled node: an I2C client called 1-0068, with compatible "maxim,ds3231". No driver has looked at it yet.
  6. A driver binds. rtc-ds1307 lists "maxim,ds3231" in its match table; its probe() reads the chip over I2C and registers /dev/rtc0.
← Start here

Stage

1 of 6

/dev/rtc0

not yet

The relay and the button stay undescribed in this boot. That is fine: user space can use them through libgpiod (the GPIO lab). The kernel only needs a node for hardware a kernel driver will drive.