Adding support for TP-Link Archer AX80 EU version(U-boot layout also)

Normal OpenWrt version: it's in 25.12.2
U-boot layout OpenWrt version: https://github.com/openwrt/openwrt/pull/21640

Both work pretty well. Also if anyone is in Istanbul, hit me up and I can set this up for you, but not for free. This is both risky and difficult device to open up, it takes some time (20 mins at least). There are methods to do without opening up, I can probably do those.
Also I can recover from hard bricks, where even U-boot is gone. So don't trash the device when this happens. It's %99 recoverable.

Btw how do we fork a router board from another board? US version is almost similiar but smaller differences like GPIO.

Hey, i managed to dig a little into TP-Link GPL code, and a managed to make a dts file for the EU version, but i did not test it, because i don’t have this router. But maybe you wil check if some things work for you. I copied some of the code from the US/CA/RU dts file. But, you are doing this at your own risk !!! Here’s the code:

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

/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>

#include "mt7986b.dtsi"

/ {
	compatible = "tplink,archer-ax80-v1-eu", "mediatek,mt7986b";
	model = "TP-Link Archer AX80V1-EU";

	aliases {
		serial0 = &uart0;
		led-boot = &led_B;
		led-failsafe = &led_R;
		led-running = &led_B;
		led-upgrade = &led_G;
	};

	chosen {
		stdout-path = "serial0:115200n8";
	};

	memory@40000000 {
		reg = <0 0x40000000 0 0x20000000>;
	};

	gpio-keys {
		compatible = "gpio-keys";

		button-reset {
			label = "reset";
			linux,code = <KEY_RESTART>;
			gpios = <&pio 7 GPIO_ACTIVE_LOW>;
		};

		button-ledswitch {
			label = "ledswitch";
			linux,code = <KEY_BRIGHTNESS_ZERO>;
			gpios = <&pio 10 GPIO_ACTIVE_LOW>;
		};

		button-wps {
			label = "wps";
			linux,code = <KEY_WPS_BUTTON>;
			gpios = <&pio 16 GPIO_ACTIVE_LOW>;
		};

		button-wifi {
			label = "wlan";
			linux,code = <KEY_WLAN>;
			gpios = <&pio 9 GPIO_ACTIVE_LOW>;
		};
	};

	reg_1p8v: regulator-1p8v {
		compatible = "regulator-fixed";
		regulator-name = "fixed-1.8V";
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <1800000>;
		regulator-boot-on;
		regulator-always-on;
	};

	reg_3p3v: regulator-3p3v {
		compatible = "regulator-fixed";
		regulator-name = "fixed-3.3V";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		regulator-boot-on;
		regulator-always-on;
	};

	reg_5v: regulator-5v {
		compatible = "regulator-fixed";
		regulator-name = "fixed-5V";
		regulator-min-microvolt = <5000000>;
		regulator-max-microvolt = <5000000>;
		regulator-boot-on;
		regulator-always-on;
	};
};

&auxadc {
	status = "okay";
};

&crypto {
	status = "okay";
};

&eth {
	status = "okay";

	gmac0: mac@0 {
		compatible = "mediatek,eth-mac";
		reg = <0>;
		phy-mode = "2500base-x";
		fixed-link {
			speed = <2500>;
			full-duplex;
		};
	};

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy-handle = <&phy6>;
	};

	mdio: mdio-bus {
		#address-cells = <1>;
		#size-cells = <0>;

		reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>;
		reset-delay-us = <1500000>;
		reset-post-delay-us = <1000000>;

		phy6: phy@6 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <6>;
		};

		switch@0 {
			compatible = "mediatek,mt7531";
			reg = <31>;
			reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
			interrupt-controller;
			#interrupt-cells = <1>;
			interrupt-parent = <&pio>;
			interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;

			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 {
					reg = <0>;
					label = "lan0";
				};
				port@1 {
					reg = <1>;
					label = "lan1";
				};
				port@2 {
					reg = <2>;
					label = "lan2";
				};
				port@3 {
					reg = <3>;
					label = "lan3";
				};
				port@6 {
					reg = <6>;
					label = "cpu";
					ethernet = <&gmac0>;
					phy-mode = "2500base-x";
					fixed-link {
						speed = <2500>;
						full-duplex;
					};
				};
			};
		};
	};
};

