Skip to content
Port Allwinner xradio driver to mainline Linux.
Branch: master
Clone or download
Pull request Compare This branch is 24 commits ahead, 2 commits behind Icenowy:master.
fifteenhex Merge pull request #8 from jimdigriz/debug-ifdefs
add ifdef's around print_hex_dump_bytes
Latest commit aa01ba7 Apr 22, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore add gitignore Nov 12, 2016
Kconfig Remove old kconfig options Dec 26, 2016
LICENSE Initial commit Nov 11, 2016
Makefile Remote p2p multivif thing that doesn't seem to actually work Jan 5, 2017
README.md Update README.md Aug 21, 2018
ap.c fix build with kernel >= 4.14.17 Dec 6, 2018
ap.h Fix build with kernel 4.15 Jan 4, 2018
bh.c
bh.h remove executable flag Dec 2, 2016
common.h
debug.h remove aliases of BUG_ON and WARN_ON Jan 4, 2017
fwio.c Remote p2p multivif thing that doesn't seem to actually work Jan 5, 2017
fwio.h remove executable flag Dec 2, 2016
ht.c split txrx.c into smaller parts Dec 30, 2016
ht.h split txrx.c into smaller parts Dec 30, 2016
hwio.c remove aliases of BUG_ON and WARN_ON Jan 4, 2017
hwio.h remove executable flag Dec 2, 2016
keys.c
keys.h Group most of the key handling functions together Dec 26, 2016
main.c fixed an ISO C90 warning, possibly badly Apr 8, 2019
main.h Decouple device probe from module init and remove globals in the proc… Nov 28, 2016
module.c get rid of awful debugfs thing Jan 2, 2017
p2p.c split txrx.c into smaller parts Dec 30, 2016
p2p.h split txrx.c into smaller parts Dec 30, 2016
pm.c Fix build with kernel 4.15 Jan 4, 2018
pm.h remove executable flag Dec 2, 2016
queue.c
queue.h fixed an ISO C90 warning, possibly badly Apr 8, 2019
rx.c copy missing implementation of xradio_check_go_neg_conf_success from … Mar 21, 2018
rx.h split txrx.c into smaller parts Dec 30, 2016
scan.c Remote p2p multivif thing that doesn't seem to actually work Jan 5, 2017
scan.h Remove rest of test mode Jan 4, 2017
sdio.c add ifdef's around print_hex_dump_bytes (even commented out ones) Apr 19, 2019
sdio.h Decouple device probe from module init and remove globals in the proc… Nov 28, 2016
sta.c use ktime.h for kernel >= 5 Apr 6, 2019
sta.h Fix build with kernel 4.15 Jan 4, 2018
sun8i-h2-plus-orangepi-zero.dts more detailed readme, some change in rx.c probably for good, dts example Jun 20, 2017
tx.c Remote p2p multivif thing that doesn't seem to actually work Jan 5, 2017
tx.h split txrx.c into smaller parts Dec 30, 2016
wsm.c add ifdef's around print_hex_dump_bytes (even commented out ones) Apr 19, 2019
wsm.h Remove rest of test mode Jan 4, 2017
xradio.h Fix build with kernel 4.15 Jan 4, 2018

README.md

xradio

Port Allwinner xradio driver to mainline Linux.

READ THIS

This driver just about works. If it loads and starts working normally it usually doesn't have any major issues until you try to reboot. The structure of the driver isn't great and it can lock up the kernel if it gets confused. It's not production ready for your large scale commercial IoT deployment.

Also: The xr819 chip/firmware drops tons and tons of frames with FCS errors and this makes performance horrible at best. Most people have lost interest in having anything to do with the xr819 because of people being idiots and demanding that issues that are incredibly hard to fix without documentation be fixed because they spent $8 on a board and somehow people that got exactly zero of their $8 are responsible.

Moral of the story: If you're going to post nasty things on the interwebs and demand people fix stuff because reasons at least have a bunch of packet dumps etc and have some idea about what you're talking about.

Building

Something like this:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C <PATH TO YOUR LINUX SRC> M=$PWD modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C <PATH TO YOUR LINUX SRC> M=$PWD INSTALL_MOD_PATH=<PATH TO INSTALL MODULE> modules_install

How to use this

You need to specify one or two regulators for the xr819's 1.8v and 3.3v supplies in your device tree. (for example, at: .../linux_sources/linux-4.12-rc5/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts)

It is possible to build dtb-s only:

make sunxi_defconfig
make dtbs

or via cross-compilation:

make -j4 ARCH=arm CROSS_COMPILE=arm-none-eabi- sunxi_defconfig
make -j4 ARCH=arm CROSS_COMPILE=arm-none-eabi- dtbs

