qualcommax: ipq50xx: add support for Linksys SPNMX56

The SPNMX56 is an ISP-branded and distributed device similar to the MX5500
with the same Wifi chips (IPQ5018 for 2.4G and QCN9074 for 5G) but has an
additional QCA8081 PHY providing a 2.5gbps ethernet WAN port.

Speficiations:
* SoC: Qualcomm IPQ5018 (64-bit dual-core ARM Cortex-A53 @ 1.0Ghz)
* Memory: Winbond W634GU6NB-11 (512 MiB DDR3-933)
* Serial Port: 3v3 TTL 115200n8
* Wi-Fi: IPQ5018 (2x2 2.4 Ghz 802.11b/g/n/ax)
         QCN9024 (4x4:4 5 Ghz 802.11an/ac/ax)
* Ethernet: IPQ5018 integrated virtual switch connected to an external
            QCA8337 switch (3 Ports 10/100/1000 GBASE-T) and a
            QCA8081 phy (up to 2.5 Gbps)
* Flash: Gigadevice GD5F2GM7RExxG (256 MiB)
* LEDs: 1x multi-color PWM LED
* Buttons: 1x WPS (GPIO 27 Active Low)
           1x Reset (GPIO 28 Acive Low)

Flash instructions:
1. On OEM firmware, login to the device (typically at http://192.168.1.1)
and click 'CA' in the bottom right corner -> Connectivity ->
Manual Upgrade. Alternatively, browse to http://<router IP>/fwupdate.html
Upload openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin
Optionally flash 2nd partition, after first boot check actual partition:
fw_printenv -n boot_part
and install firmware on second partition using command in case of 2:
mtd -r -e kernel -n write openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin kernel
and in case of 1:
mtd -r -e alt_kernel -n write openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin alt_kernel
2. Installation using serial connection from OEM firmware
hit Enter once booted and enter credentials (login: root, password: admin)
fw_printenv -n boot_part
In case of 2:
flash_erase /dev/mtd12 0 0
nandwrite -p /dev/mtd12 openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin
or in case of 1:
flash_erase /dev/mtd14 0 0
nandwrite -p /dev/mtd14 openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin
After first boot install firmware on second partition:
mtd -r -e kernel -n write openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin kernel
or:
mtd -r -e alt_kernel -n write openwrt-qualcommax-ipq50xx-linksys_spnmx56-squashfs-factory.bin alt_kernel
3. Back to the OEM firmware.
Download firmware from OEM website:
Firmware for this device cannot be searched for on the Linksys website.
Instead, we'd have to use serial to intercept the URL of the firmware
while it's trying to update. Firmware is ISP specific:
Toob (UK): http://download.linksys.com/updates/20241125t080737/FW_MX56TB_1.0.1.216218_prod.img

The intention is to collect URLs for different ISPs on a wiki page.

From serial or SSH:
fw_printenv boot_part
in case of 1:
mtd -r -e alt_kernel -n write FW_MX56TB_1.0.1.216218_prod.img alt_kernel
else in case of 2:
mtd -r -e kernel -n write FW_MX56TB_1.0.1.216218_prod.img kernel

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/17968
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
George Moussalem 2025-01-08 10:21:30 +04:00 committed by Robert Marko
parent 31dc43daf5
commit fe379eb1c1
8 changed files with 266 additions and 7 deletions

View File

@ -9,7 +9,8 @@ board=$(board_name)
case "$board" in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
idx="$(find_mtd_index u_env)"
[ -n "$idx" ] && \
ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000"

View File

@ -45,6 +45,7 @@ ALLWIFIBOARDS:= \
linksys_mx5300 \
linksys_mx5500 \
linksys_mx8500 \
linksys_spnmx56 \
linksys_whw03 \
netgear_lbr20 \
netgear_rax120v2 \
@ -184,6 +185,7 @@ $(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200))
$(eval $(call generate-ipq-wifi-package,linksys_mx5300,Linksys MX5300))
$(eval $(call generate-ipq-wifi-package,linksys_mx5500,Linksys MX5500))
$(eval $(call generate-ipq-wifi-package,linksys_mx8500,Linksys MX8500))
$(eval $(call generate-ipq-wifi-package,linksys_spnmx56,Linksys SPNMX56))
$(eval $(call generate-ipq-wifi-package,linksys_whw03,Linksys WHW03))
$(eval $(call generate-ipq-wifi-package,netgear_lbr20,Netgear LBR20))
$(eval $(call generate-ipq-wifi-package,netgear_rax120v2,Netgear RAX120v2))

