Build Device Tree Blob

This page covers the generation of devicetree source (DTS) files using Xilinx tools as well as the building/compiling of these source files using standard open-source tools.  In particular, use of the Xilinx Devicetree Generator (DTG) will be covered for generating DTS files from a Xilinx hardware project while the devicetree compiler (DTC) will be covered for compiling DTS files into a devicetree binary (DTB).  Although the primary use of the DTB is to provide it to the Linux kernel so that Linux can be initialized to specific hardware correctly, the DTB can also be used with QEMU to emulate hardware for both Linux and standalone systems.

Table of Contents

Child Pages

Devicetree 101

What is devicetree?

Device tree or simply called DT is a data structure that describes the hardware. This describes the hardware which is readable by an operating system like Linux so that it doesn't need to hard code details of the machine.
Linux uses the DT basically for platform identification, run-time configuration like bootargs and the device node population.

Devicetree Basics

Each driver or a module in the device tree is defined by the node and all its properties are defined under that node. Based on the driver it can have child nodes or parent node.

For example a device connected by SPI bus will have SPI bus controller as its parent node and that device will be one of the child node of spi node. Root node is the parent for all the nodes.

Under the root node typically consists of
1) CPUs node information
2) Memory information
3) Chosen can have configuration data like the kernel parameters string and the location of an initrd image
4) Aliases
5) Nodes which define the buses information

Devicetree Syntax Example

Devicetree Properties

compatible: The top-level compatible property typically defines a compatible string for the board, and then for the SoC.
Values always given with the most-specific first, to least-specific last.
#address-cells: Property indicate how many cells (i.e 32 bits values) are needed to form the base address part in the reg property.
#size-cells: The size part of the reg property.
interrupt-controller: Is a boolean property that indicates that the current node is an interrupt controller.
#interrupt-cells: Indicates the number of cells in the interrupts property for the interrupts managed by the selected interrupt controller.
interrupt-parent: Is a phandle that points to the interrupt controller for the current node. There is generally a top-level interrupt-parent definition for the main interrupt controller.

Devicetree Generator (DTG)

The DTG is intended to help users build their hardware-specific DTS file.  Building a DTS for custom hardware will always be a somewhat manual process but the DTG can help jump-start users to a fairly advanced starting point.  This is because a lot of information captured in a DTS can be extracted from information in the hardware hand-off file (XSA).  DTG will populate various DTS files with as much information as it can based on a supplied XSA file and then the user will be expected to fill-in the blanks or adjust as needed.

Task Dependencies (Pre-requisites)

  • DTG Source

  • XSA Hardware hand-off file generated by Xilinx Vivado tool (previously HDF)

  • Xilinx Vitis installation (or previously Xilinx SDK)

Task Output Products

The DTG generates DTS files with *.dts and *.dtsi file extensions.  There will be a single top-level *.dts file with "include" statements to reference separate DTS include (DTSI) files.  Using DTSI files allows information to be organized amongst different files.  For example, as described in more detail below, one DTSI can be used to describe fixed hardware (i.e. fixed in silicon) while another DTSI can be used to describe dynamic hardware (i.e. IP in the programmable logic).

Generally for the SOCs there will be a static dts/dtsi files, but when it comes to the FPGA there can be many complicated designs which the peripheral logic(PL) IPs may vary or might be having different configurations.
For these complicated FPGA designs we require a Device tree generator(DTG) where it can generate the dts/dtsi automatically for those designs.

Once we generate there will be different files available in the output directory, say for example pl.dtsi, pcw.dtsi, system-top.dts, zynqmp.dtsi, zynqmp-clk-ccf.dtsi.  These files are described below.

  • pl.dtsi: This is a file where all the memory mapped peripheral logic(PL) IP nodes will be available.
  • pcw.dtsi: This is a file where the dynamic properties where the PS peripheral needs.
  • system-top.dts: This is a file where it contains the memory information, early console and the boot arguments.
  • zynqmp.dtsi: This file contains all the PS peripheral information and also the cpu info.
  • zynqmp-clk-ccf.dtsi: This file contains all the clock information for the peripheral IPs.


Apart from these files, based on the board it will generate one more board.dtsi file under the same output directory dt/.  For example, if board is zcu111-reva then it generates dt/zcu111-reva.dtsi.

  • zcu111-reva.dtsi: It contains all the board specific properties like i2c might be connected to some slave etc.

The actual files output will vary based on the device architecture (e.g. ZynqUS+ vs Zynq-7000 vs MicroBlaze).

Step 1: Fetch DTG Source

DTG is an open source utility with the source code published on the Xilinx GitHub site.  It uses an interpreted language (Tcl) so there's no need to compile the source.

In the last command above <xilinx-v201X.X> should be replaced with a valid tag value (for example "xilinx-v2019.2").  Available tags can be listed using the command "git tag".

