Device Tree - bogics/rpi_gpio_driver GitHub Wiki
- www.raspberrypi.org ~ device-tree documentation
- free-electrons.com ~ device-tree-dummies.
- www.kernel.org ~ Documentation/devicetree/overlay-notes.txt
- www.kernel.org ~ Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
- www.patternagents.com ~ devicetree-overview
- www.patternagents.com ~ devicetree-overlays
- elinux.org ~ Device Tree Usage
- xillybus.com ~ A Tutorial on the Device Tree
Device tree is a tree data structure with nodes that describes the physical devices in a system. The Device Tree replaces the legacy platform data where hardware characteristics were hardcoded in the kernel source so that platform devices can be instantiated. Before device trees came into use, the bootloader had to tell the kernel what machine type it was booting. Moreover, it had to pass other information such as memory size and location, kernel command line, and more.
The compiled binary format Device Tree Blob (DTB) is read during the boot up sequence.
Device Tree source filed are stored in arch/arm/boot/dts.
test_gpio-overlay.dts is created with the following content:
// Definitions for test_gpio module
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&soc>;
__overlay__ {
#address-cells = <1>;
#size-cells = <1>;
test_gpio: test_gpio@7e200000 {
compatible = "test_gpio";
reg = <0x7e200000 0xa0>;
interrupts = <2 17>;
interrupt-controller;
#interrupt-cells = <2>;
status = "okay";
};
};
};
};
Device Tree files are compiled using Device Tree Compiler (DTC), which is included in the kernel source inside scripts/dtc and is compiled along with the kernel itself.
There are two ways to compile Device Tree:
- With the Linux kernel kbuild build system:
- Add test_gpio-overlay.dts to the arch/arm/boot/dts/overlays directory
- Insert
dtbo-$(RPI_DT_OVERLAYS) += test_gpio.dtbo
into arch/arm/boot/dts/overlays/Makefile make dtbs
- Independently
./dtc -I dts -O dtb -o test_gpio.dtbo test_gpio-overlay.dts
Whatever method is chosen, copy the generated test_gpio.dtbo to the overlays directory of the sd card's boot partition.
Add a dtoverlay=test_gpio
line to the config.txt located into the sd card's boot partition.
This ensures that the test_gpio overlay will be loaded after the next reboot.
A DT overlay comprises a number of fragments, numbered sequentially from zero, each of which targets one node and its subnodes.
-
compatible = "brcm,bcm2708";
property defines the machine types the device tree is compatible with. It identifies this as being for BCM2708, which is the base architecture of the BCM2835 part. -
target = <&soc>;
property identifies the node to apply the overlay to, using a phandle (reference to another node).soc
node is defined in the bcm2708_common.dtsi. -
__overlay__
represents a body which is added to the target node. It contains description of the gpio hardware. -
#address-cells = <1>;
property indicates how many cells (i.e 32 bits values) are needed to form the base address part in thereg
property. -
#size-cells = <1>;
property indicates how many size cells are needed in thereg
property. -
test_gpio: test_gpio@7e200000
defines new subnode into thesoc
node.
test_gpio
is the node name
7e200000
is unit address, which is according to the chapter 6 General Purpose I/O (GPIO) of the BCM2835-ARM-Peripherals, address of the first GPIO register. In general, the unit address is the primary address used to access the device, and is listed in the node'sreg
property. -
compatible = "test_gpio";
property in non-root node is used to bind device with the driver. It contains a string in the form "manufacturer,model", but here the manufacturer part is omitted.
The connection between a kernel driver and the “compatible” entries it should be attached to, is made by a code segment as follows in the driver’s source code:
static struct of_device_id test_gpio_dt_match[] = {
{ .compatible = "test_gpio", },
{ },
};
MODULE_DEVICE_TABLE(of, test_gpio_dt_match);
-
reg = <0x7e200000 0xb4>;
property represents an address range used by the device. Each address value is a list of one or more 32 bit integers called cells. Similarly, the length value can either be a list of cells, or empty. The#address-cells
and#size-cells
properties in the parent node are used to state how many cells are in each field.
From the chapter 6 General Purpose I/O (GPIO) of the BCM2835-ARM-Peripherals, 0x7e200000 is address of the firs GPIO register GPFSEL0 while 0x7e2000b0 is address of the last GPIO register denoted as Test. All registers are 32-bits except the last one (Test) which is 4 bits in size. According to this, total size of the all GPIO registers is 0xb4. -
interrupts = <2 17>;
GPIO0 from Bank 2 (interrupts in the "IRQ pending 2" register). -
#interrupt-cells = <2>;
Specifies the number of cells needed to encode an interrupt source. The value shall be 2. -
interrupt-controller;
Identifies the node as an interrupt controller -
status = "okay";
(or"ok"
or absent) property, indicates that the device is enabled. Otherwise, status should be"disabled"
, so that means the device is disabled.
- Information about Device Tree on the running system can be obtained from /proc/device-tree or /sys/firmware/devicetree/base.
gpio_test can be found at:
/proc/device-tree/soc/test_gpio@7e200000/ and
/sys/firmware/devicetree/base/soc/test_gpio@7e200000/, with the same content:
-r--r--r-- 1 root root 10 Jan 1 00:00 compatible
-r--r--r-- 1 root root 10 Jan 1 00:00 name
-r--r--r-- 1 root root 4 Jan 1 00:00 phandle
-r--r--r-- 1 root root 8 Jan 1 00:00 reg
-r--r--r-- 1 root root 5 Jan 1 00:00 status
- Get a full device tree from the filesystem:
# dtc -I fs -O dts /sys/firmware/devicetree/base
Warning (avoid_default_addr_size): Relying on default #address-cells value for /axi/vc_mem
Warning (avoid_default_addr_size): Relying on default #size-cells value for /axi/vc_mem
/dts-v1/;
/ {
model = "Raspberry Pi Model B Plus Rev 1.2";
compatible = "brcm,bcm2708";
memreserve = <0x1c000000 0x4000000>;
serial-number = "000000002dfd1846";
...
...
- Print dts from the blob:
# fdtdump /boot/overlays/test_gpio.dtbo
/dts-v1/;
// magic: 0xd00dfeed
// totalsize: 0x1fa (506)
// off_dt_struct: 0x38
// off_dt_strings: 0x1ac
// off_mem_rsvmap: 0x28
// version: 17
// last_comp_version: 16
// boot_cpuid_phys: 0x0
// size_dt_strings: 0x4e
// size_dt_struct: 0x174
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <0xdeadbeef>;
__overlay__ {
#address-cells = <0x00000001>;
#size-cells = <0x00000001>;
test_gpio@7e200000 {
compatible = "test_gpio";
reg = <0x7e200000 0x000000b4>;
status = "okay";
phandle = <0x00000001>;
};
};
};
__symbols__ {
test_gpio = "/fragment@0/__overlay__/test_gpio@7e200000";
};
__fixups__ {
soc = "/fragment@0:target:0";
};
};
Find explanation for target = <0xdeadbeef>;
, __symbols__
and __fixups__
in the www.raspberrypi.org ~ device-tree documentation.
dtc and fdtdump can be cross-compiled using buildroot by selecting the dtc programs package (Target packages ---> Libraries ---> Hardware handling ---> [*] dtc programs)