[openwrt/openwrt] ramips: mt7621: add support for ZyXEL WSM20

LEDE Commits lede-commits at lists.infradead.org
Sat Apr 29 12:55:04 PDT 2023


hauke pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/28df7f7ff251d8684caa60f07ed0ba0c4a8e71f4

commit 28df7f7ff251d8684caa60f07ed0ba0c4a8e71f4
Author: Andreas Böhler <dev at aboehler.at>
AuthorDate: Tue Apr 4 19:41:26 2023 +0200

    ramips: mt7621: add support for ZyXEL WSM20
    
    The ZyXEL WSM20 aka Multy M1 is a cheap mesh router system by ZyXEL
    based on the MT7621 CPU.
    
    Specifications
    ==============
    
    SoC: MediaTek MT7621AT (880MHz)
    RAM: 256MiB
    Flash: 128MiB NAND
    Wireless: 802.11ax (2x2 MT7915E DBDC)
    Ethernet: 4x 10/100/1000 (MT7530)
    Button: 1x WPS, 1x Reset, 1x LED On/Off
    LED: 7 LEDs (3x white, 2x red, 2x green)
    
    MAC address assignment
    ======================
    
    The MAC address assignment follows stock: The label MAC address is the LAN
    MAC address, the WAN address is read from flash.
    
    The WiFi MAC addresses are set in userspace to label MAC + 1 and label MAC
    + 2.
    
    Installation (web interface)
    ============================
    
    The device is cloud-managed, but there is a hidden local firmware upgrade
    page in the OEM web interface. The device has to be registered in the
    cloud in order to be able to access this page.
    
    The system has a dual firmware design, there is no way to tell which
    firmware is currently booted. Therefore, an -initramfs version is flashed
    first.
    
    1. Log into the OEM web GUI
    2. Access the hidden upgrade page by navigating to
       https://192.168.212.1/gui/#/main/debug/firmwareupgrade
    3. Upload the -initramfs-kernel.bin file and flash it
    4. Wait for OpenWrt to boot and log in via SSH
    5. Transfer the sysupgrade file via SCP
    6. Run sysupgrade to install the image
    7. Reboot and enjoy
    
    NB: If the initramfs version was installed in RAS2, the sysupgrade script
    sets the boot number to the first partition. A backup has to be performed
    manually in case the OEM firwmare should be kept.
    
    Installation (UART method)
    ==========================
    
    The UART method is more difficult, as the boot loader does not have a
    timeout set. A semi-working stock firmware is required to configure it:
    
    1. Attach UART
    2. Boot the stock firmware until the message about failsafe mode appears
    3. Enter failsafe mode by pressing "f" and "Enter"
    4. Type "mount_root"
    5. Run "fw_setenv bootmenu_delay 3"
    6. Reboot, U-Boot now presents a menu
    7. The -initramfs-kernel.bin image can be flashed using the menu
    8. Run the regular sysupgrade for a permanent installation
    
    Changing the partition to boot is a bit cumbersome in U-Boot, as there is
    no menu to select it. It can only be checked using mstc_bootnum. To change
    it, issue the following commands in U-Boot:
    
       nand read 1800000 53c0000 800
       mw.b 1800004 1 1
       nand erase 53c0000 800
       nand write 1800000 53c0000 800
    
    This selects FW1. Replace "mw.b 1800004 1 1" by "mw.b 1800004 2 1" to
    change to the second slot.
    
    Back to stock
    =============
    
    It is possible to flash back to stock, but a OEM firmware upgrade is
    required. ZyXEL does not provide the link on its website, but the link
    can be acquired from the OEM web GUI by analyzing the transferred JSON
    objects.
    
    It is then a matter of writing the firmware to Kernel2 and setting the
    boot partition to FW2:
    
       mtd write zyxel.bin Kernel2
       echo -ne "\x02" | dd of=/dev/mtdblock7 count=1 bs=1 seek=4 conv=notrunc
    
    Signed-off-by: Andreas Böhler <dev at aboehler.at>
    Credits to forum users Annick and SirLouen for their initial work on this
    device
