Introduction

After designing a custom carrier board for a Variscite System on Module, one of the first software tasks is to add support to the Linux kernel. This consists of:

  1. Adding a new device tree to the Linux kernel
  2. Adding devices to the device tree
  3. Enabling drivers in the kernel configuration for each device

This guide shows how to add new device tree files and configure new devices in the device tree. Please visit Variscite’s Kernel Configuration Guide to learn how to enable drivers in the kernel configuration.

What is a Device Tree?

The device tree is a node structure that describes the system hardware to the Linux kernel. During the boot process, U-Boot loads the device tree from the filesystem into memory. The Linux kernel then parses the device tree at runtime and will eventually call the probe function for each driver.

The device tree includes only devices that cannot be discovered automatically. For example, the device tree must define the SoC USB Controllers, but the kernel can discover USB devices at runtime.

Variscite Device Tree Files

Variscite i.MX8 device tree files are in the arch/arm64/boot/dts/freescale directory in the Linux source tree, and are built using a combination of NXP SoC, Variscite SoM, and Variscite carrier board files. Each carrier board should have a unique device tree that includes the relevant SoM device tree from Variscite. Figure 1 below shows an example of device tree files for Variscite’s VAR-SOM-MX8M-MINI and DART-MX8M-MINI evaluation kits:

arch/arm64/boot/dts/freescale/

imx8mm.dtsi

imx8mm-var-dart.dtsi
imx8mm-var-dart-dt8mcustomboard.dts

imx8mm-var-som.dtsi
imx8mm-var-som-symphony.dts

Getting Started with Variscite Device Trees_Figure 1

Figure 1: Example SoC, SoM, and Carrier board device tree files for Variscite VAR-SOM-MX8M-MINI and DART-MX8M-MINI evaluation kits.

Adding New Device Tree Files

It is best to create a new device tree for your custom carrier board. Although it is possible to modify Variscite’s device tree directly, doing so will make it more difficult to port your changes to newer Linux releases as it is likely to result in merge conflicts. When creating new device tree files, there are two approaches:

1. Include Variscite’s SoM level device tree and add all the necessary nodes. This approach is best if your carrier board is significantly different from Variscite’s Evaluation Kit. For example:

arch/arm64/boot/dts/freescale/imx8mm-var-som-customer.dts

/dts-v1/;
#include “imx8mm-var-som.dtsi”

2. Include Variscite’s EVK device tree and extend it to add and remove devices for your carrier board. This approach is best if your carrier board is similar to Variscite’s EVK. For example:

arch/arm64/boot/dts/freescale/imx8mm-var-som-customer.dts

/dts-v1/;
#include “imx8mm-var-som-symphony.dts”

Next, add the new device tree to the Makefile so that it will be built by the ‘dtbs’ Make target:

arch/arm64/boot/dts/freescale/Makefile

dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-customer.dtb

Adding New Devices

The following is a general process for adding new device nodes to the device tree:

1. Find Device Tree Bindings

When adding new device nodes, the first resource to use is the device tree bindings in the kernel documentation. The device tree bindings recognized by the kernel are documented in Documentation/devicetree/bindings.

One way to find the device tree bindings for your device is to grep the Documentation folder for the device model. The example below shows how to find the documentation for the DS1337 real-time clock used on some Variscite evaluation kits:

linux-imx$ grep ds1337 -lr ./Documentation/

./Documentation/devicetree/bindings/rtc/rtc-ds1307.txt

2. Add Device Node(s) to the Device Tree

Next, use the bindings documentation to add a new node to your device tree. The device tree binding documentation will provide a device description, the required and optional properties, and an example device node.
For example, here is the documentation for the DS1337 real-time clock (from the 5.4-2.3.x-imx_var01 kernel branch):
https://github.com/varigit/linux-imx/blob/5.4-2.3.x-imx_var01/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt

It can also be helpful to search the compatible string in arch/arm64/boot/dts for example nodes on similar platforms.

3. Build, Install, and Test the New Device Tree

After adding the new device node(s), test the new device by rebuilding the device tree and deploying it to the target device. First, set up your environment using the SDK provided by Yocto:

linux-imx$ source /opt/<sdk>/<sdk version>/environment-setup-aarch64-fslc-linux

Note: To learn how to install the SDK, please visit https://variwiki.com, click on the SOM and the Yocto release you want to use, and then click on the “Toolchain installation for out of Yocto builds” link.

Next, build the device tree:

linux-imx$ make mrproper
linux-imx$ make imx8_var_defconfig
linux-imx$ make dtbs

Deploy the device tree to your target device using Ethernet:

linux-imx$ scp arch/arm64/boot/dts/freescale/imx8mn-var-som-customer.dtb root@<target ip address>:/boot/

Finally, configure the target device to boot the new device tree:

root@imx8mm-var-dart:~# fw_setenv fdt_file imx8mn-var-som-customer.dtb
root@imx8mm-var-dart:~# reboot

Note: You should also verify the device driver is enabled in the kernel configuration. Please see the Variscite Kernel Configuration Guide for more information.

Debugging Tips

Device Tree Not Booting?

It is possible that an incorrectly configured device tree or driver could cause the system not to boot. If you find yourself in this situation, it can be helpful to follow this process:

  • Start with a minimal device tree that boots by removing or disabling device nodes
  • Add and test a single device at a time
  • Make small iterative changes
  • As you add and test new devices, record the changes using Git so you have a working device tree to revert to

Driver not probing?

Below are several debugging tips if the driver is not probing after adding the device node:

  • Verify the driver is enabled in the kernel config
  • Verify the device is enabled in the device tree (status = “okay”)
  • Verify the device binding matches the documentation
  • Look for other examples in arch/arm64/boot/dts
  • Check dmesg for errors related to driver

The workflow for editing and testing the device tree can be done in seconds:

  1. Edit device tree
  2. $ make dtbs
  3. $ scp arch/arm64/boot/dts/freescale/<device tree> root@<ip addr>:/boot/
  4. Reboot the board

To verify your workflow is working and you are booting the updated device tree, it can be helpful to inspect /sys/firmware/devicetree to verify the kernel correctly parsed the updated device tree.

Summary

Device trees are responsible for describing the hardware to the Linux kernel. Variscite provides reference device tree files for each of its SoMs and evaluation kit carrier boards that can be used as a reference or extended for custom carrier boards. For additional support, please visit Variscite’s software wiki, which provides detailed guides for each of Variscite’s modules and supported operating systems.

Related Resources

Webinar: Getting Started with Device Tree on Variscite SOMs
Blog post: i.MX Device Tree Pinmux Settings
Blog post: Variscite Kernel Configuration Guide
Blog post: Creating a Custom Yocto BSP Layer