From: Pawel Dembicki <paweldembicki@gmail.com>
Date: Tue, 26 May 2020 19:14:11 +0000 (+0200)
Subject: ipq806x: add support for Linksys EA7500 V1
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=20c7abd4b7b9b4203b6858136b2c811b6dbd8dae;p=openwrt%2Fstaging%2Fzorun.git

ipq806x: add support for Linksys EA7500 V1

This patch adds support for the Linksys EA7500 V1 router.

Specification:
 - CPU: Qualcomm IPQ8064
 - RAM: 256MB
 - Flash: NAND 128MB
 - WiFi: QCA9982 an+ac + QCA9983 bgn
 - Ethernet: 5 GBE Ports (WAN+ 4xLAN) (QCA8337)
 - USB: 1x USB 3.0 1x USB2.0
 - Serial console: RJ-45 115200 8n1 (1V8 Voltage level)
 - 2 Buttons
 - 1 LED

Known issues:
 - Some devices won't flash via web gui

Installation:
- Newer stock images doesn't allow to install custom firmware.
- Please downgrade software to 1.1.2 version. Official firmware:
https://downloads.linksys.com/downloads/firmware/FW_EA7500_1.1.2.172843_prod.gpg.img
- Do it two times to downgrade all stored images.
- Apply factory image via web-gui.

Serial + TFTP method:
 - downgrade to 1.1.2 two times
 - connect ehternet and serial cable
 - set ip address of tftp server to 192.168.1.254
 - put openwrt factory image to tftp folder and rename it to macan.bin
 - stop device while booting in u-boot
 - run command: "run flashimg"
 - run command: "setenv boot_part 1"
 - run command "saveenv"
 - reset

Back to stock:
- Please use old non-gpg image like this 1.1.2:
https://downloads.linksys.com/downloads/firmware/FW_EA7500_1.1.2.172843_prod.img
- ssh to router and copy image to tmp
- use sysupgrade -n -F

Tested by github users: @jack338c and @grzesiczek1

Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
[removed i2c4_pins, mdio0_pins, nand_pins, rgmii2_pins from DTSI]
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
---

diff --git a/package/boot/uboot-envtools/files/ipq806x b/package/boot/uboot-envtools/files/ipq806x
index c27bea71c1..e2f2e611cd 100644
--- a/package/boot/uboot-envtools/files/ipq806x
+++ b/package/boot/uboot-envtools/files/ipq806x
@@ -31,6 +31,7 @@ ubootenv_mtdinfo () {
 }
 
 case "$board" in
+linksys,ea7500-v1 |\
 linksys,ea8500)
 	ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000"
 	;;
diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network
index a3aa0fce70..65946d7ac5 100755
--- a/target/linux/ipq806x/base-files/etc/board.d/02_network
+++ b/target/linux/ipq806x/base-files/etc/board.d/02_network
@@ -27,6 +27,13 @@ qcom,ipq8064-ap161)
 	ucidef_add_switch "switch0" \
 		"0:lan" "1:lan" "2:lan" "3u@eth1" "6:wan" "4u@eth0"
 	;;
+linksys,ea7500-v1)
+	hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
+	ucidef_add_switch "switch0" \
+		"2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "6@eth1" "1:wan" "0@eth0"
+	ucidef_set_interface_macaddr "lan" "$hw_mac_addr"
+	ucidef_set_interface_macaddr "wan" "$hw_mac_addr"
+	;;
 linksys,ea8500)
 	hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
 	ucidef_add_switch "switch0" \
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index bb505d642f..8b4942dee1 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -13,6 +13,7 @@ case "$FIRMWARE" in
 		caldata_extract "ART" 0x1000 0x2f20
 		ath10k_patch_mac $(mtd_get_mac_binary ART 0x1e)
 		;;
+	linksys,ea7500-v1 |\
 	linksys,ea8500)
 		caldata_extract "art" 0x1000 0x2f20
 		ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +1)
@@ -47,6 +48,7 @@ case "$FIRMWARE" in
 		caldata_extract "ART" 0x5000 0x2f20
 		ath10k_patch_mac $(mtd_get_mac_binary ART 0x18)
 		;;
+	linksys,ea7500-v1 |\
 	linksys,ea8500)
 		caldata_extract "art" 0x5000 0x2f20
 		ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2)
diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount
index d0bf708e66..6e57c72e51 100755
--- a/target/linux/ipq806x/base-files/etc/init.d/bootcount
+++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount
@@ -4,6 +4,7 @@ START=99
 
 boot() {
 	case $(board_name) in
+	linksys,ea7500-v1 |\
 	linksys,ea8500)
 		mtd resetbc s_env || true
 		;;
diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
index 2be25f4a9c..560e64af3a 100644
--- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
@@ -27,6 +27,7 @@ platform_do_upgrade() {
 	zyxel,nbg6817)
 		zyxel_do_upgrade "$1"
 		;;
+	linksys,ea7500-v1 |\
 	linksys,ea8500)
 		platform_do_upgrade_linksys "$1"
 		;;
diff --git a/target/linux/ipq806x/files-5.4/arch/arm/boot/dts/qcom-ipq8064-ea7500-v1.dts b/target/linux/ipq806x/files-5.4/arch/arm/boot/dts/qcom-ipq8064-ea7500-v1.dts
new file mode 100644
index 0000000000..6454fae7f7
--- /dev/null
+++ b/target/linux/ipq806x/files-5.4/arch/arm/boot/dts/qcom-ipq8064-ea7500-v1.dts
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+#include "qcom-ipq8064-v2.0.dtsi"
+
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Linksys EA7500 V1 WiFi Router";
+	compatible = "linksys,ea7500-v1", "qcom,ipq8064";
+
+	memory@0 {
+		reg = <0x42000000 0xe000000>;
+		device_type = "memory";
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		rsvd@41200000 {
+			reg = <0x41200000 0x300000>;
+			no-map;
+		};
+	};
+
+	aliases {
+		serial0 = &gsbi4_serial;
+
+		led-boot = &led_power;
+		led-failsafe = &led_power;
+		led-running = &led_power;
+		led-upgrade = &led_power;
+	};
+
+	chosen {
+		bootargs = "console=ttyMSM0,115200n8";
+		stdout-path = "serial0:115200n8";
+		append-rootblock = "ubi.mtd=";  /* append to bootargs adding the root deviceblock nbr from bootloader */
+		find-rootblock = "ubi.mtd=";  /* look for root deviceblock nbr in this bootarg */
+	};
+
+	keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&button_pins>;
+		pinctrl-names = "default";
+
+		reset {
+			label = "reset";
+			gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+
+		wps {
+			label = "wps";
+			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WPS_BUTTON>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&led_pins>;
+		pinctrl-names = "default";
+
+		led_power: power {
+			label = "ea7500-v1:white:power";
+			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>;
+			default-state = "keep";
+		};
+	};
+};
+
+&qcom_pinmux {
+	button_pins: button_pins {
+		mux {
+			pins = "gpio65", "gpio68";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+
+	led_pins: led_pins {
+		mux {
+			pins = "gpio6";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+};
+
+&gsbi4 {
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+	status = "okay";
+	serial@16340000 {
+		status = "okay";
+	};
+	/*
+	* The i2c device on gsbi4 should not be enabled.
+	* On ipq806x designs gsbi4 i2c is meant for exclusive
+	* RPM usage. Turning this on in kernel manifests as
+	* i2c failure for the RPM.
+	*/
+};
+
+&usb3_0 {
+	status = "okay";
+};
+
+&usb3_1 {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+	force_gen1 = <1>;
+};
+
+&pcie1 {
+	status = "okay";
+};
+
+&pcie2 {
+	status = "okay";
+};
+
+&nand_controller {
+	status = "okay";
+
+	pinctrl-0 = <&nand_pins>;
+	pinctrl-names = "default";
+
+	nand@0 {
+		reg = <0>;
+		compatible = "qcom,nandcs";
+
+		nand-ecc-strength = <4>;
+		nand-bus-width = <8>;
+		nand-ecc-step-size = <512>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "SBL1";
+				reg = <0x0000000 0x0040000>;
+				read-only;
+			};
+
+			partition@40000 {
+				label = "MIBIB";
+				reg = <0x0040000 0x0140000>;
+				read-only;
+			};
+
+			partition@180000 {
+				label = "SBL2";
+				reg = <0x0180000 0x0140000>;
+				read-only;
+			};
+
+			partition@2c0000 {
+				label = "SBL3";
+				reg = <0x02c0000 0x0280000>;
+				read-only;
+			};
+
+			partition@540000 {
+				label = "DDRCONFIG";
+				reg = <0x0540000 0x0120000>;
+				read-only;
+			};
+
+			partition@660000 {
+				label = "SSD";
+				reg = <0x0660000 0x0120000>;
+				read-only;
+			};
+
+			partition@780000 {
+				label = "TZ";
+				reg = <0x0780000 0x0280000>;
+				read-only;
+			};
+
+			partition@a00000 {
+				label = "RPM";
+				reg = <0x0a00000 0x0280000>;
+				read-only;
+			};
+
+			art: partition@c80000 {
+				label = "art";
+				reg = <0x0c80000 0x0140000>;
+				read-only;
+			};
+
+			partition@dc0000 {
+				label = "APPSBL";
+				reg = <0x0dc0000 0x0100000>;
+				read-only;
+			};
+
+			partition@ec0000 {
+				label = "u_env";
+				reg = <0x0ec0000 0x0040000>;
+			};
+
+			partition@f00000 {
+				label = "s_env";
+				reg = <0x0f00000 0x0040000>;
+			};
+
+			partition@f40000 {
+				label = "devinfo";
+				reg = <0x0f40000 0x0040000>;
+			};
+
+			partition@f80000 {
+				label = "kernel1";
+				reg = <0x0f80000 0x2800000>;  /* 3 MB spill to rootfs*/
+			};
+
+			partition@1280000 {
+				label = "rootfs1";
+				reg = <0x1280000 0x2500000>;
+			};
+
+			partition@3780000 {
+				label = "kernel2";
+				reg = <0x3780000 0x2800000>;
+			};
+
+			partition@3a80000 {
+				label = "rootfs2";
+				reg = <0x3a80000 0x2500000>;
+			};
+
+			partition@5f80000 {
+				label = "sysdiag";
+				reg = <0x5f80000 0x100000>;
+			};
+
+			partition@6080000 {
+				label = "syscfg";
+				reg = <0x6080000 0x1f80000>;
+			};
+		};
+	};
+};
+
+&mdio0 {
+	status = "okay";
+
+	pinctrl-0 = <&mdio0_pins>;
+	pinctrl-names = "default";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		qca,ar8327-initvals = <
+			0x00004 0x7600000   /* PAD0_MODE */
+			0x00008 0x1000000   /* PAD5_MODE */
+			0x0000c 0x80        /* PAD6_MODE */
+			0x00010 0x2613a0    /* PWS_REG */
+			0x000e4 0x6a545     /* MAC_POWER_SEL */
+			0x000e0 0xc74164de  /* SGMII_CTRL */
+			0x0007c 0x4e        /* PORT0_STATUS */
+			0x00094 0x4e        /* PORT6_STATUS */
+			>;
+	};
+};
+
+&gmac1 {
+	status = "okay";
+	phy-mode = "rgmii";
+	qcom,id = <1>;
+
+	pinctrl-0 = <&rgmii2_pins>;
+	pinctrl-names = "default";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&gmac2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	qcom,id = <2>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&adm_dma {
+	status = "okay";
+};
diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile
index 578303e9e0..5cc66daa21 100644
--- a/target/linux/ipq806x/image/Makefile
+++ b/target/linux/ipq806x/image/Makefile
@@ -109,6 +109,23 @@ define Device/compex_wpq864
 endef
 TARGET_DEVICES += compex_wpq864
 
+define Device/linksys_ea7500-v1
+	$(call Device/LegacyImage)
+	DEVICE_VENDOR := Linksys
+	DEVICE_MODEL := EA7500
+	DEVICE_VARIANT := v1
+	SOC := qcom-ipq8064
+	PAGESIZE := 2048
+	BLOCKSIZE := 128k
+	KERNEL_SIZE := 3072k
+	KERNEL = kernel-bin | append-dtb | uImage none | append-uImage-fakehdr filesystem
+	UBINIZE_OPTS := -E 5
+	IMAGES := factory.bin sysupgrade.bin
+	IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | pad-to $$$$(PAGESIZE)
+	DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct
+endef
+TARGET_DEVICES += linksys_ea7500-v1
+
 define Device/linksys_ea8500
 	$(call Device/LegacyImage)
 	DEVICE_VENDOR := Linksys
diff --git a/target/linux/ipq806x/patches-5.4/0067-generic-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/ipq806x/patches-5.4/0067-generic-Mangle-bootloader-s-kernel-arguments.patch
index 396309d203..99a64ccadc 100644
--- a/target/linux/ipq806x/patches-5.4/0067-generic-Mangle-bootloader-s-kernel-arguments.patch
+++ b/target/linux/ipq806x/patches-5.4/0067-generic-Mangle-bootloader-s-kernel-arguments.patch
@@ -51,41 +51,62 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
  #else
  #define do_extend_cmdline 0
  #endif
-@@ -67,6 +69,59 @@ static uint32_t get_cell_size(const void
+@@ -67,6 +69,80 @@ static uint32_t get_cell_size(const void
  	return cell_size;
  }
  
 +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
++/**
++ * taken from arch/x86/boot/string.c
++ * local_strstr - Find the first substring in a %NUL terminated string
++ * @s1: The string to be searched
++ * @s2: The string to search for
++ */
++static char *local_strstr(const char *s1, const char *s2)
++{
++	size_t l1, l2;
++
++	l2 = strlen(s2);
++	if (!l2)
++		return (char *)s1;
++	l1 = strlen(s1);
++	while (l1 >= l2) {
++		l1--;
++		if (!memcmp(s1, s2, l2))
++			return (char *)s1;
++		s1++;
++	}
++	return NULL;
++}
 +
 +static char *append_rootblock(char *dest, const char *str, int len, void *fdt)
 +{
-+	char *ptr, *end;
++	char *ptr, *end, *tmp;
 +	char *root="root=";
++	char *find_rootblock;
 +	int i, l;
 +	const char *rootblock;
 +
-+	//ARM doesn't have __HAVE_ARCH_STRSTR, so search manually
-+	ptr = str - 1;
-+
-+	do {
-+		//first find an 'r' at the begining or after a space
-+		do {
-+			ptr++;
-+			ptr = strchr(ptr, 'r');
-+			if(!ptr) return dest;
++	find_rootblock = getprop(fdt, "/chosen", "find-rootblock", &l);
++	if(!find_rootblock)
++		find_rootblock = root;
 +
-+		} while (ptr != str && *(ptr-1) != ' ');
++	//ARM doesn't have __HAVE_ARCH_STRSTR, so it was copied from x86
++	ptr = local_strstr(str, find_rootblock);
 +
-+		//then check for the rest
-+		for(i = 1; i <= 4; i++)
-+			if(*(ptr+i) != *(root+i)) break;
-+
-+	} while (i != 5);
++	if(!ptr)
++		return dest;
 +
 +	end = strchr(ptr, ' ');
 +	end = end ? (end - 1) : (strchr(ptr, 0) - 1);
 +
-+	//find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX )
++	// Some boards ubi.mtd=XX,ZZZZ, so let's check for '," too.
++	tmp = strchr(ptr, ',');
++
++	if(tmp)
++		end = end < tmp ? end : tmp - 1;
++
++	//find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX | ubi.mtd=XX,ZZZZ )
 +	for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++);
 +	ptr = end + 1;
 +
@@ -111,7 +132,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
  static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
  {
  	char cmdline[COMMAND_LINE_SIZE];
-@@ -86,12 +141,21 @@ static void merge_fdt_bootargs(void *fdt
+@@ -86,12 +162,21 @@ static void merge_fdt_bootargs(void *fdt
  
  	/* and append the ATAG_CMDLINE */
  	if (fdt_cmdline) {
@@ -133,7 +154,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
  	}
  	*ptr = '\0';
  
-@@ -166,7 +230,9 @@ int atags_to_fdt(void *atag_list, void *
+@@ -166,7 +251,9 @@ int atags_to_fdt(void *atag_list, void *
  			else
  				setprop_string(fdt, "/chosen", "bootargs",
  					       atag->u.cmdline.cmdline);
@@ -144,7 +165,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
  			if (memcount >= sizeof(mem_reg_property)/4)
  				continue;
  			if (!atag->u.mem.size)
-@@ -210,6 +276,10 @@ int atags_to_fdt(void *atag_list, void *
+@@ -210,6 +297,10 @@ int atags_to_fdt(void *atag_list, void *
  		setprop(fdt, "/memory", "reg", mem_reg_property,
  			4 * memcount * memsize);
  	}
diff --git a/target/linux/ipq806x/patches-5.4/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-5.4/0069-arm-boot-add-dts-files.patch
index 1d21703bdd..8cdd198c29 100644
--- a/target/linux/ipq806x/patches-5.4/0069-arm-boot-add-dts-files.patch
+++ b/target/linux/ipq806x/patches-5.4/0069-arm-boot-add-dts-files.patch
@@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
 
 --- a/arch/arm/boot/dts/Makefile
 +++ b/arch/arm/boot/dts/Makefile
-@@ -843,6 +843,18 @@ dtb-$(CONFIG_ARCH_QCOM) += \
+@@ -843,6 +843,19 @@ dtb-$(CONFIG_ARCH_QCOM) += \
  	qcom-ipq4019-ap.dk07.1-c1.dtb \
  	qcom-ipq4019-ap.dk07.1-c2.dtb \
  	qcom-ipq8064-ap148.dtb \
@@ -18,6 +18,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
 +	qcom-ipq8064-d7800.dtb \
 +	qcom-ipq8064-db149.dtb \
 +	qcom-ipq8064-ap161.dtb \
++	qcom-ipq8064-ea7500-v1.dtb \
 +	qcom-ipq8064-ea8500.dtb \
 +	qcom-ipq8064-r7500.dtb \
 +	qcom-ipq8064-r7500v2.dtb \