&i2c0 {
	status = "okay";

	lp55231: led-controller@32 {
		#address-cells = <1>;
		#size-cells = <0>;
		compatible = "ti,lp55231";
		reg = <0x32>;
		status = "okay";
		clock-mode = /bits/ 8 <1>;

		led_B: led@0 {
			chan-name = "B";
			led-cur = /bits/ 8 <0x14>;
			max-cur = /bits/ 8 <0x20>;
			reg = <0>;
			color = <LED_COLOR_ID_BLUE>;
		};

		led_G: led@3 {
			chan-name = "G";
			led-cur = /bits/ 8 <0x14>;
			max-cur = /bits/ 8 <0x20>;
			reg = <3>;
			color = <LED_COLOR_ID_GREEN>;
		};

		led_R: led@6 {
			chan-name = "R";
			led-cur = /bits/ 8 <0x14>;
			max-cur = /bits/ 8 <0x20>;
			reg = <6>;
			color = <LED_COLOR_ID_RED>;
		};

	};
};
&spi0 {
	pinctrl-names = "default";
	pinctrl-0 = <&spi_flash_pins>;
	status = "okay";

	spi_nand_flash: flash@0 {
		compatible = "spi-nand";
		reg = <0>;

		spi-max-frequency = <52000000>;
		spi-tx-bus-width = <4>;
		spi-rx-bus-width = <4>;

		spi-cal-enable;
		spi-cal-mode = "read-data";
		spi-cal-datalen = <7>;
		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4e 0x41 0x4e 0x44>;
		spi-cal-addrlen = <5>;
		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;

		partitions: partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			partition@0 {
				label = "boot";
				reg = <0x00000 0x0200000>;
				read-only;
			};

			partition@200000 {
				label = "u-boot-env";
				reg = <0x0200000 0x0100000>;
			};

			partition@300000 {
				label = "ubi0";
				reg = <0x300000 0x3200000>;
			};

			partition@3500000 {
				label = "ubi1";
				reg = <0x3500000 0x3200000>;
			};

			partition@6700000 {
				label = "userconfig";
				reg = <0x6700000 0x800000>;
			};

			factory:partition@6f00000 {
				label = "tp_data";
				reg = <0x6f00000 0x400000>;
			};

            partition@7300000 {
				label = "mali_data";
				reg = <0x7300000 0x800000>;
            };
	    };
    };
};

&pio {
	spi_flash_pins: spi-flash-pins-33-to-38 {
		mux {
			function = "spi";
			groups = "spi0", "spi0_wp_hold";
		};
		conf-pu {
			pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
			drive-strength = <4>;
			mediatek,pull-up-adv = <0>;
		};
		conf-pd {
			pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
			drive-strength = <4>;
			mediatek,pull-down-adv = <0>;
		};
	};
	wf_2g_5g_pins: wf_2g_5g-pins {
		mux {
			function = "wifi";
			groups = "wf_2g", "wf_5g";
		};
		conf {
			pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
			"WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
			"WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
			"WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
			"WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
			"WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
			"WF1_TOP_CLK", "WF1_TOP_DATA";
			drive-strength = <4>;
		};
	};
};

&trng {
	status = "okay";
};

&uart0 {
	status = "okay";
};

&ssusb {
	vusb33-supply = <&reg_3p3v>;
	vbus-supply = <&reg_5v>;
	status = "okay";
};

&usb_phy {
	status = "okay";
};

&watchdog {
	status = "okay";
};

&wifi {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&wf_2g_5g_pins>;
};

The LED’s will obviously not work, but you should try if the buttons work.

Hi there, wonderful! Thank you. So this supposedly fixes the LAN3 issue am I right?

Like i said, i don’t have the device, so you have to test it. But i wrote this dts using original eu dts from tp-link gpl source code and openwrt’s ax80 us/ca/ru dts. Apparently, the only diffrences between versions are cpu and the led’s.

BTW, did you install openwrt using uart connection ? If so, can you post a pic of the mainboard ?

Yes I did with UART, other methods didn't work. I forgot to take photos but I will take photos. It's on the upper side of the board.

So, I add the DTS files and compile it like that, am I right? I compiled coreboot before, think I can do this.

Read about compiling openwrt images. There are wiki pages about it.

Ok I think I got it, btw what do you guys usually compile openwrt with? Is Debian 13 good?

Any semi-recent general purpose linux distribution will do. OpenWrt's buildbots are running on Debian though.

Ok finished compiling. The thing is I don't have the device right now, I gave it to my friend for a while. Meanwhile, if someone wants to try on their EU devices, hit me up. But only if you are willing to risk it. Here are the files I made, I assume I get it right:

