2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ultra96 向け Debian GNU/Linux (v2018.2版) の構築(Linux Kernel編)

Last updated at Posted at 2018-10-28

はじめに

Ultra96 に Debian GNU/Linux (v2018.2版) を構築する方法について、具体的な方法をいくつかに分けて説明します。

この記事では ZynqMP の Linux Kernel について説明をします。

注意

Linux Kernel では 起動時に ATF(ARM Trusted Firmware) のバージョンをチェックしています。Debian GNU/Linux (v2018.2版) で構築する Linux Kernel 4.14.0 (xilinx-v2018.2) では ATF(ARM Trusted Firmware) のバージョンは v1.0 である必要があります。これ以外のバージョンでは Kernel が Panic を起こして起動出来ないので注意してください。

Linux Kernel の構築

必要な環境

  • gcc-aarch64-linux-gnu

Linux Kernel 構築環境の準備

次の URL から git clone でリポジトリをダウンロードして v2018.2.1 をチェックアウトします。

shell$ git clone git://github.com/ikwzm/ZynqMP-FPGA-Linux
shell$ cd ZynqMP-FPGA-Linux
shell$ git checkout v2018.2.1

ソースコードのダウンロード

Linux Kernel のソースコードを以下の URL からダウンロードします。今回は Linux のメインラインからではなく、Xilinx が提供してる linux-xlnx を使います。

shell$ git clone https://github.com/Xilinx/linux-xlnx.git linux-xlnx-v2018.2-zynqmp-fpga

xilinx-v2018.2 をチェックアウト

linux-xlnx の xilinx-v2018.2 というタグをチェックアウトして linux-xlnx-v2018.2-zynqmp-fpga という作業用のブランチを作ります。

shell$ cd linux-xlnx-v2018.2-zynqmp-fpga
shell$ git checkout -b linux-xlnx-v2018.2-zynqmp-fpga refs/tags/xilinx-v2018.2

ZynqMP 用の各種ファイルを追加

ZynqMP 用のファイルを追加してコミットします。追加するファイルの詳細は後述します。

shell$ patch -p1 < ../files/linux-xlnx-v2018.2-zynqmp-fpga.diff
shell$ git add --update
shell$ git add arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts
shell$ git commit -m "[patch] for linux-xlnx-v2018.2-zynqmp-fpga."

ヘッダーパッケージにホスト用の実行ファイルが含まれてしまう問題

チェックアウトした xilinx-v2018.2 には、Debain のパッケージを作る際に arm64 用ではなくクロスコンパイルを実行したプラットフォーム用のパッケージが出来てしまう問題があります。そのための修正を追加します。この件の詳細は後述します。

shell$ patch -p1 < ../files/linux-xlnx-v2018.2-builddeb.diff
shell$ git add --update
shell$ git commit -m "[update] scripts/package/builddeb to add tools/include and postinst script to header package"

FPGA のロード時に raw ファイルをロード出来るように修正

チェックアウトした xilinx-v2018.2 には、FPGA のロード時に raw ファイルを指定するとフリーズするという問題があります。ここではその修正を追加します。この件の詳細は後述します。

shell$ patch -p1 < ../files/linux-xlnx-v2018.2-zynqmp-fpga-patch.diff
shell$ git add --update
shell$ git commit -m "[patch] drivers/fpga/zynqmp-fpga.c for load raw file format"

タグとバージョン番号の設定

shell$ git tag -a xilinx-v2018.2-zynqmp-fpga -m "release xilinx-v2018.2-zynqmp-fpga"
shell$ echo 0 > .version

構築の準備

環境変数を設定します。アーキテクチャ(ARCH)に arm64 を指定します。ここでは、クロスコンパイルに使うツールチェーン(CROSS_COMPILE) に aarch64-linux-gnu-を指定します。この変数は構築する環境にあわせてください。その後、ZynqMP 用のコンフィギュレーション定義ファイルを使って構築の準備をします。

shell$ cd linux-xlnx-v2018.2-zynqmp-fpga
shell$ export ARCH=arm64
shell$ export CROSS_COMPILE=aarch64-linux-gnu-
shell$ make xilinx_zynqmp_defconfig

