From 3d18ae02d889ddcd0b41e84c06e3ec85d0ea2670 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven@narfation.org>
Date: Tue, 26 Jun 2018 01:19:55 +0200
Subject: [PATCH] ar71xx: Add support for TP-Link CPE210 v2 (#1445)

---
 docs/index.rst                                |   2 +-
 ...1xx-disable-40Mhz-refclk-for-QCA953x.patch | 182 ++++++++++
 ...dd-TP-Link-Pharos-v2-board-detection.patch | 139 ++++++++
 ...xx-Add-support-for-TP-Link-CPE210-v2.patch | 324 ++++++++++++++++++
 targets/ar71xx-generic                        |   2 +
 5 files changed, 648 insertions(+), 1 deletion(-)
 create mode 100644 patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch
 create mode 100644 patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch
 create mode 100644 patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch

diff --git a/docs/index.rst b/docs/index.rst
index d5bd928dc..8f46422ed 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -182,7 +182,7 @@ ar71xx-generic
   - Archer C5 (v1) [#ath10k]_
   - Archer C59 (v1) [#80211s]_
   - Archer C7 (v2, v4) [#ath10k]_
-  - CPE210 (v1.0, v1.1)
+  - CPE210 (v1.0, v1.1, v2.0)
   - CPE220 (v1.1)
   - CPE510 (v1.0, v1.1)
   - CPE520 (v1.1)
diff --git a/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch b/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch
new file mode 100644
index 000000000..e82d7bcd7
--- /dev/null
+++ b/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch
@@ -0,0 +1,182 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 19 Jan 2018 14:02:09 +0100
+Subject: ar71xx: disable 40Mhz refclk for QCA953x
+
+The "QCA9531 v2.0 802.11n 2x2 2.4 GHz Premium SOC for WLAN Platforms"
+datasheet (80-Y7991-1 Rev. C - October 2014) doesn't specify support for a
+40 Mhz reference clock. The register description for "Bootstrap Options"
+(page 31) defines following states for the bit 4 (REF_CLK):
+
+* 0 - CLK25 (default)
+* 1 - (reserved)
+
+Devices like the TP-Link CPE210 v2 has this bit set to 1 but is using a 25
+Mhz reference clock. OpenWrt is still interpreted this bit as 40 Mhz and
+then break the bootup of the system due to this incorrect interpretation.
+
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+[refreshed patches]
+Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
+
+Origin: backport, https://github.com/openwrt/openwrt/commit/b1d57dadb2da0e010e157fd2383523578c9dcc2e
+
+diff --git a/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch
+index 777f7b2c8838f2c93f79d5d5212f90b2bd82ced3..d55c97165a5abad8cb25fcc6ddc29415f238c7e6 100644
+--- a/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch
++++ b/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch
+@@ -44,7 +44,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+  config ATH79_NVRAM
+ --- a/arch/mips/ath79/clock.c
+ +++ b/arch/mips/ath79/clock.c
+-@@ -354,6 +354,91 @@ static void __init ar934x_clocks_init(vo
++@@ -354,6 +354,87 @@ static void __init ar934x_clocks_init(vo
+  	iounmap(dpll_base);
+  }
+  
+@@ -56,13 +56,9 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+ +	unsigned long ahb_rate;
+ +	u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
+ +	u32 cpu_pll, ddr_pll;
+-+	u32 bootstrap;
+ +
+-+	bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP);
+-+	if (bootstrap &	QCA953X_BOOTSTRAP_REF_CLK_40)
+-+		ref_rate = 40 * 1000 * 1000;
+-+	else
+-+		ref_rate = 25 * 1000 * 1000;
+++	/* QCA953X only supports 25MHz ref_clk */
+++	ref_rate = 25 * 1000 * 1000;
+ +
+ +	pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG);
+ +	out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+@@ -136,7 +132,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+  static void __init qca955x_clocks_init(void)
+  {
+  	unsigned long ref_rate;
+-@@ -451,6 +536,8 @@ void __init ath79_clocks_init(void)
++@@ -451,6 +532,8 @@ void __init ath79_clocks_init(void)
+  		ar933x_clocks_init();
+  	else if (soc_is_ar934x())
+  		ar934x_clocks_init();
+@@ -247,14 +243,12 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+  
+  	ath79_wmac_data.external_reset = ar933x_wmac_reset;
+  }
+-@@ -151,6 +151,26 @@ static void ar934x_wmac_setup(void)
++@@ -151,6 +151,21 @@ static void ar934x_wmac_setup(void)
+  	ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision;
+  }
+  
+ +static void qca953x_wmac_setup(void)
+ +{
+-+	u32 t;
+-+
+ +	ath79_wmac_device.name = "qca953x_wmac";
+ +
+ +	ath79_wmac_resources[0].start = QCA953X_WMAC_BASE;
+@@ -262,11 +256,8 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+ +	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+ +	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1);
+ +
+-+	t = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP);
+-+	if (t & QCA953X_BOOTSTRAP_REF_CLK_40)
+-+		ath79_wmac_data.is_clk_25mhz = false;
+-+	else
+-+		ath79_wmac_data.is_clk_25mhz = true;
+++	/* QCA953X only supports 25MHz ref_clk */
+++	ath79_wmac_data.is_clk_25mhz = true;
+ +
+ +	ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision;
+ +}
+@@ -274,7 +265,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+  static void qca955x_wmac_setup(void)
+  {
+  	u32 t;
+-@@ -368,6 +388,8 @@ void __init ath79_register_wmac(u8 *cal_
++@@ -368,6 +383,8 @@ void __init ath79_register_wmac(u8 *cal_
+  		ar933x_wmac_setup();
+  	else if (soc_is_ar934x())
+  		ar934x_wmac_setup();
+@@ -550,7 +541,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
+ +#define QCA953X_BOOTSTRAP_SW_OPTION2	BIT(12)
+ +#define QCA953X_BOOTSTRAP_SW_OPTION1	BIT(11)
+ +#define QCA953X_BOOTSTRAP_EJTAG_MODE	BIT(5)
+-+#define QCA953X_BOOTSTRAP_REF_CLK_40	BIT(4)
+++#define QCA953X_BOOTSTRAP_REF_CLK	BIT(4)
+ +#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1)
+ +#define QCA953X_BOOTSTRAP_DDR1		BIT(0)
+ +
+diff --git a/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch
+index ed90c40d882fcff1a451533748912865cc78c6e8..de0ee4604cdeb946bab222cacaa51fb150b25aab 100644
+--- a/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch
++++ b/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch
+@@ -24,7 +24,7 @@
+  config ATH79_NVRAM
+ --- a/arch/mips/ath79/clock.c
+ +++ b/arch/mips/ath79/clock.c
+-@@ -524,6 +524,100 @@ static void __init qca955x_clocks_init(v
++@@ -520,6 +520,100 @@ static void __init qca955x_clocks_init(v
+  	clk_add_alias("uart", NULL, "ref", NULL);
+  }
+  
+@@ -125,7 +125,7 @@
+  void __init ath79_clocks_init(void)
+  {
+  	if (soc_is_ar71xx())
+-@@ -540,6 +634,8 @@ void __init ath79_clocks_init(void)
++@@ -536,6 +630,8 @@ void __init ath79_clocks_init(void)
+  		qca953x_clocks_init();
+  	else if (soc_is_qca955x())
+  		qca955x_clocks_init();
+@@ -219,7 +219,7 @@
+  }
+ --- a/arch/mips/ath79/dev-wmac.c
+ +++ b/arch/mips/ath79/dev-wmac.c
+-@@ -189,6 +189,26 @@ static void qca955x_wmac_setup(void)
++@@ -184,6 +184,26 @@ static void qca955x_wmac_setup(void)
+  		ath79_wmac_data.is_clk_25mhz = true;
+  }
+  
+@@ -246,7 +246,7 @@
+  static bool __init
+  ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data)
+  {
+-@@ -392,6 +412,8 @@ void __init ath79_register_wmac(u8 *cal_
++@@ -387,6 +407,8 @@ void __init ath79_register_wmac(u8 *cal_
+  		qca953x_wmac_setup();
+  	else if (soc_is_qca955x())
+  		qca955x_wmac_setup();
+diff --git a/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch b/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch
+index 16a0b909c570b403473346b0c992f9de02b67132..b0e15379787ade16a02363c78c143e878f27a7f2 100644
+--- a/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch
++++ b/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch
+@@ -1,6 +1,6 @@
+ --- a/arch/mips/ath79/dev-wmac.c
+ +++ b/arch/mips/ath79/dev-wmac.c
+-@@ -400,6 +400,11 @@ void __init ath79_wmac_set_ext_lna_gpio(
++@@ -395,6 +395,11 @@ void __init ath79_wmac_set_ext_lna_gpio(
+  		ar934x_set_ext_lna_gpio(chain, gpio);
+  }
+  
+diff --git a/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch
+index 8aa5957a7152af27854f6f7c197120b8029cf9e8..b59e43c7712a18e5e81944361c358dfb08c488ea 100644
+--- a/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch
++++ b/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch
+@@ -32,7 +32,7 @@
+   */
+ --- a/arch/mips/ath79/dev-wmac.c
+ +++ b/arch/mips/ath79/dev-wmac.c
+-@@ -171,6 +171,27 @@ static void qca953x_wmac_setup(void)
++@@ -166,6 +166,27 @@ static void qca953x_wmac_setup(void)
+  	ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision;
+  }
+  
+@@ -60,7 +60,7 @@
+  static void qca955x_wmac_setup(void)
+  {
+  	u32 t;
+-@@ -187,6 +208,8 @@ static void qca955x_wmac_setup(void)
++@@ -182,6 +203,8 @@ static void qca955x_wmac_setup(void)
+  		ath79_wmac_data.is_clk_25mhz = false;
+  	else
+  		ath79_wmac_data.is_clk_25mhz = true;
diff --git a/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch b/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch
new file mode 100644
index 000000000..8b418e06a
--- /dev/null
+++ b/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch
@@ -0,0 +1,139 @@
+From: Adrian Schmutzler <freifunk@adrianschmutzler.de>
+Date: Fri, 19 Jan 2018 12:58:40 +0100
+Subject: ar71xx: Add TP-Link Pharos v2 board detection
+
+Add support for detecting TP-Link Pharos v2 boards.
+They use different format in product-info partition than v1 boards.
+
+Code was written mostly by Alexander Couzens <lynxis@fe80.eu>
+
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
+
+Origin: backport, https://github.com/openwrt/openwrt/commit/2524febf7927a1bf430d64b7790feb126023e3d1
+
+diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
+index b365b6ae4aa6021960499b3889d846b5171eec0f..94311f75989b0861e188dc89b3e714b5545c1ad8 100755
+--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
+@@ -375,7 +375,7 @@ tplink_pharos_get_model_string() {
+ }
+ 
+ tplink_pharos_board_detect() {
+-	local model_string="$(tplink_pharos_get_model_string | tr -d '\r')"
++	local model_string="$1"
+ 	local oIFS="$IFS"; IFS=":"; set -- $model_string; IFS="$oIFS"
+ 
+ 	local model="${1%%\(*}"
+@@ -396,6 +396,14 @@ gl_inet_board_detect() {
+ 	esac
+ }
+ 
++tplink_pharos_v2_get_model_string() {
++	local part
++	part=$(find_mtd_part 'product-info')
++	[ -z "$part" ] && return 1
++
++	dd if=$part bs=1 skip=4360 count=64 2>/dev/null | tr -d '\r\0' | head -n 1
++}
++
+ ar71xx_board_detect() {
+ 	local machine
+ 	local name
+@@ -546,11 +554,15 @@ ar71xx_board_detect() {
+ 		;;
+ 	*"CPE210/220")
+ 		name="cpe210"
+-		tplink_pharos_board_detect
++		tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')"
++		;;
++	*"CPE210 v2")
++		name="cpe210-v2"
++		tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)"
+ 		;;
+ 	*"CPE510/520")
+ 		name="cpe510"
+-		tplink_pharos_board_detect
++		tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')"
+ 		;;
+ 	*CPE830)
+ 		name="cpe830"
+@@ -560,11 +572,11 @@ ar71xx_board_detect() {
+ 		;;
+ 	*WBS210)
+ 		name="wbs210"
+-		tplink_pharos_board_detect
++		tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')"
+ 		;;
+ 	*WBS510)
+ 		name="wbs510"
+-		tplink_pharos_board_detect
++		tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')"
+ 		;;
+ 	*CR3000)
+ 		name="cr3000"
+@@ -641,7 +653,7 @@ ar71xx_board_detect() {
+ 		;;
+ 	*"EAP120")
+ 		name="eap120"
+-		tplink_pharos_board_detect
++		tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')"
+ 		;;
+ 	*"EAP300 v2")
+ 		name="eap300v2"
+diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
+index 0b422d71c2639a31bc7e88a20976266b66ec4490..9bc49c41a6308b732e45a7ae35c851133c367254 100755
+--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
+@@ -97,10 +97,11 @@ tplink_pharos_check_support_list() {
+ 	local image="$1"
+ 	local offset="$2"
+ 	local model="$3"
++	local trargs="$4"
+ 
+ 	# Here $image is given to dd directly instead of using get_image;
+ 	# otherwise the skip will take almost a second (as dd can't seek)
+-	dd if="$image" bs=1 skip=$offset count=1024 2>/dev/null | (
++	dd if="$image" bs=1 skip=$offset count=1024 2>/dev/null | tr -d "$trargs" | (
+ 		while IFS= read -r line; do
+ 			[ "$line" = "$model" ] && exit 0
+ 		done
+@@ -110,17 +111,19 @@ tplink_pharos_check_support_list() {
+ }
+ 
+ tplink_pharos_check_image() {
+-	local magic_long="$(get_magic_long "$1")"
+-	[ "$magic_long" != "7f454c46" ] && {
+-		echo "Invalid image magic '$magic_long'"
++	local image_magic="$(get_magic_long "$1")"
++	local board_magic="$2"
++	[ "$image_magic" != "$board_magic" ] && {
++		echo "Invalid image magic '$image_magic'. Expected '$board_magic'."
+ 		return 1
+ 	}
+ 
+-	local model_string="$(tplink_pharos_get_model_string)"
++	local model_string="$3"
++	local trargs="$4"
+ 
+ 	# New images have the support list at 7802888, old ones at 1511432
+-	tplink_pharos_check_support_list "$1" 7802888 "$model_string" || \
+-	tplink_pharos_check_support_list "$1" 1511432 "$model_string" || {
++	tplink_pharos_check_support_list "$1" 7802888 "$model_string" "$trargs" || \
++	tplink_pharos_check_support_list "$1" 1511432 "$model_string" "$trargs" || {
+ 		echo "Unsupported image (model not in support-list)"
+ 		return 1
+ 	}
+@@ -507,7 +510,11 @@ platform_check_image() {
+ 	eap120|\
+ 	wbs210|\
+ 	wbs510)
+-		tplink_pharos_check_image "$1" && return 0
++		tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_get_model_string)" '' && return 0
++		return 1
++		;;
++	cpe210-v2)
++		tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0
+ 		return 1
+ 		;;
+ 	a40|\
diff --git a/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch b/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch
new file mode 100644
index 000000000..a25b10fd7
--- /dev/null
+++ b/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch
@@ -0,0 +1,324 @@
+From: Adrian Schmutzler <freifunk@adrianschmutzler.de>
+Date: Fri, 19 Jan 2018 14:45:42 +0100
+Subject: ar71xx: Add support for TP-Link CPE210 v2
+
+This PR adds support for a popular low-cost 2.4GHz N based AP
+
+Specifications:
+ - SoC: Qualcomm Atheros QCA9533 (650MHz)
+ - RAM: 64MB
+ - Storage: 8 MB SPI NOR
+ - Wireless: 2.4GHz N based built into SoC 2x2
+ - Ethernet: 1x 100/10 Mbps, integrated into SoC, 24V POE IN
+
+Installation:
+Flash factory image through stock firmware WEB UI
+or through TFTP
+To get to TFTP recovery just hold reset button while powering on for
+around 4-5 seconds and release.
+Rename factory image to recovery.bin
+Stock TFTP server IP:192.168.0.100
+Stock device TFTP adress:192.168.0.254
+
+Notes:
+TP-Link does not use bootstrap registers so without this patch reference
+clock detects as 40MHz while it is actually 25MHz.
+This is due to messed up bootstrap resistor configuration on the PCB.
+Provided GPL code just forces 25MHz reference clock.
+That causes booting with completely wrong clocks, for example, CPU tries
+to boot at 1040MHz while the stock is 650MHz.
+So this PR depends on PR #672 to remove 40MHz reference clock.
+Thanks to Sven Eckelmann <sven@narfation.org> for properly patching that.
+
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
+
+Origin: backport, https://github.com/openwrt/openwrt/commit/5c5bf8b8658a588423f6ec445d7ef6a36f99a396
+
+diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds
+index a742854bc9b0aa48c61b37e58288177bbb56d14d..54046dffc9a4d4ad0216dcda32bf98ee5d38b569 100755
+--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds
++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds
+@@ -187,16 +187,25 @@ cf-e530n)
+ 	ucidef_set_led_netdev "wan" "WAN" "$board:blue:wan" "eth1"
+ 	;;
+ cpe210|\
++cpe210-v2|\
+ cpe510|\
+ wbs210|\
+ wbs510)
+-	ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20"
+-	ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10"
+ 	ucidef_set_rssimon "wlan0" "200000" "1"
+ 	ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13"
+ 	ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13"
+ 	ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13"
+ 	ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13"
++
++	case "$board" in
++	cpe210-v2)
++		ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan0" "eth0"
++		;;
++	*)
++		ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20"
++		ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10"
++		;;
++	esac
+ 	;;
+ cr3000)
+ 	ucidef_set_led_netdev "wan" "WAN" "pcs:blue:wan" "eth1"
+diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network
+index 875a1a38ada9fb66503505d2f094310db1295a07..633d4e1b7415983f44164187ad3696311ec25621 100755
+--- a/target/linux/ar71xx/base-files/etc/board.d/02_network
++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network
+@@ -67,6 +67,7 @@ ar71xx_setup_interfaces()
+ 	cap4200ag|\
+ 	cf-e380ac-v1|\
+ 	cf-e380ac-v2|\
++	cpe210-v2|\
+ 	eap120|\
+ 	eap300v2|\
+ 	eap7660d|\
+diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt
+index 2449a8d6bce17f0a703d8fc4f82dd38e1f861ae3..35532d86ac3ad32630592c79477c79783af4addb 100644
+--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt
++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt
+@@ -1301,6 +1301,7 @@ config ATH79_MACH_ARCHER_C7
+ config ATH79_MACH_CPE510
+ 	bool "TP-LINK CPE510 support"
+ 	select SOC_AR934X
++	select SOC_QCA953X
+ 	select ATH79_DEV_ETH
+ 	select ATH79_DEV_GPIO_BUTTONS
+ 	select ATH79_DEV_LEDS_GPIO
+diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c
+index d2dbed1fe286c44d3188262e984253faaee7edba..ceb1769ddd522d51014228fe65e2662f2f3e627c 100644
+--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c
++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c
+@@ -1,7 +1,8 @@
+ /*
+- *  TP-LINK CPE210/220/510/520 board support
++ *  TP-LINK CPE210/210 v2/220/510/520 board support
+  *
+  *  Copyright (C) 2014 Matthias Schiffer <mschiffer@universe-factory.net>
++ *  Copyright (C) 2017 Robert Marko <robimarko@gmail.com>
+  *
+  *  This program is free software; you can redistribute it and/or modify it
+  *  under the terms of the GNU General Public License version 2 as published
+@@ -41,6 +42,8 @@
+ #define CPE510_KEYS_POLL_INTERVAL	20 /* msecs */
+ #define CPE510_KEYS_DEBOUNCE_INTERVAL	(3 * CPE510_KEYS_POLL_INTERVAL)
+ 
++/* CPE210 v2 reset GPIO */
++#define CPE210_V2_GPIO_BTN_RESET	17
+ 
+ static struct gpio_led cpe510_leds_gpio[] __initdata = {
+ 	{
+@@ -98,6 +101,30 @@ static struct gpio_led wbs510_leds_gpio[] __initdata = {
+ 	},
+ };
+ 
++static struct gpio_led cpe210_v2_leds_gpio[] __initdata = {
++	{
++		.name		= "tp-link:green:lan0",
++		.gpio		= CPE510_GPIO_LED_LAN0,
++		.active_low	= 1,
++	}, {
++		.name		= "tp-link:green:link1",
++		.gpio		= CPE510_GPIO_LED_L1,
++		.active_low	= 1,
++	}, {
++		.name		= "tp-link:green:link2",
++		.gpio		= CPE510_GPIO_LED_L2,
++		.active_low	= 1,
++	}, {
++		.name		= "tp-link:green:link3",
++		.gpio		= CPE510_GPIO_LED_L3,
++		.active_low	= 1,
++	}, {
++		.name		= "tp-link:green:link4",
++		.gpio		= CPE510_GPIO_LED_L4,
++		.active_low	= 1,
++	},
++};
++
+ static struct gpio_keys_button cpe510_gpio_keys[] __initdata = {
+ 	{
+ 		.desc		= "Reset button",
+@@ -109,6 +136,17 @@ static struct gpio_keys_button cpe510_gpio_keys[] __initdata = {
+ 	}
+ };
+ 
++static struct gpio_keys_button cpe210_v2_gpio_keys[] __initdata = {
++	{
++		.desc		= "Reset button",
++		.type		= EV_KEY,
++		.code		= KEY_RESTART,
++		.debounce_interval = CPE510_KEYS_DEBOUNCE_INTERVAL,
++		.gpio		= CPE210_V2_GPIO_BTN_RESET,
++		.active_low	= 1,
++	}
++};
++
+ static void __init cpe_setup(u8 *mac)
+ {
+ 	/* Disable JTAG, enabling GPIOs 0-3 */
+@@ -171,9 +209,33 @@ static void __init wbs_setup(void)
+ 	ath79_register_wmac(ee, mac);
+ }
+ 
++static void __init cpe210_v2_setup(void)
++{
++	u8 *mac = (u8 *) KSEG1ADDR(0x1f830008);
++	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
++
++	ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe210_v2_leds_gpio),
++				 cpe210_v2_leds_gpio);
++	ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL,
++					ARRAY_SIZE(cpe210_v2_gpio_keys),
++					cpe210_v2_gpio_keys);
++	ath79_register_m25p80(NULL);
++	ath79_register_mdio(0, 0x0);
++	ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0);
++	ath79_eth0_data.duplex = DUPLEX_FULL;
++	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII;
++	ath79_eth0_data.speed = SPEED_100;
++	ath79_eth0_data.phy_mask = BIT(4);
++	ath79_register_eth(0);
++	ath79_register_wmac(ee, mac);
++}
++
+ MIPS_MACHINE(ATH79_MACH_CPE210, "CPE210", "TP-LINK CPE210/220",
+ 	     cpe210_setup);
+ 
++MIPS_MACHINE(ATH79_MACH_CPE210_V2, "CPE210V2", "TP-LINK CPE210 v2",
++	     cpe210_v2_setup);
++
+ MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE510/520",
+ 	     cpe510_setup);
+ 
+diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h
+index a4c7f52fe94e17bc48bebfb460f12f3e5ac35afe..e7e7f94775a3122286dc39447f04b42f4863f313 100644
+--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h
++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h
+@@ -64,7 +64,8 @@ enum ath79_mach_type {
+ 	ATH79_MACH_CF_E380AC_V2,		/* COMFAST CF-E380AC v2 */
+ 	ATH79_MACH_CF_E520N,			/* COMFAST CF-E520N */
+ 	ATH79_MACH_CF_E530N,			/* COMFAST CF-E530N */
+-	ATH79_MACH_CPE210,			/* TP-LINK CPE210 */
++	ATH79_MACH_CPE210,			/* TP-LINK CPE210 v1 */
++	ATH79_MACH_CPE210_V2,			/* TP-LINK CPE210 v2 */
+ 	ATH79_MACH_CPE510,			/* TP-LINK CPE510 */
+ 	ATH79_MACH_CPE830,			/* YunCore CPE830 */
+ 	ATH79_MACH_CPE870,			/* YunCore CPE870 */
+diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk
+index 6a3faef518ebfa4f36d3074ee9c102b801e04275..b61ef6dc78918dd8d040c0f2bfb6451e5e13ba92 100644
+--- a/target/linux/ar71xx/image/tp-link.mk
++++ b/target/linux/ar71xx/image/tp-link.mk
+@@ -164,22 +164,26 @@ define Device/archer-c60-v1
+ endef
+ TARGET_DEVICES += archer-c60-v1
+ 
+-define Device/cpe510-520
+-  DEVICE_TITLE := TP-LINK CPE510/520
++define Device/cpexxx
+   DEVICE_PACKAGES := rssileds
+   MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,1792k(kernel),5888k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware)
+   IMAGE_SIZE := 7680k
+-  BOARDNAME := CPE510
+-  TPLINK_BOARD_NAME := CPE510
+   DEVICE_PROFILE := CPE510
+   LOADER_TYPE := elf
++  IMAGES := sysupgrade.bin factory.bin
++  IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade
++  IMAGE/factory.bin := append-rootfs | tplink-safeloader factory
++endef
++
++define Device/cpe510-520
++  $(Device/cpexxx)
++  DEVICE_TITLE := TP-LINK CPE510/520 v1
++  BOARDNAME := CPE510
++  TPLINK_BOARD_NAME := CPE510
+   LOADER_FLASH_OFFS := 0x43000
+   COMPILE := loader-$(1).elf
+   COMPILE/loader-$(1).elf := loader-okli-compile
+   KERNEL := kernel-bin | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288
+-  IMAGES := sysupgrade.bin factory.bin
+-  IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade
+-  IMAGE/factory.bin := append-rootfs | tplink-safeloader factory
+ endef
+ 
+ define Device/cpe210-220
+@@ -190,6 +194,19 @@ $(Device/cpe510-520)
+   TPLINK_BOARD_NAME := CPE210
+ endef
+ 
++define Device/cpe210-v2
++  $(Device/cpexxx)
++  DEVICE_TITLE := TP-LINK CPE210 v2
++  BOARDNAME := CPE210V2
++  TPLINK_BOARD_NAME := CPE210V2
++  KERNEL := kernel-bin | patch-cmdline | lzma | mktplinkfw-combined
++  TPLINK_HWID := 0x0
++  TPLINK_HWREV := 0
++  TPLINK_HEADER_VERSION := 1
++  TPLINK_FLASHLAYOUT := 8Mlzma
++endef
++TARGET_DEVICES += cpe210-v2
++
+ define Device/wbs210
+ $(Device/cpe510-520)
+   DEVICE_TITLE := TP-LINK WBS210
+diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c
+index 23b69f3bd0eb66aca650eb2ffd7d5cd2a7cb5194..e6ecc5b2c52c1627c8b998fa731b50ed39649f96 100644
+--- a/tools/firmware-utils/src/tplink-safeloader.c
++++ b/tools/firmware-utils/src/tplink-safeloader.c
+@@ -154,6 +154,48 @@ static struct device_info boards[] = {
+ 		.last_sysupgrade_partition = "support-list",
+ 	},
+ 
++	/** Firmware layout for the CPE210 V2 */
++	{
++		.id     = "CPE210V2",
++		.vendor = "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n",
++		.support_list =
++			"SupportList:\r\n"
++			"CPE210(TP-LINK|EU|N300-2|00000000):2.0\r\n"
++			"CPE210(TP-LINK|EU|N300-2|45550000):2.0\r\n"
++			"CPE210(TP-LINK|EU|N300-2|55530000):2.0\r\n"
++			"CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n"
++			"CPE210(TP-LINK|UN|N300-2|45550000):2.0\r\n"
++			"CPE210(TP-LINK|UN|N300-2|55530000):2.0\r\n"
++			"CPE210(TP-LINK|US|N300-2|55530000):2.0\r\n"
++			"CPE210(TP-LINK|UN|N300-2):2.0\r\n"
++			"CPE210(TP-LINK|EU|N300-2):2.0\r\n"
++			"CPE210(TP-LINK|US|N300-2):2.0\r\n",
++		.support_trail = '\xff',
++		.soft_ver = NULL,
++
++		.partitions = {
++			{"fs-uboot", 0x00000, 0x20000},
++			{"partition-table", 0x20000, 0x02000},
++			{"default-mac", 0x30000, 0x00020},
++			{"product-info", 0x31100, 0x00100},
++			{"device-info", 0x31400, 0x00400},
++			{"signature", 0x32000, 0x00400},
++			{"device-id", 0x33000, 0x00100},
++			{"os-image", 0x40000, 0x1c0000},
++			{"file-system", 0x200000, 0x5b0000},
++			{"soft-version", 0x7b0000, 0x00100},
++			{"support-list", 0x7b1000, 0x01000},
++			{"user-config", 0x7c0000, 0x10000},
++			{"default-config", 0x7d0000, 0x10000},
++			{"log", 0x7e0000, 0x10000},
++			{"radio", 0x7f0000, 0x10000},
++			{NULL, 0, 0}
++		},
++
++		.first_sysupgrade_partition = "os-image",
++		.last_sysupgrade_partition = "support-list",
++	},
++
+ 	/** Firmware layout for the CPE510/520 */
+ 	{
+ 		.id	= "CPE510",
diff --git a/targets/ar71xx-generic b/targets/ar71xx-generic
index ee97e5f0c..0aaef371d 100644
--- a/targets/ar71xx-generic
+++ b/targets/ar71xx-generic
@@ -160,6 +160,8 @@ device tp-link-cpe210-v1.0 cpe210-220
 alias tp-link-cpe210-v1.1
 alias tp-link-cpe220-v1.1
 
+device tp-link-cpe210-v2.0 cpe210-v2
+
 device tp-link-cpe510-v1.0 cpe510-520
 alias tp-link-cpe510-v1.1
 alias tp-link-cpe520-v1.1
-- 
GitLab