## 0. Outline If one day, we design a SoC for some experiment, which has up 100 transceivers and FIFOs, order 28nm/16nm process with CIC, then Device Tree is necessary for describe our device 1. Basic concept of Device Tree 2. Device tree overly 3. How to apply for Zybo-Jtag ## 1. Basic concept of Device Tree(DT) ### 1.1 When to need device tree? Discoverable or non-discoverable hardware * Some hardware busses provide discoverability mechanisms * E.g: **PCI(e), USB** * One does not need to know ahead of time what will be connected on these busses * Devices can be enumerated and identified at runtime * Concept of vendor ID, product ID, device class, etc. * But many hardware busses do not provide discoverability mechanisms * E.g: **I2C, SPI, 1-wire, memory-mapped, GPIO**, etc. * One needs to know what is connected on those busses, and how they are connected to the rest of the system * Embedded systems typically make extensive use of such busses ### 1.2 Describing non-discoverable hardware * Using ACPI tables * On **x86 systems**, but also on a **subset of ARM64** platforms * Tables **provided by the firmware(Vendor, such as ASUS, ASmedia)** * Also are known as BIOS * Using a Device Tree * On most embedded-oriented CPU architectures that run Linux: ARC, ARM64, * **RISC-V, ARM32, PowerPC, Xtensa, MIPS, etc.** * Originates from the PowerPC world, not Linux specific * Now used by Linux, U-Boot, Barebox, TF-A, FreeBSD, etc. * Writing/tweaking a DT is now always necessary when porting Linux to a new board. * The topic of this talk ! ### 1.3 Device Tree: principle * A tree data structure describing the hardware is written by a developer in a Device Tree Source file, `.dts` * Gets compiled to a more efficient *Device Tree Blob* representation, `.dtb` by the Device Tree Compiler, `dtc` * The resulting `.dtb` accurately describes the hardware platform in an OS-agnostic way and: * Can be linked directly inside a bootloader binary (U-Boot, Barebox) * Can be passed to the operating system by the bootloader (Linux) * U-Boot: bootz \<kernel-addr\> - \<dtb-addr\> ### 1.4 A simple example #### 1.4.1 To fill `...` ![](https://i.imgur.com/hObyGAB.png) #### 1.4.2 Filling about *CPU* ![](https://i.imgur.com/2RtNdCE.png) #### 1.4.3 Filling about *Memory and chooson* * `chooson` is [bootargs](https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html) ![](https://i.imgur.com/LiGaVK9.png) #### 1.4.4 Filling about *Device Master(Host)* **inside** *SoC* * Interrupt Controller(host) ![](https://i.imgur.com/AVCME8f.png) * I2C host and device(EEPROM) ![](https://i.imgur.com/4w9lFFr.png) * USB host ![](https://i.imgur.com/YcYKMRf.png) ### 1.5 Present DT `arch/<Your Arch>/boot/dts` e.g. ``` https://github.com/torvalds/linux/tree/master/arch/arm/boot/dts ``` * Duplicated/synced in various projects * Such as u-boot, linux kernel * Provided by vendor(official) or free software engineer(3rd part) * TI-ADS7950 DT binding and driver -> Free software engineer * TI-am335x-evm.dtb -> Vendor ### 1.6 Device Tree inheritance (***Flatten DT***, not *DT overlay*) * Device Tree files are not monolithic, they can be split in several files, including each other. * *.dtsi* files are included files, while `.dts` files are final Device Trees * Only `.dts` files are accepted as input to `dtc` * Typically, `.dtsi` will contain **definition of SoC-level information** (or sometimes definitions common to several almost identical boards) * Also means defalut * The `.dts` file contains the **board-level** information * Also means be changed * The inclusion works by overlaying the tree of the including file over the tree of the included file. * Uses the C pre-processor `#include` directive * Using the C pre-processor also allows to use `#define` to replace hardcoded values by human readable definitions * A example * ![](https://i.imgur.com/HraG7MU.png) * [zynq7000.dtsi](https://github.com/torvalds/linux/blob/master/arch/arm/boot/dts/xilinx/zynq-7000.dtsi) * [zybo-zynq-z7.dts](https://github.com/torvalds/linux/blob/master/arch/arm/boot/dts/xilinx/zynq-zybo-z7.dts) ### 1.7 Building Device Trees in Linux * Building Device Trees in Linux * On ARM/ARM64, `arch/<ARCH>/boot/dts/Makefile` or `arch/<ARCH>/boot/dts/<vendor>/Makefile` indicates which DT to build depending on the platform ``` // arch/arm64/boot/dts/marvell/Makefile dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-espressobin.dtb ``` * Building the kernel with `make` will also build the Device Trees on most architectures * Explicit `make dtbs` target also available ``` DTC armada-3720-db.dtb DTC armada-3720-espressobin.dtb ``` ### 1.8 Validating Device Tree in Linux * `dtc` only does syntaxic validation * *YAML* bindings allow to do semantic validation * `make dt_bindings_check`: Verify that YAML bindings are valid * `make dtbs_check`: Validate DTs currently enabled against YAML bindings ### 1.9 Exploring the DT on the target * In `/sys/firmware/devicetree/base`, there is a directory/file representation of the Device Tree contents ``` # ls -l /sys/firmware/devicetree/base/ total 0 -r--r--r-- 1 root root 4 Jan 1 00:00 #address-cells -r--r--r-- 1 root root 4 Jan 1 00:00 #size-cells drwxr-xr-x 2 root root 0 Jan 1 00:00 chosen drwxr-xr-x 3 root root 0 Jan 1 00:00 clocks -r--r--r-- 1 root root 34 Jan 1 00:00 compatible [...] -r--r--r-- 1 root root 1 Jan 1 00:00 name drwxr-xr-x 10 root root 0 Jan 1 00:00 soc ``` * If `dtc` is available on the target, possible to ”unpack” the Device Tree using: `dtc -I fs /sys/firmware/devicetree/base` ### 1.10 Modifying the Device Tree at runtime * **U-Boot automatically patches the Device Tree Blob passed to Linux** * Sets the RAM base address and size * Sets the kernel command line * *choosen*, boot argumnet * Sets MAC address for network interfaces * Additional Device Tree Blob patching in U-Boot can be done * Using fdt commands: `fdt set`, `fdt mknode`, `fdt rm` * Using **Device Tree Overlays** ### 1.11 Device Tree Overlays * A number of platforms(included Xilinx) have some flexibility aspects that are difficult to describe in a static Device Tree * Base boards to which an arbitrary number of expansion boards can be connected: BeagleBoard capes, RaspberrPi hats, etc. * FPGA with arbitrary IP blocks synthetized * A *Device Tree Overlay*(DTO) is a small snippet of Device Tree that acts as a **patch** to a Device Tree * For example to describe additional devices provided by an expansion board * U-Boot supports applying DT overlays * Examples: https://github.com/raspberrypi/linux/tree/rpi-5.4.y/arch/arm/boot/dts/overlays/ ### 1.12 Device Tree specifications * How does one know how to write the correct nodes/properties to describe a given hardware platform ? * The DeviceTree Specifications at https://www.devicetree.org/specifications/ gives the base Device Tree syntax and specifies a number of standard properties * Like a dictnory or Six Codes(六法全書) * Far from being sufficient, though ### 1.13 Device Tree Bindings * The Device Tree Bindings are documents that each **describe how a particular piece of hardware**. * `Documentation/devicetree/bindings/` in Linux kernel sources * Reviewed by DT bindings maintainer team * Legacy: human readable documents * New norm: YAML-written specifications * Old DT Binding style (txt): https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt * New DT Binding style (YAML): https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/ti%2Cads7950.yaml ### 1.14 Device Tree design principles * **Describe hardware** (how the hardware is), **not configuration** (how I choose to use the hardware) * OS-agnostic * For a given piece of HW, Device Tree should be the same for U-Boot,FreeBSD or Linux * There should be no need to change the Device Tree when updating the OS * Describe **integration of hardware components**, **not the internals of hardware components** * The details of how a specific *device/IP block* is **working** is **handled by code in *device drivers*** * The **Device Tree describes** how the *device/IP block* is **connected/integrated** with the rest of the system: IRQ lines, DMA channels, clocks, reset lines, etc. ### 1.15 The `compatible` property * Is a list of strings * From the most specific to the less specific * Describes the specific binding to which the node complies. * It **uniquely identifies** the *programming model* of the device * Practically speaking, it is used by the OS to find the appropriate driver for this device. * Special value: `simple-bus` indicates a *bus where all sub-node*s are **memory-mapped devices**(MMD). Generally used for devices *inside the SoC* * When describing real hardware, typical form is `vendor,model` * Examples: * `compatible = "arm,armv8-timer";` <- *vendor,model* * `compatible = "actions,s900-uart", "actions,owl-uart";` <- *vendor,model* * `compatible = "regulator-fixed";` <- *sub-node(MMD) inside Soc* * `compatible = "gpio-keys";` <- *sub-node(MMD) inside Soc* ### 1.16 Matching with drivers in Linux: platform driver ```c /* drivers/tty/serial/imx.c */ static const struct of_device_id imx_uart_dt_ids[] = { { .compatible = "fsl,imx6q-uart", .data = &imx_uart_imx21_devdata, }, { .compatible = "fsl,imx1-uart", .data = &imx_uart_imx1_devdata, }, { .compatible = "fsl,imx21-uart", .data = &imx_uart_imx21_devdata, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_uart_dt_ids); static struct platform_driver imx_uart_platform_driver = { .probe = imx_uart_probe, .remove = imx_uart_remove, .driver = { .name = "imx-uart", .of_match_table = imx_uart_dt_ids, .pm = &imx_uart_pm_ops, }, }; ``` ### 1.17 Common properties * Basically, we can find folloing features in the *.dtsi*(SoC level) * `reg` * Memory-mapped devices: base address and size of the registers. Can have several entries * I2C devices: address on the I2C bus * SPI devices: chip select(CS) number * `interrupts`, `interrupt-parent`, `interrupts-extended` * Interrupts lines used by the device, and which interrupt controller they are connected to * `clocks` * which clock(s) are used by the device, from which clock controller * `dmas` * which DMA controller and channels are used by the device * `status: okay` * means the device is present and should be enabled, otherwise, the device is left unused * `pinctrl-*` * indicates the pin-muxing configuration requested by the device ### 1.18 Cells concept * Integer values represented as 32-bit integers called cells * ![](https://i.imgur.com/AXTsavJ.png) * Encoding a 64-bit value requires two cells * ![](https://i.imgur.com/ePVNBvj.png) * `#address-cells` and `#size-cells` * How many cells are used in sub-nodes to encode the address and size in the reg property * `address` represent: base address * `size` represent: offset(length) base on `address` * ![](https://i.imgur.com/frHtcKD.png) * `#interrupts-cells`: * How many cells are used to encode interrupt specifiers for this interrupt controller * ![](https://i.imgur.com/8sgy7je.png) * Ditto `#clock-cells`, `#gpio-cells`, `#phy-cells`, `#pwm-cells`, `#dma-cells`, etc. * ![](https://i.imgur.com/jnlFp22.png) ### 1.19 `-names` properties * Some properties are associated to a corresponding `<prop>-names` property * Gives some human-readable names to entries of the corresponding `<prop>` properties * ![](https://i.imgur.com/gQjM58N.png) * Such names can be typically be used by the driver * `platform_get_irq_byname(pdev, "macirq");` ### 1.20 Conclusion * Representation of non-discoverable hardware * Tree of nodes, with properties * Standardization based on Device Tree bindings * New description language with lots of properties and sometimes complex bindings * Used for numerous CPU architectures * Now widely used outside of Linux * A must know for all embedded Linux developers! ## 2. Device Tree Overlay applied by zybo z7 * After compiling FPGA(`.v`) files and CPU-IP files, we got `.XSA`. We should using `.XSA` file generate: * FSBL (first stage boot loader) binary file * Device tree (basic and derived) * How to modify it for our case * Refer to [here](https://qiita.com/yhmtmt/items/cba5330ad7ded151882d#modify-and-build-device-tree) ## Reference * [Tutorial: Device Tree (DTS), Linux Board Bring-up and Kernel Version Changing ](https://youtu.be/N6IW7JJQASc?si=qgFSh1u950_HBDqN) * [Device Tree: hardware description for everybody! ](https://youtu.be/Nz6aBffv-Ek?si=Tli7JLGcnA9--sVN)