Uploaded by mikicar33

4-2 - Device Tree

advertisement
4. Linux device tree
In this section, let's understand about the Linux Device Tree. This is also called as Flattened device tree.
We'll just understand, why device tree and what problem it solves. For a time being, let's forget about
device tree and let's just pretend that we don't know what it is. Let's say, we have our own custom board,
or it could be your Beaglebone hardware.
In this board there is a SOC, which is based on ARM architecture and the board has got couple of on board
peripherals like the Zigbee transceiver, serial flash, EEPROM, SD card connector, USB interface, etc... And
they are connected via the bus interfaces like USART, SPI, I2C, SDIO, USB, etc.
In embedded systems, we usually see SPI, I2C, SDIO, UART, USB, etc. Now, the interesting thing here is, the
onboard peripherals are not dynamically discoverable.
That means, the onboard peripherals which connect to SPI, I2C, SDIO, Ethernet, etc., have no capability to
announce their existence on the board by themselves to the operating system like Linux. Why? Because,
those interfaces like I2C, SPI, SDIO, etc., they don't have that intelligence to support dynamic
discoverability. Even though those peripherals are there on the board, the operating system has no idea
about configuring them. But, the USB use these different. When you connect a pen drive or thumb drive to
use the port, it has the intelligence to announce its presence to the operating system dynamically by
pushing some information. But, these devices cannot do that.
All those who cannot announce their presence to the operating system by themselves are called as
"Platform devices". That means, USB is not a platform device. Because, it can announce its presence to the
operating system using the USB interface.
Now the question is, how can we make Linux kernel know about these platform devices or peripherals
present on the board. We need to somehow announce their existence to the kernel, since they cannot do it
themselves.
One solution which we have been using is to go for a static way, that is hard coding these platform device
details in a file called the board file.
For example, let's say I create a board file for my board and when the kernel calls this function, board_init(),
I add each and every platform device to the kernel subsystem with a platform specific data. The platform
data is nothing but a data structure which actually describes the peripheral.
That's it, there is nothing special about it.
Board file is basically the part of the Linux kernel, so when you modify to add new entries, you have to
recompile the kernel.
Then only your changes will take effect. So, when you add all those platform devices from the board file,
Linux comes to know about those platform devices, so then it basically updates a list of all the platform
devices present on the board.
When the corresponding driver is loaded, the Linux calls the "probe" function of the driver and the platform
data will be passed to the driver and the driver will then initialize the peripheral.
For example, let's say the name of the platform device zigbee is zigbee100. The corresponding driver name
must also be same as the platform device name, that is "zigbee100.ko". When you load this driver, that is
"zigbee100.ko", the Linux binds this device with this driver.
Linux immediately calls the "probe" function of this driver and the driver will then take care of initializing
the peripheral. We'll discuss more about these things later.
When you have different boards, each board will have different on board peripherals. That means the
boards are not identical.
That means, for every board you'll be having one board file. That also means that for each board, you'll be
having separate kernel image.
So, this kernel image will not run smoothly on this board. This kernel image won't run on these boards. This
is a problem which the Linux community wanted to solve. They wanted to cutoff the dependency of
platform device enumeration from the Linux kernel. That is hard coding of platform device details into the
Linux kernel.
Then the ARM community came up with this idea called "Device Tree" also called as "Flattened Device Tree
Model".
In this case, what they did is, instead of hard coding the hardware details into the Linux kernel board file,
every board vendors has to come up with a file called DTS, which stands for "Device Tree Source File" or
you can say "Device Tree Structure". This file actually consists of all the details related to the board written
using some predefined syntaxes. You can say that this file consists of lots of data structures, which will
include all the details of a hardware.
It means encoding all the hardware details in a file called DTS. So, every board will have its own DTS file.
This file will be compiled using a Device Tree Compiler that we call as DTC. This is one kind of special
compiler to convert this DTS file to the stream of bytes, that is nothing but a binary. We call this binary as
DTB. The DTB is nothing but a stream of bytes which encodes the details of the hardware, which is derived
from DTS compilation.
There will be one DTB for every board. When you edit that DTS file to add a new entry, you need not to
compile the kernel again and again, you just need to compile the DTS file and get the new DTB. That's it.
That means, there are no more board file entries. All the board file entries are now taken over by the DTB.
When the kernel boots, you should tell the kernel where this DTB resides in the memory, so that the Linux
kernel can load that DTB file and extract all the hardware details of the board. In this case you need not to
change the kernel when you change the board but you have to only change the DTB file. This is the idea
behind using the DTB.
You can go to this path in the Linux kernel and you will see lots of DTB files related to different variation of
the board.
Download