ARM Linux 3.x Device tree (Device) __linux

Source: Internet
Author: User
Tags bit set documentation first string ranges
Song Baohua Barry Song <21cnbao@gmail.com> 1. ARM Device Tree Origin

Linus Torvalds's ARM Linux mailing list on March 17, 2011 declared "This whole arm thing is a f*cking pain", triggering an earthquake in the arm Linux community, followed by a series of arm communities Significant revisions to the column. In the past of Arm Linux, arch/arm/plat-xxx and arch/arm/mach-xxx were filled with a lot of junk code, and quite a few of the code was just describing board-level detail, and these board-level details were rubbish for the kernel, such as platform equipment on board, resource, I2c_board_info, Spi_board_info and the platform_data of various hardware. Readers are interested in statistics of common s3c2410, s3c6410 and other board-level directories, the code volume in tens of thousands of lines.

The community must change this situation, so the flattened Device tree (FDT), which has been used under other architectures such as PowerPC, has entered the arm community's vision. Device tree is a data structure that describes hardware that originates from openfirmware (of). In Linux 2.6, the hardware details of the arm architecture are too heavily encoded in arch/arm/plat-xxx and arch/arm/mach-xxx, and after the device tree, many details of the hardware can be passed directly to Linux, It is no longer necessary to do a lot of redundant coding in kernel.

The Device tree consists of a series of named nodes (node) and attributes (property), and the node itself can contain child nodes. The so-called attribute, in fact, is the name and value that appear in pairs. In device tree, the information that can be described includes (the original information was mostly hard code to kernel):
Number of CPUs and categories memory base address and size bus and bridge peripheral Connection Interrupt controller and interrupt usage Gpio controller and GPIO usage clock controller and clock usage

It is basically to draw a circuit board on the CPU, bus, equipment of the tree, bootloader will pass this tree to the kernel, and then the kernel can identify the tree, and according to it to expand the Linux kernel Platform_device, i2c_client, Spi_ Device and other devices, such as memory, IRQ and other resources, also passed to the kernel, the kernel will bind these resources to the appropriate device to expand.
2. Composition and structure of Device tree

The whole device tree involves a wide range of new text formats for describing device hardware information, adding tools to compile this text, and bootloader also needs to support the transfer of compiled device tree to the Linux kernel.
DTS (device tree source)

The. dts file is a description of the device tree in ASCII text format, which is very user-friendly and suitable for human reading habits. Basically, in Arm Linux, a. dts file corresponds to an arm of the machine, typically placed in the kernel's arch/arm/boot/dts/directory. Since an SOC may correspond to multiple machine (one SOC can correspond to multiple products and circuit boards), it is bound to these. dts files need to contain many common parts, and in order to simplify the Linux kernel, the common parts of the SOC or The common parts of multiple machine are generally refined to. DTSi, similar to the C-Language header file. The other machine correspond to. DTS to include this. DTSi. For example, for vexpress, Vexpress-v2m.dtsi is referenced by Vexpress-v2p-ca9.dts, Vexpress-v2p-ca9.dts has the following line:

/include/"Vexpress-v2m.dtsi"

Of course, like the C-Language header file,. DTSi can also include other. DTSi, for example, almost all of the arm Soc's. DTSi are quoting Skeleton.dtsi.

The basic elements of. DTS (or its include. DTSi) are the nodes and attributes described above:

