[Kernel driver] Device tree compilation and loading

00. Table of Contents

01. Overview

The device tree was introduced in later versions of Linux 3.x. The device tree is used to describe the board-level details of a hardware platform. The driver we write later needs to rely on the device tree, so here we first demonstrate how to compile and load the device tree.

For specific principles, please refer to Linux device tree related blogs.
Insert image description here

02. Device tree compilation

2.1 Compile using the dtc tool in the kernel

First we need to compile the kernel (usually we only need to compile the kernel once, and the dtc tool will be generated when compiling the kernel). The location of the kernel compilation is in the directory, and the location of the kerneldtc tool in the kernel is kernel/scripts/dtc/dtc.

The usage of dtc tool is as follows

deng@local:~/code/x3399$ ./kernel/scripts/dtc/dtc  --help
Usage: dtc [options] <input file>

Options: -[qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv]
  -q, --quiet                
	Quiet: -q suppress warnings, -qq errors, -qqq all
  -I, --in-format <arg>      
	Input formats are:
		dts - device tree source text
		dtb - device tree blob
		fs  - /proc/device-tree style directory
  -o, --out <arg>            
	Output file
  -O, --out-format <arg>     
	Output formats are:
		dts - device tree source text
		dtb - device tree blob
		asm - assembler source
  -V, --out-version <arg>    
	Blob version to produce, defaults to 17 (for dtb and asm output)
  -d, --out-dependency <arg> 
	Output dependency file
  -R, --reserve <arg>        
	Make space for <number> reserve map entries (for dtb and asm output)
  -S, --space <arg>          
	Make the blob at least <bytes> long (extra space)
  -p, --pad <arg>            
	Add padding to the blob of <bytes> long (extra space)
  -a, --align <arg>          
	Make the blob align to the <bytes> (extra space)
  -b, --boot-cpu <arg>       
	Set the physical boot cpu
  -f, --force                
	Try to produce output even if the input tree has errors
  -i, --include <arg>        
	Add a path to search for include files
  -s, --sort                 
	Sort nodes and properties before outputting (useful for comparing trees)
  -H, --phandle <arg>        
	Valid phandle formats are:
		legacy - "linux,phandle" properties only
		epapr  - "phandle" properties only
		both   - Both "linux,phandle" and "phandle" properties
  -W, --warning <arg>        
	Enable/disable warnings (prefix with "no-")
  -E, --error <arg>          
	Enable/disable errors (prefix with "no-")
  -@, --symbols              
	Enable generation of symbols
  -A, --auto-alias           
	Enable auto-alias of labels
  -h, --help                 
	Print this help and exit
  -v, --version              
	Print version and exit
deng@local:~/code/x3399$ 

Examples of using the dtc tool are as follows :

# 编译 dts 为 dtb
kernel/scripts/dtc/dtc -I dts -O dtb -o xxx.dtb xxx.dts

Actual usage example, here is pseudo code, for reference only, just understand it:

kernel/scripts/dtc/dtc -I dts -O dtb -o x3399-linux.dtb x3399-linux.dts

The command for the kernel to use the dtc tool is roughly as shown above. In fact, there are many dependencies in the device tree. These dependencies are processed through Makefile files. Therefore, in general, the device tree can be compiled not only through a dtc command. from.

2.2 Compile the device tree in the kernel source code (recommended)

We can try to compile the device tree through the kernel build script, and the device tree files we want to use are stored in /home/deng/code/x3399/kernel/arch/arm64/boot/dts/it.

As mentioned earlier, the device tree will be automatically compiled when compiling the kernel, but compiling the kernel is time-consuming, so we recommend using the following command to compile only the device tree.

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig

make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs

Example:

deng@local:~/code/x3399/kernel$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  i3399_defconfig
deng@local:~/code/x3399/kernel$ make ARCH=arm64 -j4 CROSS_COMPILE=aarch64-linux-gnu- dtbs

If it is executed in the kernel source code make distclean, you must execute the first command, which is used to generate the default configuration file. If it is executed once, there is no need to execute it again. Of course, there is no problem if it is executed again. The second command starts to compile the device tree. The parameter "-j4" specifies how many threads to compile. Set it according to the actual situation of your computer. The larger the number, the faster the compilation. Of course, you don't need to set it. Device tree compilation is inherently fast.

The device tree file (.dtb) generated after successful compilation is located in the source code directory 内核源码/arch/arm64/boot/dts. The name of the device tree file adapted to the development board is x3399-linux.dtb.

/home/deng/code/x3399/kernel/arch/arm64/boot/dts/rockchip

03. Load device tree

3.1 Device tree loading method

