qualcommax: ipq50xx: add support for Linksys MX2000 and MX5500
authorGeorge Moussalem <george.moussalem@outlook.com>
Mon, 7 Oct 2024 12:09:40 +0000 (16:09 +0400)
committerRobert Marko <robimarko@gmail.com>
Thu, 6 Feb 2025 08:51:13 +0000 (09:51 +0100)
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>
package/boot/uboot-envtools/files/qualcommax_ipq50xx [new file with mode: 0644]
package/firmware/ipq-wifi/Makefile
target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi [new file with mode: 0644]
target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts [new file with mode: 0644]
target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts [new file with mode: 0644]
target/linux/qualcommax/image/ipq50xx.mk
target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network [new file with mode: 0644]
target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata [new file with mode: 0644]
target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount [new file with mode: 0755]
target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh [new file with mode: 0644]

diff --git a/package/boot/uboot-envtools/files/qualcommax_ipq50xx b/package/boot/uboot-envtools/files/qualcommax_ipq50xx
new file mode 100644 (file)
index 0000000..0e78bb8
--- /dev/null
@@ -0,0 +1,22 @@
+[ -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
index ef67490a5f80ae488d0eda49664ead2464640aca..408c821035f8572fdc5b7b4ff505ca846bda9743 100644 (file)
@@ -39,8 +39,10 @@ ALLWIFIBOARDS:= \
        edimax_cax1800 \
        linksys_homewrk \
        linksys_mr7350 \
+       linksys_mx2000 \
        linksys_mx4200 \
        linksys_mx5300 \
+       linksys_mx5500 \
        linksys_mx8500 \
        linksys_whw03 \
        netgear_lbr20 \
@@ -175,8 +177,10 @@ $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102))
 $(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))
diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi
new file mode 100644 (file)
index 0000000..57fe5c5
--- /dev/null
@@ -0,0 +1,325 @@
+#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";
+};
diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts
new file mode 100644 (file)
index 0000000..108b26f
--- /dev/null
@@ -0,0 +1,262 @@
+/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";
+};
diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts
new file mode 100644 (file)
index 0000000..630e8ba
--- /dev/null
@@ -0,0 +1,240 @@
+/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";
+};
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..affd5e6345191dc35f3b7619a356fc98431d7438 100644 (file)
@@ -0,0 +1,31 @@
+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
diff --git a/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network
new file mode 100644 (file)
index 0000000..57f11ba
--- /dev/null
@@ -0,0 +1,45 @@
+#!/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
diff --git a/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata
new file mode 100644 (file)
index 0000000..7c8cc99
--- /dev/null
@@ -0,0 +1,47 @@
+#!/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
diff --git a/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount b/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount
new file mode 100755 (executable)
index 0000000..b570428
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+boot() {
+       case $(board_name) in
+       linksys,mx2000|\
+       linksys,mx5500)
+               mtd resetbc s_env || true
+       ;;
+       esac
+}
diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh
new file mode 100644 (file)
index 0000000..a75b679
--- /dev/null
@@ -0,0 +1,84 @@
+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
+}