Compile Driver for ESPRESSObin

The following instructions shows how to prepare BLACK bean on ESPRESSObin running Linux with ath10k driver. We recommend using Debian or Ubuntu. It also might be possible to compile on OSX. Compiling directly on a Windows platform is not supported. However, if all you have available is a windows machine then we would recommend to set up a Linux based virtual machine.


Before compiling ath10k drivers for ESPRESSObin, you have to prepare the kernel and a buildroot file system. Official guides listed below:

Also make sure to install required packages as listed on ESPRESSObin build system requirements

sudo apt-get update
sudo apt-get install sed make binutils build-essential gcc g++ bash patch gzip bzip2 perl tar cpio python unzip rsync zlib1g-dev gawk ccache gettext libssl-dev xsltproc bc file lib32ncurses5-dev

Prepare toolchain

1. Download the toolchain (place at /home/user/toolchain):

mkdir -p toolchain && cd toolchain
wget https://releases.linaro.org/components/toolchain/binaries/5.2-2015.11-2/aarch64-linux-gnu/gcc-linaro-5.2-2015.11-2-x86_64_aarch64-linux-gnu.tar.xz

2. Extract the archive:

tar -xvf gcc-linaro-5.2-2015.11-2-x86_64_aarch64-linux-gnu.tar.xz

3. Add toolchain to path. Change your path to toolchain accordingly:

export PATH=$PATH:/home/${USER}/toolchain/gcc-linaro-5.2-2015.11-2-x86_64_aarch64-linux-gnu/bin

Prepare kernel sources

1. Download the sources (place at /home/user/kernel/4.14.22/):

mkdir -p kernel/4.14.22 && cd kernel/4.14.22/
git clone https://github.com/MarvellEmbeddedProcessors/linux-marvell.git -b linux-4.14.22-armada-18.09 .

2. Export the environment variables:

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

3. Create default kernel configuration file:

make mvebu_v8_lsp_defconfig

4. Add cfg80211 module to kernel configure file:

make menuconfig

In the menu config enable the following (press space to enable, symbol [M] for modules or [*] for built-in modules will appear):

[*] Networking support -> Wireless
[*] Wireless -> cfg80211 - wireless configuration API
[*] Wireless -> nl80211 testmode command
[*] Wireless -> cfg80211 wireless extensions compatibility
[*] Wireless -> Generic IEEE 802.11 Networking Stack (mac80211)
[*] Device Drivers -> Network device support -> Wireless LAN -> Atheros/Qualcomm devices
[M] Atheros 802.11ac wireless cards support
[M] Atheros ath10k PCI support
[*] Device Drivers -> Network device support -> Wireless LAN 
[*] General setup -> Kernel->user space relay support (formerly relayfs) 

Then save and exit.

5. Start building kernel:

make -j$(nproc)

Once the build process finishes, your Image will be located in arch/arm64/boot/ while device tree blob (armada-3720-community.dtb) will be placed at arch/arm64/boot/dts/marvell/.


Prepare buildroot file system

1. Download the sources:

mkdir ~/buildroot && cd ~/buildroot/
git clone -b buildroot-2015.11-16.08 https://github.com/MarvellEmbeddedProcessors/buildroot-marvell .

2. Create default configuration file:

make mvebu_armv8_le_defconfig

3. Configure buildroot:

make menuconfig

In menuconfig, select toolchain and enable the following (note that some of these settings might be pre-configured already):

[*] Toolchain Type -> External toolchain
[*] Toolchain -> Custom toolchain
[*] Toolchain origin -> Pre-installed toolchain)

Change /user/ to your own.