There are several ways to replace the device tree.

  • The first one is simple and direct. The device tree is compiled into the kernel, so reprogramming the kernel is definitely feasible. However, burning the kernel is troublesome, so I don’t recommend it and don’t explain it too much.
  • The second is to replace the original one in the development board with the device tree or device tree plug-in we compiled.

We only introduce the second method, which is to replace the compiled new device tree file with the old device tree file in the corresponding directory of the development board.

3.2 Check the device tree loading status

We added a new node to the original device tree, led_testand there is a device under this node rgb_led_red. We can load it in the following way and check whether the new device tree has taken effect and whether the new node has been added.

Copy the compiled device tree to the development board through SCP or NFS. Replace /usr/lib/linux-image-4.19.35-imx6/imx6ull-mmc-npi.dtb .

When uboot is started, it is responsible for loading the device files in this directory into memory for kernel analysis. Enter sudo rebootthe command to restart the development board.

The device tree nodes in the device tree have corresponding files in the file system, located in the "/proc/device-tree" directory. Enter the "/proc/device-tree" directory as shown below.

[root@rk3399:/]# ls /proc/device-tree/
'#address-cells'		 power-management@ff310000
'#size-cells'			 psci
 __symbols__			 pwm@ff420000
 adc-keys			 pwm@ff420010
 aliases			 pwm@ff420020
 amba				 pwm@ff420030
 backlight			 qos@ffa58000
 chosen				 qos@ffa5c000
 cif_isp@ff910000		 qos@ffa60080
 cif_isp@ff920000		 qos@ffa60100
 clock-controller@ff760000	 qos@ffa60180
 compatible			 qos@ffa70000
 cpuinfo			 qos@ffa70080
 cpus				 qos@ffa74000
 ddr_timing			 qos@ffa76000
 dfi@ff630000			 qos@ffa90000
 display-subsystem		 qos@ffa98000
 dmc				 qos@ffaa0000
 dp-sound			 qos@ffaa0080
 dp@fec00000			 qos@ffaa8000
 dsi@ff960000			 qos@ffaa8080
 dsi@ff968000			 qos@ffab0000
 dummy-codec			 qos@ffab0080
 dummy_cpll			 qos@ffab8000
 dummy_vpll			 qos@ffac0000
 dw-hdmi-audio			 qos@ffac0080
 dwmmc@fe310000			 qos@ffac8000
 dwmmc@fe320000			 qos@ffac8080
 edp@ff970000			 qos@ffad0000
 efuse@ff690000			 qos@ffad8080
 energy-costs			 qos@ffae0000
 es8323-sound			 ramoops
 ethernet@fe300000		 reserved-memory
 external-camera-clock		 rga@ff680000
 external-gmac-clock		 rkisp1@ff910000
 fiq-debugger			 rkisp1@ff920000
 gpio-keys			 rktimer@ff850000
 gpu@ff9a0000			 rkvdec@ff660000
 hdmi-hdcp2@ff988000		 rockchip-i2s-sound
 hdmi-sound			 rockchip-suspend
 hdmi@ff940000			 rockchip-system-monitor
 i2c@ff110000			 saradc@ff100000
 i2c@ff120000			 sdhci@fe330000
 i2c@ff130000			 sdio-pwrseq
 i2c@ff140000			 serial-number
 i2c@ff150000			 serial@ff180000
 i2c@ff160000			 serial@ff190000
 i2c@ff3c0000			 serial@ff1a0000
 i2c@ff3d0000			 serial@ff1b0000
 i2c@ff3e0000			 serial@ff370000
 i2s@ff880000			 spdif-out
 i2s@ff890000			 spdif-sound
 i2s@ff8a0000			 spdif@ff870000
 iep@ff670000			 spi@ff1c0000
 interrupt-controller@fee00000	 spi@ff1d0000
 interrupt-parent		 spi@ff1e0000
 iommu@ff650800			 spi@ff1f0000
 iommu@ff660480			 spi@ff200000
 iommu@ff670800			 spi@ff350000
 iommu@ff8f3f00			 syscon@ff320000
 iommu@ff903f00			 syscon@ff770000
 iommu@ff914000			 test-power
 iommu@ff924000			 thermal-zones
 leds				 timer
 memory				 tsadc@ff260000
 mipi-dphy-tx1rx1@ff968000	 usb0
 model				 usb1
 name				 usb@fe340000
 nocp-cci-msch0@ffa86000	 usb@fe380000
 nocp-cci-msch1@ffa8e000	 usb@fe3a0000
 nocp-gpu-msch0@ffa86400	 usb@fe3c0000
 nocp-gpu-msch1@ffa8e400	 usb@fe3e0000
 nocp-hp-msch0@ffa86800		 vcc-phy-regulator
 nocp-hp-msch1@ffa8e800		 vcc-sd
 nocp-lp-msch0@ffa86c00		 vcc3v3-sys
 nocp-lp-msch1@ffa8ec00		 vcc5v0-host-regulator
 nocp-video-msch0@ffa87000	 vcc5v0-sys
 nocp-video-msch1@ffa8f000	 vccadc-ref
 nocp-vio0-msch0@ffa87400	 vdd-log
 nocp-vio0-msch1@ffa8f400	 vop@ff8f0000
 nocp-vio1-msch0@ffa87800	 vop@ff900000
 nocp-vio1-msch1@ffa8f800	 voppwm@ff8f01a0
 opp-table0			 voppwm@ff9001a0
 opp-table1			 vpu_service@ff650000
 opp-table2			 watchdog@ff848000
 opp-table3			 wireless-bluetooth
 pcie-phy			 wireless-wlan
 pcie@f8000000			 xgpio_beep
 phy@ff7c0000			 xgpio_fan
 phy@ff800000			 xgpio_hdmiin_spken
 pinctrl			 xgpio_pwr4g
 pmu-clock-controller@ff750000	 xin24m
 pmu_a53			 xin32k
 pmu_a72
