Device Tree Overview

Since Linux 3.x, the device tree serves as the hardware description mechanism that separates board-specific configuration from the kernel source code.

Device Tree Forms

The device tree is represented in the following forms:
Table 1. Device Tree Forms
Device Tree Form Abbreviation Description
Device Tree Source DTS The human-readable device tree description file
Device Tree Source Include DTSI Human-readable shared header file
Device Tree Blob DTB Compiled binary loaded by the bootloader
Device Tree Compiler DTC Tool that compiles DTS/DTSI into DTB

JH-7110 Device Tree Hierarchy

The following code block illustrates the device tree file structure of JH-7110:
linux
├── arch
│   ├── riscv
│   │   ├── boot
│   │   │   ├── dts
│   │   │   │   └── starfive
│   │   │   │       ├── codecs
│   │   │   │       │   ├── sf_pdm.dtsi
│   │   │   │       │   ├── sf_pwmdac.dtsi
│   │   │   │       │   ├── sf_spdif.dtsi
│   │   │   │       │   ├── sf_tdm.dtsi
│   │   │   │       │   └── sf_wm8960.dtsi
│   │   │   │       ├── evb-overlay
│   │   │   │       │   ├── jh7110-evb-overlay-can.dts
│   │   │   │       │   ├── jh7110-evb-overlay-rgb2hdmi.dts
│   │   │   │       │   ├── jh7110-evb-overlay-sdio.dts
│   │   │   │       │   ├── jh7110-evb-overlay-spi.dts
│   │   │   │       │   ├── jh7110-evb-overlay-uart4-emmc.dts
│   │   │   │       │   ├── jh7110-evb-overlay-uart5-pwm.dts
│   │   │   │       │   └── Makefile
│   │   │   │       ├── jh7110-clk.dtsi
│   │   │   │       ├── jh7110-common.dtsi
│   │   │   │       ├── jh7110.dtsi
│   │   │   │       ├── jh7110-evb-can-pdm-pwmdac.dts
│   │   │   │       ├── jh7110-evb.dts
│   │   │   │       ├── jh7110-evb.dtsi
│   │   │   │       ├── jh7110-evb-dvp-rgb2hdmi.dts
│   │   │   │       ├── jh7110-evb-pcie-i2s-sd.dts
│   │   │   │       ├── jh7110-evb-pinctrl.dtsi
│   │   │   │       ├── jh7110-evb-spi-uart2.dts
│   │   │   │       ├── jh7110-evb-uart1-rgb2hdmi.dts
│   │   │   │       ├── jh7110-evb-uart4-emmc-spdif.dts
│   │   │   │       ├── jh7110-evb-uart5-pwm-i2c-tdm.dts
│   │   │   │       ├── jh7110-fpga.dts
│   │   │   │       ├── jh7110-visionfive-v2.dts
│   │   │   │       ├── Makefile
│   │   │   │       └── vf2-overlay
│   │   │   │           ├── Makefile
│   │   │   │           └── vf2-overlay-uart3-i2c.dts

The JH-7110 device tree follows the hierarchy below.

Table 2. Device Tree Hierarchy
Layer File Details
SoC freelight-u-sdk/linux/arch/riscv/boot/dts/starfive/jh7110.dtsi
This file defines the JH-7110 chip hardware. It is fixed and shared across all boards that use the chip, and tells Linux what hardware exists inside the chip. It defines the following:
  • Fixed hardware registers
  • Clocks and resets
  • Interrupts
  • Compatible settings
  • IP blocks (USB, I2C, UART, PWM, and so on)
  • Default status (disabled or enabled)

Normally you do not change these definitions (except status) unless you know exactly what you are doing, because these changes impact all the boards using the SoC.

Common freelight-u-sdk/linux/arch/riscv/boot/dts/starfive/jh7110-common.dtsi This file adds settings that are shared by multiple boards. It normally configures:
  • Pinmux
  • Bus modes (I2C speed, USB host/device mode, and so on)
  • Common routing
  • Default status
Board VisionFive 2: freelight-u-sdk/linux/arch/riscv/boot/dts/starfive/jh7110-visionfive-v2.dts This is the top-level file for your actual board. It overrides all previous configurations for the board (for example, VisionFive 2). It normally configures:
  • Enable peripherals
  • Override bus mode
  • Board-specific pins
  • ...
JH-7110 EVB: freelight-u-sdk/linux/arch/riscv/boot/dts/starfive/jh7110-evb.dts

Configuration Workflow

Normally, to configure a peripheral driver on your board, you following the workflow below:
  1. Identify the peripheral node in jh7110.dtsi. Note the compatible string, register base, clocks, resets, and interrupts.

  2. Enable the kernel driver via make linux-menuconfig. Select the driver corresponding to the compatible string.

  3. Override the node in the board DTS/DTSI, for example, set status to okay and configure board-specific properties including PHY address, pin mux, and clock source.

  4. Rebuild the device tree and kernel, and flash to the board.

  5. Verify and debug with peripheral-specific commands.