---
 package/boot/uboot-envtools/files/ramips           |   3 +-
 target/linux/ramips/dts/mt7621_zyxel_wsm20.dts     | 233 +++++++++++++++++++++
 target/linux/ramips/image/mt7621.mk                |  39 ++++
 .../mt7621/base-files/etc/board.d/02_network       |   3 +-
 .../etc/hotplug.d/ieee80211/10_fix_wifi_mac        |   5 +
 .../mt7621/base-files/lib/upgrade/platform.sh      |   4 +
 .../ramips/mt7621/base-files/lib/upgrade/zyxel.sh  |  39 ++++
 7 files changed, 324 insertions(+), 2 deletions(-)

diff --git a/package/boot/uboot-envtools/files/ramips b/package/boot/uboot-envtools/files/ramips
index bc56210036..4b7eeb8960 100644
--- a/package/boot/uboot-envtools/files/ramips
+++ b/package/boot/uboot-envtools/files/ramips
@@ -62,7 +62,8 @@ h3c,tx1801-plus|\
 h3c,tx1806|\
 jcg,q20|\
 linksys,e7350|\
-netgear,wax202)
+netgear,wax202|\
+zyxel,wsm20)
 	ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000"
 	;;
 haier,har-20s2u1|\
diff --git a/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts
new file mode 100644
index 0000000000..315e2e1d79
--- /dev/null
+++ b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include "mt7621.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	compatible = "zyxel,wsm20", "mediatek,mt7621-soc";
+	model = "ZyXEL WSM20";
+
+	aliases {
+		led-boot = &led_system_white;
+		led-failsafe = &led_system_red;
+		led-running = &led_system_white;
+		led-upgrade = &led_system_red;
+		label-mac-device = &gmac0;
+	};
+
+	chosen {
+		bootargs-override = "console=ttyS0,115200n1";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_system_white: led-0 {
+			gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
+			label = "white:system";
+		};
+
+		led_system_red: led-1 {
+			gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
+			label = "red:system";
+		};
+
+		led-2 {
+			gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
+			label = "green:led1";
+		};
+
+		led-3 {
+			gpios = <&gpio 0 GPIO_ACTIVE_LOW>;
+			label = "white:led2";
+		};
+
+		led-4 {
+			gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
+			label = "green:led3";
+		};
+
+		led-5 {
+			gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+			label = "red:led4";
+		};
+
+		led-6 {
+			gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+			label = "white:led5";
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		led {
+			label = "led";
+			gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		reset {
+			label = "reset";
+			gpios = <&gpio 6 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+
+		wps {
+			label = "wps";
+			gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WLAN>;
+		};
+	};
+};
+
+&nand {
+	status = "okay";
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 0 {
+			reg = <0x0 0x100000>;
+			label = "Bootloader";
+			read-only;
+		};
+
+		partition at 100000 {
+			reg = <0x100000 0x100000>;
+			label = "Config";
+		};
+
+		factory: partition at 200000 {
+			reg = <0x200000 0x1c0000>;
+			label = "Factory";
+			read-only;
+		};
+
+		partition at 3c0000 {
+			reg = <0x3c0000 0x2800000>;
+			label = "firmware";
+
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "kernel";
+				reg = <0x0 0x800000>;
+			};
+
+			partition at 800000 {
+				label = "ubi";
+				reg = <0x800000 0x2000000>;
+			};
+		};
+
+		partition at 2bc0000 {
+			reg = <0x2bc0000 0x2800000>;
+			label = "Kernel2";
+		};
+
+		partition at 53c0000 {
+			reg = <0x53c0000 0x100000>;
+			label = "persist";
+		};
+
+		partition at 54c0000 {
+			reg = <0x54c0000 0x400000>;
+			label = "rootfs_data";
+			read-only;
+		};
+
+		partition at 58C0000 {
+			reg = <0x58c0000 0x25c0000>;
+			label = "app";
+			read-only;
+		};
+
+		partition at 7e80000 {
+			reg = <0x7e80000 0x100000>;
+			label = "crt";
+			read-only;
+		};
+	};
+};
+
+&gmac0 {
+	nvmem-cells = <&macaddr_factory_1fdfa>;
+	nvmem-cell-names = "mac-address";
+};
+
+&gmac1 {
+	status = "okay";
+	label = "wan";
+	phy-handle = <&ethphy0>;
+
+	nvmem-cells = <&macaddr_factory_1fdf4>;
+	nvmem-cell-names = "mac-address";
+};
+
+&mdio {
+	ethphy0: ethernet-phy at 0 {
+		reg = <0>;
+	};
+};
+
+&pcie {
+	status = "okay";
+};
+
+&pcie1 {
+	wifi at 0,0 {
+		compatible = "mediatek,mt76";
+		reg = <0x0000 0 0 0 0>;
+		mediatek,mtd-eeprom = <&factory 0x0>;
+		mediatek,disable-radar-background;
+	};
+};
+
+&pcie2 {
+	status = "disabled";
+};
+
+&switch0 {
+	ports {
+		port at 1 {
+			status = "okay";
+			label = "lan3";
+		};
+		port at 2 {
+			status = "okay";
+			label = "lan2";
+		};
+		port at 3 {
+			status = "okay";
+			label = "lan1";
+		};
+	};
+};
+
+&state_default {
+	gpio {
+		groups = "i2c", "uart3", "jtag", "wdt";
+		function = "gpio";
+	};
+};
+
+&factory {
+	compatible = "nvmem-cells";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	macaddr_factory_1fdfa: macaddr at 1fdfa {
+		reg = <0x1fdfa 0x6>;
+	};
+
+	macaddr_factory_1fdf4: macaddr at 1fdf4 {
+		reg = <0x1fdf4 0x6>;
+	};
+};
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
index df89877c9a..96bfab3fef 100644
--- a/target/linux/ramips/image/mt7621.mk
+++ b/target/linux/ramips/image/mt7621.mk
@@ -62,6 +62,29 @@ define Build/iodata-mstc-header
 	)
 endef
 