[root@rk3399:/]# 

Then enter the xgpio_beep folder, and you can find the attributes defined in the beep node and its child nodes, as shown below.

[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# pwd
/proc/device-tree/xgpio_beep
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# ls
compatible  gpio  name	pinctrl-0  pinctrl-names  status
[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# 

There is an additional name in the node attributes. We have not defined the name attribute in the led node to save the node name.

The attribute here is a file, and the child node is a folder, and we enter the "xgpio_beep" folder again. There are four property files: compatible name reg status. We can view these properties files using the “cat” command as shown below.

[root@rk3399:/sys/firmware/devicetree/base/xgpio_beep]# cat name 
xgpio_beep

At this point, the device tree is loaded successfully.

04. Compilation and loading of device tree plug-in

Dynamic DeviceTree (Dynamic DeviceTree) was introduced after Linux 4.4. Device tree plug-ins are dynamically loaded into the system for recognition by the kernel. When compiling the device tree plug-in, there is no need to recompile the entire device tree plug-in, only the part we modified needs to be compiled.

Note that the device tree plug-in and the device tree do not replace each other, but complement each other. The device tree plug-in can dynamically expand functions not described in the main device tree after the main device tree is finalized. For example, if the device tree of board A does not enable the function of serial port 1, but board B needs to enable the function of serial port 1, you can directly use the device tree of board A and use the device tree plug-in to expand serial port 1 to meet the needs of board B.

4.1 Compile the device tree plug-in in the kernel

The device tree plug-in is compiled using the DTC tool like the device tree, except that the device tree is compiled into .dtb. The device tree plug-in needs to be compiled into .dtbo. We can use the DTC compilation command to compile and generate .dtbo, but this is more cumbersome and error-prone.

We also complete the compilation of the device tree plug-in dtbo during kernel compilation. Of course, we can also compile the device tree plug-in dtbo when we compile the device tree separately.

We provide a large number of device tree plug-ins in the kernel. For some development boards, many peripheral hardware descriptions are provided in the form of dtbo plug-ins. This is very flexible to use.

deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$ pwd
/home/deng/code/x3399/kernel/arch/arm64/boot/dts/rockchip
deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$ ls Makefile 
Makefile
deng@local:~/code/x3399/kernel/arch/arm64/boot/dts/rockchip$ 

When you try to write a device tree plug-in, you can add your own device tree plug-in to the: arch/arm/boot/dts/overlaysdirectory, modify arch/arm/boot/dts/overlays/Makefilethe file, and add compilation options in the form of imx-rgb-led.dtbo. Just append imx-rgb-led.dtbo to imx-uart8.dtbo.

After adding it, you can execute the compilation command of the device tree, and the compilation of the device tree plug-in will be completed simultaneously.

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs

It can be seen that when compiling and outputting, the dtbo file also has corresponding printing information.

4.2 Kernel compilation device tree plug-in process

Compiling the device tree plug-in is similar to compiling the device tree. Here we introduce the process of compiling the device tree plug-in using the dtc tool in the kernel.

Example of the process of compiling xxx.dts into xxx.dtbo in the kernel, for reference only:

内核构建目录/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts

For example, compile rgb-led-overlay.dts to rgb.dtbo

../ebf_linux_kernel/build_image/build/scripts/dtc/dtc -I dts -O dtb -o rgb.dtbo rgb-led-overlay.dts

The compiled device tree plug-in is rgb.dtbo.

Of course, just like compiling the device tree, the compilation of the device tree plug-in also involves dependencies, so the compilation process is also more complicated. Compilation can be completed with more than just one command.

05. Discussion

06. Appendix

Guess you like

Origin blog.csdn.net/dengjin20104042056/article/details/132873437