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.
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./ { compatible = "xlnx,zynqmp"; #address-cells = <2>; #size-cells = <2>; cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortexa53", "arm,armv8"; device-type = "cpu"; enable-method = "psci"; operating-points-v2 = <&cpu_opp_table>; reg = <0x0>; cpu-idle-states = <&CPU_SLEEP_0>; }; cpu1: cpu@1 { compatible = "arm,cortexa53", "arm,armv8"; device-type = "cpu"; enable-method = "psci"; operating-points-v2 = <&cpu_opp_table>; reg = <0x1>; cpu-idle-states = <&CPU_SLEEP_0>; }; }; chosen { bootargs = "earlycon clk_ignore_unused"; }; memory { device-type = "memory"; reg = <0x0 0x0 0x0 0x80000000>, <0x00000008 0x0 0x0 0x80000000>; }; amba_apu: amba_apu@0 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <1>; ranges = <0 0 0 0 0xffffffff>; gic: interrupt-controller@f9010000 { compatible = "arm,gic-400", "arm,cortex-a15-gic"; #interrupt-cells = <3>; reg = <0x0 0xf9010000 0x10000>, 0x0 0xf9020000 0x20000>, 0x0 0xf9040000 0x20000>, 0x0 0xf9060000 0x20000>, interrupt-controller; interrupt-parent = <&gic>; interrupts =<1 9 0xf04>; }; }; amba: amba { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; ranges; can0: can@ff060000 { compatible = "xlnx,zynq-can-1.0"; clock-names = "can_clk", "pclk"; reg =<0x0 0xff060000 0x0 0x1000>; interrupts = <0 23 4>; interrupt-parent = <&gic>; tx-fifo-depth = <0x40>; rx-fifo-depth = <0x40>; power-domains = <&pd_can0>; }; }; |
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.
The procedure for using the DTG varies for older versions of Xilinx tools. Additionally, for some tool versions, there may be GUI flows versus CLI flows. The "Generate DTS Files" section below provides several sub-sections for each of these different procedures. If you're not using the latest version of Xilinx tools make sure you refer to the appropriate sub-section beyond the first one presented. |
XSA Hardware hand-off file generated by Xilinx Vivado tool (previously HDF)
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.
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.
The actual files output will vary based on the device architecture (e.g. ZynqUS+ vs Zynq-7000 vs MicroBlaze).
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.
git clone https://github.com/Xilinx/device-tree-xlnx cd device-tree-xlnx git checkout <xilinx-v201X.X> |
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".
Only follow the individual sub-section below that applies to your use-case.
Run XSCT (available as of 2015.1 tool release)
xsct |
Open XSA/HDF file
hsi open_hw_design <design_name>.<xsa|hdf> |
Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx})
hsi set_repo_path <path to device-tree-xlnx repository> |
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".
hsi create_sw_design device-tree -os device_tree -proc psv_cortexa72_0 |
Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated
hsi generate_target -dir my_dts |
Clean up.
hsi close_hw_design [current_hw_design] exit |
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.
IP Integrator: Generate Block Design # Export the hardware system to SDK: Vivado Menu: File > Export > Export Hardware |
(In <project_name>.sdk HDF file is generated)
Open SDK from Vivado or open SDK via command line (xsdk -hwspec <filename>.hdf -workspace <workspace>
Vivado Menu: File > Launch SDK |
The Device Tree Generator Git repository needs to be cloned from the Xilinx. See the Fetch Sources page for more information on Git.
# Otherwise for SDK 2014.2 use this repo: git clone git://github.com/Xilinx/device-tree-xlnx.git |
Add the BSP repository in SDK (for SDK 2014.2 and later select "device-tree-xlnx" from the checked out git area):
SDK Menu: Xilinx Tools > Repositories > New... (<bsp repo>) > OK |
Create a Device Tree Board Support Package (BSP):
SDK Menu: File > New > Board Support Package > Board Support Package OS: device-tree > Finish |
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.
As of the 2019.2 release of tools HSI is no longer available as a standalone utility and HSI commands must be run from XSCT. Also note that XSCT has supported HSI commands since its introduction in the 2015.1 tool release. |
Run HSI (tool releases 2014.4 - 2019.1)
hsi |
Open HDF file
open_hw_design <design_name>.hdf |
Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx})
set_repo_path <path to device-tree-xlnx repository> |
Create SW design and setup CPU (for ZynqMP psu_cortexa53_0, for Zynq ps7_cortexa9_0, for Microblaze microblaze_0)
create_sw_design device-tree -os device_tree -proc ps7_cortexa9_0 |
set_property CONFIG.periph_type_overrides "{BOARD zcu102-rev1.0}" [get_os]
set_property CONFIG.periph_type_overrides "{BOARD zcu102-rev1.0}" [get_os] |
Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated
generate_target -dir my_dts |
As of the 2019.2 release of tools HSM is no longer available as a standalone utility and has been deprecated by HSI commands within XSCT. Also note that XSCT has supported HSI commands since its introduction in the 2015.1 tool release. |
Run HSM (tool releases 2014.4 - 2019.1)
hsm |
Open HDF file
open_hw_design <design_name>.hdf |
Set repository path (clone done in previous step in SDK) (On Windows use this format set_repo_path {C:\device-tree-xlnx})
set_repo_path <path to device-tree-xlnx repository> |
Create SW design and setup CPU (for ZynqMP psu_cortexa53_0, for Zynq ps7_cortexa9_0, for Microblaze microblaze_0)
create_sw_design device-tree -os device_tree -proc ps7_cortexa9_0 |
Generate DTS/DTSI files to folder my_dts where output DTS/DTSI files will be generated
generate_target -dir my_dts |
Export the hardware system to SDK.
NOTE: The GitHub repository cloned in the following instructions is no longer available online. You can download archived source from AR# 75492 |
XPS Menu: Project > Export Hardware Design to SDK... > Export && Launch SDK # The Device Tree Generator Git repository needs to be cloned from the Xilinx. See the [[www/Fetch Sources|Fetch Sources]] page for more information on Git. Note that there are two repos for differing SDK versions below. > [[code]] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > git clone git://github.com/Xilinx/device-tree.git bsp/device-tree_v0_00_x// > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > //[[code]]// > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > # //Note: In order for SDK to be able to import the Device Tree Generator correctly, the file and directory hierarchy needs to look like:// > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > //<bsp repo>/bsp/device-tree//_v0_00_x/data/device-tree_v2_1_0.mld > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > //<bsp repo>/bsp/device-tree//_v0_00_x/data/device-tree_v2_1_0.tcl// > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > # Add the BSP repository in SDK (for SDK 2014.2 and later select "device-tree-xlnx" from the checked out git area): > [[code]] > SDK Menu: Xilinx Tools > Repositories > New... (<bsp repo>) > OK |
Create a Device Tree Board Support Package (BSP):
SDK Menu: File > New > Board Support Package > Board Support Package OS: device-tree > Finish |
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/.
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:
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:
For example:
... cpus { #address-cells = <1>; #cpus = <1>; #size-cells = <0>; microblaze_0: cpu@0 { memory = <&lmb_bram>; model = "microblaze,8.40.b"; version = "8.40.b"; ... |
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.
... / { lmb_bram: memory@0 { device_type = "memory"; reg = < 0x0 0x10000000 >; } ; ... |
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.
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.
git clone https://git.kernel.org/pub/scm/utils/dtc/dtc.git cd dtc make export PATH=$PATH:/<path-to-dtc>/dtc |
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:
gcc -I my_dts -E -nostdinc -undef -D__DTS__ -x assembler-with-cpp -o system.dts system-top.dts |
cd /<path-to-dtc>/dtc dtc -I dts -O dtb -o system.dtb system.dts |
dtc -I dtb -O dts -o system.dts system.dtb |
The following sections assume you have the Linux source available.
In the Linux source directory, making the target 'dtbs' will compile all DTS files from linux-xlnx/arch/arm/boot/dts/ into DTB files.
make ARCH=arm dtbs |
make ARCH=arm <devicetree name>.dtb |
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.
cd linux-xlnx/scripts/dtc make ARCH=arm <devicetree name>.dtb dtx_diff system1.dtb system2.dtb |
This section explains how to generate the dtsi files that supports dfx flow.
1.clone the device-tree
https://github.com/Xilinx/device-tree-xlnx.git -b xlnx_rel_v2022.1
2.launch xsct
i.xsct % setws <workspace dir name>
ii.xsct % repo -set <above cloned device-tree-xlnx path>
iii.xsct % platform create -name dev -hw <static xsa path> -rm-hw <rp-rm xsa path> -proc <proc> -os device_tree
iv.xsct % bsp config dt_overlay true
v.xsct % platform generate
you will find static and partial dtsi files in the <workspace dir>/dev/psv_cortexa72_0/device_tree_domain/bsp/
convert them into dtbo files using the compiling steps.
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
This section is for users wising to extend DTG to accommodate their own custom hardware and drivers.
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.OPTION psf_version = 3.0; BEGIN driver axi_iic OPTION supported_peripherals = (axi_iic);--> the axi_iic is the IP_NAME which we get from the HDF file. OPTION supported_os_types = (DTS); OPTION driver_state = ACTIVE; OPTION NAME = axi_iic; END drive |
if {[string match -nocase $proctype "psu_cortexa53"] } { update_clk_node $drv_handle "s_axi_aclk" } |
7. The generated node in the pl.dtsi should be as below
io_bd_iic_0: i2c@a1200000 { #address-cells = <1>; #size-cells = <0>; clock-names = "s_axi_aclk"; clocks = <&misc_clk_0>; compatible = "xlnx,xps-iic-2.00.a"; interrupt-names = "iic2intc_irpt"; interrupt-parent = <&gic>; interrupts = <0 2 4>; reg = <0x0 0xa1200000 0x0 0x10000>; }; |
Custom IPs:
For Custom IPs the DTG will generate the node with "compatible" property and interrupts if any connected.