カーネルと Debian パッケージの構築

shell$ export DTC_FLAGS=--symbols
shell$ make deb-pkg

構築したカーネルのイメージとデバイスツリーを target/Ultra96/boot にコピー

無事にカーネルのイメージ(arch/arm64/boot/Image) と Ultra96 用のデバイスツリー(arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dtb) が出来たら、それを target/Ultra96/boot にコピーします。その際、作ったカーネルのバージョン等をわかりやすくするため名前を変更しておきます。
また、dtc(Device Tree Compiler) を使って、デバイスツリーのバイナリファイル (devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb) をデバイスツリーのソースファイル (devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dts) に戻しておきます。何かデバイスツリーを変更したい時は、このデバイスツリーソースファイルを修正して dtc でデバイスツリーバイナリファイルにコンパイルしてください。
なお、「デバイスツリーにシンボル情報を埋め込む」で説明したように、古いバージョンの dtc では --symbols オプションをサポートしていない場合があります。その場合は Linux Kernel をビルドした時にホスト用に生成された dtc (scripts/dtc/dtc) を使ってコンパイルすると良いでしょう。

shell$ cp arch/arm64/boot/Image ../target/Ultra96/boot/image-4.14.0-xlnx-v2018.2-zynqmp-fpga
shell$ cp arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dtb ../target/Ultra96/boot/devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb
shell$ ./scripts/dtc/dtc -I dtb -O dts --symbols -o ../target/Ultra96/boot/devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dts ../target/Ultra96/boot/devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb

Linux Kernel の起動

uEnv.txt

「Ultra96 向け Debian GNU/Linux (v2018.2版) の構築(U-Boot編)」 で構築した U-Boot は、起動の際、ストレージに uEnv.txt があればそれを読み込みます。そして uenvcmd 変数が定義されていれば、その変数で定義されている内容を実行します。そこで uEnv.txt に、この記事で構築したカーネルのイメージとデバイスツリーを指定して実行するように記述します。

target/Ultra96/boot/uEnv.txt
linux_kernel_image=image-4.14.0-xlnx-v2018.2-zynqmp-fpga
linux_fdt_image=devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb
linux_boot_args=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio

linux_img_load_cmd=fatload mmc ${sdbootdev} ${kernel_addr} ${linux_kernel_image}
linux_fdt_load_cmd=fatload mmc ${sdbootdev} ${fdt_addr}    ${linux_fdt_image}
linux_load_cmd=run linux_img_load_cmd && run linux_fdt_load_cmd
linux_boot_cmd=setenv bootargs ${linux_boot_args} && booti ${kernel_addr} - ${fdt_addr}

uenvcmd=run linux_load_cmd && run linux_boot_cmd

bootmenu_0=Boot Default=boot
  • linux_kernel_image 変数にカーネルのイメージのファイル名である image-4.14.0-xlnx-v2018.2-zynqmp-fpga を指定。
  • linux_fdt_image 変数にデバイスツリーファイル名である devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb を指定。
  • linux_boot_args 変数に Linux をブートする際の引数を指定。
    • console として ttyPS0 をボーレートと共に指定。
    • root file system として /dev/mmcblk0p2 (SD-Card の第2パーティション) を指定。
    • デバイスツリーオーバーレイで uio を指定出来るように uio_pdrv_genirq.of_id=generic-uio を指定。
  • linux_img_load_cmd 変数に sdbootdev 変数でしていされたデバイスから linux_kernel_image 変数で指定されたカーネルイメージをメモリ上の kernel_addr で指定されたアドレスにロードするコマンドを記述。
  • linux_dtb_load_cmd 変数に sdbootdev 変数でしていされたデバイスから linux_fdt_image 変数で指定されたデバイスツリーをメモリ上の fdt_addr で指定されたアドレスにロードするコマンドを記述。
  • linux_load_cmd 変数に linux_img_load_cmdlinux_dtb_load_cmd を実行するコマンドを記述。
  • linux_boot_cmd 変数に linux_boot_args 変数で設定した bootargs を設定し、booti コマンドを使ってメモリ上にロードされたカーネルをブートするコマンドを記述。
  • uenvcmd 変数に上記各種変数をコマンドとして実行するように記述。
  • bootmenu_0 変数にブートメニューの最初の選択肢のタイトルと実行するコマンドを記述。