user@debian-dell:~/GeliĹźtirme/openwrt$ find bin/targets -type f -name "*ax80*"
bin/targets/mediatek/filogic/openwrt-mediatek-filogic-tplink_archer-ax80-v1-eu-squashfs-sysupgrade.bin
bin/targets/mediatek/filogic/openwrt-mediatek-filogic-tplink_archer-ax80-v1-eu.manifest
bin/targets/mediatek/filogic/openwrt-mediatek-filogic-tplink_archer-ax80-v1-eu-initramfs-kernel.bin

Btw I also extracted the DTS file from the stock firmware, is this of any use?

Aww man, I compiled and flashed the image it works, but forgot that it's snapshot. No LUCI. HELP. Am I in the right path? You first test the firmware in snapshot build, then move into stable? Please tell me.
Also, I need to do these commands on initramfs kernel image, but those fail:

root@OpenWrt:/etc#  fw_setenv mtdids "spi-nand0=spi-nand0"
Cannot parse config file '/etc/fw_env.config': No such file or directory
Failed to find NVMEM device
Error: environment not initialized
root@OpenWrt:/etc# 
root@OpenWrt:/etc# fw_setenv bootargs "ubi.mtd=ubi0 console=ttyS0,115200n1 logle
vel=8 earlycon=uart8250,mmio32,0x11002000 init=/etc/preinit"
setenv mtdids "sCannot parse config file '/etc/fw_env.config': No such file or directory
Failed to find NVMEM device
Error: environment not initialized
root@OpenWrt:/etc# fw_setenv mtdids "spi-nand0=spi-nand0"
_setenv mtdpartsCannot parse config file '/etc/fw_env.config': No such file or directory
Failed to find NVMEM device
Error: environment not initialized
root@OpenWrt:/etc# fw_setenv mtdparts "spi-nand0:2M(boot),1M(u-boot-env),50M(ubi
0),50M(ubi1),8M(userconfig),4M(tp_data),8M(mali_data)"
_setenv tp_boot_iCannot parse config file '/etc/fw_env.config': No such file or directory
Failed to find NVMEM device
Error: environment not initialized
root@OpenWrt:/etc# fw_setenv tp_boot_idx 0
Cannot parse config file '/etc/fw_env.config': No such file or directory
Failed to find NVMEM device
Error: environment not initialized

What does printenv say ?

Nevermind, I literally didn't do these fw commands steps at all, they are unneccessary for EU version. Because on EU version there is no secure boot and stuff. To be sure, I just reset u-boot totally, must be env default -a command. then I just flashed 24.10.4 US initramfs-then squashfs firmware. Which I didn't do any fw commands AT ALL. Afterwards, I directly flashed my own compiled EU squashfs image. Not initramfs.

But LAN3 port (said on the physical port) doesn't work still. I literally created a new tag with archer-ax80-eu and copied some stuff from US definitions. Then, I changed the DTS according to what you gave me. But, nope. Look here, it works I installed the luci now:

With regards to lan3 port, that’s weird. They are defined exactly the same in both versions in original dts files.

Another thing i noticed just now, does the EU version have 256MB of storage memory or am i looking wrong ?

I think not, its 128MB. But the thing is, mtd5 was mounted on /tmp/tp_data before on the US firmware. Now it's not in my firmware, and thus Wi-Fi doesn't work. EEPROM file is in there tp_data. How to fix that?

root@OpenWrt:/tmp# gawk '{if($1 ~ /^mtd/) printf "%s\t%.1f MB\t%s\n", $1, strtonum("0x"$2)/1024/1024, $4}' /proc/mtd
mtd0:	2.0 MB	"boot"
mtd1:	1.0 MB	"u-boot-env"
mtd2:	50.0 MB	"ubi0"
mtd3:	50.0 MB	"ubi1"
mtd4:	8.0 MB	"userconfig"
mtd5:	4.0 MB	"tp_data"
mtd6:	8.0 MB	"mali_data"

root@OpenWrt:/tmp# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00200000 00020000 "boot"
mtd1: 00100000 00020000 "u-boot-env"
mtd2: 03200000 00020000 "ubi0"
mtd3: 03200000 00020000 "ubi1"
mtd4: 00800000 00020000 "userconfig"
mtd5: 00400000 00020000 "tp_data"
mtd6: 00800000 00020000 "mali_data"

I think you need to compare the partitions allocations between us version and eu, maybe there’s something wrong there.