+define Build/znet-header
+	$(eval version=$(word 1,$(1)))
+	( \
+		data_size_crc="$$(dd if=$@ 2>/dev/null | gzip -c | \
+			tail -c 8 | od -An -N4 -tx4 --endian big | tr -d ' \n')"; \
+		payload_len="$$(dd if=$@ bs=4 count=1 skip=1 2>/dev/null | od -An -tdI --endian big | tr -d ' \n')"; \
+		payload_size_crc="$$(dd if=$@ ibs=1 count=$$payload_len 2>/dev/null | gzip -c | \
+			tail -c 8 | od -An -N4 -tx4 --endian big | tr -d ' \n')"; \
+		echo -ne "\x5A\x4E\x45\x54" | dd bs=4 count=1 conv=sync 2>/dev/null; \
+		echo -ne "$$(printf '%08x' $$(stat -c%s $@) | fold -s2 | xargs -I {} echo \\x{} | tac | tr -d '\n')" | \
+			dd bs=4 count=1 conv=sync 2>/dev/null; \
+		echo -ne "$$(echo $$data_size_crc | sed 's/../\\x&/g')" | \
+			dd bs=4 count=1 conv=sync 2>/dev/null; \
+		echo -ne "$$(echo $$payload_size_crc | sed 's/../\\x&/g')" | \
+			dd bs=4 count=1 conv=sync 2>/dev/null; \
+		echo -ne "\x12\x34\x56\x78" | dd bs=4 count=1 conv=sync 2>/dev/null; \
+		echo -ne "$(version)" | dd bs=28 count=1 conv=sync 2>/dev/null; \
+		dd if=/dev/zero bs=262096 count=1 conv=sync 2>/dev/null | tr "\000" "\377"; \
+		cat $@; \
+	) > $@.new
+	mv $@.new $@
+endef
+
 define Build/belkin-header
 	$(eval magic=$(word 1,$(1)))
 	$(eval hw_ver=$(word 2,$(1)))
@@ -2875,3 +2898,19 @@ define Device/zyxel_wap6805
   IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
 endef
 TARGET_DEVICES += zyxel_wap6805
