Compile Driver for Linux (ESPRESSObin)

The following instructions cover the driver compiling process for BLUE bean on devices running Linux. 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 qcacld 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.4.52/):

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

2. Apply official ESPRESSObin kernel patches:

wget -O kernel_patches.zip "wiki.espressobin.net/tiki-download_file.php?fileId=150"
unzip kernel_patches.zip
git apply kernel_patches/0001-fix-regulator-armada-37xx-overwrite-CPU-voltage-valu.patch
git apply kernel_patches/0002-fix-ARM64-dts-marvell-armada-37xx-update-CPU-voltage.patch

3. Get the latest qcacld-2.0 sources from 8devices:

git clone https://github.com/8devices/qcacld-2.0 ~/qcacld-2.0

4. Copy and apply qcacld driver patches:

cp ~/qcacld-2.0/patches/Marvell-ESPRESSObin/0003-qcacld-gpio-stdio-voltage.patch .
cp ~/qcacld-2.0/patches/Marvell-ESPRESSObin/0004-qcacld-64bit-kernel.patch .
git apply 0003-qcacld-gpio-stdio-voltage.patch
git apply 0004-qcacld-64bit-kernel.patch
for i in ~/qcacld-2.0/patches/kernel/v4.4.15/* ; do patch -p1 < $i ; done

5. Export the environment variables:

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

6. Create default kernel configuration file:

make mvebu_v8_lsp_defconfig

7. Add cfg80211 module to kernel configure file:

make menuconfig

In the menu config enable the following (press space to enable, symbol * will appear):

* Networking support -> Wireless
* Wireless -> cfg80211
* Wireless -> nl80211
* Wireless -> cfg80211 wireless extensions compatibility
* Wireless -> Generic IEEE 802.11 Networking Stack (mac80211)
*  Device Drivers -> Network device support -> Wireless LAN 
* General setup -> Kernel->user space relay support (formerly relayfs) 

Then save and exit.

8. 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. Apply ESPRESSObin patch to buildroot:

cp ~/qcacld-2.0/patches/Marvell-ESPRESSObin/Buildroot-fio-reop.patch .
patch -p1 < Buildroot-fio-reop.patch

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


Building qcacld driver

1. Download the sources:

git clone https://github.com/8devices/qcacld-2.0
cd qcacld-2.0

2. Edit variables in the make file ARCH, KERNEL_SRC, CROSS_COMPILE accordingly (also change /user/ to your own):

ARCH = arm64
KERNEL_SRC = /home/user/kernel/4.4.52
CROSS_COMPILE = /home/user/toolchain/gcc-linaro-5.2-2015.11-2-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-

3. Start building the qcacld driver:

make -j$(nproc)

If the build process completes successfully, then you should be able to locate wlan-usb.ko in qcacld-2.0 directory


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.4.52/arch/arm64/boot/Image /mnt/usb/boot/
sudo cp /home/user/kernel/4.4.52/arch/arm64/boot/dts/marvell/armada-3720-community.dtb /mnt/usb/boot/

7. Copy compiled qcacld driver to root folder:

sudo cp ~/qcacld-2.0/wlan-sdio.ko /mnt/sdio/root/
sudo cp -r ~/qcacld-2.0/firmware_bin/sdio/* /mnt/sdio/lib/firmware/

8. 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 sould 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 module, use insmod wlan-sdio.ko command:

insmod wlan-sdio.ko

The interfaces wlan0 and p2p0 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