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>
master
Pawel Dembicki 2020-05-26 21:14:11 +02:00 committed by Petr Štetiar
parent d64b20da21
commit 20c7abd4b7
9 changed files with 375 additions and 22 deletions

View File

@ -31,6 +31,7 @@ ubootenv_mtdinfo () {
} }
case "$board" in case "$board" in
linksys,ea7500-v1 |\
linksys,ea8500) linksys,ea8500)
ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000" ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000"
;; ;;

View File

@ -27,6 +27,13 @@ qcom,ipq8064-ap161)
ucidef_add_switch "switch0" \ ucidef_add_switch "switch0" \
"0:lan" "1:lan" "2:lan" "3u@eth1" "6:wan" "4u@eth0" "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) linksys,ea8500)
hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ucidef_add_switch "switch0" \ ucidef_add_switch "switch0" \

View File

@ -13,6 +13,7 @@ case "$FIRMWARE" in
caldata_extract "ART" 0x1000 0x2f20 caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary ART 0x1e) ath10k_patch_mac $(mtd_get_mac_binary ART 0x1e)
;; ;;
linksys,ea7500-v1 |\
linksys,ea8500) linksys,ea8500)
caldata_extract "art" 0x1000 0x2f20 caldata_extract "art" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +1) 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 caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary ART 0x18) ath10k_patch_mac $(mtd_get_mac_binary ART 0x18)
;; ;;
linksys,ea7500-v1 |\
linksys,ea8500) linksys,ea8500)
caldata_extract "art" 0x5000 0x2f20 caldata_extract "art" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2) ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2)

View File

@ -4,6 +4,7 @@ START=99
boot() { boot() {
case $(board_name) in case $(board_name) in
linksys,ea7500-v1 |\
linksys,ea8500) linksys,ea8500)
mtd resetbc s_env || true mtd resetbc s_env || true
;; ;;

View File

@ -27,6 +27,7 @@ platform_do_upgrade() {
zyxel,nbg6817) zyxel,nbg6817)
zyxel_do_upgrade "$1" zyxel_do_upgrade "$1"
;; ;;
linksys,ea7500-v1 |\
linksys,ea8500) linksys,ea8500)
platform_do_upgrade_linksys "$1" platform_do_upgrade_linksys "$1"
;; ;;

View File

@ -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";
};

View File

@ -109,6 +109,23 @@ define Device/compex_wpq864
endef endef
TARGET_DEVICES += compex_wpq864 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 define Device/linksys_ea8500
$(call Device/LegacyImage) $(call Device/LegacyImage)
DEVICE_VENDOR := Linksys DEVICE_VENDOR := Linksys

View File

@ -51,41 +51,62 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
#else #else
#define do_extend_cmdline 0 #define do_extend_cmdline 0
#endif #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; return cell_size;
} }
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +#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) +static char *append_rootblock(char *dest, const char *str, int len, void *fdt)
+{ +{
+ char *ptr, *end; + char *ptr, *end, *tmp;
+ char *root="root="; + char *root="root=";
+ char *find_rootblock;
+ int i, l; + int i, l;
+ const char *rootblock; + const char *rootblock;
+ +
+ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually + find_rootblock = getprop(fdt, "/chosen", "find-rootblock", &l);
+ ptr = str - 1; + if(!find_rootblock)
+ find_rootblock = root;
+ +
+ do { + //ARM doesn't have __HAVE_ARCH_STRSTR, so it was copied from x86
+ //first find an 'r' at the begining or after a space + ptr = local_strstr(str, find_rootblock);
+ do {
+ ptr++;
+ ptr = strchr(ptr, 'r');
+ if(!ptr) return dest;
+ +
+ } while (ptr != str && *(ptr-1) != ' '); + if(!ptr)
+ + return dest;
+ //then check for the rest
+ for(i = 1; i <= 4; i++)
+ if(*(ptr+i) != *(root+i)) break;
+
+ } while (i != 5);
+ +
+ end = strchr(ptr, ' '); + end = strchr(ptr, ' ');
+ end = end ? (end - 1) : (strchr(ptr, 0) - 1); + 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++); + for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++);
+ ptr = end + 1; + 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) static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
{ {
char cmdline[COMMAND_LINE_SIZE]; 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 */ /* and append the ATAG_CMDLINE */
if (fdt_cmdline) { if (fdt_cmdline) {
@ -133,7 +154,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
} }
*ptr = '\0'; *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 else
setprop_string(fdt, "/chosen", "bootargs", setprop_string(fdt, "/chosen", "bootargs",
atag->u.cmdline.cmdline); atag->u.cmdline.cmdline);
@ -144,7 +165,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
if (memcount >= sizeof(mem_reg_property)/4) if (memcount >= sizeof(mem_reg_property)/4)
continue; continue;
if (!atag->u.mem.size) 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, setprop(fdt, "/memory", "reg", mem_reg_property,
4 * memcount * memsize); 4 * memcount * memsize);
} }

View File

@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
--- a/arch/arm/boot/dts/Makefile --- a/arch/arm/boot/dts/Makefile
+++ b/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-c1.dtb \
qcom-ipq4019-ap.dk07.1-c2.dtb \ qcom-ipq4019-ap.dk07.1-c2.dtb \
qcom-ipq8064-ap148.dtb \ qcom-ipq8064-ap148.dtb \
@ -18,6 +18,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
+ qcom-ipq8064-d7800.dtb \ + qcom-ipq8064-d7800.dtb \
+ qcom-ipq8064-db149.dtb \ + qcom-ipq8064-db149.dtb \
+ qcom-ipq8064-ap161.dtb \ + qcom-ipq8064-ap161.dtb \
+ qcom-ipq8064-ea7500-v1.dtb \
+ qcom-ipq8064-ea8500.dtb \ + qcom-ipq8064-ea8500.dtb \
+ qcom-ipq8064-r7500.dtb \ + qcom-ipq8064-r7500.dtb \
+ qcom-ipq8064-r7500v2.dtb \ + qcom-ipq8064-r7500v2.dtb \