Loading and using the WFx Kernel Module
At this point you should have :
- Downloaded Kernel headers matching your running platform
- Downloaded Kernel sources matching your running platform
- Built the WFX kernel module
wfx.ko
- Installed the WFK kernel module on the system
Loading the kernel module
This step is straightforward if all previously happened successfully . Simply used modprobe wfx
as super user:
pi@raspberrypi:~/wfx_driver/linux-stable/drivers/net/wireless/silabs/wfx $ sudo modprobe wfx
To verify the module is loaded just use lsmod this way : lsmod | grep wfx
Output should be :
pi@raspberrypi:~/wfx_driver/linux-stable/drivers/net/wireless/silabs/wfx $ lsmod | grep wfx
wfx 151552 0
mac80211 974848 1 wfx
cfg80211 925696 3 wfx,brcmfmac,mac80211
Using the kernel module to enable the WF200
Enabling module load at boot time
This step is distribution dependent. As we are running RaspiOS, we will be using systemd and its ability to load mosules at boot time.
Edit /etc/modules-load.d/modules.conf
as super user and add wfx
at the end of the file as below:
pi@raspberrypi:~ $ cat /etc/modules-load.d/modules.conf
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-dev
wfx
Once done just reboot : sudo reboot
Just check the module is now loaded upon startup by calling lsmod | grep wfx
:
pi@raspberrypi:~ $ lsmod | grep wfx
wfx 151552 0
mac80211 974848 1 wfx
cfg80211 925696 2 wfx,mac80211
You can check if the driver is detecting the card properly by using dmesg | grep wfx
:
pi@raspberrypi:~ $ dmesg | grep wfx
[ 6.687705] wfx: loading out-of-tree module taints kernel.
[ 6.740432] wfx-sdio mmc1:37dd:1: no compatible device found in DT
Disabling embedded 2.4GHz radios
On a Raspberry Pi we will start by disabling the onboard WiFi chipset. For test purposes, to avoid any other interference with 2.4GHz activity also disable Bluetooth.
To do so, append the 2 lines below at the end of /boot/config.txt
dtoverlay=disable-wifi
dtoverlay=disable-bt
Declaring the module in the device tree
Certain kernel version might allow the use of undeclared devices in th device tree DT
Often (if not everytime) this will prevent the wfx module from connecting to the WF200 : wfx-sdio mmc2:0001:1: no compatible device found in DT
Fortunately Silicon Labs provides a device tree source in their WFx200 tools' repo
To use it download it in your wfx workspace using wget https://raw.githubusercontent.com/SiliconLabs/wfx-linux-tools/SD5/overlays/wfx-sdio-overlay.dts
THIS CANNOT BE USED AS IS
When using the mainstream kernel module, compatible should be set to compatible = "silabs,wf200";
The wfx-linux-tools .dts file uses compatible = "silabs,wfx-sdio";
which will prevent SDIO detection to occur
Once edited, we will use dtc (Device Tree Compiler) to compile this into a .dtbo (Device Tree Blob) file using dtc -@ -I dts -O dtb -o wfx-sdio.dtbo wfx-sdio-overlay.dts
.
dtc is available from apt :apt install device-tree-compiler
This should create a new file named wfx-sdio.dtbo. Simply copy this into /boot/overlays
as super user:
cp wfx-sdio.dtbo /boot/overlays/
Finally enable the overlay by adding dtoverlay=wfx-sdio
to /boot/config.txt
:
dtoverlay=wfx-sdio,sdio_overclock=25
Note : Silicon Labs has also added a power sequence in the ovrelay source. It is recomended to use it as well
Note 2 : Silicon Labs' DTS will enable sdio on the RPi and disable the one used by the brcm-wifi
Note 3: The Silicon Labs Hat has a hardware limitation preventing it work faster than 25MHz, pass along sdio_overclock=25 to the dtoverlay config
Checking sdio on the Raspberry Pi hardware
To check that SDIO is up and running, start by pushing device tree contents into a file named device_tree.out
:
dtc --sort -I fs -O dts /sys/firmware/devicetree/base > device_tree.out
Then look for sdio_pins
into it grep -A 5 sdio_pins device_tree.out
and check the pinout:
pi@raspberrypi:~ $ grep -A 5 sdio_pins device_tree.out
sdio_pins = "/soc/gpio@7e200000/sdio_pins";
smi = "/soc/smi@7e600000";
soc = "/soc";
sound = "/soc/sound";
spi = "/soc/spi@7e204000";
spi0 = "/soc/spi@7e204000";
--
sdio_pins {
brcm,function = <0x07>;
brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>;
brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>;
phandle = <0x97>;
};
Finally identify the mmc interface used for sdio by rebooting and issuing dmesg | grep 'new high speed SDIO'
:
pi@raspberrypi:~ $ dmesg | grep 'new high speed SDIO'
[ 3.148442] mmc2: new high speed SDIO card at address 0001
Check that everything is fine by issuing cat /sys/kernel/debug/mmc2/ios
:
pi@raspberrypi:~ $ sudo cat /sys/kernel/debug/mmc2/ios
clock: 50000000 Hz
actual clock: 25000000 Hz
vdd: 21 (3.3 ~ 3.4 V)
bus mode: 2 (push-pull)
chip select: 0 (don't care)
power mode: 2 (on)
bus width: 2 (4 bits)
timing spec: 2 (sd high-speed)
signal voltage: 0 (3.30 V)
driver type: 0 (driver type B)
Downloading and setting up WFx200 SEC firmware
WFx200 has no firmware and is required to be flashed by the wfx driver upon startup
By default the driver will look in /lib/firmware/wfx/wfm_wf200.sec
To download the latest version start by cloning the wfx-firmare repo :
cd ~/wfx_driver
git clone https://github.com/SiliconLabs/wfx-firmware.git
cd wfx-firmware
Once done copy the .sec file provided in the destination directory as super user:
cp wfm_wf200_C0.sec /lib/firmware/wfx/
wget https://github.com/SiliconLabs/wfx-firmware/raw/FW3.17.0/wfm_wf200_C0.sec
Generating and setting up the WFx200 PDS file
WFx200 also needs a PDS (Platform Data Set) file to be fed to the chipset
By default the driver will look in /lib/firmware/wfx/wf200.pds
*** IMPORTANT ** When using mainsteam kernel, the PDS file format is different:
Mainstream didn't allow Silicon Labs to publish with their initial format. Silicon Labs had to change to a tlv format (type/length/value), which needs to be generated from a new version of pds_compress, one that supports the tlv format.
Get the latest pds_compress script :
wget https://raw.githubusercontent.com/SiliconLabs/wfx-linux-tools/master/pds_compress
Add execute permissions to the script :
sudo chmod +x pds_compress
Get the PDS of your choice. I wil use the one dedicated to BRD8022 :
wget https://raw.githubusercontent.com/SiliconLabs/wfx-pds/API3.0/BRD8022A_Rev_A06.pds.in
Get the definitions.in that match your firmware version. In our case v3.17:
wget https://raw.githubusercontent.com/SiliconLabs/wfx-firmware/FW3.17.0/PDS/definitions.in
Modify the PDS file by commenting out 2 lines :
// FRONT_END_LOSS_CORRECTION_QDB
// RSSI_CORRECTION
And run the script :
pds_compress -l BRD8022A_Rev_A06.pds.in wf200.pds
Once done copy the .pds file provided in the destination directory as super user:
cp wf200.pds /lib/firmware/wfx/wf200.pds
Reboot and start using the WFx200
lab@raspberrypi:~ $ dmesg | grep wfx
[ 6.836028] wfx: loading out-of-tree module taints kernel.
[ 6.978024] wfx-sdio mmc3:0001:1: started firmware 3.17.0 "WF200_ASIC_WFM_(Jenkins)_FW3.17.0" (API: 3.12, keyset: C0, caps: 0x00000002)
[ 7.000346] wfx-sdio mmc3:0001:1: MAC address 0: 00:0d:6f:73:93:69
[ 7.000424] wfx-sdio mmc3:0001:1: MAC address 1: 00:0d:6f:73:93:6a
Troubleshoot
Debugging sdio detection on the Raspberry Pi hardware
- Error :
mmc2: error -110 whilst initialising SDIO card
This usually is due to clock speed being too high.
Silcion Labs shared hardware limitations related to their eval boards on this KBA sction "Max SDIO speed too high":
There is a SDIO speed limitation with BRD8022/BRD8023 due to the onboard switches. For this reason, we need to reduce the SDIO clock speed. 25 MHz is generally a good choice, given that choices are limited and vary depending on the platform.
If enabling traces reflect the -110 error in dmesg
then reduce clock speed by downclocking the bus in /boot/config.txt
:
dtoverlay=wfx-sdio,sdio_overclock=25
Another way to debug Device Tree is to use /boot/config.txt as follows:
# Enable DRM VC4 V3D driver
#dtoverlay=vc4-kms-v3d
#max_framebuffers=2
dtdebug=1
And vcdbg log msg
Debugging .sec injection into wfx200
dmesg | grep wfx
[ 6.651443] wfx: loading out-of-tree module taints kernel.
[ 6.687967] wfx-sdio mmc2:0001:1: can't load wfx/wfm_wf200_C0.sec, falling back to wfx/wfm_wf200.sec
[ 6.688083] wfx-sdio mmc2:0001:1: Direct firmware load for wfx/wfm_wf200.sec failed with error -2
[ 6.688119] wfx-sdio mmc2:0001:1: can't load wfx/wfm_wf200.sec
[ 6.694957] wfx-sdio: probe of mmc2:0001:1 failed with error -2
dmesg | grep wfx
[ 6.640329] wfx: loading out-of-tree module taints kernel.
[ 6.691847] wfx-sdio mmc2:0001:1: can't load wfx/wfm_wf200_C0.sec, falling back to wfx/wfm_wf200.sec
Debugging .pds injection into wfx200
pi@raspberrypi:~ $ dmesg | grep wfx
[ 6.809445] wfx: loading out-of-tree module taints kernel.
[ 6.867018] wfx-sdio mmc2:0001:1: can't load wfx/wfm_wf200_C0.sec, falling back to wfx/wfm_wf200.sec
[ 7.085869] wfx-sdio mmc2:0001:1: started firmware 3.17.0 "WF200_ASIC_WFM_(Jenkins)_FW3.17.0" (API: 3.12, keyset: C0, caps: 0x00000002)
[ 7.086069] wfx-sdio mmc2:0001:1: Direct firmware load for wfx/wf200.pds failed with error -2
[ 7.086118] wfx-sdio mmc2:0001:1: can't load antenna parameters (PDS file wfx/wf200.pds). The device may be unstable.
[ 7.112949] wfx-sdio mmc2:0001:1: timeout while wake up chip
[ 7.128974] wfx-sdio mmc2:0001:1: timeout while wake up chip
[ 7.144951] wfx-sdio mmc2:0001:1: timeout while wake up chip
[ 7.164905] wfx-sdio mmc2:0001:1: max wake-up retries reached
[ 7.171020] wfx-sdio mmc2:0001:1: wfx_data_write: bus communication error: -84
[ 8.133000] wfx-sdio mmc2:0001:1: chip is abnormally long to answer
[ 11.237016] wfx-sdio mmc2:0001:1: chip did not answer
[ 11.242318] wfx-sdio mmc2:0001:1: hardware request WRITE_MIB/GL_OPERATIONAL_POWER_MODE (0x06) on vif 2 returned error -110
[ 11.254156] wfx-sdio mmc2:0001:1: MAC address 0: 00:0d:6f:73:93:69
[ 11.254506] wfx-sdio mmc2:0001:1: MAC address 1: 00:0d:6f:73:93:6a
dmesg | grep wfx
[ 6.767220] wfx: loading out-of-tree module taints kernel.
[ 7.042675] wfx-sdio mmc2:0001:1: started firmware 3.17.0 "WF200_ASIC_WFM_(Jenkins)_FW3.17.0" (API: 3.12, keyset: C0, caps: 0x00000002)
[ 7.296633] wfx-sdio mmc2:0001:1: PDS: malformed file (legacy format?)
[ 7.304044] wfx-sdio: probe of mmc2:0001:1 failed with error -22
WFx200 wakeup
pi@raspberrypi:~ $ dmesg | grep wfx
[ 6.694119] wfx: loading out-of-tree module taints kernel.
[ 7.011533] wfx-sdio mmc2:0001:1: started firmware 3.17.0 "WF200_ASIC_WFM_(Jenkins)_FW3.17.0" (API: 3.12, keyset: C0, caps: 0x00000002)
[ 7.360657] wfx-sdio mmc2:0001:1: MAC address 0: 00:0d:6f:73:93:69
[ 7.361673] wfx-sdio mmc2:0001:1: MAC address 1: 00:0d:6f:73:93:6a
[ 13.213003] wfx-sdio mmc2:0001:1: timeout while wake up chip
Hint: to avoid the ‘timeout while wake up chip', it is possible to comment (in the device tree) the wfx_wakeup segment. most Linux platforms won't really need to use device power save anyway (Saving the additional mW is generally not an issue on Linux platforms as it is on battery-powered IoT products).