Published On: May, 31, 2018 By: Eshtaartha Basu | Updated: November 18, 2024 by Andrew Taylor
Most modern general-purpose computers, like a desktop or laptop, will consist of several peripherals connected to a main processor through a bus such as PCI, USB, etc. An operating system, such as Windows or Linux, running on the computer can discover or learn about the connected peripherals through enumeration. Enumeration is a process through which the OS can enquire and receive information, such as the type of the device, the manufacturer, or the device configuration, about all the devices connected to a given bus. Once the OS gathers information about a device, it can load the appropriate driver for the device. However, this is not the case when it comes to most embedded systems.
In embedded systems, many peripherals are connected to the main processor with busses like I2C, SPI, and UART, which do not support enumeration. Therefore, when an embedded system uses an operating system, such as Linux, it is necessary to convey the hardware configuration of the system, i.e. all the information about the connected peripherals, to the OS in a standard form. The most common way to do this in Linux is to use a device tree. A device tree is a tree data structure that describes the hardware configuration of the system to the Linux operating system. During boot, the Linux kernel will use the information in the device tree to recognize, load appropriate drivers and manage the hardware devices in the system.
This article will help you get started with Linux device trees by introducing the structure of device trees, describing some properties of device trees and showing you how to modify an existing device tree for your custom hardware configuration. If you are working with Device Trees, you will also benefit from the follow up article OSD335x Lesson 2: Linux Device Tree Overlay .
Prerequisite
This article is a part of the broader OSD335x Reference Design Lesson 2 series which consists of a sequence of articles designed to help you build the bare minimum circuitry required to boot Linux on the OSD335x. We recommend reading the article OSD335x Lesson 2: Linux Boot Process with the OSD335x before this one. This article builds upon the foundation outlined in it.
All PCB design files for this lesson can be downloaded here.
Lesson 2 Device Tree files can be downloaded here.
1Linux Device Tree
1.1Introduction
1.2Device Tree Structure and Properties
1.3Modifying an Existing Device Tree
1.4Pin Multiplexing
A PDF version of this Lesson as well as the entire OSD335x Design Tutorial can be downloaded here.
A Linux device tree begins from a root node (i.e. the Tree Root) and will consist of a level of child nodes and one or more levels of children nodes. Each child node represents a hardware component of the micro-processor. For example, in the OSD335x, each child node represents a component of the AM335x processor, such as the CPU, an I2C peripheral, etc. Each children node represents a sub-component of a child node or a device attached to the child node. For example, in the OSD335x, the TPS65217C PMIC is attached to the I2C0 peripheral bus and appears as a children node under the I2C0 child node. Each node consists of property-value pairs that describe the hardware of the node. Each child node or children node can have only one parent and the root node has no parent. A block diagram of a simple device tree structure is shown in Figure 1.
In the above picture, you can see the parent-child relationship that exists between the child and children nodes. For example, all CPU cores are grouped as children nodes under CPU child node. Similarly, all I2C devices on a given I2C bus are grouped as children under that I2C node
To express these relationships, the Linux device tree has a specific syntax and structure that should be followed to ensure a device tree works as intended. Let’s look at a simple device tree template (Figure 2) that shows the generic syntax of the root node, child nodes, children nodes and property-value pairs.
.
In the above figure:
The official Device Tree Specification can be found here (this article will refer to information from version v0.2). A more detailed explanation of the device tree structure and basic concepts is available on the Device Tree Usage webpage. Please make sure you are familiar with these two documents before proceeding.
Now that the structure and the syntax of a device tree is clearer, the next question is: what property-value pairs should be used to describe a particular component and where can that information be found? The answer can be found in Device Tree Bindings. The properties that are necessary to describe a particular component in the device tree depends on the requirements of the Linux driver, or kernel module, for that component. All the required properties must be supplied to ensure that the Linux kernel recognizes the component properly and loads the appropriate drivers for that component. The Device Tree Bindings for a particular hardware device will give you this information. Therefore, it is essential to find the right Device Tree Bindings information for your component. More supporting documentation about device tree bindings can be found on the Device Tree Reference webpage.
As an example of Device Tree Bindings, the Lesson 2 board has a peripheral header that supports MikroElektronika Click Boards. To use a MPU 9DOF Click that has MPU-9150 9-axis motion tracking component, the appropriate information must be added to the device tree. This Click communicates with the host using I2C and has a single interrupt line to the processor. The device tree bindings for this component can be found here. Based on this, the following entry would be added to the device tree as a children node under the appropriate I2C child node:
1 2 3 4 5 6 | mpu9150@69 { compatible = "invensense,mpu9150"; reg = <0x69> ; interrupt-parent = <&gpio0> ; interrupts = <23 1> ; }; |
The unit address (i.e. the @69 after the mpu9150) and reg values are both 69 because the MPU 9DOF Click’s address on the I2C bus is 0x69. The INT pin of the peripheral header, which is used for interrupts from the MPU 9DOF Click, is connected to the GPMC_AD9 pin of the OSD335x (which is the GPMC_AD9 pin of AM335x, see the Lesson 2 board schematics for more information). The GPMC_AD9 pin is also available to the system as bit 23 in GPIO bank 0 (see the Pin Attributes section of AM335x datasheet). Hence, the interrupt-parent for this device is a phandle for gpio0 node and the first value of interrupts property is 23. The second value of the interrupts property is used to describe the behavior of the interrupt, i.e. the trigger type and level, which can be found in the AM335x TRM. See here for more information about device tree interrupts.
The device tree bindings for all the hardware components must be consolidated to form a complete device tree so that the system can function properly. While this may seem like a daunting task, device trees are seldom built from scratch. The next section will discuss modification and reuse of existing device trees.
For an embedded Linux system, a device tree is generally a complex data structure requiring several hundred nodes to describe the entire system hardware architecture. Creating a device tree from scratch and validating it can be a daunting and time-consuming task. Therefore, you should look to reuse device tree include files and modify an existing device tree to meet your requirements.
A device tree for the Lesson 2 board can be created by modifying the published device tree from the OSD3358-SM RED board. You can download the device tree files here.
The OSD3358-SM RED board has several components that do not exist on the Lesson 2 board. Those components will need to be removed from the device tree to make it suitable for the Lesson 2 board. However, before doing this, you need to understand how the OSD3358-SM RED board device tree is structured.
The device tree consists of 2 files:
Dividing the device tree into separate files helps with code reusability. Since the internal hardware of the OSD335x-SM remains the same irrespective of where it’s used, the device tree corresponding to it can be put into an include file (osd335x-sm.dtsi). Then, this file can be used in many device trees that utilize the OSD335x-SM.
When using device tree include files, it is important to understand the status of each node (i.e. after loading the include file, is a given node in an okay or a disabled state). The main device tree file (osd3358-bsm-refdesign.dts in this case) can then enabled or disable nodes depending on the system hardware. The nodes with the preceding ampersand (&) in the main device tree file are referencing nodes that are already declared in osd335x-sm.dtsi.
At this point, the OSD3358-SM-RED board’s device tree can be modified to match the hardware on Lesson 2 board. The nodes and node references that do not correspond to the Lesson 2 board can be removed in osd3358-bsm-refdesign.dts. Figure 3 lists all the nodes that are present in this file. The nodes that are marked with X should be removed.
After the modifications, the osd3358-bsm-refdesign.dts will look like Figure 4. Since it now reflects the Lesson 2 hardware, the file can be renamed to osd335x-lesson2.dts
You can directly download the osd335x-lesson2.dts device tree file for the Lesson 2 board here. The .dts device tree source files are human readable and can be viewed in your favorite text editor. Next, this source file will be converted to a Device Tree Blob or .dtb file, i.e. a binary file that is smaller and easier to parse by the Linux kernel. For the OSD335x Family of devices, Robert Nelson’s Device Tree Rebuilder can be used to compile the device tree source. You can download it here. (We have tested our .dts files using 4.14-ti branch with the OSD3358-SM RED Debian image. For a different image, use a branch that matches the image’s kernel version).
The steps to compile and use the new device tree on the Lesson 2 board are as follows:
The board should now boot using the new device tree
The OSD335x family of devices provides access to all 123 signal pins of the AM335x processor. Each of these signal pins can have up to seven (7) different functions, or modes, which allows a given peripheral within the AM335x to be multiplexed to different pins. The pin modes for each pin can be found in the Pin Attributes table of AM335x datasheet (the OSD335x family uses ZCZ package of AM335x when referring to pin names / pin functionality). The RESET REL. MODE column of the table shows the default mode that will be assigned to the pin after the processor is released from reset. If this mode is not the mode required by system, you will need to add information to the device tree to set the pin mulitplexing so that the connected components interface properly with the AM335x processor.
For example, below shows a device tree snippet from the am33xx_pinmux node of the osd3358-bsm-refdesign.dts file. The pinctrl-single driver is used to set the appropriate pin configuration (more information about pinctrl-single driver can be found here). The AM33XX_IOPAD macro (which can be found in the dt-bindings/pinctrl/omap.h file, which is included by the dt-bindings/pinctrl/am33xx.h file, which is included by the osd335x-sm.dtsi file) helps configure each pin (more information about AM33XX_IOPAD macro can be found here)
1 2 3 4 5 6 7 8 9 10 | &am33xx_pinmux { user_leds_default: user_leds_default { pinctrl-single,pins = < AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpmc_a5.gpio1_21 */ AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLUP | MUX_MODE7) /*gpmc_a6.gpio1_22 */ AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpmc_a5.gpio1_23 */ AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7) /*gpmc_a5.gpio1_24 */ >; }; }; |
You can find the absolute physical address of the pins, which is required for the macro, in the CONTROL_MODULE REGISTERS table of AM335x TRM. In the table, each signal pin name is prefixed with conf_. For example, the absolute physical address of the GPMC_A5 pin, 0x854, is shown in Figure 6.
In addition, you can also use TI’s PinMux Tool to ensure the pin muxing of your pins do not conflict with each other (You will need a TI user account to use the tool). You can watch the TI PinMux Tool getting started video here to learn more about the tool.
For any questions or concerns, you can reach us at: https://octavosystems.com/forums/
We’d like to thank lewing@isc.tamu.edu and The GIMP for permission to use the ‘Tux’ Linux image used in our social media about this post
<< Return to “OSD335x Lesson 2 : Linux Boot Process with the OSD335x” | Continue to “OSD335x Lesson 2 Linux Device Tree Overlay” >> |
Octavo Systems LLC all rights reserved
OCTAVO is registered in the U.S. Patent and Trademark Office. OSD, C-SiP, and the Octavo Logo are trademarks of Octavo Systems LLC.
"*" indicates required fields
"*" indicates required fields
"*" indicates required fields
"*" indicates required fields