Zynq と異なるのは、ブートするカーネルのイメージが Linux kernel ARM boot executable zImage 形式ではなく、arm64 Linux Image 形式であることです。arm64 用に構築した U-Boot には arm64 Linux Image 形式のイメージをブートするためのコマンド booti があるので、そちらを使います。

ファイルの説明

ここでは linux-xlnx を ZynqMP 用に構築する際に新たに追加したファイルおよび修正したファイルの説明をします。

arch/arm64/configs/xilinx_zynqmp_defconfig

ZynqMP 用のコンフィギュレーション定義ファイルです。基本的には linux-xlnx にすでにある xilinx_zynqmp_defconfig と同じですが、Device Tree Overlay を使うために CONFIG_OF_OVERLAY=yを、さらに Device Tree Overlay を Configuration File System から行うために CONFIG_OF_CONFIGFS=y を新たに追加しています。

arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts

Ultra96 用のデバイスツリーです。実はこれと同じデバイスツリーを U-Boot のビルド時にも流用しています。

arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts
arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts
// SPDX-License-Identifier: GPL-2.0+
/*
 * dts file for Xilinx ZynqMP Ultra96
 *
 */

/dts-v1/;

#include "zynqmp.dtsi"
#include "zynqmp-clk-ccf.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
#include <dt-bindings/phy/phy.h>

/ {
	model = "ZynqMP Ultra96";
	compatible = "xlnx,zynqmp-ultra96", "xlnx,zynqmp";

	aliases {
		gpio0 = &gpio;
		i2c0 = &i2c1;
		rtc0 = &rtc;
		serial0 = &uart1;
		serial1 = &uart0;
		serial2 = &dcc;
		spi0 = &spi0;
		spi1 = &spi1;
		usb0 = &usb0;
		usb1 = &usb1;
		mmc0 = &sdhci0;
		mmc1 = &sdhci1;
	};

	chosen {
		bootargs = "earlycon";
		stdout-path = "serial0:115200n8";
	};

	memory@0 {
		device_type = "memory";
		reg = <0x0 0x0 0x0 0x80000000>;
	};

	amba_pl: amba_pl@0 {
		#address-cells = <2>;
		#size-cells = <2>;
		compatible = "simple-bus";
		ranges ;
	};

	gpio-keys {
		compatible = "gpio-keys";
		#address-cells = <1>;
		#size-cells = <0>;
		autorepeat;
		sw4 {
			label = "sw4";
			gpios = <&gpio 23 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_POWER>;
			gpio-key,wakeup;
			autorepeat;
		};
	};

	iio-hwmon {
		compatible = "iio-hwmon";
		io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>,
			      <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>,
			      <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>,
			      <&xilinx_ams 9>, <&xilinx_ams 10>,
			      <&xilinx_ams 11>, <&xilinx_ams 12>;
	};

	leds {
		compatible = "gpio-leds";
		ds2 {
			label = "ds2";
			gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
		};

		ds3 {
			label = "ds3";
			gpios = <&gpio 19 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "phy0tx"; /* WLAN tx */
			default-state = "off";
		};

		ds4 {
			label = "ds4";
			gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "phy0rx"; /* WLAN rx */
			default-state = "off";
		};

		ds5 {
			label = "ds5";
			gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "bluetooth-power";
		};

		vbus_det { /* U5 USB5744 VBUS detection via MIO25 */
			label = "vbus_det";
			gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
			default-state = "on";
		};
	};

	ltc2954: ltc2954 { /* U7 */
		compatible = "lltc,ltc2954", "lltc,ltc2952";
		trigger-gpios = <&gpio 26 GPIO_ACTIVE_LOW>; /* INT line - input */
		/* If there is HW watchdog on mezzanine this signal should be connected there */
		watchdog-gpios = <&gpio 35 GPIO_ACTIVE_HIGH>; /* MIO on PAD */
		kill-gpios = <&gpio 34 GPIO_ACTIVE_LOW>; /* KILL signal - output */
	};

	wmmcsdio_fixed: fixedregulator-mmcsdio {
		compatible = "regulator-fixed";
		regulator-name = "wmmcsdio_fixed";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		regulator-always-on;
		regulator-boot-on;
	};

	sdio_pwrseq: sdio_pwrseq {
		compatible = "mmc-pwrseq-simple";
		reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
	};
};

