Add support for Linksys MX2000 (Atlas 6) and MX5500 (Atlas 6 Pro).
These devices are completely identical except for the secondary wifi
chip used for 5Ghz: QCN6102 is used on MX2000 while QCN9024 is used
on MX5500
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)
* Wi-Fi: MX2000: QCN6102 (2x2:2 5 Ghz 802.11an/ac/ax)
MX5500: QCN9024 (4x4:4 5 Ghz 802.11an/ac/ax)
* Ethernet: IPQ5018 integrated virtual switch connected to an external
QCA8337 switch (4 Ports 10/100/1000 GBASE-T)
* Flash: Macronix MX35UF2GE4AD (256 MiB)
* LEDs: 1x multi-color PWM LED
* Buttons: 1x WPS (GPIO 27 Active Low)
1x Reset (GPIO 28 Acive Low)
Flash instructions (in case of MX2000, else replace with MX5500 images):
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.
Upgrade firmware using openwrt-qualcommax-ipq50xx-linksys_mx2000-squashfs-factory.bin image.
Optionally install on second 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_mx2000-squashfs-factory.bin kernel
and in case of 1:
mtd -r -e alt_kernel -n write openwrt-qualcommax-ipq50xx-linksys_mx2000-squashfs-factory.bin alt_kernel
2. Installation using serial connection from OEM firmware (default 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_mx2000-squashfs-factory.bin
or in case of 1:
flash_erase /dev/mtd14 0 0
nandwrite -p /dev/mtd14 openwrt-qualcommax-ipq50xx-linksys_mx2000-squashfs-factory.bin
After first boot install firmware on second partition:
mtd -r -e kernel -n write openwrt-qualcommax-ipq50xx-linksys_mx2000-squashfs-factory.bin kernel
or:
mtd -r -e alt_kernel -n write openwrt-qualcommax-ipq50xx-linksys_mx2000-squashfs-factory.bin alt_kernel
3. Back to the OEM firmware.
Download firmware from OEM website:
MX2000: https://support.linksys.com/kb/article/585-en/
MX5500: https://support.linksys.com/kb/article/587-en/
From serial or SSH:
fw_printenv boot_part
in case of 1:
mtd -r -e alt_kernel -n write FW_MX2000_1.1.7.210469_prod.img alt_kernel
else in case of 2:
mtd -r -e kernel -n write FW_MX2000_1.1.7.210469_prod.img kernel
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/17182
Signed-off-by: Robert Marko <robimarko@gmail.com>
--- /dev/null
+[ -e /etc/config/ubootenv ] && exit 0
+
+touch /etc/config/ubootenv
+
+. /lib/uboot-envtools.sh
+. /lib/functions.sh
+
+board=$(board_name)
+
+case "$board" in
+linksys,mx2000|\
+linksys,mx5500)
+ idx="$(find_mtd_index u_env)"
+ [ -n "$idx" ] && \
+ ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000"
+ ;;
+esac
+
+config_load ubootenv
+config_foreach ubootenv_add_app_config
+
+exit 0
edimax_cax1800 \
linksys_homewrk \
linksys_mr7350 \
+ linksys_mx2000 \
linksys_mx4200 \
linksys_mx5300 \
+ linksys_mx5500 \
linksys_mx8500 \
linksys_whw03 \
netgear_lbr20 \
$(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800))
$(eval $(call generate-ipq-wifi-package,linksys_homewrk,Linksys HomeWRK))
$(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350))
+$(eval $(call generate-ipq-wifi-package,linksys_mx2000,Linksys MX2000))
$(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_whw03,Linksys WHW03))
$(eval $(call generate-ipq-wifi-package,netgear_lbr20,Netgear LBR20))
--- /dev/null
+#include "ipq5018.dtsi"
+#include "ipq5018-ess.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+
+ aliases {
+ ethernet0 = &dp1;
+ ethernet1 = &dp2;
+ led-boot = &led_system_blue;
+ led-failsafe = &led_system_red;
+ led-running = &led_system_blue;
+ led-upgrade = &led_system_red;
+ serial0 = &blsp1_uart1;
+ };
+
+ chosen {
+ bootargs-append = " root=/dev/ubiblock0_0 coherent_pool=2M";
+ stdout-path = "serial0:115200n8";
+ };
+
+ keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&button_pins>;
+ pinctrl-names = "default";
+
+ wps-button {
+ label = "wps";
+ gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+
+ reset-button {
+ label = "reset";
+ gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+ };
+
+ leds {
+ compatible = "pwm-leds";
+
+ led_system_red: red {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_POWER;
+ pwms = <&pwm 3 1250000>;
+ max-brightness = <255>;
+ };
+
+ green {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_POWER;
+ pwms = <&pwm 0 1250000>;
+ max-brightness = <255>;
+ };
+
+ led_system_blue: blue {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_POWER;
+ pwms = <&pwm 1 1250000>;
+ max-brightness = <255>;
+ };
+ };
+
+ reserved-memory {
+ q6_mem_regions: q6_mem_regions@4b000000 {
+ no-map;
+ reg = <0x0 0x4b000000 0x0 0x3000000>;
+ };
+ };
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&xo_board_clk {
+ clock-frequency = <24000000>;
+};
+
+&blsp1_uart1 {
+ status = "okay";
+
+ pinctrl-0 = <&serial_0_pins>;
+ pinctrl-names = "default";
+};
+
+&crypto {
+ status = "okay";
+};
+
+&cryptobam {
+ status = "okay";
+};
+
+&prng {
+ status = "okay";
+};
+
+&pwm {
+ status = "okay";
+
+ #pwm-cells = <2>;
+ pinctrl-0 = <&pwm_pins>;
+ pinctrl-names = "default";
+};
+
+&qfprom {
+ status = "okay";
+};
+
+&qpic_bam {
+ status = "okay";
+};
+
+&qpic_nand {
+ pinctrl-0 = <&qpic_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ partitions {
+ status = "disabled";
+ };
+
+ nand@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nand-ecc-engine = <&qpic_nand>;
+
+ nand-ecc-strength = <8>;
+ nand-ecc-step-size = <512>;
+ nand-bus-width = <8>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "0:SBL1";
+ reg = <0x00000000 0x80000>;
+ read-only;
+ };
+
+ partition@80000 {
+ label = "0:MIBIB";
+ reg = <0x00080000 0x80000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "0:QSEE";
+ reg = <0x00100000 0x100000>;
+ read-only;
+ };
+
+ partition@200000 {
+ label = "0:DEVCFG";
+ reg = <0x00200000 0x40000>;
+ read-only;
+ };
+
+ partition@240000 {
+ label = "0:CDT";
+ reg = <0x00240000 0x40000>;
+ read-only;
+ };
+
+ partition@280000 {
+ label = "0:APPSBLENV";
+ reg = <0x00280000 0x80000>;
+ };
+
+ partition@300000 {
+ label = "0:APPSBL";
+ reg = <0x00300000 0x140000>;
+ read-only;
+ };
+
+ partition@440000 {
+ label = "0:ART";
+ reg = <0x00440000 0x100000>;
+ read-only;
+ };
+
+ partition@540000 {
+ label = "0:TRAINING";
+ reg = <0x00540000 0x80000>;
+ read-only;
+ };
+
+ partition@5c0000 {
+ label = "u_env";
+ reg = <0x005c0000 0x80000>;
+ };
+
+ partition@640000 {
+ label = "s_env";
+ reg = <0x00640000 0x40000>;
+ };
+
+ partition@680000 {
+ label = "devinfo";
+ reg = <0x00680000 0x40000>;
+ read-only;
+ };
+
+ partition@6c0000 {
+ label = "kernel";
+ reg = <0x006c0000 0x5200000>;
+ };
+
+ partition@ec0000 {
+ label = "rootfs";
+ reg = <0x0ec0000 0x4a00000>;
+ };
+
+ partition@58c0000 {
+ label = "alt_kernel";
+ reg = <0x058c0000 0x5200000>;
+ };
+
+ partition@60c0000 {
+ label = "alt_rootfs";
+ reg = <0x060c0000 0x4a00000>;
+ };
+
+ partition@aac0000 {
+ label = "sysdiag";
+ reg = <0x0aac0000 0x200000>;
+ read-only;
+ };
+
+ partition@acc0000 {
+ label = "syscfg";
+ reg = <0x0acc0000 0x4400000>;
+ read-only;
+ };
+ };
+ };
+};
+
+&tlmm {
+ button_pins: button-state {
+ pins = "gpio27", "gpio28";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ mdio1_pins: mdio-state {
+ mdc-pins {
+ pins = "gpio36";
+ function = "mdc";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ mdio-pins {
+ pins = "gpio37";
+ function = "mdio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ pwm_pins: pwm-state {
+ mux_1 {
+ pins = "gpio1";
+ function = "pwm1";
+ drive-strength = <8>;
+ };
+
+ mux_2 {
+ pins = "gpio30";
+ function = "pwm3";
+ drive-strength = <8>;
+ };
+
+ mux_3 {
+ pins = "gpio46";
+ function = "pwm0";
+ drive-strength = <8>;
+ };
+ };
+
+ qpic_pins: qpic-state {
+ clock-pins {
+ pins = "gpio9";
+ function = "qspi_clk";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ cs-pins {
+ pins = "gpio8";
+ function = "qspi_cs";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ function = "qspi_data";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
+
+ serial_0_pins: uart0-state {
+ pins = "gpio20", "gpio21";
+ function = "blsp0_uart0";
+ bias-disable;
+ };
+};
+
+&tsens {
+ status = "okay";
+};
--- /dev/null
+/dts-v1/;
+
+#include "ipq5018.dtsi"
+#include "ipq5018-mx-base.dtsi"
+
+/ {
+ model = "Linksys MX2000";
+ compatible = "linksys,mx2000", "qcom,ipq5018";
+};
+
+/*
+ * ===============================================================
+ * _______________________ _______________________
+ * | IPQ5018 | | QCA8337 |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | | MAC0 |---| GE Phy | | | | Phy0 |---| MAC1 | |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | | MAC1 |---| Uniphy |-+-SGMII-+-| SerDes |---| MAC6 | |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * |_______________________| |_______________________|
+ *
+ * ===============================================================
+ */
+
+&switch {
+ status = "okay";
+
+ switch_mac_mode = <MAC_MODE_SGMII_CHANNEL0>;
+
+ qcom,port_phyinfo {
+ // MAC0 -> GE Phy -> QCA8337 Phy4
+ port@0 {
+ port_id = <1>;
+ mdiobus = <&mdio0>;
+ phy_address = <7>;
+ };
+
+ // MAC1 ---SGMII---> QCA8337 SerDes
+ port@1 {
+ port_id = <2>;
+ forced-speed = <1000>;
+ forced-duplex = <1>;
+ };
+ };
+};
+
+// MAC1 ---SGMII---> QCA8337 SerDes
+&dp2 {
+ status = "okay";
+ phy-mode = "sgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
+
+&mdio0 {
+ status = "okay";
+};
+
+/* IPQ5018 GE Phy -> Not connected
+ * needs to be enabled for QSDK to identify the IPQ5018 dummy switch
+ */
+&ge_phy {
+ status = "okay";
+};
+
+&mdio1 {
+ status = "okay";
+
+ pinctrl-0 = <&mdio1_pins>;
+ pinctrl-names = "default";
+ reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
+
+ // QCA8337 Phy0 not connected
+ qca8337_0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ // QCA8337 Phy1 -> WAN
+ qca8337_1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ // QCA8337 Phy2 -> LAN1
+ qca8337_2: ethernet-phy@2 {
+ reg = <2>;
+ };
+
+ // QCA8337 Phy3 -> LAN2
+ qca8337_3: ethernet-phy@3 {
+ reg = <3>;
+ };
+
+ // QCA8337 Phy4 -> LAN3
+ qca8337_4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ // 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 = "wan";
+ phy-handle = <&qca8337_1>;
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ phy-handle = <&qca8337_2>;
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "lan2";
+ phy-handle = <&qca8337_3>;
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "lan1";
+ phy-handle = <&qca8337_4>;
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ phy-mode = "sgmii";
+ ethernet = <&dp2>;
+ qca,sgmii-enable-pll;
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+};
+
+&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",
+ "ath11k/QCN6122/hw1.0/m3_fw.mdt";
+
+ /* The QCN6102 radio should map to UPD ID 2. Without */
+ /* bootargs, the firmware will expect it to be on UPD ID 3 */
+ boot-args = <
+ /* type: */ 0x1 /* PCIE0 */
+ /* length: */ 4
+ /* UPD ID: */ 2
+ /* reset GPIO: */ 15
+ /* reserved: */ 0 0>;
+
+ // 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";
+
+ // qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
+ interrupts-extended =
+ <&wcss_smp2p_in 8 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 9 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 12 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 11 IRQ_TYPE_NONE>;
+ 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";
+ status = "okay";
+ };
+
+ // QCN6102 5G
+ q6_wcss_pd2: pd-2 {
+ firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt";
+
+ interrupts-extended =
+ <&wcss_smp2p_in 16 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 17 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 20 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 19 IRQ_TYPE_NONE>;
+ interrupt-names =
+ "fatal",
+ "ready",
+ "spawn-ack",
+ "stop-ack";
+
+ qcom,smem-states =
+ <&wcss_smp2p_out 16>,
+ <&wcss_smp2p_out 17>,
+ <&wcss_smp2p_out 18>;
+ qcom,smem-state-names =
+ "shutdown",
+ "stop",
+ "spawn";
+ status = "okay";
+ };
+};
+
+&wifi0 {
+ // IPQ5018
+ qcom,rproc = <&q6_wcss_pd1>;
+ qcom,ath11k-calibration-variant = "Linksys-MX2000";
+ qcom,ath11k-fw-memory-mode = <2>;
+ qcom,bdf-addr = <0x4c400000>;
+
+ status = "okay";
+};
+
+&wifi1 {
+ // QCN6102 5G
+ qcom,rproc = <&q6_wcss_pd2>;
+ qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
+ qcom,ath11k-calibration-variant = "Linksys-MX2000";
+ qcom,ath11k-fw-memory-mode = <2>;
+ qcom,bdf-addr = <0x4d100000>;
+ qcom,m3-dump-addr = <0x4df00000>;
+
+ status = "okay";
+};
--- /dev/null
+/dts-v1/;
+
+#include "ipq5018.dtsi"
+#include "ipq5018-mx-base.dtsi"
+
+/ {
+ model = "Linksys MX5500";
+ compatible = "linksys,mx5500", "qcom,ipq5018";
+};
+
+/*
+ * ===============================================================
+ * _______________________ _______________________
+ * | IPQ5018 | | QCA8337 |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | | MAC0 |---| GE Phy | | | | Phy0 |---| MAC1 | |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * | | MAC1 |---| Uniphy |-+-SGMII-+-| SerDes |---| MAC6 | |
+ * | +------+ +--------+ | | +--------+ +------+ |
+ * |_______________________| |_______________________|
+ *
+ * ===============================================================
+ */
+
+&switch {
+ status = "okay";
+
+ switch_mac_mode = <MAC_MODE_SGMII_CHANNEL0>;
+
+ qcom,port_phyinfo {
+ // MAC0 -> GE Phy -> QCA8337 Phy4
+ port@0 {
+ port_id = <1>;
+ mdiobus = <&mdio0>;
+ phy_address = <7>;
+ };
+
+ // MAC1 ---SGMII---> QCA8337 SerDes
+ port@1 {
+ port_id = <2>;
+ forced-speed = <1000>;
+ forced-duplex = <1>;
+ };
+ };
+};
+
+// MAC1 ---SGMII---> QCA8337 SerDes
+&dp2 {
+ status = "okay";
+ phy-mode = "sgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
+
+&mdio0 {
+ status = "okay";
+};
+
+/* IPQ5018 GE Phy -> Not connected
+ * needs to be enabled for QSDK to identify the IPQ5018 dummy switch
+ */
+&ge_phy {
+ status = "okay";
+};
+
+&mdio1 {
+ status = "okay";
+
+ pinctrl-0 = <&mdio1_pins>;
+ pinctrl-names = "default";
+ reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
+
+ // QCA8337 Phy0 not connected
+ qca8337_0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ // QCA8337 Phy1 -> WAN
+ qca8337_1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ // QCA8337 Phy2 -> LAN1
+ qca8337_2: ethernet-phy@2 {
+ reg = <2>;
+ };
+
+ // QCA8337 Phy3 -> LAN2
+ qca8337_3: ethernet-phy@3 {
+ reg = <3>;
+ };
+
+ // QCA8337 Phy4 -> LAN3
+ qca8337_4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ // 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 = "wan";
+ phy-handle = <&qca8337_1>;
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ phy-handle = <&qca8337_2>;
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "lan2";
+ phy-handle = <&qca8337_3>;
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "lan1";
+ phy-handle = <&qca8337_4>;
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ phy-mode = "sgmii";
+ ethernet = <&dp2>;
+ qca,sgmii-enable-pll;
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+};
+
+&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-MX5500";
+ };
+ };
+};
+
+&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";
+ status = "okay";
+ };
+};
+
+&wifi0 {
+ // IPQ5018
+ qcom,rproc = <&q6_wcss_pd1>;
+ qcom,ath11k-calibration-variant = "Linksys-MX5500";
+ qcom,ath11k-fw-memory-mode = <2>;
+ qcom,bdf-addr = <0x4c400000>;
+
+ status = "okay";
+};
+define Device/linksys_ipq50xx_mx_base
+ $(call Device/FitImageLzma)
+ DEVICE_VENDOR := Linksys
+ BLOCKSIZE := 128k
+ PAGESIZE := 2048
+ KERNEL_SIZE := 8192k
+ IMAGE_SIZE := 83968k
+ NAND_SIZE := 256m
+ SOC := ipq5018
+ IMAGES += factory.bin
+ IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=$$$$(DEVICE_MODEL)
+endef
+
+define Device/linksys_mx2000
+ $(call Device/linksys_ipq50xx_mx_base)
+ DEVICE_MODEL := MX2000
+ DEVICE_DTS_CONFIG := config@mp03.5-c1
+ DEVICE_PACKAGES := ath11k-firmware-qcn6122 \
+ ipq-wifi-linksys_mx2000
+endef
+TARGET_DEVICES += linksys_mx2000
+
+define Device/linksys_mx5500
+ $(call Device/linksys_ipq50xx_mx_base)
+ DEVICE_MODEL := MX5500
+ DEVICE_DTS_CONFIG := config@mp03.1
+ DEVICE_PACKAGES := kmod-ath11k-pci \
+ ath11k-firmware-qcn9074 \
+ ipq-wifi-linksys_mx5500
+endef
+TARGET_DEVICES += linksys_mx5500
--- /dev/null
+#!/bin/sh
+
+. /lib/functions/uci-defaults.sh
+. /lib/functions/system.sh
+
+ipq50xx_setup_interfaces()
+{
+ local board="$1"
+ case $board in
+ linksys,mx2000|\
+ linksys,mx5500)
+ ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan"
+ ;;
+ esac
+}
+
+ipq50xx_setup_macs()
+{
+ local board="$1"
+ local lan_mac=""
+ local wan_mac=""
+ local label_mac=""
+
+ case "$board" in
+ linksys,mx2000|\
+ linksys,mx5500)
+ label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
+ lan_mac=$label_mac
+ wan_mac=$label_mac
+ ucidef_set_network_device_mac eth0 $label_mac
+ ;;
+ esac
+
+ [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
+ [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
+ [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac
+}
+
+board_config_update
+board=$(board_name)
+ipq50xx_setup_interfaces $board
+ipq50xx_setup_macs $board
+board_config_flush
+
+exit 0
--- /dev/null
+#!/bin/sh
+
+[ -e /lib/firmware/$FIRMWARE ] && exit 0
+
+. /lib/functions/caldata.sh
+
+board=$(board_name)
+
+case "$FIRMWARE" in
+"ath11k/IPQ5018/hw1.0/cal-ahb-c000000.wifi.bin")
+ case "$board" in
+ linksys,mx2000|\
+ linksys,mx5500)
+ 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
+ ath11k_remove_regdomain
+ ath11k_set_macflag
+ ;;
+ esac
+ ;;
+"ath11k/QCN6122/hw1.0/cal-ahb-b00a040.wifi1.bin")
+ case "$board" in
+ linksys,mx2000)
+ 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
+ ath11k_remove_regdomain
+ ath11k_set_macflag
+ ;;
+ esac
+ ;;
+"ath11k/QCN9074/hw1.0/cal-pci-0001:01:00.0.bin")
+ case "$board" in
+ linksys,mx5500)
+ 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
+ ath11k_remove_regdomain
+ ath11k_set_macflag
+ ;;
+ esac
+ ;;
+*)
+ exit 1
+ ;;
+esac
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+START=99
+
+boot() {
+ case $(board_name) in
+ linksys,mx2000|\
+ linksys,mx5500)
+ mtd resetbc s_env || true
+ ;;
+ esac
+}
--- /dev/null
+PART_NAME=firmware
+REQUIRE_IMAGE_METADATA=1
+
+RAMFS_COPY_BIN='fw_printenv fw_setenv head'
+RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
+
+remove_oem_ubi_volume() {
+ local oem_volume_name="$1"
+ local oem_ubivol
+ local mtdnum
+ local ubidev
+
+ mtdnum=$(find_mtd_index "$CI_UBIPART")
+ if [ ! "$mtdnum" ]; then
+ return
+ fi
+
+ ubidev=$(nand_find_ubi "$CI_UBIPART")
+ if [ ! "$ubidev" ]; then
+ ubiattach --mtdn="$mtdnum"
+ ubidev=$(nand_find_ubi "$CI_UBIPART")
+ fi
+
+ if [ "$ubidev" ]; then
+ oem_ubivol=$(nand_find_volume "$ubidev" "$oem_volume_name")
+ [ "$oem_ubivol" ] && ubirmvol "/dev/$ubidev" --name="$oem_volume_name"
+ fi
+}
+
+linksys_mx_do_upgrade() {
+ local setenv_script="/tmp/fw_env_upgrade"
+
+ CI_UBIPART="rootfs"
+ boot_part="$(fw_printenv -n boot_part)"
+ if [ -n "$UPGRADE_OPT_USE_CURR_PART" ]; then
+ if [ "$boot_part" -eq "2" ]; then
+ CI_KERNPART="alt_kernel"
+ CI_UBIPART="alt_rootfs"
+ fi
+ else
+ if [ "$boot_part" -eq "1" ]; then
+ echo "boot_part 2" >> $setenv_script
+ CI_KERNPART="alt_kernel"
+ CI_UBIPART="alt_rootfs"
+ else
+ echo "boot_part 1" >> $setenv_script
+ fi
+ fi
+
+ boot_part_ready="$(fw_printenv -n boot_part_ready)"
+ if [ "$boot_part_ready" -ne "3" ]; then
+ echo "boot_part_ready 3" >> $setenv_script
+ fi
+
+ auto_recovery="$(fw_printenv -n auto_recovery)"
+ if [ "$auto_recovery" != "yes" ]; then
+ echo "auto_recovery yes" >> $setenv_script
+ fi
+
+ if [ -f "$setenv_script" ]; then
+ fw_setenv -s $setenv_script || {
+ echo "failed to update U-Boot environment"
+ return 1
+ }
+ fi
+ nand_do_upgrade "$1"
+}
+
+platform_check_image() {
+ return 0;
+}
+
+platform_do_upgrade() {
+ case "$(board_name)" in
+ linksys,mx2000|\
+ linksys,mx5500)
+ remove_oem_ubi_volume rootfs
+ linksys_mx_do_upgrade "$1"
+ ;;
+ *)
+ default_do_upgrade "$1"
+ ;;
+ esac
+}