UltraZed で SD Card が書き込み不可になってしまう問題







# はじめに



## UltraZed とは


UltraZed-EG スターターキットは Xilinx 社の Zynq UltraScale+ MPSoC(XCZU3EG-SFVA625) を搭載した UltraZed-EG-SOM と UltraZed IOキャリアカードで構成された Avnet 社のキットです。詳細は次の URL を参照してください。

 ・ [UltraZed-EG スターターキット](https://www.avnet.co.jp/kits/avnet/UltraZed-EG-STA.aspx)



この記事では、UltraZed で SD Card を使おうとすると、ライトプロテクションがかかってて書き込み不可になってしまう問題の対処方法を示します。




# 症状


UltaraZed でSD Card を使おうとすると、ライトプロテクションがかかってて書き込み不可になってしまいます。

そのため、SD Card のパーティションに Linux の Root FS を置いてマウントしようとすると、マウント出来ずにカーネルがパニックを起こして停止します。これは  Linux が Root FS をマウントするためには書き込み可でなければならないからです。下記にマウントに失敗した時の Linux Kernel のログ(抜粋)を示します。mmcblk1 の認識時に "mmcblk1: mmc1:aaaa SL08G 7.40 GiB (ro)" となっている点に注意してください。"(ro)" は Ready Only を意味します。書き込み可ならば "(ro)" はつきません。


```Shell
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.9.0-xilinx-v2017.2 (vk@ubuntu) (gcc version 6.2.1 20161016 (Linaro GCC 6.2-2016.11) ) #1 SMP Sun Oct 15 23:58:04 PDT 2017
	:
	(中略)
	:
[    2.970474] mmc1: new high speed SDHC card at address aaaa
[    2.970690] mmcblk1: mmc1:aaaa SL08G 7.40 GiB (ro)
[    2.971557]  mmcblk1: p1 p2
	:
	(中略)
	:
[    3.285624] VFS: Cannot open root device "mmcblk0p2" or unknown-block(179,2): error -6
[    3.293489] Please append a correct "root=" boot option; here are the available partitions:
[    3.301818] 0100           65536 ram0 [    3.305347]  (driver?)
[    3.307699] 0101           65536 ram1 [    3.311566]  (driver?)
[    3.313921] 0102           65536 ram2 [    3.317474]  (driver?)
[    3.319824] 0103           65536 ram3 [    3.323371]  (driver?)
[    3.325727] 0104           65536 ram4 [    3.329278]  (driver?)
[    3.331624] 0105           65536 ram5 [    3.335181]  (driver?)
[    3.337531] 0106           65536 ram6 [    3.341083]  (driver?)
[    3.343429] 0107           65536 ram7 [    3.346985]  (driver?)
[    3.349337] 0108           65536 ram8 [    3.352889]  (driver?)
[    3.355234] 0109           65536 ram9 [    3.358791]  (driver?)
[    3.361141] 010a           65536 ram10 [    3.364780]  (driver?)
[    3.367126] 010b           65536 ram11 [    3.371394]  (driver?)
[    3.373746] 010c           65536 ram12 [    3.377383]  (driver?)
[    3.379735] 010d           65536 ram13 [    3.383368]  (driver?)
[    3.385723] 010e           65536 ram14 [    3.389362]  (driver?)
[    3.391712] 010f           65536 ram15 [    3.395346]  (driver?)
[    3.397706] b300         7438336 mmcblk0 [    3.401514]  driver: mmcblk
[    3.404300]   b301          250040 mmcblk0p1 00000000-01[    3.409413] 
[    3.410891] b318            4096 mmcblk0rpmb [    3.415056]  (driver?)
[    3.417406] b310           16384 mmcblk0boot1 [    3.421652]  (driver?)
[    3.424003] b308           16384 mmcblk0boot0 [    3.428249]  (driver?)
[    3.430595] b320         7761920 mmcblk1 [    3.434411]  driver: mmcblk
[    3.437198]   b321          524288 mmcblk1p1 d1fdbe62-01[    3.442310] 
[    3.443794]   b322         7233536 mmcblk1p2 d1fdbe62-02[    3.448907] 
[    3.450385] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
[    3.458815] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.9.0-xilinx-v2017.2 #1
[    3.465923] Hardware name: xlnx,zynqmp (DT)
[    3.470088] Call trace:
[    3.472526] [<ffffff8008088138>] dump_backtrace+0x0/0x198
[    3.477905] [<ffffff80080882e4>] show_stack+0x14/0x20
[    3.482939] [<ffffff80083de514>] dump_stack+0x94/0xb8
[    3.487974] [<ffffff800812e980>] panic+0x114/0x25c
[    3.492747] [<ffffff8008c110e8>] mount_block_root+0x198/0x270
[    3.498475] [<ffffff8008c113f8>] mount_root+0x11c/0x134
[    3.503682] [<ffffff8008c1157c>] prepare_namespace+0x16c/0x1b4
[    3.509499] [<ffffff8008c10d14>] kernel_init_freeable+0x1c0/0x1e0
[    3.515575] [<ffffff80089359a0>] kernel_init+0x10/0x100
[    3.520782] [<ffffff8008082e80>] ret_from_fork+0x10/0x50
[    3.526075] SMP: stopping secondary CPUs
[    3.529982] Kernel Offset: disabled
[    3.533452] Memory Limit: none
[    3.536493] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
```



# 原因


ZynqMP の SDIO I/F には WP(Write Protection) pin があります。この入力ピンを適切に設定していないと、何故か ZynqMP は Write Protection 状態と認識してしまいます。




![Fig.1 ZynqMP Re-customize IP](https://qiita-image-store.s3.amazonaws.com/0/24981/209b2390-82df-432d-28ae-6478c38aaec5.png  "Fig.1 ZynqMP Re-customize IP")

Fig.1 ZynqMP Re-customize IP

<br />

この UI はちょっと紛らわしくて、普通は WP にチェックを入れないと Write Protection にならないと勘違いしてしまいますが、実はこの UI は単にピンの設定を行っているだけで、ピンの設定をしないとどうなるかは関係ないのです。で、何故か ZynqMP はこのピンを設定していないとWrite Protection 状態と認識してしまうのです。

Write Protection にならないようにするには、このピンを設定した上で MIO 44 を Low に接続するか、もしくはソフトウェアの方で Write Protection を無効にしなければなりません。

UltraZed ではどうなっているかと言うと、仕様上は次のようになっています。


![Fig.2 UltraZed I/O Carrie Card User Guide](https://qiita-image-store.s3.amazonaws.com/0/24981/26b9533a-afaa-5527-ffff-91284416d8a1.png "Fig.2 UltraZed I/O Carrie Card User Guide")

Fig.2 UltraZed I/O Carrie Card User Guide

<br />



この図を見るかぎり、MIO44 ピンの入力は JP2 をオープンしている時は Low Level に、JP2 をクローズするとHigh Level になります。通常はJP2はオープンになっているので MIO44ピンの入力は  Low Level となり問題ないと思われます。

ところが、Avnet が提供している UltraZed-EG-IOCC のボード設定ファイルを使って FPGA のデザインを行うと、何故か WP にチェックが入っていません。


![Fig.3 ZynqMP Re-customize IP (ultrazed-3eg-iocc 1.0)](https://qiita-image-store.s3.amazonaws.com/0/24981/94642801-9eff-d116-4686-decc0caa9df9.png "Fig.3 ZynqMP Re-customize IP (ultrazed-3eg-iocc 1.0)")

Fig.3 ZynqMP Re-customize IP (ultrazed-3eg-iocc 1.0)

<br />

このボード設定ファイルを使って FPGA をデザインした場合、SD-Card が書き込み不可になってしまいます。


# 対処方法



## その１ ボード設定ファイルを修正する


もともとボード設定ファイルに問題があるのだから、ボード設定ファイルを修正するのが基本的な解決方法です。Avnet が提供するボード設定ファイルは次のURL にあります。

  * [https://github.com/Avnet/bdf](https://github.com/Avnet/bdf)

このボード設定ファイル群は、 Vivado をインストールしたディレクトリの下のdata/boar/board_files に置かれます。その中の ultrazed_3eg_iocc/1.0/preset.xml に次の行を追加します。


```Shell:ultrazed_3eg_iocc/1.0/preset.xml 
<user_parameter name = "CONFIG.PSU__SD1__GRP_WP__ENABLE" value = "1" />
<user_parameter name = "CONFIG.PSU__SD1__GRP_WP__IO" value = "MIO 44" />
 
```


ただしこの方法は当然すでに作ってしまった FPGA デザインに関しては有効ではありません。例えばAvnet が提供しているチュートリアル用デザインなんかを再配置配線せずに使う場合はどうにもなりません。




## その２ Vivado の Custmize IP で WP をチェックする


ボードファイルを修正するのはちょっと抵抗があるという人は、FPGA をデザインするときに忘れずに WP にチェックを入れてください。


![Fig.4 ZynqMP Re-customize IP](https://qiita-image-store.s3.amazonaws.com/0/24981/209b2390-82df-432d-28ae-6478c38aaec5.png "Fig.4 ZynqMP Re-customize IP")

Fig.4 ZynqMP Re-customize IP

<br />




## その３ Linux のデバイスツリーで Write Protection を無効にする


これは Linux 限定ですが、デバイスツリーで SDIO  の Write Protection を強制的に無効にすることが出来ます。この方法なら FPGA の再デザインは必要ありません。デバイスツリーの sdhci1 の記述を探し出して、disable-wp プロパティを追加します。




```devicetree
/dts-v1/;
/ {
	:
	(中略)
	:
		sdhci@ff170000 {
			u-boot,dm-pre-reloc;
			compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
			status = "okay";
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x31 0x4>;
			reg = <0x0 0xff170000 0x0 0x1000>;
			clock-names = "clk_xin", "clk_ahb";
			xlnx,device_id = <0x1>;
			#stream-id-cells = <0x1>;
			iommus = <0xe 0x871>;
			power-domains = <0x23>;
			nvmem-cells = <0x1f>;
			nvmem-cell-names = "soc_revision";
			clocks = <0x3 0x37 0x3 0x1f>;
			clock-frequency = <0xbebba30>;
			xlnx,mio_bank = <0x1>;
			max-frequency = <0x2faf080>;
			no-1-8-v;
			disable-wp;
			linux,phandle = <0x69>;
			phandle = <0x69>;
		};
	:
	(中略)
	:
};
```



# 参考


この問題は Xilinx のフォーラムでも話題となっていて、Linux のデバイスツリーを修正する方法が提案されています。

  *  [Beginners problems with Ultrazed-eg](https://forums.xilinx.com/t5/Embedded-Development-Tools/Beginners-problems-with-Ultrazed-eg/td-p/800802)



Avnet のフォーラムでもスレッドがありますが、このスレッドでも上の Xilinx のフォーラムを解決方法として提案されていて解決済みとなっています。

  *  [Issues with loading rootfs from SD Card](http://zedboard.org/content/issues-loading-rootfs-sd-card)



筆者はボードファイルの問題ではないかと Avnet のフォーラムにスレッドを立てましたが、UltraZed IO Carrier Card は WP pin を使っていないからボード設定ファイルを変更する必要は無いと言われてしまいました。どっちが正しいのでしょうか？

  *  [Since SD1/WP of board definition file is not set to MIO44, SD card is write protected.](http://zedboard.org/content/sd1wp-board-definition-file-not-set-mio44-sd-card-write-protected)



UltraZed に関する資料は次の通りです。

  *  [UltraZed-EG スターターキット](https://www.avnet.co.jp/kits/avnet/UltraZed-EG-STA.aspx)
  *  [https://github.com/Avnet/bdf](https://github.com/Avnet/bdf)
  *  [UltraZed I/O Carrier Card User Guide](http://zedboard.org/sites/default/files/documentations/UltraZed%20IOCC-UG%201v1-1.pdf)