A database approach to describing device hardware
When moving an operating system to a new platform, one of the major headaches is describing the hardware. Where are the peripheral registers located? What interrupts are the devices connected to? How are devices interconnected? Historically, these issues have been addressed by modifying the device driver code. The result is a unique kernel image for each platform.
Suppose we could describe the hardware in a database that could be passed to the kernel at boot time? The kernel and its driver code are now generic and can be easily adapted to new platforms. Device trees are a database mechanism for describing a system’s hardware independent of the operating system and its device drivers. Hardware is described in plain text and translated to a binary “blob” by the Device Tree Compiler.
Introducing the problem
One of the biggest problems with porting an operating system such as Linux to a new platform is describing the hardware. That’s because the hardware description is scattered over a dozen or so device drivers, the kernel, and the boot loader just to name a few. The ultimate result is that these various pieces of software become unique to each platform and the number of configuration options grows.
There have been a number of approaches to addressing this problem. The notion of a “board support package” or BSP attempts to gather all of the hardware dependent code in a few files in one place. It could be argued that the entire arch/ subtree of the Linux kernel source tree is a gigantic board support package.
Take a look at the arch/arm/ subtree. In there you’ll find a large number of directories of the form mach-* and plat-*, presumably short for “machine” and “platform” respectively. Most of the files in these directories provide configuration information for a specific implementation of the ARM architecture. And of course, each implementation describes its configuration differently.
Wouldn’t it be nice to have a single language that could be used to unambiguously describe the hardware of a computer system? That’s the premise, and promise, of device trees.
The device tree concept evolved in the Open Firmware project that became IEEE 1275. The IEEE subsequently withdrew support for the standard and the project ultimately morphed in UEFI. Nevertheless, Open Firmware became the de facto method of booting Power PCs, including Apple MacIntoshes.
When the 32-bit and 64-bit Power PC arch/ trees in the Linux kernel were merged, a decision was made to require device trees as the only mechanism for describing hardware. The idea has since spread to several other architectures supported by Linux including ARM.
Platform devices vs. “discoverable” devices
The peripheral devices in a system can be characterized along a number of dimensions. There are, for example, character vs. block devices. There are memory mapped devices and those that connect through an external bus such as I2C or USB. Then there are platform devices and discoverable devices.
Discoverable devices are those that live on external busses such as PCI and USB that can tell the system what they are and how they are configured. That is, they can be “discovered” by the kernel. Having identified a device, it’s a fairly simple matter to load the corresponding driver, which then interrogates the device to determine its precise configuration.
Platform devices, on the other hand, lack any mechanism to identify themselves. SoC (System on Chip) implementations are rife with these platform devices—system clocks, interrupt controllers, GPIO, serial ports, to name a few. The device tree mechanism is particularly useful for managing platform devices.
Basics of a device tree
A device tree is a hierarchical data structure that describes the collection of devices and interconnecting busses of a computer system. It is organized as nodes that begin at a root represented by “/”. Every node has a name and consists of “properties” that are name-value pairs. It may also contain “child” nodes.
Figure 1 is a sample device tree taken from the devicetree.org website. It doesn’t do anything beyond illustrating the structure. Here we have two nodes named node1 and node2. node1 has two child nodes and node2 has one child. Properties are represented by name=value. Values can be strings, lists of strings, one or more numeric values enclosed by square brackets, or one or more “cells” enclosed in angle brackets. The value can also be empty if the property conveys a Boolean value by its presence or absence.