[openwrt/openwrt] ath79: support ZTE MF286C

LEDE Commits lede-commits at lists.infradead.org
Sun Mar 16 14:11:00 PDT 2025


hauke pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/5ac6f56dbef4b3c575e0e40d6df5edff03e13d6e

commit 5ac6f56dbef4b3c575e0e40d6df5edff03e13d6e
Author: Lech Perczak <lech.perczak at gmail.com>
AuthorDate: Mon Nov 25 00:36:24 2024 +0100

    ath79: support ZTE MF286C
    
    ZTE MF286 is an indoor LTE category 12 CPE router with simultaneous
    dual-band 802.11ac plus 802.11n Wi-Fi radios and quad-port gigabit
    Ethernet switch, FXS and external USB 2.0 port.
    
    Software-wise it's compatible with previous MF286A, save for different
    5GHz Wi-Fi board definition file, requiring a separate image.
    
    Hardware highlights:
    - CPU: QCA9563 SoC at 775MHz,
    - RAM: 128MB DDR2,
    - NOR Flash: MX25L1606E 2MB SPI Flash, for U-boot only,
    - NAND Flash: W25N01GV 128MB SPI NAND-Flash, for all other data,
    - Wi-Fi 5GHz: QCA9886 2x2 MIMO 802.11ac Wave2 radio,
    - WI-Fi 2.4GHz: QCA9563 3x3 MIMO 802.11n radio,
    - Switch: QCA8337v2 4-port gigabit Ethernet, with single SGMII CPU port,
    - WWAN: MDM9250-based category 12 internal LTE modem
      in extended  mini-PCIE form factor, with 5 internal antennas and
      2 external antenna connections, single mini-SIM slot.
    - FXS: one external ATA port (handled entirely by modem part) with two
      physical connections in parallel,
    - USB: Single external USB 2.0 port,
    - Switches: power switch, WPS, Wi-Fi and reset buttons,
    - LEDs: Wi-Fi, Test (internal). Rest of LEDs (Phone, WWAN, Battery,
      Signal state) handled entirely by modem. 4 link status LEDs handled by
      the switch on the backside.
    - Label MAC device: eth0
    
    Internal modem of MF286C is supported via uqmi.
    
    Console connection: connector X2 is the console port, with the following
    pinout, starting from pin 1, which is the topmost pin when the board is
    upright:
    - VCC (3.3V). Do not use unless you need to source power for the
      converer from it.
    - TX
    - RX
    - GND
    Default port configuration in U-boot as well as in stock firmware is
    115200-8-N-1.
    
    Installation:
    Due to different flash layout from stock firmware, sysupgrade from
    within stock firmware is impossible, despite it's based on QSDK which
    itself is based on OpenWrt.
    
    STEP 0: Stock firmware update:
    As installing OpenWrt cuts you off from official firmware updates for
    the modem part, it is recommended to update the stock firmware to latest
    ath79: support ZTE MF286C
    
    STEP 1: Booting initramfs image:
    
    Method 1: using serial console (RECOMMENDED):
    - Have TFTP server running, exposing the OpenWrt initramfs image, and
      set your computer's IP address as 192.168.0.22. This is the default
      expected by U-boot. You may wish to change that, and alter later
      commands accordingly.
    - Connect the serial console if you haven't done so already,
    - Interrupt boot sequence by pressing any key in U-boot when prompted
    - Use the following commands to boot OpenWrt initramfs through TFTP:
    
      setenv serverip 192.168.0.22
      setenv ipaddr 192.168.0.1
      tftpboot 0x81000000 openwrt-ath79-nand-zte_mf286c-initramfs-kernel.bin
      bootm 0x81000000
    
      (Replace server IP and router IP as needed). There is no  emergency
      TFTP boot sequence triggered by buttons, contrary to MF283+.
    - When OpenWrt initramfs finishes booting, proceed to actual
      installation.
    
    STEP 2: Backing up original software:
    As the stock firmware may be customized by the carrier and is not
    officially available in the Internet, IT IS IMPERATIVE to back up the
    stock firmware, if you ever plan to returning to stock firmware.
    It is highly recommended to perform backup using both methods, to avoid
    hassle of reassembling firmware images in future, if a restore is
    needed.
    
    Method 1: after booting OpenWrt initramfs image via TFTP:
    - Connect your USB-UART adapter
    - Dump stock firmware located on stock kernel and ubi partitions:
    
      ssh root at 192.168.1.1: cat /dev/mtd9 > mtd3_ubiconcat0.bin
      ssh root at 192.168.1.1: cat /dev/mtd4 > mtd4_kernel.bin
      ssh root at 192.168.1.1: cat /dev/mtd9 > mtd5_ubiconcat1.bin
    
    And keep them in a safe place, should a restore be needed in future.
    
    Method 2: using stock firmware:
    - Connect an external USB drive formatted with FAT or ext4 to the USB
      port.
    - The drive will be auto-mounted to /var/usb_disk
    - Check the flash layout of the device:
    
      cat /proc/mtd
    
      It should show the following:
      mtd0: 000a0000 00010000 "u-boot"
      mtd1: 00020000 00010000 "u-boot-env"
      mtd2: 00140000 00010000 "reserved1"
      mtd3: 000a0000 00020000 "fota-flag"
      mtd4: 00080000 00020000 "art"
      mtd5: 00080000 00020000 "mac"
      mtd6: 000c0000 00020000 "reserved2"
      mtd7: 00400000 00020000 "cfg-param"
      mtd8: 00400000 00020000 "log"
      mtd9: 000a0000 00020000 "oops"
      mtd10: 00500000 00020000 "reserved3"
      mtd11: 00800000 00020000 "web"
      mtd12: 00300000 00020000 "kernel"
      mtd13: 01a00000 00020000 "rootfs"
      mtd14: 01900000 00020000 "data"
      mtd15: 03200000 00020000 "fota"
      mtd16: 01d00000 00020000 "firmware"
    
      Differences might indicate that this is NOT a MF286C device but
      one of other variants.
    - Copy over all MTD partitions, for example by executing the following:
    
      for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do cat /dev/mtd$i > \
      /var/usb_disk/mtd$i; done
    
      "Firmware" partition can be skipped, it is a concatenation
      of "kernel" and "rootfs".
    
    - If the count of MTD partitions is different, this might indicate that
      this is not a MF286C device, but one of its other variants.
    - (optionally) rename the files according to MTD partition names from
      /proc/mtd
    - Unmount the filesystem:
    
      umount /var/usb_disk; sync
    
      and then remove the drive.
    - Store the files in safe place if you ever plan to return to stock
      firmware. This is especially important, because stock firmware for
      this device is not available officially, and is usually customized by
      the mobile providers.
    
    STEP 3: Actual installation:
    - Set your computer IP to 192.168.1.22/24
    - scp the sysupgrade image to the device:
    
      scp -O openwrt-ath79-nand-zte_mf286a-squashfs-sysupgrade.bin \
      root at 192.168.1.1:/tmp/
    
    - ssh into the device and execute sysupgrade:
    
      sysupgrade -n /tmp/openwrt-ath79-nand-zte_mf286a-squashfs-sysupgrade.bin
    
    - Wait for router to reboot to full OpenWrt.
    
    STEP 4: WAN connection establishment
    Since the router is equipped with LTE modem as its main WAN interface, it
    might be useful to connect to the Internet right away after
    installation. To do so, please put the following entries in
    /etc/config/network, replacing the specific configuration entries with
    one needed for your ISP:
    
    config interface 'wan'
            option proto 'qmi'
            option device '/dev/cdc-wdm0'
            option auth '<auth>' # As required, usually 'none'
            option pincode '<pin>' # If required by SIM
            option apn '<apn>' # As required by ISP
            option pdptype '<pdp>' # Typically 'ipv4', or 'ipv4v6' or 'ipv6'
    
    For example, the following works for most polish ISPs
    config interface 'wan'
            option proto 'qmi'
            option device '/dev/cdc-wdm0'
            option auth 'none'
            option apn 'internet'
            option pdptype 'ipv4'
    
    The required minimum is:
    config interface 'wan'
            option proto 'qmi'
            option device '/dev/cdc-wdm0'
    In this case, the modem will use last configured APN from stock
    firmware - this should work out of the box, unless your SIM requires
    PIN which can't be switched off.
    
    If you have build with LuCI, installing luci-proto-qmi helps with this
    task.
    
    Restoring the stock firmware:
    
    - Boot to initramfs as in step 3:
    - Completely detach ubi0 partition using ubidetach /dev/ubi0_0
    - Copy over the stock kernel image using scp to /tmp
    - Erase kernel and restore stock kernel:
      (scp mtd4_kernel.bin root at 192.168.1.1:/tmp/)
      mtd write kernel /tmp/mtd4_kernel.bin
      rm /tmp/mtd4_kernel.bin
    - Copy over the stock partition backups one-by-one using scp to /tmp, and
      restore them individually. Otherwise you might run out of space in
      tmpfs:
    
      (scp -O mtd3_ubiconcat0.bin root at 192.168.1.1:/tmp/)
    
      mtd write ubiconcat0 /tmp/mtd3_ubiconcat0.bin
      rm /tmp/mtd3_ubiconcat0.bin
    
      (scp -O mtd5_ubiconcat1.bin root at 192.168.1.1:/tmp/)
    
      mtd write ubiconcat1 /tmp/mtd5_ubiconcat1.bin
      rm /tmp/mtd5_ubiconcat1.bin
    
    - If the write was correct, force a device reboot with
    
      reboot -f
    
    Quirks and known issues
    - It was observed, that CH340-based USB-UART converters output garbage
      during U-boot phase of system boot. At least CP2102 is known to work
      properly.
    - Kernel partition size is increased to 4MB compared to stock 3MB, to
      accomodate future kernel updates - at this moment OpenWrt 5.10 kernel
      image is at 2.5MB which is dangerously close to the limit. This has no
      effect on booting the system - but keep that in mind when reassembling
      an image to restore stock firmware.
    - uqmi seems to be unable to change APN manually, so please use the one
      you used before in stock firmware first. If you need to change it,
      please use protocok '3g' to establish connection once, or use the
      following command to change APN (and optionally IP type) manually:
      echo -ne 'AT+CGDCONT=1,"IP","<apn>' > /dev/ttyUSB0
    - The only usable LED as a "system LED" is the blue debug LED hidden
      inside the case. All other LEDs are controlled by modem, on which the
      router part has some influence only on Wi-Fi LED.
    - GPIO5 used for modem reset is a suicide switch, causing a hardware
      reset of whole board, not only the modem. It is attached to
      gpio-restart driver, to restart the modem on reboot as well, to ensure
      QMI connectivity after reboot, which tends to fail otherwise.
    - Modem, as in MF283+, exposes root shell over ADB - while not needed
      for OpenWrt operation at all - have fun lurking around.
      The same modem module is used as in older MF286.
    
    Signed-off-by: Lech Perczak <lech.perczak at gmail.com>
    Link: https://github.com/openwrt/openwrt/pull/17620
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 package/boot/uboot-envtools/files/ath79                     |  1 +
 target/linux/ath79/dts/qca9563_zte_mf286c.dts               | 13 +++++++++++++
 target/linux/ath79/image/nand.mk                            |  9 +++++++++
 target/linux/ath79/nand/base-files/etc/board.d/02_network   |  1 +
 .../ath79/nand/base-files/etc/board.d/03_gpio_switches      |  1 +
 5 files changed, 25 insertions(+)

