注意(2021年12月1日追記)
この記事は2019年7月26日に投稿したものであり、古い内容が含まれています。
2021年12月1日に以下の記事を投稿しましたので参照してください。
はじめに
Ultra96-V2 は 2018年にリリースされた Ultra96 を更新&再構成したものです。Ultra96 の WiFi/Bluetooth モジュールは TI 社製の WL1831MOD が使われていましたが、Ultra96-V2 からは Microchip 社製の ATWILC3000 に変わりました。ATWILC3000 は比較的新しいモジュールらしく、Linux 用のデバイスドライバが Xilinx 社の提供する Linux Kernel(linux-xlnx v2019.1)には含まれていません。
この記事では、Ultra96-V 向け Debian GNU/Linux (v2019.1版) で WiFi を使うために ATWILC3000 の Linux Driver を組み込んだときの話をします。
デバイスドライバのリポジトリ
Ultra96-V2 では ATWILC3000 の Linux Driver は Avnet が提供しているものを使います。
このリポジトリの Readme.md に記載されている注意事項をよくみてください。
Linux Kernel のソースコードに追加する
上記 URL からダウンロードしたファイルを drivers/staging にコピーします。
shell$ git clone https://github.com/Avnet/u96v2-wilc-driver.git
shell$ git clone --depth 1 -b xilinx-v2019.1 https://github.com/Xilinx/linux-xlnx.git linux-xlnx-v2019.1-zynqmp-fpga
shell$ cd linux-xlnx-v2019.1-zynqmp-fpga
shell$ cp -r ../u96v2-wilc-driver/wilc drivers/staging/wilc3000/
drivers/staging/Kconfig と drivers/staging/Makefile に wilc3000 を追加します。
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b66275191..05a605794 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -96,6 +96,8 @@ source "drivers/staging/fsl-dpaa2/Kconfig"
source "drivers/staging/wilc1000/Kconfig"
+source "drivers/staging/wilc3000/Kconfig"
+
source "drivers/staging/most/Kconfig"
source "drivers/staging/ks7010/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 9ee2eff76..0ff264844 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_XILINX_FCLK) += fclk/
obj-$(CONFIG_FB_TFT) += fbtft/
obj-$(CONFIG_FSL_DPAA2) += fsl-dpaa2/
obj-$(CONFIG_WILC1000) += wilc1000/
+obj-$(CONFIG_WILC) += wilc3000/
obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_KS7010) += ks7010/
obj-$(CONFIG_GREYBUS) += greybus/
Linux Kernel のイメージに組み込む
Ultra96-V2 では ATWILC3000 は ZynqMP の sdio1 に接続しています。ATWILC3000 を SDIO から制御するためのデバイスドライバは CONFIG_WILC_SDIO
です。arch/arm64/configs/xilinx_zynqmp_defconfig に CONFIG_WILC_SDIO=y
を追加します。ここではモジュールではなく Linux Kernel Image に組み込んでしまうために =m
でなく =y
を指定しています。
diff --git a/arch/arm64/configs/xilinx_zynqmp_defconfig b/arch/arm64/configs/xilinx_zynqmp_defconfig
index b74c3b14c..da0a8b22e 100644
--- a/arch/arm64/configs/xilinx_zynqmp_defconfig
+++ b/arch/arm64/configs/xilinx_zynqmp_defconfig
@@ -183,6 +183,7 @@ CONFIG_USB_USBNET=y
CONFIG_WL18XX=y
CONFIG_WLCORE_SPI=y
CONFIG_WLCORE_SDIO=y
+CONFIG_WILC_SDIO=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_GPIO_POLLED=y
Device Tree に組み込む
Ultra96-V2 では ATWILC3000 は ZynqMP の sdio1 に接続しています。したがって Device Tree の sdio1 のノードに追加します。
&sdhci1 {
status = "okay";
bus-width = <0x4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sdhci1_default>;
xlnx,mio_bank = <0>;
non-removable;
disable-wp;
#address-cells = <1>;
#size-cells = <0>;
wlcore: wilc_sdio@0 {
compatible = "microchip,wilc1000", "microchip,wilc3000";
irq-gpios = <&gpio 76 GPIO_ACTIVE_HIGH>; /* MIO76 WLAN_IRQ 1V8 */
reset-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; /* MIO7 RADIO_RST_N 1V8 */
chip_en-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; /* MIO8 RADIO_EN 1V8 */
status = "okay";
reg = <0>;
bus-width = <4>;
};
};
compatible
プロパティには "microchip,wilc1000", "microchip,wilc3000" を指定します。
reset-gpios
プロパティには <&gpio 7 GPIO_ACTIVE_HIGH>
を指定します。Ultra96-V2 では ATWILC3000 の RESETN ピンは ZynqMP の MIO7 に接続されています。RESETNの最後のNはNegative(Low Active)を意味するのですが、ここでは GPIO_ACTIVE_HIGH を指定しなければなりません。紛らわしいので注意してください。
chip_en-gpios
プロパティには <&gpio 8 GPIO_ACTIVE_HIGH>
を指定します。Ultra96-V2 では ATWILC3000 の CHIP_EN ピンは ZynqMP の MIO8 に接続されています。
Firmware を Root File System にインストールしておく
ATWILC3000 の Linux Driver は、起動時に firmware を ATWILC3000 にロードします。firmware は以下の URL にあります。
この firmware は /lib/firmware/mchp になければなりません。Root File System を作る時にインストールしておくか、後で追加してください。ネットワークが使えないと後から追加するのにも不便なので、あらかじめインストールしておいたほうが良いでしょう。
debian10-rootfs# mkdir /lib/firmware/mchp
debian10-rootfs# git clone git://github.com/linux4wilc/firmware linux4wilc-firmware
debian10-rootfs# cp linux4wilc-firmware/*.bin /lib/firmware/mchp
debian10-rootfs# rm -rf linux4wilc-firmware
苦労した点
当初、筆者は以下の URL で示す Linux Driver を使って WiFi を動かそうと試みていました。
このリポジトリは ATWILC3000 の製造元である Microchip がオフィシャルに提供しているものです。製造元が提供しているのだから大丈夫だろうと思っていたのですが、どうにも動きません。
動かなかった時のログ(長いので折りたたみ)
[ 5.408188] mmc1: new high speed SDIO card at address 0001
[ 5.413983] (unnamed net_device) (uninitialized): INFO [wilc_create_wiphy]Registering wifi device
[ 5.422852] (unnamed net_device) (uninitialized): INFO [wilc_wfi_cfg_alloc]Allocating wireless device
[ 5.432814] (unnamed net_device) (uninitialized): INFO [wilc_create_wiphy]Registering wifi device
[ 5.441679] (unnamed net_device) (uninitialized): INFO [wilc_wfi_cfg_alloc]Allocating wireless device
[ 5.451387] wifi_pm : 0
[ 5.453869] wilc_sdio mmc1:0001:1: succesfully got gpio_reset
[ 5.459707] wilc_sdio mmc1:0001:1: succesfully got gpio_chip_en
[ 5.465710] wifi_pm : 1
[ 5.468159] wilc_sdio mmc1:0001:1: succesfully got gpio_reset
[ 5.473992] wilc_sdio mmc1:0001:1: succesfully got gpio_chip_en
[ 5.485074] usb 1-1: new high-speed USB device number 2 using xhci-hcd
[ 5.491649] wilc_sdio mmc1:0001:1: Driver Initializing success
:
:
:
[ 8.490581] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.501114] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.510108] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.520636] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.529625] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.540145] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.549131] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.559647] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.568635] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.579155] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.588150] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.598669] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.607651] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.618168] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.627154] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.637671] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.646662] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.657175] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.666164] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.676679] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.685666] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.696186] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.705179] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.715697] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.724683] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.735200] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.744187] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.754704] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.763692] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.774208] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.783196] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.793712] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.802700] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 1
[ 8.813218] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 8.822286] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mac_open]MAC OPEN[(____ptrval____)] wlan0
[ 8.830813] WILC POWER UP
[ 8.833425] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_init_host_int]Host[(____ptrval____)][(____ptrval____)]
[ 8.843085] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mac_open]*** re-init ***
[ 8.850132] wilc_sdio mmc1:0001:1 wlan0: INFO [wlan_init_locks]Initializing Locks ...
[ 8.857967] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_wlan_init]Initializing WILC_Wlan
[ 8.865714] wilc_sdio mmc1:0001:1: SDIO speed: 50000000
[ 8.871107] wilc_sdio mmc1:0001:1: wilc_sdio_cmd52..failed, err(-110)
[ 8.877546] wilc_sdio mmc1:0001:1: Fail cmd 52, enable csa...
[ 8.883295] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_wlan_initialize:1123] Initializing WILC_Wlan FAILED
[ 8.892606] wilc_sdio mmc1:0001:1 wlan0: INFO [wlan_deinit_locks]De-Initializing Locks
[ 8.900518] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_wlan_initialize:1204] WLAN initialization FAILED
[ 8.909565] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_mac_open:1248] Failed to initialize wilc
[ 8.917936] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_send_config_pkt:1903] Set Timed out
[ 8.925851] wilc_sdio mmc1:0001:1 wlan0: ERR [handle_set_wfi_drv_handler:433] Failed to set driver handler
[ 8.936084] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mac_open]MAC OPEN[(____ptrval____)] wlan0
[ 8.944616] power up request for already powered up source Wifi
[ 8.950538] Device already up. request source is Wifi
[ 8.955592] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_init_host_int]Host[(____ptrval____)][(____ptrval____)]
[ 8.965250] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mac_open]*** re-init ***
[ 8.972297] wilc_sdio mmc1:0001:1 wlan0: INFO [wlan_init_locks]Initializing Locks ...
[ 8.980124] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_wlan_init]Initializing WILC_Wlan
[ 8.987870] wilc_sdio mmc1:0001:1: SDIO speed: 50000000
[ 8.993235] wilc_sdio mmc1:0001:1: wilc_sdio_cmd52..failed, err(-110)
[ 8.999683] wilc_sdio mmc1:0001:1: Fail cmd 52, enable csa...
[ 9.005427] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_wlan_initialize:1123] Initializing WILC_Wlan FAILED
[ 9.014733] wilc_sdio mmc1:0001:1 wlan0: INFO [wlan_deinit_locks]De-Initializing Locks
[ 9.022645] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_wlan_initialize:1204] WLAN initialization FAILED
[ 9.031684] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_mac_open:1248] Failed to initialize wilc
[ 9.040050] wilc_sdio mmc1:0001:1 wlan0: ERR [wilc_send_config_pkt:1903] Set Timed out
[ 9.047969] wilc_sdio mmc1:0001:1 wlan0: ERR [handle_set_wfi_drv_handler:433] Failed to set driver handler
[ 9.057746] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.068297] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.077282] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.087835] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.096816] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.107359] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116350] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116356] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116361] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116365] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116370] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116375] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116380] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116384] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116389] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116394] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116399] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116403] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116408] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116413] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116418] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116422] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116427] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116432] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116437] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116441] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116447] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116450] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116455] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116459] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116464] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116468] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[ 9.116472] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Frame registering Frame Type: d0: Boolean: 0
[ 9.116476] wilc_sdio mmc1:0001:1 wlan0: INFO [wilc_mgmt_frame_register]Return since mac is closed
[FAILED] Failed to start Raise network interfaces.
どうも ATWILC3000 が動いていない(反応していない)かんじです。この手の問題は、たいていパワーオンシーケンスが上手くいっていないのが原因なことが多いのでそこを重点的にデバッグしたのですが、どうにもうまくいきませンでした。
結局、デバイスドライバを Microchip 純正から Avnet が Ultra96-V2 用にカスタマイズしたものに替えたらあっさり動きました。
ちなみに Microchip 純正のパワーオンは次のようになっています。
static void wilc_wlan_power(struct wilc *wilc, int power)
{
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_chip_en;
pr_info("wifi_pm : %d\n", power);
:
(中略)
:
if (power) {
gpiod_direction_output(gpio_chip_en, 1);
mdelay(5);
gpiod_direction_output(gpio_reset, 1);
} else {
gpiod_direction_output(gpio_reset, 0);
gpiod_direction_output(gpio_chip_en, 0);
}
gpiod_put(gpio_chip_en);
gpiod_put(gpio_reset);
}
Avnet 製 Linux Driver のパワーオンは次のようになっています。
static void wilc_wlan_power(struct wilc *wilc, int power)
{
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_chip_en;
pr_info("wifi_pm : %d\n", power);
// pr_info("WILC DRIVER SETUP TO NOT TOUCH CHIP_EN and RESETN!\n");
return ;
:
(中略)
:
}
なんとパワーオンシーケンスがまるごとバッサリ削除されていました。いいのかなこれで。。。