FPGA Subsystem(FPGA-region)でFPGAをコンフィグする

# はじめに
Linuxの本家Mainline Kernelにも組み込まれているFPGAをコンフィグレーションするための FPGA subsystemについて書かせていただきます。主にARM CPUを内蔵するFPGAをLinuxで動作させている時に使うものです。デバイスツリーオーバーレイの仕組みを使い、このSubsystemのFPGA regionをオーバーレイすることによりFPGAのコンフィグレーションが行えます。
Partial Reconfigurationの対応まで考えられた仕組みですが、とりあえずここでは、FPGA全体をコンフィグレーションする場合を中心に書いております。

ご参考まで： 
[デバイスツリーについて調べてみた](https://qiita.com/eofz/items/20cfa99601756fc98905) 、
[デバイスツリー Overlay について調べてみた](https://qiita.com/eofz/items/fbc72b39c6a176995444)

# 構成要素と動作の仕組み

FPGA Subsystemは、次の3つのframeworkで構成されています。

- FPGA region
FPGA Manager, FPGA bridgeを使いFPGAのコンフィグレーションを行います。FPGAの書き換え中にCPU側に変な信号(spurious signals)が送られないようにし、安全に再コンフィグレーションが行える仕組みになっています（FPGA bridge を disable にする -> FPGA Manager でコンフィグする -> FPGA bridge を enable にする、という動作）。コンフィグレーションの動作は、オーバーレイにて指定されたpropertyによりコントロールされます。

- FPGA Manager
FPGAのコンフィグレーションコントローラ。ここにビットストリームを送り込むことでコンフィグレーションが行われる。FPGAの状態もここで管理される。

- FPGA bridge
書き換えらるFPGA部 とCPU側 を接続するバスブリッジ。実装によっては、不要な場合もあり（FPGA Managerが必要なFPGA Bridgeの動作ケアをしている場合。X系のフルFPGAコンフィグレーション）。
Partial Reconfigurationの場合は、FPGA内のソフトロジックで作られたものになるかと思います。

# FPGAコンフィグをするために必要なデバイスツリー記述
FPGA subsystemを使ってFPGAをコンフィグレーションするためのデバイスツリー記述について書きます。
## Base Tree において
少なくとも以下のnodeがBase Device tree(起動時に読み込まれるデバイスツリー）に入っている必要があります。

- FPGA Manager node
FPGAのコンフィグレーションコントローラ。compatible property は使うFPGA用のドライバようの文字列を使う: X系なら "xlnx,zynq-devcfg-1.0", I系なら"altr,socfpga-fpga-mgr"。

- FPGA region node
Base tree中の最上位のFPGA regionは、Base FPGA regionと呼ばれ、FPGA全体を表すnodeとなります。このFPGA regionのpropertyには、`fpga-mgr = <FPGA Managerへのphandle>;` が書かれていることが必要です。もし、Partial reconfigに対応するなら、Base FPGA region の子nodeとしてさらにFPGA region node を作り、Partial reconfig regionとします。 compatible property は "fpga-region"。

- FPGA bridge node 
これは必要に応じて(FPGAの種類による）。FPGA bridgeは、FPGA regionの親nodeとするか、FPGA regionのpropertyに入れることで、FPGA regionの制御対象となります。

```text:sample_base.dts(一部)
	fpga_mgr: fpga-mgr@ff706000 {
		compatible = "altr,socfpga-fpga-mgr";
        ...
	};

	fpga_bridge0: fpga-bridge@ff400000 {
		compatible = "altr,socfpga-lwhps2fpga-bridge";
        ...
	};

	base_fpga_region0: base-fpga-region0 {
		compatible = "fpga-region";
		fpga-mgr = <&fpga_mgr>;
	};

```


## Overlay において
デバイスツリー オーバーレイファイルにおいて、以下の記述をするとコンフィグレーションが実行できます。ルート直下のnodeにおいて、以下のproperty, nodeを記述します。

 * "target-path" もしくは "target" プロパティ
   オーバーレイをするターゲットのnodeとしてBase treeに存在しているFPGA region node を指定する。`target-path` ではフルパス名を指定、`target` では、phandle を指定する


 * "\_\_overlay\_\_" node
オーバレイの仕組みに従い、オーバーレイする内容（property, nodes)をこのnode下に書く。以下の内容は、この \_\_overlay\_\_ node の下に書く。

  * "firmware-name" プロパティ:
      コンフィグレーションファイル名を指定する。指定したコンフィグレーションファイルは、/lib/firmware/ に置いておく。このプロパティがあると、オーバーレイ実行時にFPGAコンフィグレーションが行われる。
なお、オーバーレイ削除時には、制御対象となっている fpga-bridge は disable される（ -> 結果 FPGA アクセスはできなくなる)。

  * "external-fpga-config" プロパティ: 
  FPGA のコンフィグレーションを行わない場合は、firmware-name プロパティを指定する代わりにこのプロパティを記述しておく。


  * \#address-cells, #size-cells, ranges プロパティ : 
  アドレスマッピングをする子nodeを持つ場合には必要。
   

  * 子nodeたち : 
  オプション。コンフィグレーションしたことにより、あらたに追加されたハードウェアのためのnodeを記述。(別のnodeの下に追加しても良い）


```text:sample_overlay.dtso(一部)
/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&base_fpga_region0>;
        ...
        __overlay__ {
            firmware-name = "soc_system.rbf"; 
            ...
        };
    };
};
```



# 参考資料
Kernel Source Tree の Documentation/devicetree/bindings/fpga/fpga-region.txt
https://www.kernel.org/doc/html/latest/driver-api/fpga/index.html
https://elinux.org/images/8/88/Fpga_and_dt.pdf
[Solution Zynq PL Programming With FPGA Manager](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841645/Solution+Zynq+PL+Programming+With+FPGA+Manager#Test+Procedure-Using+Device+Tree+Overlay:)
[Linux Kernel 4.10 でのFPGAのサポート事情](https://qiita.com/ikwzm/items/2ff7d5429da8ace7c0bd)