[*] Toolchain path -> /home/user/toolchain/gcc-linaro-5.2-2015.11-2-x86_64_aarch64-linux-gnu/
[*] Toolchain prefix -> aarch64-linux-gnu
[*] External toolchain gcc version --> 5.x
[*] External toolchain kernel headers series -> 4.0.x(

After setting up the toolchain, additionaly can add other packages:

[*] Target packages -> Networking applications -> iw
[*] Target packages -> Networking applications -> wpa_supplicant

Save the '.config' and exit.

4. Change the FIO_SITE variable to use correct repository server:

nano package/fio/fio.mk

Change 8 line from:

FIO_SITE = https://fossies.org/linux/misc

to:

FIO_SITE = https://github.com/axboe/fio/archive

5. Start building root file system:

make -j$(nproc)

If the build process finishes successfully, your images will be placed in output/images/.

If you get the gdate.c:2497:7: error, see https://github.com/widora/openwrt_widora/issues/12
For ./buildtools/bin/waf", line 76 error, visit http://git.catalyst.net.nz/gw?p=samba.git;a=commitdiff_plain;h=edb109f6
For host-lzop-1.03/.stamp_configured' failed, visit https://raw.githubusercontent.com/openembedded/openembedded-core/master/meta/recipes-support/lzop/lzop/lzop-1.03-gcc6.patch


Prepare USB drive

Prepare USB drive to format it and boot from it. Any USB drive above 1GB of storage will do.

1. Wipe the USB drive (must have at least 1GB storage, also double check USB label with fdisk -l (in our case - /dev/sdb):

sudo dd if=/dev/zero of=/dev/sdb bs=1M count=100

2. Create partition:

(echo n; echo p; echo 1; echo ''; echo ''; echo w) | sudo fdisk /dev/sdb

3. Create file system:

sudo mkfs.ext4 /dev/sdb1

4. Create directory and mount the USB drive:

sudo mkdir -p /mnt/usb
sudo mount /dev/sdb1 /mnt/usb

5. Select mounted directory and extract the file system:

cd /mnt/usb
sudo tar -xvf /home/user/buildroot/output/images/rootfs.tar.gz

6. Make boot directory then copy the kernel and device tree:

sudo mkdir -p boot
sudo cp /home/user/kernel/4.14.22/arch/arm64/boot/Image /mnt/usb/boot/
sudo cp /home/user/kernel/4.14.22/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtb /mnt/usb/boot/armada-3720-community.dtb

7. Install modules:

cd /home/user/kernel/4.14.22/
make INSTALL_MOD_PATH=~/tmp/ modules_install
sudo cp -r ~/tmp/* /mnt/usb/

8. Copy binary files from this repo:

mkdir -p /mnt/usb/lib/firmware/ath10k/QCA9377/hw1.0/
cp ath10k-firmware/QCA9377/hw1.0/WLAN.TF.1.0/firmware-5.bin_WLAN.TF.1.0-00002-QCATFSWPZ-5 /mnt/usb/lib/firmware/ath10k/QCA9377/hw1.0/firmware-5.bin
cp ath10k-firmware/QCA9377/hw1.0/board.bin /mnt/usb/lib/firmware/ath10k/QCA9377/hw1.0/
cp ath10k-firmware/QCA9377/hw1.0/board-2.bin /mnt/usb/lib/firmware/ath10k/QCA9377/hw1.0/

9. Go to USB drive and do sync

cd /mnt/usb
sync
 

10. Change working directory and unmount the USB drive

cd
sudo umount /mnt/usb

Booting from USB

1. Connect USB cable to ESPRESSObin and check, how connection is named

dmesg | tail

The output should be similar to:

[86000.246258] pl2303 2-1.3:1.0: device disconnected
[86001.904945] usb 2-1.3: new full-speed USB device number 11 using ehci-pci
[86002.057267] pl2303 2-1.3:1.0: pl2303 converter detected
[86002.059323] usb 2-1.3: pl2303 converter now attached to ttyUSB0

Our device: ttyUSB0

2. Connect to device (serial in this case):

picocom -b 115200 /dev/ttyUSB0

3. Plug the external power to the board and enter bootloader:

While booting, keep repeatedly pressing ESC until you're inside the bootloader.

4. Plug in USB device into USB2 port and verify that it's recognized (execute command inside bootloader):

usb start

Should see: ext4ls usb 0:1 boot

5. Set environment variables (execute command inside bootloader):

setenv image_name boot/Image
setenv fdt_name boot/armada-3720-community.dtb
setenv bootusb 'usb start;ext4load usb 0:1 $kernel_addr $image_name;ext4load usb 0:1 $fdt_addr $fdt_name;setenv bootargs $console root=/dev/sda1 rw rootwait; booti $kernel_addr - $fdt_addr'
saveenv

6. Begin booting from USB (execute command inside bootloader):

run bootusb

7. Login and insert module: If everything was done correctly, should be greeted with:

Welcome to Buildroot
buildroot login:

The default login name is root, no password.

Welcome to Buildroot
buildroot login: root

To insert modules, use modprobe command:

modprobe ath
modprobe ath10k_core
modprobe ath10_pci

The interfaces wlan0 should be created:

# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 32:22:84:41:5d:8f brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 532
link/ether f0:ad:4e:04:96:3a brd ff:ff:ff:ff:ff:ff
4: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
5: wan@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop switchid 00000000 state DOWN mode DEFAULT group default qlen 1000
link/ether f0:ad:4e:04:96:3a brd ff:ff:ff:ff:ff:ff
6: lan0@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop switchid 00000000 state DOWN mode DEFAULT group default qlen 1000
link/ether f0:ad:4e:04:96:3a brd ff:ff:ff:ff:ff:ff
7: lan1@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop switchid 00000000 state DOWN mode DEFAULT group default qlen 1000
link/ether f0:ad:4e:04:96:3a brd ff:ff:ff:ff:ff:ff
8: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether c4:93:00:0f:93:6a brd ff:ff:ff:ff:ff:ff
9: p2p0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether c6:93:00:90:93:6a brd ff:ff:ff:ff:ff:ff

Possible issue

When you choose to compile Atheros 802.11ac wireless cards support, Atheros ath10k PCI support modules into kernel, you will probably get this error. It is because system root filesystem is not mounted at driver initialization stage. Driver will fail to load firmware files that usually stored on root filesystem, because system will not find it.

 [    3.794813] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/cal-pci-0000:00:00.0.bin failed with error -2
 [    3.794813] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/cal-pci-0000:00:00.0.bin failed with error -2
 [    3.794848] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-6.bin failed with error -2
 [    3.794848] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-6.bin failed with error -2
 [    3.794881] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-5.bin failed with error -2
 [    3.794881] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-5.bin failed with error -2
 [    3.794914] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-4.bin failed with error -2
 [    3.794914] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-4.bin failed with error -2
 [    3.794949] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-3.bin failed with error -2
 [    3.794949] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-3.bin failed with error -2
 [    3.794983] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-2.bin failed with error -2
 [    3.794983] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-2.bin failed with error -2
 [    3.794990] ath10k_pci 0000:00:00.0: Failed to find firmware-N.bin (N between 2 and 6) from ath10k/QCA9377/hw1.0: -2
 [    3.794990] ath10k_pci 0000:00:00.0: Failed to find firmware-N.bin (N between 2 and 6) from ath10k/QCA9377/hw1.0: -2
 [    3.794995] ath10k_pci 0000:00:00.0: could not fetch firmware files (-2)
 [    3.794995] ath10k_pci 0000:00:00.0: could not fetch firmware files (-2)
 [    3.795017] ath10k_pci 0000:00:00.0: could not probe fw (-2)
 [    3.795017] ath10k_pci 0000:00:00.0: could not probe fw (-2)

Workaround here is to unbind pci device after system boots, and then again bind it. Go to ath10k_pci folder

# cd /sys/bus/pci/drivers/ath10k_pci

Check for device pci address, which is 0000:00:00.0

# ls
0000:00:00.0  bind  module  new_id  remove_id  uevent  unbind

Unbind it and then bind.

# echo "0000:00:00.0" > unbind
# echo "0000:00:00.0" > bind

After these steps, module should be loaded correctly.

[ 1527.336741] ath10k_pci 0000:00:00.0: pci irq msi oper_irq_mode 2 irq_mode 0 reset_mode 0
[ 1527.666879] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/pre-cal-pci-0000:00:00.0.bin failed with error -2
[ 1527.677745] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/cal-pci-0000:00:00.0.bin failed with error -2
[ 1527.688547] ath10k_pci 0000:00:00.0: Direct firmware load for ath10k/QCA9377/hw1.0/firmware-6.bin failed with error -2
[ 1527.700995] ath10k_pci 0000:00:00.0: qca9377 hw1.1 target 0x05020001 chip_id 0x003821ff sub 0000:0000
[ 1527.710565] ath10k_pci 0000:00:00.0: kconfig debug 0 debugfs 0 tracing 0 dfs 0 testmode 1
[ 1527.721142] ath10k_pci 0000:00:00.0: firmware ver WLAN.TF.1.0-00002-QCATFSWPZ-5 api 5 features ignore-otp crc32 c3e0d04f
[ 1527.796015] ath10k_pci 0000:00:00.0: failed to fetch board data for bus=pci,vendor=168c,device=0042,subsystem-vendor=0000,subsystem-device=0000 from ath10k/QCA9377/hw1.0/board-2.bin
[ 1527.812963] ath10k_pci 0000:00:00.0: board_file api 1 bmi_id N/A crc32 544289f7
[ 1528.447934] ath10k_pci 0000:00:00.0: htt-ver 3.44 wmi-op 4 htt-op 3 cal otp max-sta 32 raw 0 hwcrypto 1