PetaLinux + Ubuntu 20.04でUltra96-V2のWi-Fiを使う

## 環境

- PetaLinux 2020.2
- ユーザランド: Ubuntu 20.04

## ハードウェア定義の適用

[Vivado](https://japan.xilinx.com/products/design-tools/vivado.html)で生成したハードウェアファイル(.xsa)を用意する。

```bash
$ petalinux-config --get-hw-description=<ハードウェアファイルを置いたフォルダ>
```

## ユーザーモジュールの追加

ATWILC3000 用のドライバーを用意する。

https://github.com/Avnet/u96v2-wilc-driver

適当なフォルダにクローンする

```shell
$ git clone https://github.com/Avnet/u96v2-wilc-driver.git
```

これを Petalinux に組み込む。

wilc モジュールを作成

```shell
$ cd <PetaLinuxのプロジェクトフォルダ>
$ petalinux-create -t modules -n wilc --enable
```

project-spec/meta-user/recipes-modules に wilc フォルダが生成される。

wilc フォルダ内のデフォルトの c ファイルを削除する。

u96v2-wilc-driver の「\*.c, \*.h, Makefile」を wilc フォルダの files ディレクトリにコピーする。

wilc.bb を次のように変更

```wilc.bb
SUMMARY = "Recipe for  build an external wilc Linux kernel module"
SECTION = "PETALINUX/modules"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e"

inherit module

INHIBIT_PACKAGE_STRIP = "1"

SRC_URI = "file://Makefile \
           file://host_interface.c \
           file://host_interface.h \
           file://linux_mon.c \
           file://linux_wlan.c \
           file://linux_wlan.h \
           file://sysfs.c \
           file://wilc_bt.c \
           file://wilc_debugfs.c \
           file://wilc_debugfs.h \
           file://wilc_sdio.c \
           file://wilc_spi.c \
           file://wilc_wfi_cfgoperations.c \
           file://wilc_wfi_cfgoperations.h \
           file://wilc_wfi_netdevice.h \
           file://wilc_wlan_cfg.c \
           file://wilc_wlan_cfg.h \
           file://wilc_wlan_if.h \
           file://wilc_wlan.c \
           file://wilc_wlan.h \
	   file://COPYING \
          "

S = "${WORKDIR}"

EXTRA_OEMAKE = 'CONFIG_WILC=y \
		WLAN_VENDOR_MCHP=y \
		CONFIG_WILC_SDIO=m \
		CONFIG_WILC_SPI=n \
		CONFIG_WILC1000_HW_OOB_INTR=n \
		KERNEL_SRC="${STAGING_KERNEL_DIR}" \
		O=${STAGING_KERNEL_BUILDDIR}'

# The inherit of module.bbclass will automatically name module packages with
# "kernel-module-" prefix as required by the oe-core build environment.

```

ここまで来たらビルドを行う。

```bash
$ petalinux-build -c wilc
$ petalinux-build -c kernel
$ petalinux-build -c rootfs
$ petalinux-package --boot --fsbl images/linux/zynqmp_fsbl.elf --pmufw images/linux/pmufw.elf --fpga images/linux/system.bit --u-boot --force
```

これで生成された"BOOT.BIN", "image.ub", "boot.scr"をUltraのSDのパーティション1(FAT32)に書き込む。
また、"rootfs.tar.gz"を展開し、パーティション2(Ext4)の/lib/modules/以下に書き込む。

## Firmware を Root File System にインストール

firmware は以下の URL にある。

https://github.com/linux4wilc/firmware

この firmware を /lib/firmware/mchp に置く。

```
$ mkdir /lib/firmware/mchp
$ git clone git://github.com/linux4wilc/firmware  linux4wilc-firmware
$ cp linux4wilc-firmware/*.bin /lib/firmware/mchp
```

## Ultra96-V2で動作確認

```shell
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0

$ sudo modprobe wilc_sdio

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DORMANT group default qlen 1000
    link/ether fa:f0:05:79:71:7a brd ff:ff:ff:ff:ff:ff
4: p2p0: <NO-CARRIER,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DORMANT group default qlen 1000
    link/ether f8:f0:05:79:71:7a brd ff:ff:ff:ff:ff:ff

$ sudo nmcli device wifi
$ sudo nmcli device wifi connect [SSID] password [PASSWORD]
```

Wifi にアクセスできるようになった。


## 問題点
[systemd-networkd](https://wiki.archlinux.jp/index.php/Systemd-networkd)デーモンがactive(running)状態でmodprobeすると以下のようなカーネルパニックを起こす。

```
$ sudo modprobe wilc_sdio
[  204.040760] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[  204.049545] Mem abort info:
[  204.052335]   ESR = 0x96000004
[  204.055415]   EC = 0x25: DABT (current EL), IL = 32 bits
[  204.060717]   SET = 0, FnV = 0
[  204.063755]   EA = 0, S1PTW = 0
[  204.066879] Data abort info:
[  204.069744]   ISV = 0, ISS = 0x00000004
[  204.073563]   CM = 0, WnR = 0
[  204.076518] user pgtable: 4k pages, 48-bit VAs, pgdp=00000000619b8000
[  204.082947] [0000000000000000] pgd=0000000000000000
[  204.087820] Internal error: Oops: 96000004 [#1] SMP
[  204.092687] Modules linked in: wilc_sdio(O)
[  204.103039] CPU: 3 PID: 7 Comm: kworker/u8:0 Tainted: G        W  O      5.4.0 #1
[  204.110506] Hardware name: Avnet Ultra96 Rev1 (DT)
[  204.115310] Workqueue: WILC_wq handle_get_rssi [wilc_sdio]
[  204.120786] pstate: a0000085 (NzCv daIf -PAN -UAO)
[  204.125578] pc : __wake_up_common+0x58/0x170
[  204.129837] lr : __wake_up_locked+0x18/0x20
[  204.134002] sp : ffff8000111c3ba0
[  204.137300] x29: ffff8000111c3ba0 x28: 0000000000000001
[  204.142595] x27: 0000000000000000 x26: 0000000000000000
[  204.147890] x25: 0000000000000003 x24: 0000000000000000
[  204.153185] x23: 0000000000000001 x22: 0000000000000000
[  204.158480] x21: ffff00006869d0b8 x20: 0000000000000000
[  204.163774] x19: ffff00006869d0a8 x18: 0000000000000000
[  204.169069] x17: 0000000000000000 x16: 0000000000000000
[  204.174364] x15: ffff800011093000 x14: 6974616d726f666e
[  204.179659] x13: 00000004fffffffb x12: 0000000000000001
[  204.184953] x11: 0000000000000001 x10: 0000000000000810
[  204.190248] x9 : ffff00006f04f86c x8 : fefefefefefefeff
[  204.195543] x7 : 0000000000000051 x6 : ffffffffffffffe8
[  204.200838] x5 : 0000000000000000 x4 : 0000000000000000
[  204.206132] x3 : 0000000000000000 x2 : 0000000000000001
[  204.211427] x1 : 0000000000000003 x0 : 0000000000000000
[  204.216723] Call trace:
[  204.219157]  __wake_up_common+0x58/0x170
[  204.223069]  __wake_up_locked+0x18/0x20
[  204.226891]  complete+0x64/0xa0
[  204.230027]  wilc_wlan_cfg_commit+0x98/0x278 [wilc_sdio]
[  204.235330]  cfg_get+0x74/0x160 [wilc_sdio]
[  204.239505]  wilc_send_config_pkt+0x18c/0x2f0 [wilc_sdio]
[  204.244895]  handle_get_rssi+0x6c/0xf0 [wilc_sdio]
[  204.249678]  process_one_work+0x1c4/0x338
[  204.253675]  worker_thread+0x4c/0x488
[  204.257322]  kthread+0x120/0x128
[  204.260544]  ret_from_fork+0x10/0x18
[  204.264113] Code: 54000700 a90153f3 2a0203f7 52800018 (f9400cd3)
[  204.270195] ---[ end trace d77646652d3c26ce ]---

Message from syslogd@raspberrypi at Sep 20 03:52:20 ...
 kernel:[  204.087820] Internal error: Oops: 96000004 [#1] SMP

Message from syslogd@raspberrypi at Sep 20 03:52:20 ...
 kernel:[  204.264113] Code: 54000700 a90153f3 2a0203f7 52800018 (f9400cd3)
```

systemd-networkdを止めて、modprobeし、再びデーモンをstartさせれば普通に動く。

```
$ sudo systemctl stop systemd-networkd
$ sudo modprobe wilc_sdio
$ sudo systemctl start systemd-networkd
```

Ubuntu18.04 では起こらなかった。
原因は良くわかりません。
何か分かる方がおりましたら教えて欲しいです・・・

## 参考URL
- https://qiita.com/ikwzm/items/2b50d1228282ebf150dd
- https://discuss.96boards.org/t/ultra96-wifi-issue-19-2-vitis-ubuntu-18-4-3/9709
- https://github.com/Avnet/u96v2-wilc-driver
- https://github.com/linux4wilc/firmware