&dcc {
	status = "okay";
};

&gpio {
	status = "okay";
	gpio-line-names = "UART1_TX", "UART1_RX", "UART0_RX", "UART0_TX", "I2C1_SCL",
			  "I2C1_SDA", "SPI1_SCLK", "WLAN_EN", "BT_EN", "SPI1_CS",
			  "SPI1_MISO", "SPI1_MOSI", "I2C_MUX_RESET", "SD0_DAT0", "SD0_DAT1",
			  "SD0_DAT2", "SD0_DAT3", "PS_LED3", "PS_LED2", "PS_LED1",
			  "PS_LED0", "SD0_CMD", "SD0_CLK", "GPIO_PB", "SD0_DETECT",
			  "VBUS_DET", "POWER_INT", "DP_AUX", "DP_HPD", "DP_OE",
			  "DP_AUX_IN", "INA226_ALERT", "PS_FP_PWR_EN", "PL_PWR_EN", "POWER_KILL",
			  "", "GPIO-A", "GPIO-B", "SPI0_SCLK", "GPIO-C",
			  "GPIO-D", "SPI0_CS", "SPI0_MISO", "SPI_MOSI", "GPIO-E",
			  "GPIO-F", "SD1_D0", "SD1_D1", "SD1_D2", "SD1_D3",
			  "SD1_CMD", "SD1_CLK", "USB0_CLK", "USB0_DIR", "USB0_DATA2",
			  "USB0_NXT", "USB0_DATA0", "USB0_DATA1", "USB0_STP", "USB0_DATA3",
			  "USB0_DATA4", "USB0_DATA5", "USB0_DATA6", "USB0_DATA7", "USB1_CLK",
			  "USB1_DIR", "USB1_DATA2", "USB1_NXT", "USB1_DATA0", "USB1_DATA1",
			  "USB1_STP", "USB1_DATA3", "USB1_DATA4", "USB1_DATA5", "USB1_DATA6",
			  "USB_DATA7", "WLAN_IRQ", "PMIC_IRQ", /* MIO end and EMIO start */
			  "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "", "", "", "", "", "", "",
			  "", "", "", "";
};

&gpu {
	status = "okay";
};

&i2c1 {
	status = "okay";
	pinctrl-names = "default", "gpio";
	pinctrl-0 = <&pinctrl_i2c1_default>;
	pinctrl-1 = <&pinctrl_i2c1_gpio>;
	scl-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>;
	sda-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
	clock-frequency = <100000>;
	i2c-mux@75 { /* u11 */
		compatible = "nxp,pca9548";
		#address-cells = <1>;
		#size-cells = <0>;
		reg = <0x75>;
		i2csw_0: i2c@0 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <0>;
			label = "LS-I2C0";
		};
		i2csw_1: i2c@1 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <1>;
			label = "LS-I2C1";
		};
		i2csw_2: i2c@2 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <2>;
			label = "HS-I2C2";
		};
		i2csw_3: i2c@3 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <3>;
			label = "HS-I2C3";
		};
		i2csw_4: i2c@4 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <0x4>;

			pmic: pmic@5e { /* Custom TI PMIC u33 */
				compatible = "ti,tps65086";
				reg = <0x5e>;
				interrupt-parent = <&gpio>;
				interrupts = <77 GPIO_ACTIVE_LOW>;
				#gpio-cells = <2>;
				gpio-controller;
			};
		};
		i2csw_5: i2c@5 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <5>;
			/* PS_PMBUS */
			ina226@40 { /* u35 */
				compatible = "ti,ina226";
				reg = <0x40>;
				shunt-resistor = <10000>;
				/* MIO31 is alert which should be routed to PMUFW */
			};
		};
		i2csw_6: i2c@6 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <6>;
			/*
			 * Not Connected
			 */
		};
		i2csw_7: i2c@7 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <7>;
			/*
			 * usb5744 (DNP) - U5
			 * 100kHz - this is default freq for us
			 */
		};
	};
};

