Question

Was reading the Device Tree Usage and reached to the section describing the ranges key attribute for a node.

external-bus {
        #address-cells = <2>
        #size-cells = <1>;
        ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet
                  1 0  0x10160000   0x10000     // Chipselect 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>;
        };
    };
  1. What is the difference between ranges and reg ?
  2. What are the dimensions for the ranges, how the parser figure out what is written in it?
  3. One missing part I didn't understand yet? Can't include .h files instead of hard-coding values in a the .dts file?
Was it helpful?

Solution

The "range" property maps one or more addresses (the second number from the left of the range) in the current node, the "external bus" node, to addresses in the parent node (probably the CPU) address space (the third number in the range). The fourth number is the length of the range. Buses can have their own idea of addresses on their external side to which peripherals are attached, so the drivers that manage the peripherals on the bus will need to know these ranges in order to read to or write from the the devices.

The "reg" property indicates the address at which a device resides in the address range of the node (the "external bus" in this case) in which the device is defined. So in this case, flash@2,0 resides at address 0 in the external bus range, and extends to address 0x04000000. This corresponds to address range 0x30000000 to 0x34000000 in the parent (CPU) address space.

I am assuming that the length specifier of the third range, 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash should in fact be 0x04000000 rather than 0x1000000.

OTHER TIPS

For this perticular example, Jonathan Ben-Avraham's explanation is correct. But its good to understand the detailed structure of ranges property in device tree.

  • ranges is a list of address translations.
  • Each entry in the ranges table is a tuple containing the child address, the parent address, and the size of the region in the child address space.

like

ranges = < Child1Address ParentAddressForChild1 sizeofchild1 
           Child2Address ParentAddressForChild2 sizeofchild2
           Child3Address ParentAddressForChild3 sizeofchild3
>;
  • The size of each field is determined as below

For taking the child Address size check #address-cells value of child node.

For taling the the parent address size check #address-cells value of its parent node,

For taking the length of size check #size-cells value of child node.


Exampe1: Mentioned in as Question

    #address-cells = <1>;
    #size-cells = <1>;
    external-bus {
        #address-cells = <2>;
        #size-cells = <1>;
        ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet
                  1 0  0x10160000   0x10000     // Chipselect 2, i2c controller
                  2 0  0x30000000   0x1000000>; // Chipselect 3, NOR Flash

Let's decode first entry.

  1. Child address-cells size is 2 so first two entry mention child address. (This address is specific to local child addressing only) Further how to decode these 2 entry are device specific. Device driver should have documentation for these)
  2. parent address-cells size is 1 so next entry is of parent address for that child.
  3. child size-cells is 1 so next entry is of child's range (wrt to parent address.)

Exampe2: PCI device entry

#address-cells = <1>;
#size-cells = <1>;
pci@0x10180000 {
    compatible = "arm,versatile-pci-hostbridge", "pci";
    reg = <0x10180000 0x1000>;
    interrupts = <8 0>;
    bus-range = <0 0>;

    #address-cells = <3>
    #size-cells = <2>;
    ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
              0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
              0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;

Here

0x42000000 0 0x80000000 is the address of child1. How to decode these 3 entry is mentioned in PCI driver documentation.

0x80000000 is the parent address. Parent node is cpu so from cpu this address is used to talk to this devide.

0 0x20000000 is the size of this device in parent address space. (0 to 512MB of address)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top