はじめに
Zynq UltraScale+ MPSoC(ZynqMP) の PS-PL Interface は Fig.1 のように12本あります。そのうちの10本はデータのビット幅を 32bit、64bit、128bit から選択出来ます。
Fig.1 ZynqMP の PS-PL Interface
これら AXI I/Fのデータのビット幅の変更は、通常、PL 側をビルドするときに指定して、それに対応した FSBL(First Stage Boot Loader) を使ってブートすることで行われます。しかし、『Ultra96 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供』(@Qiita)で紹介したような汎用の FSBL を使って Linux を起動してから Device Tree Overlay を使って PL 側のコンフィギュレーションを行うような場合には使えません。
この記事では、Device Tree を使って AXI I/F のデータのビット幅を変更する方法を紹介します。
Xilinx の AFI デバイスドライバ
実は、Xilinx が提供している Linux のディストリビューション(linux-xlnx)には、ZynqMP の AXI I/F のデータ幅を変更するデバイスドライバがすでに存在します。名前は xilinx-afi です。
ソースコードは drivers/fpga/xilinx-afi.c です。menu config などで、CONFIG_XILINX_AFI=y にすることで、このドライバが Linux Kernel に組み込まれます。 『Ultra96 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供』(@Qiita)で紹介した Linux Kernel にはすでにこのデバイスドライバが組み込まれています。
xilinx-afi ドライバを使って AXI のデータ幅を設定するには、device tree で次のように指定します。
afi0: afi0 {
compatible = "xlnx,afi-fpga";
config-afi = <0 0>, <1 0>;
};
device tree にどのような記述をするかは、linux-xlnk の Documentation/devicetree/bindings/fpga/xlnx,afi-fpga.txt に説明があります。以下に引用します。
Xilinx ZynqMp AFI interface Manager
The Zynq UltraScale+ MPSoC Processing System core provides access from PL
masters to PS internal peripherals, and memory through AXI FIFO interface
(AFI) interfaces.
Required properties:
-compatible: Should contain "xlnx,afi-fpga"
-config-afi: Pairs of <regid value >
The possible values of regid and values are
regid: Regids of the register to be written possible values
0- AFIFM0_RDCTRL
1- AFIFM0_WRCTRL
2- AFIFM1_RDCTRL
3- AFIFM1_WRCTRL
4- AFIFM2_RDCTRL
5- AFIFM2_WRCTRL
6- AFIFM3_RDCTRL
7- AFIFM3_WRCTRL
8- AFIFM4_RDCTRL
9- AFIFM4_WRCTRL
10- AFIFM5_RDCTRL
11- AFIFM5_WRCTRL
12- AFIFM6_RDCTRL
13- AFIFM6_WRCTRL
14- AFIFS
15- AFIFS_SS2
- value: Array of values to be written.
for FM0_RDCTRL(0) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM0_WRCTRL(1) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM1_RDCTRL(2) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM1_WRCTRL(3) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM2_RDCTRL(4) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM2_WRCTRL(5) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM3_RDCTRL(6) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM3_WRCTRL(7) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM4_RDCTRL(8) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM4_WRCTRL(9) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM5_RDCTRL(10) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM5_WRCTRL(11) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM6_RDCTRL(12) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for FM6_WRCTRL(13) the valid values-fabric width 2: 32-bit,1 : 64-bit ,0: 128-bit enabled
for AFI_FA(14)
dw_ss1_sel bits (11:10)
dw_ss0_sel bits (9:8)
0x0: 32-bit AXI data width),
0x1: 64-bit AXI data width,
0x2: 128-bit AXI data
All other bits are 0 write ignored.
for AFI_FA(15) selects for ss2AXI data width valid values
0x000: 32-bit AXI data width),
0x100: 64-bit AXI data width,
0x200: 128-bit AXI data
Example:
afi0: afi0 {
compatible = "xlnx,afi-fpga";
config-afi = <0 2>, <1 1>, <2 1>;
};
Xilinx の AFI デバイスツリーのregid とレジスタの対応
前節の Documentation/devicetree/bindings/fpga/xlnx,afi-fpga.txt が分かりづらいのは、regid の説明です。これでは regid が何を意味するのかさっぱり分かりません。そこで Linux Kernel や Firmware のソースコードを追って調べてみました。その際に判明した、regid に対応する ZynqMP Register Module と AXI I/F を次の表に示します。
regid | Name | Register | AXI I/F | value | |
Module | Register | ||||
0 | AFIFM0_RDCTRL | AFIFM0 | RDCTRL | S_AXI_HPC0_FPD | 2'b10: 32-bit 2'b01: 64-bit 2'b00: 128-bit |
1 | AFIFM0_WRCTRL | WRCTRL | |||
2 | AFIFM1_RDCTRL | AFIFM1 | RDCTRL | S_AXI_HPC1_FPD | |
3 | AFIFM1_WRCTRL | WRCTRL | |||
4 | AFIFM2_RDCTRL | AFIFM2 | RDCTRL | S_AXI_HP0_FPD | |
5 | AFIFM2_WRCTRL | WRCTRL | |||
6 | AFIFM3_RDCTRL | AFIFM3 | RDCTRL | S_AXI_HP1_FPD | |
7 | AFIFM3_WRCTRL | WRCTRL | |||
8 | AFIFM4_RDCTRL | AFIFM4 | RDCTRL | S_AXI_HP2_FPD | |
9 | AFIFM4_WRCTRL | WRCTRL | |||
10 | AFIFM5_RDCTRL | AFIFM5 | RDCTRL | S_AXI_HP3_FPD | |
11 | AFIFM5_WRCTRL | WRCTRL | |||
12 | AFIFM6_RDCTRL | AFIFM6 | RDCTRL | S_AXI_LPD | |
13 | AFIFM6_WRCTRL | WRCTRL | |||
14 | AFIFS | FPD_SLCR | afi_fs | SS0=M_AXI_HPM0_FPD SS1=M_AXI_HPM1_FPD |
SS0_SEL bits[9:8] SS1_SEL bits[11:10] 2'b00: 32-bit 2'b01: 64-bit 2'b10: 128-bit |
15 | AFIFS_SS2 | LPD_SLCR | afi_fs | SS2=M_AXI_HPM0_LPD | SS2_SEL bits[9:8] 2'b00: 32-bit 2'b01: 64-bit 2'b10: 128-bit |
各レジスタの詳細は『Zynq UltraScale+ Devices Register Reference』を参照してください。この資料は以下の URL で示すページが見やすくて良いと思います。
次に device tree overlay を使ってPL のコンフィギュレーションと同時に S_AXI_HPC0_FPD と M_AXI_HPM0_FPD のビット幅を128bit に設定する例を示します。
/dts-v1/; /plugin/;
/ {
fragment@0 {
target-path = "/fpga-full";
__overlay__ {
firmware-name = "design_1_wrapper.bin";
};
};
fragment@1 {
target-path = "/amba_pl@0";
__overlay__ {
afi0 {
compatible = "xlnx,afi-fpga";
config-afi = <0 0>, <1 0>, <14 0x200>;
};
};
};
};