View File

@ -0,0 +1,240 @@
/dts-v1/;
#include "ipq5018.dtsi"
#include "ipq5018-mx-base.dtsi"
/ {
model = "Linksys SPNMX56";
compatible = "linksys,spnmx56", "qcom,ipq5018";
};
/*
* =================================================================
* _______________________ _______________________
* | IPQ5018 | | QCA8337 |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC0 |---| GE Phy |-+--- MDI ---+ | Phy4 |---| MAC5 | |
* | +------+ +--------+ | | +--------+ +------+ |
* | | |_______________________|
* | | _______________________
* | | | QCA8081 |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC1 |---| Uniphy |-+-- SGMII+--+ | Phy |---| MAC | |
* | +------+ +--------+ | | +--------+ +------+ |
* |_______________________| |_______________________|
*
* =================================================================
*/
&switch {
status = "okay";
switch_mac_mode = <MAC_MODE_SGMII_CHANNEL0>;
qcom,port_phyinfo {
// MAC0 -> GE Phy --- MDI --- QCA8337 Switch
port@0 {
port_id = <1>;
mdiobus = <&mdio0>;
phy_address = <7>;
phy_dac = <0x10 0x10>;
};
// MAC1 -> Uniphy --- SGMII --- QCA8081
port@1 {
port_id = <2>;
mdiobus = <&mdio1>;
phy_address = <28>;
port_mac_sel = "QGMAC_PORT";
};
};
};
// MAC0 -> GE Phy
&dp1 {
status = "okay";
};
// MAC1 ---SGMII---> QCA8081
&dp2 {
status = "okay";
label = "wan";
phy-handle = <&qca8081>;
};
&mdio0 {
status = "okay";
};
// IPQ5018 GE Phy -> QCA8337 PHY4
&ge_phy {
qcom,dac = <0x10 0x10>;
};
&mdio1 {
status = "okay";
pinctrl-0 = <&mdio1_pins>;
pinctrl-names = "default";
reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
// Not connected
qca8337_0: ethernet-phy@0 {
reg = <0>;
};
// QCA8337 Phy1 -> LAN1
qca8337_1: ethernet-phy@1 {
reg = <1>;
};
// QCA8337 Phy2 -> LAN2
qca8337_2: ethernet-phy@2 {
reg = <2>;
};
// QCA8337 Phy3 -> LAN3
qca8337_3: ethernet-phy@3 {
reg = <3>;
};
// QCA8337 Phy4 -> MDI -> IPQ5018 GE PHY
qca8337_4: ethernet-phy@4 {
reg = <4>;
};
// QCA8081 Phy -> WAN
qca8081: ethernet-phy@28 {
compatible = "ethernet-phy-id004d.d101";
reg = <28>;
reset-deassert-us = <10000>;
reset-gpios = <&tlmm 24 GPIO_ACTIVE_LOW>;
};
// QCA8337 switch
switch1: ethernet-switch@17 {
compatible = "qca,qca8337";
reg = <17>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@2 {
reg = <2>;
label = "lan3";
phy-handle = <&qca8337_1>;
};
port@3 {
reg = <3>;
label = "lan2";
phy-handle = <&qca8337_2>;
};
port@4 {
reg = <4>;
label = "lan1";
phy-handle = <&qca8337_3>;
};
port@5 {
reg = <5>;
phy-handle = <&qca8337_4>;
phy-mode = "gmii";
ethernet = <&dp1>;
};
};
};
};
&pcie0_phy {
status = "okay";
};
&pcie0 {
status = "okay";
perst-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>;
bridge@0,0 {
reg = <0x00000000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
ranges;
wifi@1,0 {
status = "okay";
/* QCN9074: ath11k lacks DT compatible for PCI cards */
compatible = "pci17cb,1104";
reg = <0x00010000 0 0 0 0>;
qcom,ath11k-calibration-variant = "Linksys-SPNMX56";
};
};
};
&q6v5_wcss {
status = "okay";
memory-region = <&q6_mem_regions>;
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt",
"ath11k/IPQ5018/hw1.0/m3_fw.mdt";
// IPQ5018
q6_wcss_pd1: pd-1 {
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt";
resets =
<&gcc GCC_WCSSAON_RESET>,
<&gcc GCC_WCSS_BCR>,
<&gcc GCC_CE_BCR>;
reset-names =
"wcss_aon_reset",
"wcss_reset",
"ce_reset";
clocks =
<&gcc GCC_WCSS_AHB_S_CLK>,
<&gcc GCC_WCSS_ACMT_CLK>,
<&gcc GCC_WCSS_AXI_M_CLK>;
clock-names =
"gcc_wcss_ahb_s_clk",
"gcc_wcss_acmt_clk",
"gcc_wcss_axi_m_clk";
interrupts-extended =
<&wcss_smp2p_in 8 0>,
<&wcss_smp2p_in 9 0>,
<&wcss_smp2p_in 12 0>,
<&wcss_smp2p_in 11 0>;
interrupt-names =
"fatal",
"ready",
"spawn-ack",
"stop-ack";
qcom,smem-states =
<&wcss_smp2p_out 8>,
<&wcss_smp2p_out 9>,
<&wcss_smp2p_out 10>;
qcom,smem-state-names =
"shutdown",
"stop",
"spawn";
};
};
&wifi0 {
// IPQ5018
qcom,rproc = <&q6_wcss_pd1>;
qcom,ath11k-calibration-variant = "Linksys-SPNMX56";
qcom,ath11k-fw-memory-mode = <2>;
qcom,bdf-addr = <0x4c400000>;
status = "okay";
};