&pinctrl0 {
	status = "okay";
	pinctrl_i2c1_default: i2c1-default {
		mux {
			groups = "i2c1_1_grp";
			function = "i2c1";
		};

		conf {
			groups = "i2c1_1_grp";
			bias-pull-up;
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};
	};

	pinctrl_i2c1_gpio: i2c1-gpio {
		mux {
			groups = "gpio0_4_grp", "gpio0_5_grp";
			function = "gpio0";
		};

		conf {
			groups = "gpio0_4_grp", "gpio0_5_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};
	};

	pinctrl_sdhci0_default: sdhci0-default {
		mux {
			groups = "sdio0_3_grp";
			function = "sdio0";
		};

		conf {
			groups = "sdio0_3_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
			bias-disable;
		};

		mux-cd {
			groups = "sdio0_cd_0_grp";
			function = "sdio0_cd";
		};

		conf-cd {
			groups = "sdio0_cd_0_grp";
			bias-high-impedance;
			bias-pull-up;
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};
	};

	pinctrl_sdhci1_default: sdhci1-default {
		mux {
			groups = "sdio1_2_grp";
			function = "sdio1";
		};

		conf {
			groups = "sdio1_2_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
			bias-disable;
		};
	};

	pinctrl_spi0_default: spi0-default {
		mux {
			groups = "spi0_3_grp";
			function = "spi0";
		};

		conf {
			groups = "spi0_3_grp";
			bias-disable;
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		mux-cs {
			groups = "spi0_ss_9_grp";
			function = "spi0_ss";
		};

		conf-cs {
			groups = "spi0_ss_9_grp";
			bias-disable;
		};

	};

	pinctrl_spi1_default: spi1-default {
		mux {
			groups = "spi1_0_grp";
			function = "spi1";
		};

		conf {
			groups = "spi1_0_grp";
			bias-disable;
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		mux-cs {
			groups = "spi1_ss_0_grp";
			function = "spi1_ss";
		};

		conf-cs {
			groups = "spi1_ss_0_grp";
			bias-disable;
		};

	};

	pinctrl_uart0_default: uart0-default {
		mux {
			groups = "uart0_0_grp";
			function = "uart0";
		};

		conf {
			groups = "uart0_0_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		conf-rx {
			pins = "MIO2";
			bias-high-impedance;
		};

		conf-tx {
			pins = "MIO3";
			bias-disable;
		};
	};

	pinctrl_uart1_default: uart1-default {
		mux {
			groups = "uart1_0_grp";
			function = "uart1";
		};

		conf {
			groups = "uart1_0_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		conf-rx {
			pins = "MIO1";
			bias-high-impedance;
		};

		conf-tx {
			pins = "MIO0";
			bias-disable;
		};
	};

	pinctrl_usb0_default: usb0-default {
		mux {
			groups = "usb0_0_grp";
			function = "usb0";
		};

		conf {
			groups = "usb0_0_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		conf-rx {
			pins = "MIO52", "MIO53", "MIO55";
			bias-high-impedance;
		};

		conf-tx {
			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
			       "MIO60", "MIO61", "MIO62", "MIO63";
			bias-disable;
		};
	};

	pinctrl_usb1_default: usb1-default {
		mux {
			groups = "usb1_0_grp";
			function = "usb1";
		};

		conf {
			groups = "usb1_0_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		conf-rx {
			pins = "MIO64", "MIO65", "MIO67";
			bias-high-impedance;
		};

		conf-tx {
			pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
			       "MIO72", "MIO73", "MIO74", "MIO75";
			bias-disable;
		};
	};
};

&rtc {
	status = "okay";
};

/* SD0 only supports 3.3V, no level shifter */
&sdhci0 {
	status = "okay";
	no-1-8-v;
	broken-cd; /* CD has to be enabled by default */
	disable-wp;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_sdhci0_default>;
	xlnx,mio_bank = <0>;
};

&sdhci1 {
	status = "okay";
	bus-width = <0x4>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_sdhci1_default>;
	xlnx,mio_bank = <0>;
	non-removable;
	disable-wp;
	cap-power-off-card;
	mmc-pwrseq = <&sdio_pwrseq>;
	vqmmc-supply = <&wmmcsdio_fixed>;
	#address-cells = <1>;
	#size-cells = <0>;
	wlcore: wifi@2 {
		compatible = "ti,wl1831";
		reg = <2>;
		interrupt-parent = <&gpio>;
		interrupts = <76 IRQ_TYPE_EDGE_RISING>; /* MIO76 WLAN_IRQ 1V8 */
	};
};

&serdes {
	status = "okay";
};

&spi0 { /* Low Speed connector */
	status = "okay";
	label = "LS-SPI0";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_spi0_default>;
};

&spi1 { /* High Speed connector */
	status = "okay";
	label = "HS-SPI1";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_spi1_default>;
};

&uart0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart0_default>;
	bluetooth {
		compatible = "ti,wl1831-st";
		enable-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
	};

};

&uart1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1_default>;

};

/* ULPI SMSC USB3320 */
&usb0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usb0_default>;
};

