Turn from: http://www.embedu.org/column/3648.html, for personal reference only. Linux Device Tree Detailed Time: 2016-03-17 huaqing Vision
Why the ARM Linux community introduces the device tree
The father of Linux Linus Torvalds Idle, when looking at the arm Linux code, one day finally can not help. He said in an ARM Linux mailing list on March 17, 2011: "This whole arm thing is a f*cking pain in the". This sentence forces the ARM Linux community to introduce a device tree.
Why would Linus Torvalds be mad? And why are the cows in the arm Linux community so obedient? You have to first understand a very good design in the Linux device driver framework: Device information and drive separation.
To illustrate the concept of device information and drive separation, let's look at a simple example of a mock code:
"Example 1" implements a code that simply writes the information to be used to die in the code:
int Add ()/* Simulate driver code */
{
return 3+5; /* Simulate device information */
}
Advantages: Simple
Cons: Once addend and Summand change, you have to change the code.
The improved design is as follows:
Example 2 implements a code that separates the information to be used and the operation code:
struct dev{
int id;
int x;
int y;
}; /* Simulate device information structure */
Strcut drv{
int id;
Int (*add) (struct dev *info);
}; /* Analog Drive structure */
int add (struct dev *info)/*/Analog Drive Code */
{
return info->x + info->y; /* Analog Device information-passed in via parameters */
}
struct DRV DRV = {
. id = 1,
. Add = Add,
};
/* Simulate device information */
struct Dev dev = {
. id = 1,
. x = 3,
. y = 5,
};
/* Analog bus initialization matches device information and driver code */
int bus ()
{
if (dev.id = = drv.id) {
Return Drv.add (&dev);
}
...
}
Pros: No need to modify code, no matter how addend and summand change, only need to modify the information
Cons: The structure is more complex
What does the device information and drive separation design have to do with the drive? The students familiar with hardware programming know that the general composition of hardware can be used simple expression:
The driver code logic of the operating peripherals, as long as the hardware is the same, will not change. But the peripheral hangs to the different host, may have the I/O address change, if has the interruption also is same, the interrupt number may also be different. These I/O addresses and interrupts are device information, and the code that uses this information to manipulate the control hardware is the driver.
If the "Example 1" design method, then the same hardware peripherals to different host, or change the address line/in the disconnection, the device information changes, you have to modify the driver. However, using the "Example 2" approach to design, the problem is solved: no matter where the same peripheral hardware received or the platform, its driver code logic does not need to change, but only need to modify the device information, the main is the I/O address and the interrupt number.
What does it have to do with introducing a plant tree? The Development Board (A8/A9) used in Huaqing teaching uses the DM9000 card chip. DM9000 Drive is open source, in the mainline kernel source code is there. Each time we based on the A8/A9 board transplant, the DM9000 driver has not been modified, just optional, the main task is to add device information in the board level file. The DM9000 driver uses the platform framework, so a platform_device message is added for the DM9000 NIC chip. The problem comes, if the use of C code to describe the device information, then in the kernel source code, there will be multiple copies of DM9000 Platform_device device information, resulting in kernel code redundancy.
The solution to this problem is to introduce the device tree and transform "Example 2" to illustrate the role of the device tree.
"Example 3" implements a code that separates not only the information to be used but also the operation code, and the information is not written in C code but is saved by the text configuration file:
struct dev{
int id;
int x;
int y;
}; /* Simulate device information structure */
Strcut drv{
int id;
Int (*add) (struct dev *info);
}; /* Analog Drive structure */
int add (struct dev *info)/*/Analog Drive Code */
{
return info->x + info->y; /* Analog Device information-passed in via parameters */
}
struct DRV DRV = {
. id = 1,
. Add = Add,
};
/* analog Device Tree-a special configuration file, Xxx.dtbs text file */
/{
......
dm9000{
x = 3;
y = 5;
};
......
};
/* Analog bus initialization matches device information and driver code */
int bus ()
{
/* Simulation of Device tree initialization processing */
Read the document (XXX.DTBS);
Parse the contents of the file (according to the rules of the device tree);
Generate the struct dev device information;
if (dev.id = = drv.id) {
Return Drv.add (&dev);
}
...
}
If you like "Example 3", you can solve the problem of code redundancy for large amounts of device information.
By and by, the system's hardware and software information can be described using the device tree. In this way, the ARM Linux community will not support the board and drive more and more cause the kernel source code in a lot of redundant codes (mainly board-level files), only need to transplant, the system hardware and software information through the device tree to provide, optional kernel code, you can.
Why Linux should be introduced into the device tree