Step 2: Generate DTS Files

Only follow the individual sub-section below that applies to your use-case.

Generate DTS Files Using XSCT

  1. Source Xilinx design tools
  2. Run XSCT (available as of 2015.1 tool release)

  3. Open XSA/HDF file

  4. Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx})

  5. Create SW design and setup CPU.  The -proc option should be followed be one of these values: for Versal "psv_cortexa72_0", for ZynqMP "psu_cortexa53_0", for Zynq-7000 "ps7_cortexa9_0", for Microblaze "microblaze_0".

  6. Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated

  7. Clean up. 

Note that to compliment XSCT User Guide documentation some tips on using HSI can be found here: HSI debugging and optimization techniques.  For example, a command that lists all processor cells in the hardware design can be found there (i.e. IP_TYPE==PROCESSOR); these processor cell names represent valid values for the -proc option in step 5 above.

Generate DTS Files Using Xilinx SDK (GUI flow: tool version 2014.2-2019.1)

Generate HDF file from hardware project (if not already available)

  1. Open the hardware project in Vivado.
  2. Generate Block Design

(In <project_name>.sdk HDF file is generated)

Generate a Device Tree Source (.dts/.dtsi) files from SDK

  1. Open SDK from Vivado or open SDK via command line (xsdk -hwspec <filename>.hdf -workspace <workspace>


  2. The Device Tree Generator Git repository needs to be cloned from the Xilinx. See the Fetch Sources page for more information on Git.

  3. Add the BSP repository in SDK (for SDK 2014.2 and later select "device-tree-xlnx" from the checked out git area):

  4. Create a Device Tree Board Support Package (BSP):

  5. A BSP settings window will appear. This window can also be accessed by opening the Device Tree BSP's system.mss file and clicking 'Modify this BSP's Settings'. Fill in the values as appropriate:
    • The 'bootargs' parameter specifies the arguments passed to the kernel at boot time (kernel command line). ***
    • The 'console device' parameter specifies which serial output device will be used. Select a value from the drop-down.


The .dts/.dtsi files are now located in <SDK workspace>/device_tree_bsp_0/ folder.

*** e.g. console=<tty>,<baudrate> root=/dev/ram rw ip=:::::eth0:dhcp earlyprintk
*** Some example values for <tty> are ttyPS0 when using Zynq, ttyUL0 when using the UART Lite soft ip, or ttyS0 when using the UART16550 soft ip.

Generate DTS Files Using HSI (CLI flow deprecated by XSCT)

  1. Source Xilinx design tools
  2. Run HSI (tool releases 2014.4 - 2019.1)

  3. Open HDF file 

  4. Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx}) 

  5. Create SW design and setup CPU (for ZynqMP psu_cortexa53_0, for Zynq ps7_cortexa9_0, for Microblaze microblaze_0) 

  6. set_property CONFIG.periph_type_overrides "{BOARD zcu102-rev1.0}" [get_os] 

  7. Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated 

  8. In the generated my_dts folder zcu102-rev1.0.dtsi file should be present.


Generate DTS Files Using HSM (CLI flow deprecated by XSCT)

  1. Source Xilinx design tools
  2. Run HSM (tool releases 2014.4 - 2019.1)

  3. Open HDF file

  4. Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx})

  5. Create SW design and setup CPU (for ZynqMP psu_cortexa53_0, for Zynq ps7_cortexa9_0, for Microblaze microblaze_0)

  6. Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated

Generate DTS Files Using XPS/SDK (legacy GUI flow: tool versions 2014.1 and prior)

  1. Open the hardware project in XPS.
  2. Export the hardware system to SDK. 

  3. Create a Device Tree Board Support Package (BSP):

  4. A BSP settings window will appear. This window can also be accessed by opening the Device Tree BSP's system.mss file and clicking 'Modify this BSP's Settings'. Fill in the values as appropriate:
    • The 'bootargs' parameter specifies the arguments passed to the kernel at boot time (kernel command line). ***
    • The 'console device' parameter specifies which serial output device will be used. Select a value from the drop-down.


The .dts file is now located in <SDK workspace>/<device-tree bsp name>/<processor name>/libsrc/device-tree_v0_00_x/xilinx.dts.

*** e.g. console=<tty>,<baudrate> root=/dev/ram rw ip=:::::eth0:dhcp earlyprintk
*** Some example values for <tty> are ttyPS0 when using Zynq, ttyUL0 when using the UART Lite soft ip, or ttyS0 when using the UART16550 soft ip.

In the Linux source directory, there are also some DTS files available for use in linux-xlnx/arch/<architecture>/boot/dts/.

Step 3: Additional Check for Standalone MicroBlaze Emulation Only