diff --git a/package/boot/uboot-envtools/files/ath79 b/package/boot/uboot-envtools/files/ath79
index c989e61bd5..dc46d5ed39 100644
--- a/package/boot/uboot-envtools/files/ath79
+++ b/package/boot/uboot-envtools/files/ath79
@@ -176,6 +176,7 @@ wallys,dr531)
 	;;
 zte,mf286|\
 zte,mf286a|\
+zte,mf286c|\
 zte,mf286r)
 	ubootenv_add_uci_config "/dev/mtd7" "0x0" "0x20000" "0x10000"
 	;;
diff --git a/target/linux/ath79/dts/qca9563_zte_mf286c.dts b/target/linux/ath79/dts/qca9563_zte_mf286c.dts
new file mode 100644
index 0000000000..dbf9ab1cd4
--- /dev/null
+++ b/target/linux/ath79/dts/qca9563_zte_mf286c.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+// Copyright (c) 2021 Cezary Jackiewicz
+// Copyright (c) 2021, 2022 Lech Perczak
+#include "qca9563_zte_mf286ar.dtsi"
+
+/ {
+	model = "ZTE MF286C";
+	compatible = "zte,mf286c", "qca,qca9563";
+};
+
+&wifi_ath10k {
+	qcom,ath10k-calibration-variant = "ZTE-MF286C";
+};
diff --git a/target/linux/ath79/image/nand.mk b/target/linux/ath79/image/nand.mk
index 34c6eccfbd..f473fa780f 100644
--- a/target/linux/ath79/image/nand.mk
+++ b/target/linux/ath79/image/nand.mk
@@ -488,6 +488,15 @@ define Device/zte_mf286a
 endef
 TARGET_DEVICES += zte_mf286a
 
