Support for the Linksys MR9000

So there is a kernel panic at the beginning. It works when you do a bootipq but not a regular boot from either partition. Doing some digging around against other devices to figure why this is an issue.

The issue with the third radio could be wrong or missing firmware. BTW the info provided by Hardware Specs is wrong, the third radio is not a QCA9884 but a QCA9988. Couldn't find much info on this chip but it seems more or less the same as the QCA9984 so the ath10k-firmware-qca9984-ct package should do the trick.

Regarding the kernel panic, do you have a bootlog?

Yes and yes. Just gotta find the correct drivers for it.

Figured it out. The MDIO pin and reset definitions are missing in the .dts file which causes the kernel to panic or, with newer builds, to endlessly retry communication with the switch. Once those are fixed the MR9000 also boots OpenWrt from flash. Why it works at all for the MR8300 without those definitions is rather strange since both devices share the same hardware design apart from the 3rd radio.

Getting the 3rd radio to work was straight forward, replacing ath10k-firmware-qca9888-ct with ath10k-firmware-qca9984-ct and extracting the board calibration files from the OEM firmware was all that was needed.

After applying those fixes to NoTengoBattery's build (in a very dirty way I'm sure) I was able to build and flash a working firmware.

Please give details on your fixes so we can also try it out in a snapshot build. Thanks!

Here is my qcom-ipq4019-mr9000.dts. It makes use of the same xx8300.dtsi that the EA8300 and MR8300 use because the hardware configuration is more or less the same:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT

#include "qcom-ipq4019-xx8300.dtsi"

/ {
	model = "Linksys MR9000 (Dallas)";
	compatible = "linksys,mr9000", "qcom,ipq4019";

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;

		ramoops@87500000 {
			compatible = "ramoops";
			reg = <0x87500000 0x600000>;
			console-size = <0x200000>;
			pmsg-size    = <0x200000>;
			record-size  = <0x200000>;
			ecc-size = <16>;
	aliases {
		led-boot = &led_blue;
		led-failsafe = &led_red;
		led-running = &led_green;
		led-upgrade = &led_blue;
		serial0 = &blsp1_uart1;

	// Top panel LEDs, above Linksys logo
	leds {
		compatible = "gpio-leds";
		led_blue: blue {
			label = "blue:panel";
			gpios = <&tlmm 46 GPIO_ACTIVE_LOW>;

		led_red: red {
			label = "red:panel";
			gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;

		led_green: green {
			label = "green:panel";
			gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>;

		// On back panel, above USB socket

		led_usb: usb {
			label = "green:usb";
			gpios = <&tlmm 61 GPIO_ACTIVE_LOW>;
			trigger-sources = <&usb3_port1>, <&usb3_port2>,
			linux,default-trigger = "usbport";

	keys {
		compatible = "gpio-keys";

		reset {
			label = "reset";
			linux,code = <KEY_RESTART>;
			gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;

		wps {
			label = "wps";
			linux,code = <KEY_WPS_BUTTON>;
			gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;

&mdio {
	status = "okay";
	pinctrl-0 = <&mdio_pins>;
	pinctrl-names = "default";
	reset-gpios = <&tlmm 54 GPIO_ACTIVE_LOW>;
	reset-delay-us = <2000>;
	reset-post-delay-us = <1000>;
&tlmm {
	status = "okay";
	mdio_pins: mdio_pinmux {
		mux_1 {
			pins = "gpio6";
			function = "mdio";
		mux_2 {
			pins = "gpio7";
			function = "mdc";

&wifi0 {
	status = "okay";
	qcom,ath10k-calibration-variant = "linksys-mr9000-fcc";

&wifi1 {
	status = "okay";
	ieee80211-freq-limit = <5170000 5330000>;
	qcom,ath10k-calibration-variant = "linksys-mr9000-fcc";

&wifi2 {
	status = "okay";
	ieee80211-freq-limit = <5490000 5835000>;
	qcom,ath10k-calibration-variant = "linksys-mr9000-fcc";

The LED config may not be entirely correct yet. There are 5 LEDs defined in the OEM DTB but in reality there is just 1 Multicolour LED. 2 of the GPIOs defined in the OEM DTB seem to drive the same green node of the LED while another of those GPIOs is apparently not connected to a LED at all.

Thanks. That gets the eth ports working in master!
But I get no wifi now. I think the build is missing linksys-mr9000-fcc. Can you please tell me how to include it in a build?

That refers to the board calibration files. Those can be extracted from OEM firmware or, since our device has a backup partition, simply copied over from there (/lib/firmware/). Then with the help of the qca-swiss-army-knife they have to be converted to generate the board-2.bin files for the radios. The big question is which of the considerable number of files to use.

If you just remove the calibration-variant statement from the .dts file, it should work with the standard board-2.bin supplied by the ath10k-firmware packages. This may or may not impair wireless performance.

1 Like

After removing the calibration-variant statement from the .dts file, I still get no wireless. In dmesg is the error "can not find board-2.bin or board.bin for"... (sic).

I thought it would work at least for the first 2 radios. Try replacing the board-2.bin files with those which contain the right calibration variant files. You have to rename the files to board-2.bin and place them in the folders /lib/firmware/ath10k/QCA4019/hw1.0/ and /QCA9984/hw1.0/.

Oh, and of course you have to put the calibration-variant statement back in.

Seems there is room for some refinement. I just tested the firmware on a second unit. It bootet as well, but the boot log shows a few retries when accessing the PHY. This gets better with the reset-post-delay prolonged to 2ms, will try 5ms next.

I also replaced a Linksys EA8300 in my wifi setup with the MR9000. Wifi performance of the MR9000 is OK, but not as good as the EA8300's so maybe I did use the wrong boarddata_x.bin file from the OEM firmware. If only I knew which one the OEM wifi driver loads ...

There's a folder for each reg domain which contains 4 different files for the QCA9988.


I've started with boarddata_0.bin, but this doesn't seem to be the right one.

I got it to work, using your board files, but had to use the -ct drivers. I was using non-ct before.

I also use -ct drivers, but don't see a reason for it not to work with non-ct.

Suggestion: you could copy all the board files over to the device, and then copy them in/out of lib/firmware/ath10k/ one by one, and reload the ath10k_pci via
rmmod ath10k_pci
modprobe ath10k_pci
and test each board-2.bin file that way rather quickly (better than building a whole new firmware).

Don't know if that will work. board-2.bin is a kind of container file, usually with several different calibration files in it. Your suggestion would depend on the driver to also accept raw calibration files.

But of course I could build several containers and then try your approach. Still faster than building new firmware each time.

Update: Not much difference when using the boardData_QCA... files. For the QCA4019 radios there are only 2 files to choose from so let's try something else. The files from the MR8300 should also work for those, shouldn't they? The design is more or less identical apart from the 3rd radio.

Oh, the choice is easier than expected: A simple cmp showed all the files for one reg domain to be bit-perfect copies of each other. No wonder there wasn't much difference to be seen.

@drandyhaas How does wifi perform with your unit?