/{
    Node1 {
        A-string-property = "a string";
        A-string-list-property = "A-string", "second string";
        A-byte-data-property = [0x01 0x23 0x34 0x56];
        child-node1 {
            first-child-property;
            Second-child-property = <1>;
            A-string-property = "Hello, world";
        };
        Child-node2 {
        };
    Node2 {
        an-empty-property;
        A-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
        child-node1 {
        };
    };

The above. dts file has no real purpose, but it basically represents the structure of a device tree source file:

1 root node "/";

The root node contains a series of sub nodes, in this case "Node1" and "Node2";

The node "Node1" also contains a series of sub nodes, in this case "Child-node1" and "Child-node2";

Each node has a series of attributes. These properties may be empty, such as "An-empty-property"; may be strings, such as "a-string-property"; it might be an array of strings, such as "A-string-list-property" ; may be cells (composed of u32 integers), such as "Second-child-property", which may be binary numbers, such as "A-byte-data-property".

Here's an example of how to write a. dts file with one of the simplest machine. Suppose this machine is configured as follows:

1 Dual-core arm CORTEX-A9 32-bit processor;

The memory-mapped area on the local bus of ARM distributes 2 serial ports (located at 0x101f1000 and 0x101f2000 respectively), the Gpio controller (located in 0x101f3000), the SPI controller (located in 0x10170000), and the interrupt controller (located in 0x10140000) and a external bus bridge;

External Bus bridge is connected with SMC SMC91111 Ethernet (located in 0x10100000), I2C Controller (located in 0x10160000), 64MB NOR Flash (located in 0x30000000);

The Maxim DS1338 Real-time Clock (I2C) is connected to the I2C bus on the I2C controller connected to the External buses bridge.

Its corresponding. dts file is:

/{compatible = "acme,coyotes-revenge";
    #address-cells = <1>;
    #size-cells = <1>;

    Interrupt-parent = <&intc>;
        CPUs {#address-cells = <1>;
        #size-cells = <0>;
            cpu@0 {compatible = "arm,cortex-a9";
        Reg = <0>;
        };
            cpu@1 {compatible = "arm,cortex-a9";
        Reg = <1>;
    };

    };
        serial@101f0000 {compatible = "arm,pl011";
        reg = <0x101f0000 0x1000 >;
    Interrupts = < 1 0 >;

    };
        serial@101f2000 {compatible = "arm,pl011";
        reg = <0x101f2000 0x1000 >;
    Interrupts = < 2 0 >;

    };
        gpio@101f3000 {compatible = "arm,pl061";
        reg = <0x101f3000 0x1000 0x101f4000 0x0010>;
    Interrupts = < 3 0 >;

    };
        intc:interrupt-controller@10140000 {compatible = "arm,pl190"; Reg = <0x10140000 0x1000 >;
        Interrupt-controller;
    #interrupt-cells = <2>;

    };
        spi@10115000 {compatible = "arm,pl022";
        reg = <0x10115000 0x1000 >;
    Interrupts = < 4 0 >;

    };
        External-bus {#address-cells = <2> #size-cells = <1>; Ranges = <0 0 0x10100000 0x10000//chipselect 1, Ethernet 1 0 0x10160000 0x10000//Ch Ipselect 2, I2C Controller 2 0 0x30000000 0x1000000>;
            Chipselect 3, NOR Flash ethernet@0,0 {compatible = "smc,smc91c111";
            Reg = <0 0 0x1000>;
        Interrupts = < 5 2 >;

        };
            i2c@1,0 {compatible = "Acme,a1234-i2c-bus";
            #address-cells = <1>;
            #size-cells = <0>;
            Reg = <1 0 0x1000>;
            Interrupts = < 6 2 >;
              rtc@58 {compatible = "maxim,ds1338";  Reg = <58>;
            Interrupts = < 7 3 >;
        };

        };
            flash@2,0 {compatible = "SAMSUNG,K8F1315EBM", "Cfi-flash";
        Reg = <2 0 0x4000000>;
    };
}; };

In the above. dts file, the compatible attribute of the root node "/" compatible = "Acme,coyotes-revenge"; the name of the system is defined and its organization is:<manufacturer>,< Model>. The Linux kernel can determine what machine it starts through the compatible attribute of the root node "/".

Each device in a. dts file has a compatible property, compatible property user-driven, and device binding. The Compatible property is a list of strings in which the first string represents the exact device represented by the end point, in the form of "<manufacturer>,<model>", followed by a string representing the other devices that can be compatible. It can be said that the front is specific, the latter will cover a wider range. such as the Flash node in Arch/arm/boot/dts/vexpress-v2m.dtsi:

flash@0,00000000 {
     compatible = "Arm,vexpress-flash", "Cfi-flash";
     reg = <0 0x00000000 0x04000000>,
     <1 0x00000000 0x04000000>;
     Bank-width = <4>;
 };

The 2nd string "Cfi-flash" of the compatible property is significantly more extensive than the 1th string "Arm,vexpress-flash".

For example, the Freescale MPC8349 Soc contains a serial device that implements the NS16550 register interface of National Semiconductor. Then the compatible property of MPC8349 serial device is compatible = "Fsl,mpc8349-uart", "ns16550". Wherein, fsl,mpc8349-uart refers to the exact device, which ns16550 on behalf of the device to maintain register compatibility with National Semiconductor's 16550 UART.

Next the CPUs node of the root node "/" contains 2 CPU nodes, describing 2 CPUs on this machine, and the compatible property of the two is "arm,cortex-a9".

Note the names of the 2 CPU CPUs and CPUs, which follow the form of:<name>[@<unit-address>],<> content is required, and [] are optional. Name is an ASCII string that describes the device type that corresponds to the node, such as the node name for the 3com Ethernet adapter should be Ethernet rather than 3com509. If a node describes a device that has an address, a @unit-address should be given. The name of multiple device nodes of the same type can be the same, as long as the unit-address is different, as in this case, cpu@0, cpu@1, and serial@101f0000 and serial@101f2000 have the same name nodes. The unit-address address of the device is also often given in the Reg attribute of its corresponding node. The EPAPR standard gives the specification of the end-point nomenclature.

Addressable devices use the following information to encode address information in device tree:
Reg #address-cells #size-cells

Where Reg is organized as a reg = <address1 length1 [address2 length2] [address3 length3] ..., where each set of address length indicates the use of one of the addresses of the device Range. The address is 1 or more 32-bit integers (that is, the cell), while length is either a list of the cell or empty (if #size-cells = 0). The address and length fields are variable lengths, and the #address-cells and #size-cells of the parent node determine the length of the address and length fields of the Reg property of the child node respectively. In this example, the #address-cells = <1>; and #size-cells = <1>; of the root node determines that the address and length fields of the serial, Gpio, and SPI nodes are 1 respectively. CPUs node #address-cells = <1>; and #size-cells = <0>; determines the address of 2 CPU nodes is 1, and length is empty, thus forming 2 CPU Reg = <0 >; reg = <1>;. External-bus node #address-cells = <2> and #size-cells = <1>; determines the Ethernet, I2C, and Flash reg fields in the form of Reg = <0 0 0x1000 >;, Reg = <1 0 0x1000>; and Reg = <2 0 0x4000000>;. Where the Address field length is 0, the first cell (0, 1, 2) is the corresponding slice, the 2nd cell (0,0,0) is relative to the selected base, and the 3rd cell (0x1000, 0x1000, 0x4000000) is length. It is particularly important to note that the #address defined in the I2C node-cells = <1>; and #size-cells = <0>; also acts on the RTC connected to the I2C bus, and its address field is 0x58, which is the I2C of the device.

The child nodes of the root node describe the view of the CPU, so the address area of the root node is directly located in the memory area of the CPU. However, the address after the bus bridge often needs to be converted to the corresponding CPU memory mapping. The External-bus Ranges property defines how the address range after the External-bus bridge maps to the memory area of the CPU.

        Ranges = <0 0  0x10100000   0x10000     //chipselect 1, Ethernet
                  1 0  0x10160000   0x10000     // Chipselect 2, I2C controller
                  2 0  0x30000000   0x1000000>;//Chipselect 3, NOR Flash

Ranges is the address translation table where each item is a child address, a parent address, and a mapping of the size of the child address space. The child address, parent address in the mapping table takes the #address-cells of the child address space and the #address-cells size of the parent address space, respectively. For this example, the #address-cells of the child address space is 2 and the #address-cells value of the parent address space is 1, so the first 2 cell of 0 0 0x10100000 0x10000 is offset 0 on the External-bus back slice 0, The 3rd cell indicates that the address space of the External-bus 0 offset 0 is mapped to the 0x10100000 position of the CPU, and the 4th cell represents the size of the map as 0x10000. The meaning of the following 2 items of ranges can be analogous.

The Device tree also interrupts the connection information, which provides the following properties for the interrupt controller:

interrupt-controller– This property is NULL, the interrupt controller should add this attribute to indicate its identity;

#interrupt-cells– is similar to the #address-cells and #size-cells, which indicates the cell size of the interrupts property of the device that connects this interrupt controller.

In the entire device tree, the attributes associated with the interrupt include:

The interrupt-parent– device node, through which it specifies the phandle of the interrupt controller to which it is attached, inherits from the parent node when the node does not specify Interrupt-parent. For this example, the root node specifies interrupt-parent = <&intc>; it corresponds to intc:interrupt-controller@10140000, The nodes of the root node do not specify Interrupt-parent, so they inherit the INTC, which is the interrupt controller located at 0x10140000.

interrupts– uses the interrupted device node to specify the interrupt number, triggering method, etc., which contains the number of cell, determined by the #interrupt-cells attribute of the interrupt Controller node it attaches to. What each cell is meant to be, is generally determined by the driver's implementation, and is also explained in the binding document of Device tree. For example, for the arm GIC Interrupt Controller, #interrupt-cells is 3, its 3 cell specific meaning documentation/devicetree/bindings/arm/gic.txt have the following text description:

01 The 1st cell is the interrupt type;
0 for SPI interrupts, 1 for PPI interrupts.
The 2nd cell contains the interrupt number for the interrupt type.  SPI interrupts are in the range [0-987].
PPI interrupts are in the [0-15].
The 3rd cell is the flags, encoded as follows:09 bits[3:0] trigger type and level flags.  1 = Low-to-high edge triggered 2 = High-to-low Edge triggered 12 4 = Active High level-sensitive 8 = active low level-sensitive Bits[15:8] PPI Interrupt CPU Mas  K. Each bit corresponds to each of the 8 possible CPUs attached to the GIC.  A bit set to ' 1 ' indicated the interrupt are wired to that CPU. Only valid for PPI interrupts. 

In addition, it is worth noting that a device may also use multiple interrupt numbers. For ARM GIC, if a device uses the SPI 168, 169th, 2 interrupts, is a high level trigger, then the device node interrupts attribute can be defined as: interrupts = <0 4> <0 169

In addition to interruptions, clock, GPIO, and Pinmux in arm Linux can be described through the nodes and attributes in. DTS.
DTC (device tree compiler)

A tool that compiles. DTS to. DtB. DTC source code is located in the kernel of the SCRIPTS/DTC directory, in the Linux kernel enables device tree, the host tool DTC is compiled when the kernel is compiled, corresponding to the scripts/dtc/makefile in the "Hostprogs-y: = DTC "This hostprogs compiles target.

In the Linux kernel arch/arm/boot/dts/makefile, it is described which. dtb files are compiled when a certain Soc is selected, as in the case of Vexpress. DTB includes:

dtb-$ (config_arch_vexpress) + + VEXPRESS-V2P-CA5S.DTB \
        vexpress-v2p-ca9.dtb \
        VEXPRESS-V2P-CA15-TC1.DTB \
        VEXPRESS-V2P-CA15_A7.DTB \
        XENVM-4.2.DTB

Under Linux, we can compile the device tree file separately. When we run make Dtbs in the Linux kernel, if we have previously chosen arch_vexpress, the above. DTB will be compiled by the corresponding. DTS. Because Arch/arm/makefile contains a DTBS to compile the target project.
Device Tree Blob (. DtB)

. DTB is a description of the device tree in the binary format compiled by the DTC, which can be parsed by the Linux kernel. Usually when we make the NAND, SD start image for the circuit board, we leave a very small area for the. dtb file to store it, and then bootloader will read the. DtB to memory in the process of booting the kernel.
Binding

For the nodes and attributes in the device tree how to describe the hardware details of the device, generally need documentation to explain, the document suffix name is generally. txt. These documents are located in the Documentation/devicetree/bindings directory of the kernel and are divided into subdirectories.
Bootloader

Uboot mainline from v1.1.3 to support device tree, and its support for ARM is with the ARM core support device tree to complete the same period.

In order to enable device tree, you need to compile uboot to add in config file

#define CONFIG_OF_LIBFDT

In Uboot, the. DTB can be read into memory from any media such as NAND, SD, or TFTP, assuming that. DTB the memory address is 0x71000000, then you can run the command uboot FDT command settings in addr. DTB address, such as:

u-boot> FDT Addr 0x71000000

FDT Other commands can be used, such as FDT resize, FDT print, and so on.

For ARM, it can be done through Bootz Kernel_add

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.