+define Device/zte_mf286c
+  $(Device/zte_mf28x_common)
+  DEVICE_MODEL := MF286C
+  DEVICE_PACKAGES += ath10k-firmware-qca9888-ct kmod-usb-net-qmi-wwan \
+	-ath10k-board-qca9888 ipq-wifi-zte_mf286c \
+	kmod-usb-serial-option uqmi
+endef
+TARGET_DEVICES += zte_mf286c
+
 define Device/zte_mf286r
   $(Device/zte_mf28x_common)
   DEVICE_MODEL := MF286R
diff --git a/target/linux/ath79/nand/base-files/etc/board.d/02_network b/target/linux/ath79/nand/base-files/etc/board.d/02_network
index b60586a15e..968a441617 100644
--- a/target/linux/ath79/nand/base-files/etc/board.d/02_network
+++ b/target/linux/ath79/nand/base-files/etc/board.d/02_network
@@ -73,6 +73,7 @@ ath79_setup_interfaces()
 		;;
 	zte,mf286|\
 	zte,mf286a|\
+	zte,mf286c|\
 	zte,mf286r)
 		ucidef_add_switch "switch0" \
 			"0 at eth0" "1:lan:4" "2:lan:3" "3:lan:2" "5:lan:1"
diff --git a/target/linux/ath79/nand/base-files/etc/board.d/03_gpio_switches b/target/linux/ath79/nand/base-files/etc/board.d/03_gpio_switches
index 1fe83bc65c..5951644a30 100644
--- a/target/linux/ath79/nand/base-files/etc/board.d/03_gpio_switches
+++ b/target/linux/ath79/nand/base-files/etc/board.d/03_gpio_switches
@@ -10,6 +10,7 @@ board=$(board_name)
 
 case "$board" in
 zte,mf286a|\
+zte,mf286c|\
 zte,mf286r)
 	ucidef_add_gpio_switch "power_btn_block" "Power button blocker" "532" "0"
 	;;




More information about the lede-commits mailing list