ipq806x: add support for Linksys EA7500 V1
authorPawel Dembicki <paweldembicki@gmail.com>
Tue, 26 May 2020 19:14:11 +0000 (21:14 +0200)
committerPetr Štetiar <ynezz@true.cz>
Wed, 8 Jul 2020 14:07:05 +0000 (16:07 +0200)
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>
package/boot/uboot-envtools/files/ipq806x
target/linux/ipq806x/base-files/etc/board.d/02_network
target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
target/linux/ipq806x/base-files/etc/init.d/bootcount
target/linux/ipq806x/base-files/lib/upgrade/platform.sh
target/linux/ipq806x/files-5.4/arch/arm/boot/dts/qcom-ipq8064-ea7500-v1.dts [new file with mode: 0644]
target/linux/ipq806x/image/Makefile
target/linux/ipq806x/patches-5.4/0067-generic-Mangle-bootloader-s-kernel-arguments.patch
target/linux/ipq806x/patches-5.4/0069-arm-boot-add-dts-files.patch

index c27bea71c156761210d49e520ec5603bd99e63b1..e2f2e611cd2754a374ffcd950b33f2e7a3a14292 100644 (file)
@@ -31,6 +31,7 @@ ubootenv_mtdinfo () {
 }
 
 case "$board" in
+linksys,ea7500-v1 |\
 linksys,ea8500)
        ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000"
        ;;
index a3aa0fce7071f6b9ce14f457d922b67080b88eb6..65946d7ac50dc20d777993e9d342ae7851073f76 100755 (executable)
@@ -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" \
index bb505d642fee300f5c1cab40df9919d7a453345c..8b4942dee1a339d280f7f1576a569ef92dc15969 100644 (file)
@@ -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)
index d0bf708e66a98fead97a1ffc949d3c4debd4f43c..6e57c72e51a0c106ed26a44d69872e18b15c62f6 100755 (executable)
@@ -4,6 +4,7 @@ START=99
 
 boot() {
        case $(board_name) in
+       linksys,ea7500-v1 |\
        linksys,ea8500)
                mtd resetbc s_env || true
                ;;
index 2be25f4a9c9d5a03f1a99d7a461a0a674eab4aea..560e64af3a7f51c924554a10138bcff66e84e75a 100644 (file)
@@ -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 (file)
index 0000000..6454fae
--- /dev/null
@@ -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";
+};
index 578303e9e066faf3e2b0f8b71130d09c4b9725d3..5cc66daa21f8763bc894b7159798314766b58c2f 100644 (file)
@@ -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
index 396309d2030ad4b83c3840809a6c5623cb53c045..99a64ccadc7ce943aa113f14d7a9137c12d8ddd7 100644 (file)
@@ -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);
        }
index 1d21703bddfb5e6d56595600b296a35457357671..8cdd198c2959293b078fcaec0cc5c662eabd4417 100644 (file)
@@ -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 \