View File

@ -29,3 +29,13 @@ define Device/linksys_mx5500
ipq-wifi-linksys_mx5500
endef
TARGET_DEVICES += linksys_mx5500
define Device/linksys_spnmx56
$(call Device/linksys_ipq50xx_mx_base)
DEVICE_MODEL := SPNMX56
DEVICE_DTS_CONFIG := config@mp03.1
DEVICE_PACKAGES := kmod-ath11k-pci \
ath11k-firmware-qcn9074 \
ipq-wifi-linksys_spnmx56
endef
TARGET_DEVICES += linksys_spnmx56

View File

@ -8,7 +8,8 @@ ipq50xx_setup_interfaces()
local board="$1"
case $board in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan"
;;
esac
@ -23,7 +24,8 @@ ipq50xx_setup_macs()
case "$board" in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
lan_mac=$label_mac
wan_mac=$label_mac

View File

@ -10,7 +10,8 @@ case "$FIRMWARE" in
"ath11k/IPQ5018/hw1.0/cal-ahb-c000000.wifi.bin")
case "$board" in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
caldata_extract "0:ART" 0x1000 0x20000
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ath11k_patch_mac $(macaddr_add $label_mac 1) 0
@ -32,7 +33,8 @@ case "$FIRMWARE" in
;;
"ath11k/QCN9074/hw1.0/cal-pci-0001:01:00.0.bin")
case "$board" in
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
caldata_extract "0:ART" 0x26800 0x20000
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ath11k_patch_mac $(macaddr_add $label_mac 2) 0

View File

@ -5,7 +5,8 @@ START=99
boot() {
case $(board_name) in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
mtd resetbc s_env || true
;;
esac

View File

@ -73,7 +73,8 @@ platform_check_image() {
platform_do_upgrade() {
case "$(board_name)" in
linksys,mx2000|\
linksys,mx5500)
linksys,mx5500|\
linksys,spnmx56)
remove_oem_ubi_volume rootfs
linksys_mx_do_upgrade "$1"
;;