&dwc3_0 {
	status = "okay";
	dr_mode = "peripheral";
	phy-names = "usb3-phy";
	phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>;
	maximum-speed = "super-speed";
};

/* ULPI SMSC USB3320 */
&usb1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usb1_default>;
};

&dwc3_1 {
	status = "okay";
	dr_mode = "host";
	phy-names = "usb3-phy";
	phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>;
	maximum-speed = "super-speed";
};

&watchdog0 {
	status = "okay";
};

&zynqmp_dpsub {
	status = "okay";
	phy-names = "dp-phy0", "dp-phy1";
	phys = <&lane1 PHY_TYPE_DP 0 1 27000000>,
	       <&lane0 PHY_TYPE_DP 1 1 27000000>;
};

&zynqmp_dp_snd_pcm0 {
	status = "okay";
};

&zynqmp_dp_snd_pcm1 {
	status = "okay";
};

&zynqmp_dp_snd_card0 {
	status = "okay";
};

&zynqmp_dp_snd_codec0 {
	status = "okay";
};

&xlnx_dpdma {
	status = "okay";
};

&xilinx_ams {
	status = "okay";
};

&ams_ps {
	status = "okay";
};

もともと、このデバイスツリーは arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts が元になっています。zynqmp-zcu100-revC.dts との違いを説明します。

amba_pl@0 を追加

デバイスツリーオーバーレイを使って、各種デバイスドライバのロード/アンロードおよび PL のプログラムを行う際、そのターゲットとなるノードです。このノードは単なるノードで特に対応するデバイスドライバとかはありません。名前は何でも良かったのですが、UltraZed と同じノード名にしています。そうすれば UltraZed といろいろ兼用できて都合が良いからです。

arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts
	amba_pl: amba_pl@0 {
		#address-cells = <2>;
		#size-cells = <2>;
		compatible = "simple-bus";
		ranges ;
	};

pinctrl_uart0_default の conf-rx と conf-tx の pins を交換

zynqmp-zcu100-revC.dts では conf-rx ノードの pins プロパティが "MIO3" に、conf-tx ノードの pins プロパティが "MIO2" に設定されていましたが、改めて Sample Design の I/O pin を調べてみるとどうも逆のようです。

arch/arm64/boot/dts/xilinx/zynqmp-ultra96.dts
	pinctrl_uart0_default: uart0-default {
		mux {
			groups = "uart0_0_grp";
			function = "uart0";
		};

		conf {
			groups = "uart0_0_grp";
			slew-rate = <SLEW_RATE_SLOW>;
			io-standard = <IO_STANDARD_LVCMOS18>;
		};

		conf-rx {
			pins = "MIO2";
			bias-high-impedance;
		};

		conf-tx {
			pins = "MIO3";
			bias-disable;
		};
	};

ZynqMP での pinctrl の ピンアサインについては次の記事を参考にしてください。

