[openwrt/openwrt] ramips: add support for ZyXEL NWA50AX / NWA55AXE

LEDE Commits lede-commits at lists.infradead.org
Wed Jul 20 12:52:30 PDT 2022


blocktrron pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/a0b7fef0ffe4cd9cca39a652a37e4f3ce8f0a681

commit a0b7fef0ffe4cd9cca39a652a37e4f3ce8f0a681
Author: David Bauer <mail at david-bauer.net>
AuthorDate: Fri May 27 17:48:06 2022 +0200

    ramips: add support for ZyXEL NWA50AX / NWA55AXE
    
    Hardware
    --------
    CPU:    Mediatek MT7621
    RAM:    256M DDR3
    FLASH:  128M NAND
    ETH:    1x Gigabit Ethernet
    WiFi:   Mediatek MT7915 (2.4/5GHz 802.11ax 2x2 DBDC)
    BTN:    1x Reset (NWA50AX only)
    LED:    1x Multi-Color (NWA50AX only)
    
    UART Console
    ------------
    NWA50AX:
    Available below the rubber cover next to the ethernet port.
    NWA55AXE:
    Available on the board when disassembling the device.
    
    Settings: 115200 8N1
    
    Layout:
    
    <12V> <LAN> GND-RX-TX-VCC
    
    Logic-Level is 3V3. Don't connect VCC to your UART adapter!
    
    Installation Web-UI
    -------------------
    Upload the Factory image using the devices Web-Interface.
    
    As the device uses a dual-image partition layout, OpenWrt can only
    installed on Slot A. This requires the current active image prior
    flashing the device to be on Slot B.
    
    If the currently installed image is started from Slot A, the device will
    flash OpenWrt to Slot B. OpenWrt will panic upon first boot in this case
    and the device will return to the ZyXEL firmware upon next boot.
    
    If this happens, first install a ZyXEL firmware upgrade of any version
    and install OpenWrt after that.
    
    Installation TFTP
    -----------------
    This installation routine is especially useful in case
     * unknown device password (NWA55AXE lacks reset button)
     * bricked device
    
    Attach to the UART console header of the device. Interrupt the boot
    procedure by pressing Enter.
    
    The bootloader has a reduced command-set available from CLI, but more
    commands can be executed by abusing the atns command.
    
    Boot a OpenWrt initramfs image available on a TFTP server at
    192.168.1.66. Rename the image to owrt.bin
    
     $ atnf owrt.bin
     $ atna 192.168.1.88
     $ atns "192.168.1.66; tftpboot; bootm"
    
    Upon booting, set the booted image to the correct slot:
    
     $ zyxel-bootconfig /dev/mtd10 get-status
     $ zyxel-bootconfig /dev/mtd10 set-image-status 0 valid
     $ zyxel-bootconfig /dev/mtd10 set-active-image 0
    
    Copy the OpenWrt ramboot-factory image to the device using scp.
    Write the factory image to NAND and reboot the device.
    
     $ mtd write ramboot-factory.bin firmware
     $ reboot
    
    Signed-off-by: David Bauer <mail at david-bauer.net>
---
 package/utils/zyxel-bootconfig/Makefile            |  38 +++
 .../zyxel-bootconfig/files/95_apply_bootconfig     |  16 +
 package/utils/zyxel-bootconfig/src/Makefile        |   7 +
 .../utils/zyxel-bootconfig/src/zyxel-bootconfig.c  | 331 +++++++++++++++++++++
 scripts/mkits-zyxel-fit.sh                         |  38 +++
 target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi   | 151 ++++++++++
 target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts   |  45 +++
 target/linux/ramips/dts/mt7621_zyxel_nwa55axe.dts  |   6 +
 target/linux/ramips/image/mt7621.mk                |  34 +++
 .../mt7621/base-files/etc/board.d/02_network       |   4 +-
 .../etc/hotplug.d/ieee80211/10_fix_wifi_mac        |   6 +
 .../mt7621/base-files/lib/upgrade/platform.sh      |   4 +-
 12 files changed, 678 insertions(+), 2 deletions(-)

