#TeamTrees

With Nathan, we work a lot on the creation of the Linux distribution. On my side, I am working on how to add an sd card on an SPI bus and Nathan is working on the driver for the USB WiFi Dongle.

Device tree

An SD card can not be detected and set automatically like a USB device. We have to tell Linux there is a micro SD host on an SPI bus. We have to put a micro SD host on an SPI bus because the eMMC bus is already taken by the Flash. To tell Linux, there is a micro SD host on the SPI bus, the simplest method is to add it in the device tree blob.

The device tree blob is a file that will be read by U-Boot to know which peripherals are present and which drivers must be loaded to use those peripherals. The device tree blob (.dtb) has to be placed in the same partition as Linux. It is created while Linux kernel compilation thanks to a .dts file. The .dtb file is just a binary version of the .dts one.

How to plant its own device tree

The structure of the tree

As its name suggests, a device tree has a tree structure. Each node represents a piece of hardware or a category of hardware. Each node has parameters and can contain other nodes that are part of it. For instance, if there is a touchscreen plug on the I2C0 bus. The I2C0 node will contain a node that represents the touchscreen. To create the device tree blob, we have to write a DTS file. The structure is quite close to a JSON file as you can below:

{
	#address-cells = < 0x01 >;
	#size-cells = < 0x01 >;
	model = "Aries MCV LitSpin";
	compatible = "denx,mcvevk\0altr,socfpga-cyclone5\0altr,socfpga";

	
	cpus {
		#address-cells = < 0x01 >;
		#size-cells = < 0x00 >;
		enable-method = "altr,socfpga-smp";

		cpu@0 {
			compatible = "arm,cortex-a9";
			device_type = "cpu";
			reg = < 0x00 >;
			next-level-cache = < 0x01 >;
			phandle = < 0x03 >;
		};

		cpu@1 {
			compatible = "arm,cortex-a9";
			device_type = "cpu";
			reg = < 0x01 >;
			next-level-cache = < 0x01 >;
			phandle = < 0x04 >;
		};
	};

And here is the part of the DTS file of the ARIES MCVEVK board for the touchscreen.

i2c@ffc04000 {
			#address-cells = < 0x01 >;
			#size-cells = < 0x00 >;
			compatible = "snps,designware-i2c";
			reg = < 0xffc04000 0x1000 >;
			resets = < 0x23 0x2c >;
			clocks = < 0x28 >;
			interrupts = < 0x00 0x9e 0x04 >;
			status = "okay";
			clock-frequency = < 0x186a0 >;

			stmpe811@41 {
				compatible = "st,stmpe811";
				#address-cells = < 0x01 >;
				#size-cells = < 0x00 >;
				reg = < 0x41 >;
				id = < 0x00 >;
				blocks = < 0x05 >;
				irq-gpio = < 0x29 0x1c 0x04 >;

				stmpe_touchscreen {
					compatible = "st,stmpe-ts";
					ts,sample-time = < 0x04 >;
					ts,mod-12b = < 0x01 >;
					ts,ref-sel = < 0x00 >;
					ts,adc-freq = < 0x01 >;
					ts,ave-ctrl = < 0x01 >;
					ts,touch-det-delay = < 0x03 >;
					ts,settling = < 0x04 >;
					ts,fraction-z = < 0x07 >;
					ts,i-drive = < 0x01 >;
				};
			};
		};

Let’s bind trees

So, as you can imagine, every time a board is changed, we have to change its DTS file. So, each board has its own device tree. However, some boards have a lot in common. For instance, we use the Aries MCV SoM which is used on already 2 ARIES boards: the MCVEVK and the MCVEVP. Moreover, we will make our own board. However, there are lots of things in common: Flash memory is still the same, the buses are still the same, etc… So, it would be stupid to create different files with almost the same device tree each time. This is where the .dtsi files make their arrival. Those files are incomplete or more general device tree which will not be compiled into device tree blob but will be included in DTS file. For instance, for the LitSpin board, we import the socfpga_cyclone5_mcv.dtsi file which represents the device tree of the MCV SoM. So we will just have to add the micro SD Card on the SPI bus and that’s all. So, this is the DTS file for our board:

#include "socfpga_cyclone5_mcv.dtsi"

/ {
	model = "Aries MCV LitSpin";
	compatible = "altr,socfpga-cyclone5", "altr,socfpga";


};

&spi1 {
    status = "okay";
    // parameters

    mmc-slot@0{
        // parameters
    };
};

&usb1 {
	status = "okay";
};

We active the spi1 and tell there is an MMC host on it. And we active the USB1 bus because the USB WiFi dongle will be plugged on it.

When we will compile, the includes will be done and each parameter in the DTS file will be added to the right place if there are not set or will overwrite the value in the DTSI file, like status parameter for spi1 and usb1 buses.

Goodbye Yocto

For now, we decided not to use Yocto and there are several reasons:

  1. It is too complicated to compile. It takes too much time (more than a night) and it is very restrictive on the Linux distribution we can use.
  2. It is quite overkilled. As you can see above, we should only have to create our own DTS file for one board. It is quite overkilled to make a recipe for this. Clearly, we are not the public of Yocto. This project is more for companies that make a lot of different boards. Not for students who make only one.
  3. With the help of Tarik Graba, we did the same things with the DE1-SoC by adding the good DTS file to the Altera Linux-socfpga repository. It takes only a few minutes to compile the kernel. And it is less restrictive than Yocto.

Leave a Reply

Your email address will not be published. Required fields are marked *