You're reading from Linux Device Driver Development Cookbook
Device tree internals
A device tree is a tree data structure with nodes that tell you which devices are currently present in a system along with their configuration settings. Every node has property/value pairs that describe the attributes of the device being represented. Every node has exactly one parent but the root node has no parent.
The next code shows an example representation of a simple device tree that is nearly complete enough to boot a simple operating system, with the platform type, CPU, memory, and a single universal synchronous and asynchronous receiver-transmitter (UART) described with its clocks and interrupt lines. Device nodes are shown with properties and values inside each node.
The device tree syntax is quasi self-explanatory; however, we're going to explain it in detail in this paragraph by taking a look at the simple_platform.dts file from the GitHub...
Using the device tree compiler and utilities
Here are some notes about some interesting usages of the dtc and its utilities which can be really useful during device drivers development and kernel configuration.
Obtaining a source form of a running device tree
dtc can also be used to convert a running device tree into a human-readable form too! Let's suppose we wish to know how our ESPRESSObin has been configured; the first thing to do is to take a look at ESPRESSObin's DTS file in the kernel sources. However, suppose we don't have it. In this situation, we can ask dtc to revert to the corresponding DTB file, as seen in the preceding section, but suppose we still don't have it. What we can do? Well, dtc...
Using a device tree to describe a character driver
We have seen that by using a device tree, we can specify different driver settings and then modify the driver's functionalities. However, our possibilities do not finish here! In fact, we can use the same code for different driver's releases or a different types of the same device.
How to manage different device types
Let's suppose our chrdev has two other implementations (plus the current one) in which the hardware is done in such a way that most parameters are fixed (and well known) and not selectable by the developer; in this case, we can still use node properties to specify them, but doing this is error prone and it forces the user to know these constraints...
Configuring the CPU pins for specific peripherals
Even if the ESPRESSObin is the reference platform of this book, in this paragraph, we'll explain how a kernel developer can modify the pins settings for different platforms due to the fact this task may vary across different implementations. In fact, even if all of these implementations are device tree-based, they have some differences among each other that must be outlined.
Current CPUs are very complex systems — so complex that most of them are given the acronym SoC, which means System-On-Chip; in fact, in a single chip, we may find not only the Central Processing Unit (CPU) but also a lot of peripherals, which the CPU can use to communicate with the external environment. So, we can have the display controller, the keyboard controller, a USB host or device controller, disks, and network controllers all together inside...
Using a device tree to describe a character driver
To test the code presented in the recipe in the chapter and to show how everything works, we have to compile it before any further steps are taken:
$ make KERNEL_DIR=../../../linux
make -C ../../../linux \
ARCH=arm64 \
CROSS_COMPILE=aarch64-linux-gnu- \
SUBDIRS=/home/giometti/Projects/ldddc/github/chapter_4/chrdev modules
make[1]: Entering directory '/home/giometti/Projects/ldddc/linux'
CC [M] /home/giometti/Projects/ldddc/github/chapter_4/chrdev/chrdev.o
CC [M] /home/giometti/Projects/ldddc/github/chapter_4/chrdev/chrdev-req.o
...
LD [M] /home/giometti/Projects/ldddc/github/chapter_4/chrdev/chrdev.ko
make[1]: Leaving directory '/home/giometti/Projects/ldddc/linux'
Then, we have to move the chrdev.ko and chrdev-req.ko files to the ESPRESSObin. Now, if we insert the first module...