ヘッダーパッケージにホスト用の実行ファイルが含まれてしまう問題

詳細は以下の記事を参照してください。

このパッチを当てる差分ファイルが次に示す files/linux-xlnx-v2018.2-builddeb.diff です。

files/linux-xlnx-v2018.2-builddeb.diff
files/linux-xlnx-v2018.2-builddeb2.diff
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 0bc8747..515963f 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -313,7 +313,7 @@ fi
 
 # Build kernel header package
 (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find arch/*/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
+(cd $srctree; find arch/*/include include tools/include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
 if grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then
@@ -330,6 +330,15 @@ mkdir -p "$destdir"
 (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
 ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
 rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
+mkdir -m 755 -p "$kernel_headers_dir/DEBIAN"
+cat <<EOF >> $kernel_headers_dir/DEBIAN/postinst
+#!/bin/sh -e
+
+make -C /usr/src/linux-headers-$version scripts
+
+EOF
+
+chmod 755 $kernel_headers_dir/DEBIAN/postinst
 
 cat <<EOF >> debian/control
 

FPGA のロード時に raw ファイルをロード出来るように修正

チェックアウトした xilinx-v2018.2 には、FPGA のロード時に raw ファイルを指定するとフリーズするという問題がありました。ここではその修正を追加します。具体的には ATF(ARM Trusted Firmware) に渡す3番目の引数にファイルサイズを示す物理メモリ上のアドレスを指定します。

このパッチを当てる差分ファイルが次に示す files/linux-xlnx-v2018.2-zynqmp-fpga-patch.diff です。

files/linux-xlnx-v2018.2-zynqmp-fpga-patch.diff
files/linux-xlnx-v2018.2-zynqmp-fpga-patch.diff
diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
index b0c482f..4a91d64 100644
--- a/drivers/fpga/zynqmp-fpga.c
+++ b/drivers/fpga/zynqmp-fpga.c
@@ -48,7 +48,8 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
 {
 	struct zynqmp_fpga_priv *priv;
 	char *kbuf;
-	size_t dma_size;
+	size_t kbuf_size;
+	size_t algn_size = (size + (sizeof(u32)-1)) & (~(sizeof(u32)-1));
 	dma_addr_t dma_addr;
 	int ret;
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
@@ -59,25 +60,30 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
 	priv = mgr->priv;
 
 	if (mgr->flags & IXR_FPGA_ENCRYPTION_EN)
-		dma_size = size + ENCRYPTED_KEY_LEN;
+		kbuf_size = algn_size + ENCRYPTED_KEY_LEN;
 	else
-		dma_size = size;
+		kbuf_size = algn_size + sizeof(u32);
 
-	kbuf = dma_alloc_coherent(priv->dev, dma_size, &dma_addr, GFP_KERNEL);
+	kbuf = dma_alloc_coherent(priv->dev, kbuf_size, &dma_addr, GFP_KERNEL);
 	if (!kbuf)
 		return -ENOMEM;
 
 	memcpy(kbuf, buf, size);
 
-	if (mgr->flags & IXR_FPGA_ENCRYPTION_EN)
-		memcpy(kbuf + size, mgr->key, ENCRYPTED_KEY_LEN);
+	if (mgr->flags & IXR_FPGA_ENCRYPTION_EN) {
+		memcpy(kbuf + algn_size, mgr->key, ENCRYPTED_KEY_LEN);
+        }
+	else {
+		u32* size_ptr = (u32*)(kbuf + algn_size);
+		*size_ptr = (u32)size;
+	}
 
 	__flush_cache_user_range((unsigned long)kbuf,
-				 (unsigned long)kbuf + dma_size);
+				 (unsigned long)kbuf + kbuf_size);
 
-	ret = eemi_ops->fpga_load(dma_addr, dma_addr + size, mgr->flags);
+	ret = eemi_ops->fpga_load(dma_addr, dma_addr + algn_size, mgr->flags);
 
-	dma_free_coherent(priv->dev, dma_size, kbuf, dma_addr);
+	dma_free_coherent(priv->dev, kbuf_size, kbuf, dma_addr);
 
 	return ret;
 }

参考

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?