If generating DTS files for emulation of Standalone MicroBlaze applications with QEMU some additional checks should be made and some minimum requirements noted.  With regards to requirements, the MicroBlaze sub-system (defined in the Vivado IP Integrator block design) must have at least the following components:

  • MicroBlaze Processor
  • Memory
  • Serial Interface (AXI UART)
  • Interrupt Controller (AXI INTC)

Attached is an example DTS with only these minimum requirements:

The generated DTS should be checked, and modified as necessary, to ensure the MicroBlaze node (i.e. / > cpus > microblaze_0) in the pl.dtsi file has the following properties:

  • memory
  • model
  • version

For example:

If a memory node already exists, you may just need to add label to it so it can be referenced ("lmb_bram" in above example).  The name for the label is arbitrary but most be consistent between the the node definition and reference.  For example, if the system has DDR then a label like "ddr_mem" would be more appropriate.  If a memory node was not generated (system-top.dts or pl.dtsi) then it must be added manually.  An example of adding a memory node to the system-top.dtsi is given below.

DTG Limitations

  • zynqmp-clk-ccf.dtsi has static clock node configuration, if user wants to change any of the clock information update those in system-user.dtsi.
  • Multi concat Interrupt blocks wont be supported by the DTG.
  • DTG doesn't support IP that are packaged in a subsystem(multiple BD's)
  • Interrupt port width more than one wont be supported.
  • When multicore is enabled for the MAC IPs(if the MAC IPs are more than 1) then there is issue with the label in DTG and it fails. But there wont be an issue if the MAC IP is one and multicore is enabled.
  • DTG wont support for generation of private peripheral interrupts(PPI).
  • DTG supports the video pipeline generation based on the internal TRD designs as mentioned in the wiki https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/25329832/Zynq+UltraScale+MPSoC+VCU+TRD+2018.3
  • DTG doesn't support custom IP, For Multimedia use case If there are any custom IPs connected between the video pipeline IPs DTG wont support those, user may need to add the input and output ports.
  • For broadcaster IP the output can connect to multiple output ports and DTG cant know which output port is a valid for the correct pipeline.
  • If there are multiple similar video pipelines in the design user need to add the input and output port information in the nodes.The below wiki gives someinfo about how to add the input and output ports
  • DTG limitation for multimedia IPs

New Features for 2020.1:

  • Added mrmac IP initial support.
  • Added DPU IP support
  • Replaced the hardcoded values with the macros for reset and power.
  • Added dma channels for axi_mcdma IP support in DTG.
  • Generate the memory node for each axi_noc IP for Versal


List of drivers supported in the DTG and their bindings in Linux tree

  • can, canfd
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/net/can/xilinx_can.txt
  • axi_cdma
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/dma/xilinx/axi-cdma.txt
  • axi_dma
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt
  • axi_emc
  • axi_ethernet, axi_10g_ethernet,xxv_ethernet
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/net/xilinx_axienet.txt
  • axi_gpio
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/commits/master/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
  • axi_iic
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/i2c/i2c-xiic.txt
  • axi_pcie,axi_pcie3,xdma
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/pci/xilinx-pcie.txt
  • axi_perf_mon
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/uio/xilinx_apm.txt
  • axi_quad_spi
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/spi/spi-xilinx.txt
  • axi_sysace
  • axi_tft
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/video/xilinx-fb.txt
  • axi_timebase_wdt
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
  • axi_traffic_gen
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/misc/xilinx-axitrafgen.txt
  • axi_usb2_device
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/usb/udc-xilinx.txt
  • vcu
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/soc/xilinx/xlnx%2Cvcu.txt
  • axi_vdma
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
  • xadc_wiz
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/iio/adc/xilinx-xadc.txt
  • axi_intc
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/interrupt-controller/xilinx%2Cintc.txt
  • ddr4,ddr3,mig_7series
  • pr_decoupler
  • usp_rf_data_converter
  • axi_timer
  • tsn_endpoint_ethernet_mac
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/net/xilinx_tsn.txt
  • axi_uartlite
Bindings from the Linux tree: https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/serial/uartlite.c
  • axi_uart16550
For other IPs DTG will invoke the generic driver.

Compiling Devicetree Sources

This section describes the process of using the devicetree compiler (DTC) to compile devicetree sources into a devicetree blob (DTB).  Device Tree Blob is a part of the Xilinx design flow described in Getting Started.

Step 1: Fetch Devicetree Compiler Source

Below are commands that can be used to fetch the DTC directly from its Git repository.  Alternatively, DTC is supplied as part of the Linux source.  For example, if the Xilinx Linux source directory is available the DTC would be found at linux-xlnx/scripts/dtc.

Step 2: Pre-processing Devicetree Sources

As covered in the previous section, the DTG produces multiple devicetree files and links them together using "#include" directives.  Before this devicetree source can be fed to the compiler (DTC) the top-level DTS must be pre-processed to consolidate all sources into a single DTS.  This can be done using a standard GNU C compiler.  For example:

Step 3: Compiling a Devicetree Blob (.dtb) file from the DTS

A utility called device tree compiler (DTC) is used to compile the DTS file into a DTB file. DTC is part of the Linux source directory. linux-xlnx/scripts/dtc/ contains the source code for DTC and needs to be compiled in order to be used. One way to compile the DTC is to build the Linux tree. The DTC might also be available through your OS's package manager.

Once the DTC is available, the tool may be invoked to generate the DTB, where "system.dts" is the aggregate devicetree source that resulted from pre-processing.
DTC may also be used to convert a DTB back into a DTS:

Miscellaneous Topics

The following sections assume you have the Linux source available.

Alternative: For ARM only

In the Linux source directory, making the target 'dtbs' will compile all DTS files from linux-xlnx/arch/arm/boot/dts/ into DTB files.


The compiled DTB files will be located in linux-xlnx/arch/arm/boot/dts/.

A single linux-xlnx/arch/arm/boot/dts/<devicetree name>.dts may be compiled into linux-xlnx/arch/arm/boot/dts/<devicetree name>.dtb:

Devicetree Binarys Comparision

Linux source also includes a script for DTB comparisons.  We can check the differences between two devicetree blobs (DTB files) using the dtx_diff binary as below.


Advanced DTG Topics

How to enable DT OVERLAY from DTG

This section only focuses on DTG aspects of devicetree overlays.  For more comprehensive information on using overlays refer to the applicable FPGA Manager driver page.  Links to the applicable page can be found under Linux Drivers.

Using HSI commands
1.Clone the device tree repo
https://github.com/Xilinx/device-tree-xlnx
2) Go to the HSI prompt
[vabbarap@xhdl3763 /proj/xhdsswstaff/vabbarap/Overlay/New_hdf> % hsi
hsi v2017.3 (64-bit)SW Build 2018833 on Wed Oct 4 19:58:07 MDT 2017
Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.
3)
hsi% open_hw_design system.hdf
4)
hsi% set_repo_path /home/vabbarap/workspace/sync_dt_tip/clk_wiz_15_12_2017 (DTG repo path)
5)
hsi% create_sw_design -proc psu_cortexa53_0 sd22 -os device_tree
6)
hsi% set_property CONFIG.dt_overlay true [get_os]
7)
hsi% generate_target -dir dt/
hsi% ls dt/
pcw.dtsi pl.dtsi sd22.mss system-top.dts zynqmp-clk-ccf.dtsi zynqmp.dtsi

Using XSCT (From 2019.2 release no hsi support)

2) Go to the XSCT prompt

[issue]→xsct

****** Xilinx Software Commandline Tool (XSCT) v2020.1.0

3) hsi open_hw_design system.xsa

4) hsi set_repo_path /home/vabbarap/workspace/sync_dt_tip/dt_15_12_2019 (DTG repo path)

5) hsi create_sw_design -proc psu_cortexa53_0 sd22 -os device_tree 

6)hsi generate_target -dir dt

Customizing/Extending DTG for Custom Hardware and Drivers

This section is for users wising to extend DTG to accommodate their own custom hardware and drivers.

Relevant Files

Microprocessor software specification(MSS) file

The MSS file contains directives for customizing operating systems (OSs), libraries, and drivers.

Microprocessor Driver Definition(MDD) file

An MDD file contains directives for customizing software drivers.
Each device driver has an MDD file and a Tcl file associated with it. The MDD file is used by the Tcl file to customize the driver, depending on different options configured in the MSS file.
The driver source files and the MDD file for each driver must be located at specific directories in order to find the files and the drivers.

Driver Definition

Driver Definition involves defining a Data Definition file (MDD) and a Data Generation file (Tcl file).
Data Definition File: The MDD file (<driver_name>.mdd) contains the configurable parameters.
Data Generation File: The second file (<driver_name>.tcl, with the filename being the same as the MDD filename) uses the parameters configured in the MSS file for the
driver to generate data.

How to add a new driver to the DTG

1. Sync the repo https://github.com/xilinx/device-tree-xlnx
2. Create a folder with the driver name say for example axi_iic device-tree-xlnx/axi_iic/
3. Add the file data under axi_iic like device-tree-xlnx/axi_iic/data/
4. Create the files axi_iic.mdd and axi_iic.tcl under device-tree-xlnx/axi_iic/data/axi_iic.mdd axi_iic.tcl
5. The syntax for the file axi_iic.mdd is as

6. The syntax for the file axi_iic.tcl where you can have the properties which need to be set based on the some condition will be defined
We use HSI APIs to update the node properities. The below we update the clock property for axi_iic calling a generic function as below

7. The generated node in the pl.dtsi should be as below

Custom IPs:
For Custom IPs the DTG will generate the node with "compatible" property and interrupts if any connected.