For example, with appropriate archlinux arm kernel build you could use mainline kernel without rebuiding everything, only replacing your dtb-file at /boot/dtbs/.

The orange pi zero only has control over the 1.8v regulator and a 3.3v fixed regulator is provided elsewhere so we only need one here:

vdd_wifi: vdd_wifi {
	compatible = "regulator-fixed";
	regulator-name = "wifi";
	regulator-min-microvolt = <1800000>;
	regulator-max-microvolt = <1800000>;
	gpio = <&pio 0 20 GPIO_ACTIVE_HIGH>;
	startup-delay-us = <70000>;
	enable-active-high;
};

Next you need a pwrseq node that controls the reset pin of the xr819.

pwrseq_wifi: pwrseq_wifi@0 {
	compatible = "mmc-pwrseq-simple";
	pinctrl-names = "default";
	pinctrl-0 = <&wifi_rst>;
	reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>;
	post-power-on-delay-ms = <50>;
};

Next you need to add some things to the mmc node that the xr819 is connected to.

&mmc1 {
	pinctrl-names = "default";
	pinctrl-0 = <&mmc1_pins_a>;
	vqmmc-supply = <&vdd_wifi>;
	vmmc-supply = <&reg_vcc3v3>;
	bus-width = <4>;
	mmc-pwrseq = <&pwrseq_wifi>;
	non-removable;
	status = "okay";

        xr819wifi: xr819wifi@1 {
                reg = <1>;
                compatible = "xradio,xr819";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_wake>;
                interrupt-parent = <&pio>;
                interrupts = <6 10 IRQ_TYPE_EDGE_RISING>;
                interrupt-names = "host-wake";
                local-mac-address = [dc 44 6d c0 ff ee];
        };
};

and probably we also need this:

&pio {
	wifi_wake: wifi_wake {
		pins = "PG10";
		function = "gpio_in";
    };
};

&r_pio {
	wifi_rst: wifi_rst {
		pins = "PL7";
		function = "gpio_out";
    };
};

example sun8i-h2-plus-orangepi-zero.dts is provided too.

vqmmc-supply and vmmc-supply should reference the regulators that control the xr819 supplies. The device tree for the SoC the orange pi zero is based on supplies a fixed 3.3v regulator so we use that for vmmc-supply and provide the 1.8v controllable regulator as vqmmc-supply. vqmcc-supply is apparently for the IO supply which is 3.3v for the orange pi zero but swapping vqmmc and vmmc around results in the kernel complaining that the card's (the xr819) required IO voltage isn't supported. The setup above might not be technically correct but does work. The xr819 node should be self explanatory. The compatible string is used by the driver to find the node. The wake interrupt from the xr819 needs to be provided.

Finally you can specify a MAC address to use. If you don't set one you will get a random one on each boot. Instead of creating a new device tree file for every system you should probably overwrite the address given after loading the device tree in u-boot. For the sunxi uboot all you have to actually do is add something like "ethernet1 = &xr819wifi;" to the aliases section of the device tree you give to the kernel and u-boot will update the mac address to something based on the unique chip id for you.

Running

place xradio_wlan.ko to your modules folder (for archlinux: /lib/modules/.../kernel/net/wireless/xradio)

Don't forget to take firmware binaries from somewhere: boot_xr819.bin, fw_xr819.bin, sdd_xr819.bin (for archlunux place it to /lib/firmware/xr819/)

What works, what doesn't

Working:

Standard client station mode seems to work fine. Master (AP) mode works with WPA/WPA2 enabled etc. Dual role station and master mode.

Issues

The firmware running on the xr819 is very crash happy and the driver is a bit stupid. For example the driver can get confused about how many packets of data the xr819 has for it to read and can try to read too many. The firmware on the xr819 responds by triggering an assert and shutting down. The driver gets a packet that tells it that the firmware is dead and shuts down the thread used to push and pull data but the rest of the driver and the os has no idea and if the os tries to interact with the driver everything starts to lock up.

Pings from the device to the network are faster than from the network to the device. This seems to be because of latency between the interrupt and servicing RX reports from the device.

Fun stuff

The driver is based on the driver for the ST CW1100/CW1200 chips. The XR819 is probably a clone, licensed version or actually a CW1100 family chip that has been packaged by xradio/allwinner as the CW1100 is available as a raw wafer.

The silicon version from the XR819 and procedure for loading firmware matches up with the CW1x60 chips which were apparently never released so maybe Allwinner bought the design after the ST/Ericsson split?

If anyone wants to mainline support for the XR819 they should probably do it by adding support for the XR819 to the existing CW1200 driver so they don't have to get thousands and thousands of lines of code signed off.

You can’t perform that action at this time.