## 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 `...`

#### 1.4.2 Filling about *CPU*

#### 1.4.3 Filling about *Memory and chooson*
* `chooson` is [bootargs](https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html)

#### 1.4.4 Filling about *Device Master(Host)* **inside** *SoC*
* Interrupt Controller(host)

* I2C host and device(EEPROM)

* USB host

### 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
* 
* [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
* 
* Encoding a 64-bit value requires two cells
* 
* `#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`
* 
* `#interrupts-cells`:
* How many cells are used to encode interrupt specifiers for this interrupt controller
* 
* Ditto `#clock-cells`, `#gpio-cells`, `#phy-cells`, `#pwm-cells`, `#dma-cells`, etc.
* 
### 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
* 
* 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)