MPFS-DISCO-KIT 向け Ubuntu 22.04 で Lチカ


## はじめに

筆者は MPFS-DISCO-KIT(Microchip PolarFire SoC FPGA Discovery Kit) で動作する Ubuntu 22.04 を独自に構築しています。この記事では、この MPFS-DISCO-KIT 向け Ubuntu 22.04 で USER LED を GPIO ドライバを使って制御する方法を説明します。

### MPFS-DISCO-KIT とは

MPFS-DISCO-KIT(Microchip PolarFire SoC FPGA Discovery Kit) は、Microchip Technology 社の PolarFire SoC FPGA(MPFS095T_1FCSG325E) を搭載した開発用のキットです。

 * PolarFire SoC FPGA with 95k LEs
 * 1GByte main memory
 * 1x Gigabit Ethernet
 * 3x UART
 * 1x micro-SD interface
 * Form factor 4.1" x3.3"
 * 8x USER LED
 * 8x DIP SWITCH

詳細は次の URL を参照してください。

 * https://www.microchip.com/en-us/development-tool/mpfs-disco-kit

### MPFS-DISCO-KIT 向け Ubuntu 22.04 とは

筆者は MPFS-DISCO-KIT(Microchip PolarFire SoC FPGA Discovery Kit) で動作する Ubuntu 22.04 を独自に構築しています。以下の URL で公開しています。

 * https://github.com/ikwzm/MPFS-FPGA-Ubuntu22.04

なお、これらはオフシャルなものではなく、筆者の魔改造がはいっています。ご使用の際はこの点にご留意してください。

## 準備

### polarfire-soc-discovery-kit-reference-design 

この記事では FPGA(Fabric) にプログラムするデザインとして、polarfire-soc-discovery-kit-reference-design を利用します。これは MPFS-DISCO-KIT 用に Fabric部(FPGA部)に SRAM、I2C、GPIO、DMAなどを実装したリファレンスデザインです。この記事では USER LED の制御に Fabric部(FPGA部) にある GPIO を使います。