+
+define Device/zyxel_wsm20
+  $(Device/dsa-migration)
+  BLOCKSIZE := 128k
+  PAGESIZE := 2048
+  KERNEL_SIZE := 8192k
+  IMAGE_SIZE := 41943040
+  UBINIZE_OPTS := -E 5
+  DEVICE_VENDOR := ZyXEL
+  DEVICE_MODEL := WSM20
+  DEVICE_PACKAGES := kmod-mt7915-firmware
+  KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | znet-header V1.00(ABZF.0)C0
+  KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | znet-header V1.00(ABZF.0)C0
+  IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
+endef
+TARGET_DEVICES += zyxel_wsm20
diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
index e357b47a4c..39c8080e83 100644
--- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
+++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
@@ -49,7 +49,8 @@ ramips_setup_interfaces()
 	xiaomi,mi-router-cr6606|\
 	xiaomi,mi-router-cr6608|\
 	xiaomi,mi-router-cr6609|\
-	xiaomi,redmi-router-ac2100)
+	xiaomi,redmi-router-ac2100|\
+	zyxel,wsm20)
 		ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan"
 		;;
 	asiarf,ap7621-001|\
diff --git a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
index b6337f397b..f042830e02 100644
--- a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
+++ b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
@@ -181,4 +181,9 @@ case "$board" in
 		[ "$PHYNBR" = "0" ] && macaddr_add $hw_mac_addr 1 > /sys${DEVPATH}/macaddress
 		[ "$PHYNBR" = "1" ] && macaddr_add $hw_mac_addr 2 > /sys${DEVPATH}/macaddress
 		;;
+	zyxel,wsm20)
+		hw_mac_addr="$(mtd_get_mac_binary Factory 0x1fdfa)"
+		[ "$PHYNBR" = "0" ] && macaddr_add $hw_mac_addr 1 > /sys${DEVPATH}/macaddress
+		[ "$PHYNBR" = "1" ] && macaddr_add $hw_mac_addr 2 > /sys${DEVPATH}/macaddress
+		;;
 esac
diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
index bfdbd6a09d..ce5fdd61ed 100755
--- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
@@ -155,6 +155,10 @@ platform_do_upgrade() {
 		CI_KERNPART="Kernel"
 		nand_do_upgrade "$1"
 		;;
+	zyxel,wsm20)
+		zyxel_mstc_upgrade_prepare
+		nand_do_upgrade "$1"
+		;;
 	*)
 		default_do_upgrade "$1"
 		;;
diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/zyxel.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/zyxel.sh
new file mode 100644
index 0000000000..59c8d237dd
--- /dev/null
+++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/zyxel.sh
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2023 OpenWrt.org
+#
+
+. /lib/functions.sh
+
+zyxel_mstc_prepare_fail() {
+	echo "failed to check and prepare the environment, rebooting..."
+	umount -a
+	reboot -f
+}
+
+zyxel_mstc_upgrade_prepare() {
+	local persist_mtd="$(find_mtd_part persist)"
+	local firmware_mtd="$(find_mtd_part firmware)"
+
+	if [ -z "$persist_mtd" ] || [ -z "$firmware_mtd" ]; then
+		echo 'cannot find mtd partition(s) "persist" or "firmware"'
+		zyxel_mstc_prepare_fail
+	fi
+
+	local bootnum=$(hexdump -s 4 -n 1 -e '"%x"' ${persist_mtd})
+
+	if [ "$bootnum" != "1" ] && [ "$bootnum" != "2" ]; then
+		echo "failed to get bootnum, please check the value at 0x4 in ${persist_mtd}"
+		zyxel_mstc_prepare_fail
+	fi
+	echo "current: bootnum => ${bootnum}"
+
+	[ "$(fw_printenv -n bootmenu_delay)" = "3" ] || fw_setenv bootmenu_delay 3
+
+	if [ "$bootnum" = "2" ]; then
+		if ! ( echo -ne "\x01" | dd of=${persist_mtd} count=1 bs=1 seek=4 conv=notrunc 2>/dev/null ); then
+			echo "failed to set new boot partition"
+			zyxel_mstc_prepare_fail
+		fi
+		echo "### switch to 1st os-image on next boot ###"
+	fi
+}




More information about the lede-commits mailing list