diff --git a/package/utils/zyxel-bootconfig/Makefile b/package/utils/zyxel-bootconfig/Makefile
new file mode 100644
index 0000000000..eb2dd79b82
--- /dev/null
+++ b/package/utils/zyxel-bootconfig/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2022 David Bauer <mail at david-bauer.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zyxel-bootconfig
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/zyxel-bootconfig
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Utility for handling ZyXEL Bootconfig settings
+  MAINTAINER:=David Bauer <mail at david-bauer.net>
+endef
+
+define Package/zyxel-bootconfig/description
+ This package contains an utility that allows handling ZyXEL Bootconfig settings.
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall"
+endef
+
+define Package/zyxel-bootconfig/install
+	$(INSTALL_DIR) $(1)/usr/bin $(1)/lib/preinit
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/zyxel-bootconfig $(1)/usr/bin/
+	$(CP) ./files/95_apply_bootconfig $(1)/lib/preinit/95_apply_bootconfig
+endef
+
+$(eval $(call BuildPackage,zyxel-bootconfig))
diff --git a/package/utils/zyxel-bootconfig/files/95_apply_bootconfig b/package/utils/zyxel-bootconfig/files/95_apply_bootconfig
new file mode 100644
index 0000000000..c47857b082
--- /dev/null
+++ b/package/utils/zyxel-bootconfig/files/95_apply_bootconfig
@@ -0,0 +1,16 @@
+apply_bootconfig() {
+	. /lib/functions.sh
+
+	local part
+
+	case $(board_name) in
+	zyxel,nwa50ax|\
+	zyxel,nwa55axe)
+        mtd_idx=$(find_mtd_index "bootconfig")
+		zyxel-bootconfig "/dev/mtd$mtd_idx" set-image-status 0 valid
+		zyxel-bootconfig "/dev/mtd$mtd_idx" set-active-image 0
+		;;
+	esac
+}
+
+[ "$INITRAMFS" = "1" ] || boot_hook_add preinit_main apply_bootconfig
diff --git a/package/utils/zyxel-bootconfig/src/Makefile b/package/utils/zyxel-bootconfig/src/Makefile
new file mode 100644
index 0000000000..66741c8acf
--- /dev/null
+++ b/package/utils/zyxel-bootconfig/src/Makefile
@@ -0,0 +1,7 @@
+all: zyxel-bootconfig
+
+zyxel-bootconfig:
+	$(CC) $(CFLAGS) -Wall zyxel-bootconfig.c -o zyxel-bootconfig
+
+clean:
+	rm -f zyxel-bootconfig
diff --git a/package/utils/zyxel-bootconfig/src/zyxel-bootconfig.c b/package/utils/zyxel-bootconfig/src/zyxel-bootconfig.c
new file mode 100644
index 0000000000..6dd2f8969f
--- /dev/null
+++ b/package/utils/zyxel-bootconfig/src/zyxel-bootconfig.c
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2022 David Bauer <mail at david-bauer.net> */
+
+/*
+ * First byte: Image status
+ *
+ * Possible status-codes:
+ * 0x0: none
+ * 0x1: new
+ * 0x2: valid
+ * 0x3: invalid
+ *
+ * Example: Image 0 valid; Image 1 invalid
+ * 11001000
+ * ||  ||
+ * img1||
+ *     img0
+ *
+ * Second byte: Active Image
+ * Possible values:
+ * 0x0: Image0 active
+ * 0x1: Image1 active
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+
+#define BOOTCONFIG_SIZE			0x20
+#define BOOTCONFIG_IMAGE_STATUS		0x0
+#define BOOTCONFIG_ACTIVE_IMAGE		0x1
+
+#define IMAGE_0_SHIFT			2
+#define IMAGE_0_MASK			0x0c
+#define IMAGE_1_SHIFT			6
+#define IMAGE_1_MASK			0xc0
+
+#define IMAGE_STATUS(img0, img1)	(((img0 << IMAGE_0_SHIFT) & IMAGE_0_MASK) | ((img1 << IMAGE_1_SHIFT) & IMAGE_1_MASK))
+
+#define ACTIVE_IMAGE_MASK		0x1
+#define ACTIVE_IMAGE(img)		(img & ACTIVE_IMAGE_MASK)
+
+enum zyxel_bootconfig_image_status {
+	IMAGE_STATUS_NONE = 0x0,
+	IMAGE_STATUS_NEW = 0x1,
+	IMAGE_STATUS_VALID = 0x2,
+	IMAGE_STATUS_INVALID = 0x3,
+	__IMAGE_STATUS_EINVAL,
+};
+
+struct zyxel_bootconfig {
+	enum zyxel_bootconfig_image_status image0_status;
+	enum zyxel_bootconfig_image_status image1_status;
+	unsigned int active_image;
+};
+
+struct zyxel_bootconfig_mtd {
+	struct mtd_info_user mtd_info;
+	int fd;
+};
+
+struct zyxel_image_status {
+	enum zyxel_bootconfig_image_status code;
+	const char *name;
+};
+
+struct zyxel_image_status image_status_codes[] = {
+	{ .code = IMAGE_STATUS_NONE, .name = "none" },
+	{ .code = IMAGE_STATUS_NEW, .name = "new" },
+	{ .code = IMAGE_STATUS_VALID, .name = "valid" },
+	{ .code = IMAGE_STATUS_INVALID, .name = "invalid" },
+	{},
+};
+
+
+static enum zyxel_bootconfig_image_status zyxel_bootconfig_image_status_parse(const char *status) {
+	struct zyxel_image_status* s;
+
+	for (s = image_status_codes; s->name; s++) {
+		if (!strcmp(status, s->name)) {
+			return s->code;
+		}
+	}
+
+	return __IMAGE_STATUS_EINVAL;
+}
+
+const char *zyxel_bootconfig_image_status_name(const enum zyxel_bootconfig_image_status bootconfig) {
+	struct zyxel_image_status* s;
+
+	for (s = image_status_codes; s->name; s++) {
+		if (bootconfig == s->code) {
+			return s->name;
+		}
+	}
+
+	return "N/A";
+}
+
+static void zyxel_bootconfig_mtd_close(struct zyxel_bootconfig_mtd *mtd) {
+	close(mtd->fd);
+}
+
+
+static int zyxel_bootconfig_mtd_open(struct zyxel_bootconfig_mtd *mtd, const char *mtd_name) {
+	int ret = 0;
+
+	mtd->fd = open(mtd_name, O_RDWR | O_SYNC);
+	if (mtd->fd < 0) {
+		fprintf(stderr, "Could not open mtd device: %s\n", mtd_name);
+		ret = -1;
+		goto out;
+	}
+
+	if (ioctl(mtd->fd, MEMGETINFO, &mtd->mtd_info)) {
+		fprintf(stderr, "Could not get MTD device info from %s\n", mtd_name);
+		ret = -1;
+		zyxel_bootconfig_mtd_close(mtd);
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+
+static int zyxel_bootconfig_read(struct zyxel_bootconfig *config, struct zyxel_bootconfig_mtd *mtd) {
+	char *args = NULL;
+	int ret = 0;
+
+	/* Allocate memory for reading boot-config partition */
+	args = calloc(1, mtd->mtd_info.erasesize);
+	if (!args) {
+		fprintf(stderr, "Could not allocate memory!\n");
+		ret = -1;
+		goto out;
+	}
+
+	/* Read bootconfig partition */
+	pread(mtd->fd, args, mtd->mtd_info.erasesize, 0);
+
+	/* Parse config */
+	memset(config, 0, sizeof(*config));
+
+	config->image0_status = (args[BOOTCONFIG_IMAGE_STATUS] & IMAGE_0_MASK) >> IMAGE_0_SHIFT;
+	config->image1_status = (args[BOOTCONFIG_IMAGE_STATUS] & IMAGE_1_MASK) >> IMAGE_1_SHIFT;
+	config->active_image = (args[BOOTCONFIG_ACTIVE_IMAGE] & ACTIVE_IMAGE_MASK);
+
+out:
+	if (args)
+		free(args);
+	return ret;
+}
+
+
+static int zyxel_bootconfig_write(struct zyxel_bootconfig *config, struct zyxel_bootconfig_mtd *mtd)
+{
+	struct erase_info_user erase_info;
+	char img_status, img_active;
+	char *args = NULL;
+	int ret = 0;
+
+	/* Allocate memory for reading boot-config partition */
+	args = calloc(1, mtd->mtd_info.erasesize);
+	if (!args) {
+		fprintf(stderr, "Could not allocate memory!\n");
+		ret = -1;
+		goto out;
+	}
+
+	/* Read bootconfig partition */
+	pread(mtd->fd, args, mtd->mtd_info.erasesize, 0);
+
+	img_status = IMAGE_STATUS(config->image0_status, config->image1_status);
+	img_active = ACTIVE_IMAGE(config->active_image);
+
+	/* Check if bootconfig has to be written */
+	if (args[BOOTCONFIG_IMAGE_STATUS] == img_status && args[BOOTCONFIG_ACTIVE_IMAGE] == img_active) {
+		ret = 0;
+		goto out;
+	}
+
+	/* Erase first block (containing the magic) */
+	erase_info.start = 0;
+	erase_info.length = mtd->mtd_info.erasesize;
+	ret = ioctl(mtd->fd, MEMERASE, &erase_info);
+	if (ret < 0) {
+		fprintf(stderr, "Failed to erase block: %i\n", ret);
+		goto out;
+	}
+
+
+	/* Write bootconfig */
+	args[BOOTCONFIG_IMAGE_STATUS] = img_status;
+	args[BOOTCONFIG_ACTIVE_IMAGE] = img_active;
+
+	if (pwrite(mtd->fd, args, mtd->mtd_info.erasesize, 0) != mtd->mtd_info.erasesize) {
+		fprintf(stderr, "Error writing bootconfig!\n");
+		ret = -1;
+		goto out;
+	}
+
+out:
+	if (args)
+		free(args);
+	return ret;
+}
+
+
+static void zyxel_bootconfig_print_usage(char *programm)
+{
+	struct zyxel_image_status* s = image_status_codes;
+
+	printf("Usage: %s <mtd-device> <command> [args]\n", programm);
+	printf("Available commands:\n");
+	printf("	get-status\n");
+	printf("	set-image-status [0/1] [");
+
+	while (s->name) {
+		printf("%s", s->name);
+		s++;
+
+		if (s->name)
+			printf(",");
+	}
+
+	printf("]\n");
+	printf("	set-active-image [0/1]\n");
+}
+
+int main(int argc, char *argv[])
+{
+	enum zyxel_bootconfig_image_status image_status;
+	struct zyxel_bootconfig_mtd mtd;
+	struct zyxel_bootconfig config;
+	const char *mtd_name, *command;
+	bool writeback = false;
+	int image_idx;
+
+	if (argc < 3) {
+		zyxel_bootconfig_print_usage(argv[0]);
+		return 1;
+	}
+
+	mtd_name = argv[1];
+	command = argv[2];
+
+	if (zyxel_bootconfig_mtd_open(&mtd, mtd_name)) {
+		fprintf(stderr, "Error opening %s!\n", mtd_name);
+		return 1;
+	}
+
+	if (zyxel_bootconfig_read(&config, &mtd)) {
+		fprintf(stderr, "Error reading bootconfig!\n");
+		zyxel_bootconfig_mtd_close(&mtd);
+		return 1;
+	}
+
+	if (!strcmp(command, "set-image-status")) {
+		if (argc < 5) {
+			zyxel_bootconfig_print_usage(argv[0]);
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		image_idx = atoi(argv[3]);
+		if (image_idx > 1 || image_idx < 0) {
+			fprintf(stderr, "Invalid image-slot set!\n");
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		image_status = zyxel_bootconfig_image_status_parse(argv[4]);
+		if (image_status == __IMAGE_STATUS_EINVAL) {
+			fprintf(stderr, "Invalid image-status!\n");
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		if (image_idx == 0) {
+			config.image0_status = image_status;
+		} else {
+			config.image1_status = image_status;
+		}
+
+		writeback = true;
+	} else if (!strcmp(command, "set-active-image")) {
+		if (argc < 4) {
+			zyxel_bootconfig_print_usage(argv[0]);
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		image_idx = atoi(argv[3]);
+		if (image_idx > 1 || image_idx < 0) {
+			fprintf(stderr, "Invalid image-slot set!\n");
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		config.active_image = image_idx;
+
+		writeback = true;
+	} else if (!strcmp(command, "get-status")) {
+		printf("Active Image: %d\n", config.active_image);
+		printf("Image 0 Status: %s\n", zyxel_bootconfig_image_status_name(config.image0_status));
+		printf("Image 1 Status: %s\n", zyxel_bootconfig_image_status_name(config.image1_status));
+
+		writeback = false;
+	}
+
+	if (writeback) {
+		if (zyxel_bootconfig_write(&config, &mtd)) {
+			fprintf(stderr, "Error writing bootconfig!\n");
+			zyxel_bootconfig_mtd_close(&mtd);
+			return 1;
+		}
+
+		zyxel_bootconfig_mtd_close(&mtd);
+	}
+
+	return 0;
+}
diff --git a/scripts/mkits-zyxel-fit.sh b/scripts/mkits-zyxel-fit.sh
new file mode 100755
index 0000000000..8ace1941eb
--- /dev/null
+++ b/scripts/mkits-zyxel-fit.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+#
+# Licensed under the terms of the GNU GPL License version 2 or later.
+# Author: David Bauer <mail at david-bauer.net>, based on mkits-zyxel-factory.sh.
+
+usage() {
+	echo "Usage: `basename $0` output file compat-models"
+	exit 1
+}
+
+# We need at least 3 arguments
+[ "$#" -lt 3 ] && usage
+
+# Target output file
+OUTPUT="$1"; shift
+FILE="$1"; shift
+MODELS="$1"; shift
+
+# Create a default, fully populated DTS file
+echo "\
+/dts-v1/;
+
+/ {
+	description = \"Zyxel FIT (Flattened Image Tree)\";
+	compat-models = [${MODELS}];
+	#address-cells = <1>;
+
+	images {
+		firmware {
+			data = /incbin/(\"${FILE}\");
+			type = \"firmware\";
+			compression = \"none\";
+			hash at 1 {
+				algo = \"sha1\";
+			};
+		};
+	};
+};" > ${OUTPUT}
diff --git a/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi
new file mode 100644
index 0000000000..e1353346a8
--- /dev/null
+++ b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi
@@ -0,0 +1,151 @@
+#include "mt7621.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	aliases {
+		label-mac-device = &gmac0;
+	};
+};
+
+&nand {
+	status = "okay";
+
+	mediatek,nmbm;
+	mediatek,bmt-max-ratio = <15>;
+	mediatek,bmt-max-reserved-blocks = <64>;
+	mediatek,bmt-remap-range =
+		<0x0 0x980000>,
+		<0x2980000 0x7800000>;
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 0 {
+			label = "u-boot";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition at 80000 {
+			label = "u-boot-env";
+			reg = <0x80000 0x80000>;
+			read-only;
+		};
+
+		factory: partition at 100000 {
+			label = "factory";
+			reg = <0x100000 0x80000>;
+			read-only;
+		};
+
+		partition at 180000 {
+			label = "firmware";
+			reg = <0x180000 0x2800000>;
+
+			/* This concatenates kernel1 & kernel2 & rootfs */
+
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "kernel";
+				reg = <0x0 0x800000>;
+			};
+
+			partition at 400000 {
+				label = "ubi";
+				reg = <0x800000 0x2000000>;
+			};
+		};
+
+		partition at 2980000 {
+			label = "zy_firmware_1";
+			reg = <0x2980000 0x2800000>;
+			read-only;
+		};
+
+		partition at 5180000 {
+			label = "zy_rootfs_data";
+			reg = <0x5180000 0x1400000>;
+			read-only;
+		};
+
+		partition at 6580000 {
+			label = "zy_logs";
+			reg = <0x6580000 0xd00000>;
+			read-only;
+		};
+
+		partition at 7280000 {
+			label = "myzyxel";
+			reg = <0x7280000 0x480000>;
+			read-only;
+		};
+
+		partition at 7700000 {
+			label = "bootconfig";
+			reg = <0x7700000 0x80000>;
+		};
+
+		mrd: partition at 7780000 {
+			label = "mrd";
+			reg = <0x7780000 0x80000>;
+			read-only;
+		};
+	};
+};
+
+&pcie {
+	status = "okay";
+};
+
+&pcie1 {
+	wlan_5g: wifi at 0,0 {
+		reg = <0x0 0 0 0 0>;
+		compatible = "mediatek,mt76";
+
+		mediatek,mtd-eeprom = <&factory 0x0>;
+
+		/* MAC-Address set in userspace */
+	};
+};
+
+&gmac0 {
+	nvmem-cells = <&macaddr_mrd_1fff8>;
+	nvmem-cell-names = "mac-address";
+};
+
+&switch0 {
+	ports {
+		port at 4 {
+			status = "okay";
+			label = "lan";
+		};
+	};
+};
+
+&mrd {
+	compatible = "nvmem-cells";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	macaddr_mrd_1fff8: macaddr at 1fff8 {
+		reg = <0x1fff8 0x6>;
+	};
+};
+
+&state_default {
+	gpio {
+		groups = "uart3", "rgmii2";
+		function = "gpio";
+	};
+};
+
+&ethernet {
+	pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>;
+};
diff --git a/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts b/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts
new file mode 100644
index 0000000000..70323f2422
--- /dev/null
+++ b/target/linux/ramips/dts/mt7621_zyxel_nwa50ax.dts
@@ -0,0 +1,45 @@
+#include "mt7621_zyxel_nwa-ax.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	compatible = "zyxel,nwa50ax", "mediatek,mt7621-soc";
+	model = "ZyXEL NWA50AX";
+
+	aliases {
+		led-boot = &led_system_green;
+		led-failsafe = &led_system_red;
+		led-running = &led_system_green;
+		led-upgrade = &led_system_red;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_system_red: system_red {
+			label = "red:system";
+			gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_system_green: system_green {
+			label = "green:system";
+			gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		system_blue {
+			label = "blue:system";
+			gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "reset";
+			gpios = <&gpio 30 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+};
diff --git a/target/linux/ramips/dts/mt7621_zyxel_nwa55axe.dts b/target/linux/ramips/dts/mt7621_zyxel_nwa55axe.dts
new file mode 100644
index 0000000000..04bbe340f2
--- /dev/null
+++ b/target/linux/ramips/dts/mt7621_zyxel_nwa55axe.dts
@@ -0,0 +1,6 @@
+#include "mt7621_zyxel_nwa-ax.dtsi"
+
+/ {
+	compatible = "zyxel,nwa55axe", "mediatek,mt7621-soc";
+	model = "ZyXEL NWA55AX";
+};
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
index 4d2f2a3610..34eac32112 100644
--- a/target/linux/ramips/image/mt7621.mk
+++ b/target/linux/ramips/image/mt7621.mk
@@ -95,6 +95,13 @@ define Build/zytrx-header
 	mv $@.new $@
 endef
 
+define Build/zyxel-nwa-fit
+	$(TOPDIR)/scripts/mkits-zyxel-fit.sh \
+		$@.its $@ "6b e1 6f e1 ff ff ff ff ff ff"
+	PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new
+	@mv $@.new $@
+endef
+
 define Device/dsa-migration
   DEVICE_COMPAT_VERSION := 1.1
   DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA
@@ -2211,6 +2218,33 @@ define Device/zyxel_nr7101
 endef
 TARGET_DEVICES += zyxel_nr7101
 
+define Device/zyxel_nwa-ax
+  $(Device/dsa-migration)
+  DEVICE_VENDOR := ZyXEL
+  BLOCKSIZE := 128k
+  PAGESIZE := 2048
+  KERNEL_SIZE := 8192k
+  UBINIZE_OPTS := -E 5
+  DEVICE_PACKAGES := kmod-mt7915e uboot-envtools zyxel-bootconfig
+  KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
+  IMAGES += factory.bin ramboot-factory.bin
+  IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | zyxel-nwa-fit
+  IMAGE/ramboot-factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi
+  IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
+endef
+
+define Device/zyxel_nwa50ax
+  $(Device/zyxel_nwa-ax)
+  DEVICE_MODEL := NWA50AX
+endef
+TARGET_DEVICES += zyxel_nwa50ax
+
+define Device/zyxel_nwa55axe
+  $(Device/zyxel_nwa-ax)
+  DEVICE_MODEL := NWA55AXE
+endef
+TARGET_DEVICES += zyxel_nwa55axe
+
 define Device/zyxel_wap6805
   $(Device/dsa-migration)
   BLOCKSIZE := 128k
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 39e095584d..320325f487 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
@@ -21,7 +21,9 @@ ramips_setup_interfaces()
 	tplink,re650-v1|\
 	tplink,re650-v2|\
 	ubnt,unifi-6-lite|\
-	ubnt,unifi-nanohd)
+	ubnt,unifi-nanohd|\
+	zyxel,nwa50ax|\
+	zyxel,nwa55axe)
 		ucidef_set_interface_lan "lan"
 		;;
 	ampedwireless,ally-r1900k|\
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 4649b9e9d0..bced044234 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
@@ -104,4 +104,10 @@ case "$board" in
 		[ "$PHYNBR" = "1" ] && \
 			macaddr_setbit_la "$(mtd_get_mac_binary Factory 0xe000)" > /sys${DEVPATH}/macaddress
 		;;
+	zyxel,nwa50ax|\
+	zyxel,nwa55axe)
+		hw_mac_addr="$(mtd_get_mac_binary mrd 0x1fff8)"
+		[ "$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 9becffa357..8a84130ab5 100755
--- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
@@ -96,7 +96,9 @@ platform_do_upgrade() {
 	xiaomi,mi-router-cr6606|\
 	xiaomi,mi-router-cr6608|\
 	xiaomi,mi-router-cr6609|\
-	xiaomi,redmi-router-ac2100)
+	xiaomi,redmi-router-ac2100|\
+	zyxel,nwa50ax|\
+	zyxel,nwa55axe)
 		nand_do_upgrade "$1"
 		;;
 	iodata,wn-ax1167gr2|\




More information about the lede-commits mailing list