このリファレンスデザインのダウンロード、ビルド、MPFS-DISCO-KIT へのプログラムに関しては、以下の記事を参照してください。

 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(HSS編)』@Qiita](https://qiita.com/ikwzm/items/3d6d0a645dd60aba90d2)

### MPFS-DISCO-KIT 向け Ubuntu 22.04 の起動

SD-Card に MPFS-DISCO-KIT 向け Ubuntu 22.04 を書き込んで MPFS-DISCO-KIT を起動します。
詳細は以下の記事を参照してください。

 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(SD-Card 作成編)』@Qiita](https://qiita.com/ikwzm/items/19af3dd7a34ea5364683)
 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(SD-Card 起動編)』@Qiita](https://qiita.com/ikwzm/items/42a1aa7b355734a813f8)

### gpiod のインストール

この記事では gpio を制御するアプリケーションとして gpiod を使います。 パッケージをインストールしてください。

```console
shell$ sudo apt install gpiod
```

### デバイスツリーの用意

MPFS-DISCO-KIT 向け Ubuntu 22.04 では、FPGA(Fabric) にプログラムした IP を制御するためのデバイスドライバは Device Tree Overlay を使って Linux 起動後に動的にロードします。polarfire-soc-discovery-kit-reference-design では、USER LED は CoreGPIO という gpio コンポーネントに接続されています。そこで、次のような DTS(Device Tree Blob Source) を用意します。この DTS は gpio コンポーネントを Microchip 社提供の GPIO ドライバを使って制御するためのものです。

```dts:core-gpio-c0.dts
/dts-v1/; /plugin/;

/ {
	fragment@0 {
		target-path = "/fabric-bus@40000000";
		#address-cells = <2>;
		#size-cells = <2>;

		__overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			clock_and_reset_0_fic_3_clk: clock_and_reset_0_fic_3_clk {
				compatible = "fixed-clock";
				#clock-cells = <0>;
				clock-frequency = <50000000>;
			};
			core_gpio_c0: coregpio@40000100 {
				compatible = "microchip,coregpio-rtl-v3";
				reg = <0x0 0x40000100 0x0 0x0100>;
				clocks = <&clock_and_reset_0_fic_3_clk>;
				status = "okay";
			};
		};
	};
};
```

これを dtc(Device Tree Compiler) を使って DTB(Device Tree Blob) に変換します。

```console
shell$ dtc -I dts -O dtb -o core-gpio-c0.dtb core-gpio-c0.dts
```

### デバイスツリーのオーバーレイ

core-gpio-c0.dtb を Device Tree に Overlay します。

```console
shell$ sudo mkdir /sys/kernel/config/device-tree/overlays/core-gpio-c0
shell$ sudo cp core-gpio-c0.dtb /sys/kernel/config/device-tree/overlays/core-gpio-c0/dtbo
```

これで /sys/class/gpio に coregpio が見えるようなるはずです。以下の例では gpiochip568 として見えています。

```console
shell$ ls -la /sys/class/gpio/
total 0
drwxr-xr-x  2 root root    0 Nov 22  2023 .
drwxr-xr-x 48 root root    0 Nov 22  2023 ..
--w-------  1 root root 4096 Nov 22  2023 export
lrwxrwxrwx  1 root root    0 Nov 22  2023 gpiochip512 -> ../../devices/platform/soc/20121000.gpio/gpio/gpiochip512
lrwxrwxrwx  1 root root    0 Nov 22  2023 gpiochip536 -> ../../devices/platform/soc/20122000.gpio/gpio/gpiochip536
lrwxrwxrwx  1 root root    0 Dec 24 10:44 gpiochip568 -> ../../devices/platform/fabric-bus@40000000/40000100.coregpio/gpio/gpiochip568
--w-------  1 root root 4096 Nov 22  2023 unexport
```

## 動作

### gpioinfo

```console
shell$ sudo gpioinfo
gpiochip0 - 24 lines:
	line   0:      unnamed       unused  output  active-high 
	line   1:      unnamed       unused  output  active-high 
	line   2:      unnamed       unused  output  active-high 
	line   3:      unnamed       unused  output  active-high 
	line   4:      unnamed       unused  output  active-high 
	line   5:      unnamed       unused  output  active-high 
	line   6:      unnamed       unused  output  active-high 
	line   7:      unnamed       unused  output  active-high 
	line   8:      unnamed       unused  output  active-high 
	line   9:      unnamed       "led8"  output  active-high [used]
	line  10:      unnamed       unused  output  active-high 
	line  11:      unnamed       unused  output  active-high 
	line  12:      unnamed       unused  output  active-high 
	line  13:      unnamed       unused  output  active-high 
	line  14:      unnamed       unused  output  active-high 
	line  15:      unnamed       unused  output  active-high 
	line  16:      unnamed       unused  output  active-high 
	line  17:      unnamed       unused  output  active-high 
	line  18:      unnamed       unused  output  active-high 
	line  19:      unnamed       unused  output  active-high 
	line  20:      unnamed       unused  output  active-high 
	line  21:      unnamed       unused  output  active-high 
	line  22:      unnamed       unused  output  active-high 
	line  23:      unnamed       unused  output  active-high 
gpiochip1 - 32 lines:
	line   0:      unnamed       unused  output  active-high 
	line   1:      unnamed       unused  output  active-high 
	line   2:      unnamed       unused  output  active-high 
	line   3:      unnamed       unused  output  active-high 
	line   4:      unnamed       unused  output  active-high 
	line   5:      unnamed       unused  output  active-high 
	line   6:      unnamed       unused  output  active-high 
	line   7:      unnamed       unused  output  active-high 
	line   8:      unnamed       unused  output  active-high 
	line   9:      unnamed       unused  output  active-high 
	line  10:      unnamed       unused  output  active-high 
	line  11:      unnamed       unused  output  active-high 
	line  12:      unnamed       unused  output  active-high 
	line  13:      unnamed       unused  output  active-high 
	line  14:      unnamed       unused  output  active-high 
	line  15:      unnamed       unused  output  active-high 
	line  16:      unnamed       unused  output  active-high 
	line  17:      unnamed       "led1"  output  active-high [used]
	line  18:      unnamed       "led2"  output  active-high [used]
	line  19:      unnamed       "led3"  output  active-high [used]
	line  20:      unnamed       "led4"  output  active-high [used]
	line  21:      unnamed       "led5"  output  active-high [used]
	line  22:      unnamed       "led6"  output  active-high [used]
	line  23:      unnamed       "led7"  output  active-high [used]
	line  24:      unnamed       unused  output  active-high 
	line  25:      unnamed       unused  output  active-high 
	line  26:      unnamed       unused  output  active-high 
	line  27:      unnamed       unused  output  active-high 
	line  28:      unnamed       unused  output  active-high 
	line  29:      unnamed       unused  output  active-high 
	line  30:      unnamed       unused  output  active-high 
	line  31:      unnamed       unused  output  active-high 
gpiochip2 - 32 lines:
	line   0:      unnamed       unused  output  active-high 
	line   1:      unnamed       unused  output  active-high 
	line   2:      unnamed       unused  output  active-high 
	line   3:      unnamed       unused  output  active-high 
	line   4:      unnamed       unused  output  active-high 
	line   5:      unnamed       unused  output  active-high 
	line   6:      unnamed       unused  output  active-high 
	line   7:      unnamed       unused  output  active-high 
	line   8:      unnamed       unused  output  active-high 
	line   9:      unnamed       unused  output  active-high 
	line  10:      unnamed       unused  output  active-high 
	line  11:      unnamed       unused  output  active-high 
	line  12:      unnamed       unused  output  active-high 
	line  13:      unnamed       unused  output  active-high 
	line  14:      unnamed       unused  output  active-high 
	line  15:      unnamed       unused  output  active-high 
	line  16:      unnamed       unused  output  active-high 
	line  17:      unnamed       unused  output  active-high 
	line  18:      unnamed       unused  output  active-high 
	line  19:      unnamed       unused  output  active-high 
	line  20:      unnamed       unused  output  active-high 
	line  21:      unnamed       unused  output  active-high 
	line  22:      unnamed       unused  output  active-high 
	line  23:      unnamed       unused  output  active-high 
	line  24:      unnamed       unused  output  active-high 
	line  25:      unnamed       unused  output  active-high 
	line  26:      unnamed       unused  output  active-high 
	line  27:      unnamed       unused  output  active-high 
	line  28:      unnamed       unused  output  active-high 
	line  29:      unnamed       unused  output  active-high 
	line  30:      unnamed       unused  output  active-high 
	line  31:      unnamed       unused  output  active-high 
```

### USER LED1 点灯

```console
shell$ sudo gpioset gpiochip2 0=1
```

### USER LED1 消灯

```console
shell$ sudo gpioset gpiochip2 0=0
```

### USER LED2 点灯

```console
shell$ sudo gpioset gpiochip2 1=1
```

### USER LED2 消灯

```console
shell$ sudo gpioset gpiochip2 1=0
```

## 後始末

### デバイスツリーのリリース

オーバーレイしたデバイスツリーをリリースします。

```console
shell$ sudo rmdir /sys/kernel/config/device-tree/overlays/core-gpio-c0
```

```console
shell$ ls -la /sys/class/gpio
total 0
drwxr-xr-x  2 root root    0 Nov 22  2023 .
drwxr-xr-x 48 root root    0 Nov 22  2023 ..
--w-------  1 root root 4096 Nov 22  2023 export
lrwxrwxrwx  1 root root    0 Nov 22  2023 gpiochip512 -> ../../devices/platform/soc/20121000.gpio/gpio/gpiochip512
lrwxrwxrwx  1 root root    0 Nov 22  2023 gpiochip536 -> ../../devices/platform/soc/20122000.gpio/gpio/gpiochip536
--w-------  1 root root 4096 Nov 22  2023 unexport
```

## ポイント

この記事のポイントは、DTS(Device Tree Blob Source) です。

```dts:core-gpio-c0.dts
/dts-v1/; /plugin/;

/ {
	fragment@0 {
		target-path = "/fabric-bus@40000000";
		#address-cells = <2>;
		#size-cells = <2>;

		__overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			clock_and_reset_0_fic_3_clk: clock_and_reset_0_fic_3_clk {
				compatible = "fixed-clock";
				#clock-cells = <0>;
				clock-frequency = <50000000>;
			};
			core_gpio_c0: coregpio@40000100 {
				compatible = "microchip,coregpio-rtl-v3";
				reg = <0x0 0x40000100 0x0 0x0100>;
				clocks = <&clock_and_reset_0_fic_3_clk>;
				status = "okay";
			};
		};
	};
};
```

実はこの DTS の前は、次のような DTS を用意していました。

```dts:core-gpio-c0-ng.dts
/dts-v1/; /plugin/;

#include "dt-bindings/clock/microchip,mpfs-clock.h"

/ {
	fragment@0 {
		target-path = "/fabric-bus@40000000";
		#address-cells = <2>;
		#size-cells = <2>;

		__overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			core_gpio_c0: coregpio@40000100 {
				compatible = "microchip,coregpio-rtl-v3";
				reg = <0x0 0x40000100 0x0 0x0100>;
				clocks = <&ccc_nw CLK_CCC_PLL0_OUT3>;
				status = "okay";
			};
		};
	};
};
```

この DTS は、Microchip Technology 社謹製の linux のデバイスツリーを元にしています。 残念ながら、この DTS では上手くいきませんでした。具体的には /sys/class/gpio に coregpio が見えなかったのです。どうやらデバイスドライバのロードに失敗しているようでした。
いろいろ調べてみたところ、clocks オプションで指定した clock ドライバ ccc_nw の status が disable になっているに気がつきました。試しに ccc_nw の stutus を okay にしてみましたが Linux Kernel が Panic を起しました。

polarfire-soc-discovery-kit-reference-design では Fabric に供給するクロックとして ccc(Clock Conditioning Circuitry) を使っています。ただし DRI(Dynamic Reconfiguration Interface) を disable にしていて、出力するクロックの週波数等は固定値に設定されています。

これは推測ですが、Linux Kernel にある ccc のデバイスドライバ drivers/clk/microchip/clk-mpfs-ccc.c は DRI が有効なときにしか動かないのではないでしょうか。

そこで、週波数が固定な clock ドライバ(fixed-clock)を定義して coregpio の clocks に設定してみました。そうすると、coregpio がロードされるようになりました。

これが最良な方法なのかわかりませんが、とりあえずご報告まで。

## 参考

### MPFS-FPGA-Example-1-DISCO-KIT

ここで紹介した DTS(Device Tree Blob Source) は以下の URL で公開しています。

 * https://github.com/ikwzm/MPFS-FPGA-Example-1-DISCO-KIT
   + examples/core-gpio/
     - [core-gpio-c0.dts](https://github.com/ikwzm/MPFS-FPGA-Example-1-DISCO-KIT/blob/main/examples/core-gpio/core-gpio-c0.dts)
 

### MPFS-DISCO-KIT 向け Ubuntu 22.04 に関する記事

 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(イントロ編)』@Qiita](https://qiita.com/ikwzm/items/1866dc3bb5292fd1f6e1)
 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(HSS編)』@Qiita](https://qiita.com/ikwzm/items/3d6d0a645dd60aba90d2)
 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(SD-Card 作成編)』@Qiita](https://qiita.com/ikwzm/items/19af3dd7a34ea5364683)
 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 の構築(SD-Card 起動編)』@Qiita](https://qiita.com/ikwzm/items/42a1aa7b355734a813f8)
 * https://github.com/ikwzm/MPFS-FPGA-Ubuntu22.04

### MPFS-DISCO-KIT 関連

 * https://www.microchip.com/en-us/development-tool/mpfs-disco-kit

### CoreGPIO 関連

 * https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/coregpio
 * https://ww1.microchip.com/downloads/aemdocuments/documents/fpga/ProductDocuments/SupportingCollateral/CoreGPIO_HB.pdf

### その他

 * [『FPGA+SoC+LinuxでDevice Tree Overlayを試してみた』@Qiita](https://qiita.com/ikwzm/items/ec514e955c16076327ce)
 * [『MPFS-DISCO-KIT 向け Ubuntu 22.04 で Lチカ(UIO 編)』@Qiita](https://qiita.com/ikwzm/items/https://qiita.com/ikwzm/items/b2013ba880b1b1280f8c)