[openwrt/openwrt] ath79: add support for Huawei AP5030DN

LEDE Commits lede-commits at lists.infradead.org
Tue Apr 2 17:57:28 PDT 2024


blocktrron pushed a commit to openwrt/openwrt.git, branch openwrt-23.05:
https://git.openwrt.org/f314debd4f9fb19bc3e9111bba2a9659b46408c6

commit f314debd4f9fb19bc3e9111bba2a9659b46408c6
Author: Marco von Rosenberg <marcovr at selfnet.de>
AuthorDate: Sun Mar 31 17:07:39 2024 +0200

    ath79: add support for Huawei AP5030DN
    
    Huawei AP5030DN is a dual-band, dual-radio 802.11ac Wave 1 3x3 MIMO
    enterprise access point with two Gigabit Ethernet ports and PoE
    support.
    
    Hardware highlights:
    - CPU: QCA9550 SoC at 720MHz
    - RAM: 256MB DDR2
    - Flash: 32MB SPI-NOR
    - Wi-Fi 2.4GHz: QCA9550-internal radio
    - Wi-Fi 5GHz: QCA9880 PCIe WLAN SoC
    - Ethernet 1: 10/100/1000 Mbps Ethernet through Broadcom B50612E PHY
    - Ethernet 2: 10/100/1000 Mbps Ethernet through Marvell 88E1510 PHY
    - PoE: input through Ethernet 1 port
    - Standalone 12V/2A power input
    - Serial console externally available through RJ45 port
    - External watchdog: SGM706 (1.6s timeout)
    
    Serial console:
      9600n8 (9600 baud, no stop bits, no parity, 8 data bits)
    
    MAC addresses:
      Each device has 32 consecutive MAC addresses allocated by
      the vendor, which don't overlap between devices.
      This was confirmed with multiple devices with consecutive
      serial numbers.
      The MAC address range starts with the address on the label.
      To be able to distinguish between the interfaces,
      the following MAC address scheme is used:
        - eth0 = label MAC
        - eth1 = label MAC + 1
        - radio0 (Wi-Fi 5GHz) = label MAC + 2
        - radio1 (Wi-Fi 2.4GHz) = label MAC + 3
    
    Installation:
    0. Connect some sort of RJ45-to-USB adapter to "Console" port of the AP
    
    1. Power up the AP
    
    2. At prompt "Press f or F  to stop Auto-Boot in 3 seconds",
       do what they say.
       Log in with default admin password "admin at huawei.com".
    
    3. Boot the OpenWrt initramfs from TFTP using the hidden script
       "run ramboot". Replace IP address as needed:
    
       > setenv serverip 192.168.1.10
       > setenv ipaddr 192.168.1.1
       > setenv rambootfile
         openwrt-ath79-generic-huawei_ap5030dn-initramfs-kernel.bin
       > saveenv
       > run ramboot
    
    4. Optional but recommended as the factory firmware cannot
       be downloaded publicly:
       Back up contents of "firmware" partition using the web interface or ssh:
    
       $ ssh root at 192.168.1.1 cat /dev/mtd11 > huawei_ap5030dn_fw_backup.bin
    
    5. Run sysupgrade using sysupgrade image. OpenWrt
       shall boot from flash afterwards.
    
    Return to factory firmware (using firmware upgrade package downloaded from
    non-public Huawei website):
    1. Start a TFTP server in the directory where
       the firmware upgrade package is located
    
    2. Boot to u-boot as described above
    
    3. Install firmware upgrade package and format the config partitions:
    
       > update system FatAP5X30XN_SOMEVERSION.bin
       > format_fs
    
    Return to factory firmware (from previously created backup):
    1. Copy over the firmware partition backup to /tmp,
       for example using scp
    
    2. Use sysupgrade with force to restore the backup:
       sysupgrade -F huawei_ap5030dn_fw_backup.bin
    
    3. Boot AP to U-Boot as described above
    
    Quirks and known issues
    -----------------------
    
    - On initial power-up, the Huawei-modified bootloader suspends both
    ethernet PHYs (it sets the "Power Down" bit in the MII control
    register). Unfortunately, at the time of the initial port, the kernel
    driver for the B50612E/BCM54612E PHY behind eth0 doesn't have a resume
    callback defined which would clear this bit. This makes the PHY unusable
    since it remains suspended forever. This is why the backported kernel
    patches in this commit are required which add this callback and for
    completeness also a suspend callback.
    
    - The stock firmware has a semi dual boot concept where the primary
    kernel uses a squashfs as root partition and the secondary kernel uses
    an initramfs. This dual boot concept is circumvented on purpose to gain
    more flash space and since the stock firmware's flash layout isn't
    compatible with mtdsplit.
    
    - The external watchdog's timeout of 1.6s is very hard to satisfy
    during bootup. This is why the GPIO15 pin connected to the watchdog input
    is configured directly in the LZMA loader to output the CPU_CLK/4 signal
    which keeps the watchdog happy until the wdt-gpio kernel driver takes
    over. Because it would also take too long to read the whole kernel image
    from flash, the uImage header only includes the loader which then reads
    the kernel image from flash after GPIO15 is configured.
    
    Signed-off-by: Marco von Rosenberg <marcovr at selfnet.de>
    [fixed 6.6 backport patch naming]
    Signed-off-by: David Bauer <mail at david-bauer.net>
    (cherry picked from commit 06cdc07f8cc703ef7dcb3e7b329b9abff0806a6e)
---
 package/boot/uboot-envtools/files/ath79            |   3 +
 target/linux/ath79/dts/qca9550_huawei_ap5030dn.dts | 257 +++++++++++++++++++++
 .../generic/base-files/etc/board.d/02_network      |   4 +
 .../generic/base-files/lib/upgrade/platform.sh     |   8 +
 target/linux/ath79/image/generic.mk                |  16 ++
 .../ath79/image/lzma-loader/src/ar71xx_regs.h      |   2 +
 target/linux/ath79/image/lzma-loader/src/board.c   |  26 +++
 ...v6.8-net-phy-bcm54612e-add-suspend-resume.patch |  27 +++
 8 files changed, 343 insertions(+)

diff --git a/package/boot/uboot-envtools/files/ath79 b/package/boot/uboot-envtools/files/ath79
index 5201b8b27a..bf9adc9e5d 100644
--- a/package/boot/uboot-envtools/files/ath79
+++ b/package/boot/uboot-envtools/files/ath79
@@ -119,6 +119,9 @@ domywifi,dw33d)
 glinet,gl-ar150)
 	ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x8000" "0x10000"
 	;;
+huawei,ap5030dn)
+	ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x20000" "0x20000"
+	;;
 netgear,wndr3700|\
 netgear,wndr3700-v2|\
 netgear,wndrmac-v1)
diff --git a/target/linux/ath79/dts/qca9550_huawei_ap5030dn.dts b/target/linux/ath79/dts/qca9550_huawei_ap5030dn.dts
new file mode 100644
index 0000000000..1c2a75f1dd
--- /dev/null
+++ b/target/linux/ath79/dts/qca9550_huawei_ap5030dn.dts
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include "qca955x.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "Huawei AP5030DN";
+	compatible = "huawei,ap5030dn", "qca,qca9550", "qca,qca9558";
+
+	chosen {
+		bootargs = "console=ttyS0,9600n8";
+	};
+
+	aliases {
+		led-boot = &led_function_red;
+		led-failsafe = &led_function_red;
+		led-running = &led_function_green;
+		led-upgrade = &led_function_red;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_function_green: led-status-red {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
+		};
+
+		led_function_red: led-status-green {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+		};
+
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		restart {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio 21 GPIO_ACTIVE_LOW>;
+			debounce-interval = <60>;
+		};
+	};
+
+	watchdog {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wdt_gpio15>;
+
+		compatible = "linux,wdt-gpio";
+		gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
+		hw_algo = "toggle";
+		hw_margin_ms = <100>;
+		always-running;
+	};
+
+	virtual_flash {
+		compatible = "mtd-concat";
+		devices = <&fwconcat0 &fwconcat1>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "firmware";
+				reg = <0x0 0x1e00000>;
+				compatible = "openwrt,uimage", "denx,uimage";
+			};
+		};
+	};
+};
+
+&spi {
+	status = "okay";
+
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <25000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "u-boot-a";
+				reg = <0x0 0x80000>;
+				read-only;
+			};
+
+			// The BootupA/B partitions store the addresses
+			// of the main and backup kernel in flash (which is the same here).
+			// During sysupgrade, these addresses are set to the start of the
+			// "firmware" partition.
+			partition at 80000 {
+				label = "BootupA";
+				reg = <0x80000 0x20000>;
+			};
+
+			partition at a0000 {
+				label = "BootupB";
+				reg = <0xa0000 0x20000>;
+			};
+
+			partition at c0000 {
+				label = "u-boot-env";
+				reg = <0xc0000 0x20000>;
+				read-only;
+			};
+
+			partition at e0000 {
+				label = "BoardData";
+				reg = <0xe0000 0x20000>;
+				read-only;
+			};
+
+			// In the vendor layout, there are the "SysImageA" (12 MiB)
+			// and the "ConfigA" (3 MiB) partitions here.
+			fwconcat0: partition at 100000 {
+				label = "fwconcat0";
+				reg = <0x100000 0xF00000>;
+			};
+
+			partition at 1000000 {
+				label = "u-boot-b";
+				reg = <0x1000000 0x80000>;
+				read-only;
+			};
+
+			partition at 1080000 {
+				label = "ResultA";
+				reg = <0x1080000 0x20000>;
+				read-only;
+			};
+
+			partition at 10a0000 {
+				label = "ResultB";
+				reg = <0x10a0000 0x20000>;
+				read-only;
+			};
+
+			// In the vendor layout, there are the "SysImageB" (12 MiB)
+			// and the "ConfigB" (3 MiB) partitions here.
+			fwconcat1: partition at 10c0000 {
+				label = "fwconcat1";
+				reg = <0x10c0000 0xF00000>;
+			};
+
+			art: partition at 1fc0000 {
+				label = "art";
+				reg = <0x1fc0000 0x40000>;
+				read-only;
+
+				nvmem-layout {
+					compatible = "fixed-layout";
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					macaddr_art_2005b: macaddr at 2005b {
+						compatible = "mac-base";
+						reg = <0x2005b 0x6>;
+						#nvmem-cell-cells = <1>;
+					};
+
+					cal_art_1000: cal at 1000 {
+						reg = <0x1000 0x440>;
+					};
+
+					cal_art_5000: cal at 5000 {
+						reg = <0x5000 0x844>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&wmac {
+	status = "okay";
+
+	nvmem-cells = <&macaddr_art_2005b 3>, <&cal_art_1000>;
+	nvmem-cell-names = "mac-address", "calibration";
+};
+
+&pcie0 {
+	status = "okay";
+
+	wifi at 0,0 {
+		compatible = "qcom,ath10k";
+		reg = <0x0000 0 0 0 0>;
+		nvmem-cells = <&macaddr_art_2005b 2>, <&cal_art_5000>;
+		nvmem-cell-names = "mac-address", "calibration";
+	};
+};
+
+&eth0 {
+	status = "okay";
+
+	nvmem-cells = <&macaddr_art_2005b 0>;
+	nvmem-cell-names = "mac-address";
+
+	pll-data = <0xa6000000 0xa0000101 0xa0001313>;
+	phy-handle = <&phy0>;
+
+	gmac-config {
+		device = <&gmac>;
+		rxdv-delay = <3>;
+		rxd-delay = <3>;
+		txen-delay = <0>;
+		txd-delay = <0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+
+	nvmem-cells = <&macaddr_art_2005b 1>;
+	nvmem-cell-names = "mac-address";
+
+	pll-data = <0x03000101 0x00000101 0x00001313>;
+	phy-handle = <&phy1>;
+};
+
+&mdio0 {
+	status = "okay";
+
+	phy0: ethernet-phy at 18 {
+		reg = <0x18>;
+	};
+};
+
+&mdio1 {
+	status = "okay";
+
+	phy1: ethernet-phy at 1 {
+		reg = <1>;
+	};
+};
+
+&pinmux {
+	wdt_gpio15: pinmux_wdt_gpio15 {
+		pinctrl-single,bits = <0xc 0x0 0xFF000000>;
+	};
+};
+
+&wdt {
+	status = "disabled";
+};
diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network
index ca35bd3223..191138f521 100644
--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network
+++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network
@@ -143,6 +143,7 @@ ath79_setup_interfaces()
 	engenius,enstationac-v1|\
 	engenius,ews511ap|\
 	engenius,ews660ap|\
+	huawei,ap5030dn|\
 	ocedo,ursus|\
 	ruckus,zf7363|\
 	ruckus,zf7372|\
@@ -709,6 +710,9 @@ ath79_setup_macs()
 	hak5,packet-squirrel)
 		label_mac=$(mtd_get_mac_binary u-boot 0x1fc00)
 		;;
+	huawei,ap5030dn)
+		label_mac=$(mtd_get_mac_binary art 0x2005b)
+		;;
 	iodata,etg3-r)
 		lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr)
 		wan_mac=$(macaddr_add "$lan_mac" -1)
diff --git a/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh b/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
index 67a3635075..e845057f42 100644
--- a/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
@@ -66,6 +66,14 @@ platform_do_upgrade() {
 		ROOTFS_FILE="root.squashfs"
 		platform_do_upgrade_failsafe_datachk "$1"
 		;;
+	huawei,ap5030dn)
+		# Store beginning address of the "firmware" partition
+		# as KernelA address and KernelB address, each to BootupA & BootupB
+		# This is the address from which the bootloader will try to load the kernel.
+		echo -n -e "\x9e\x10\x00\x00\x9e\x10\x00\x00" | dd of=$(find_mtd_part BootupA) bs=1 seek=$((0x254)) conv=notrunc
+		echo -n -e "\x9e\x10\x00\x00\x9e\x10\x00\x00" | dd of=$(find_mtd_part BootupB) bs=1 seek=$((0x254)) conv=notrunc
+		default_do_upgrade "$1"
+		;;
 	jjplus,ja76pf2)
 		platform_do_upgrade_redboot_fis "$1" linux
 		;;
diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk
index 1a558c30a0..f264c14314 100644
--- a/target/linux/ath79/image/generic.mk
+++ b/target/linux/ath79/image/generic.mk
@@ -1627,6 +1627,22 @@ define Device/hiwifi_hc6361
 endef
 TARGET_DEVICES += hiwifi_hc6361
 
+define Device/huawei_ap5030dn
+  SOC := qca9550
+  DEVICE_VENDOR := Huawei
+  DEVICE_MODEL := AP5030DN
+  DEVICE_PACKAGES := ath10k-firmware-qca988x-ct kmod-ath10k-ct
+  LOADER_TYPE := bin
+  LOADER_FLASH_OFFS := 0x111DC0
+  KERNEL_SIZE := 15360k
+  IMAGE_SIZE := 30720k
+  COMPILE := loader-$(1).bin
+  COMPILE/loader-$(1).bin := loader-okli-compile | pad-to 64k | uImage none
+  KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 8128
+  KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-kernel | uImage none
+endef
+TARGET_DEVICES += huawei_ap5030dn
+
 define Device/iodata_etg3-r
   SOC := ar9342
   DEVICE_VENDOR := I-O DATA
diff --git a/target/linux/ath79/image/lzma-loader/src/ar71xx_regs.h b/target/linux/ath79/image/lzma-loader/src/ar71xx_regs.h
index 245042fdab..e7d7683973 100644
--- a/target/linux/ath79/image/lzma-loader/src/ar71xx_regs.h
+++ b/target/linux/ath79/image/lzma-loader/src/ar71xx_regs.h
@@ -671,6 +671,8 @@
 
 #define AR934X_GPIO_OUT_GPIO		0x00
 
+#define QCA955X_GPIO_OUTSEL_CLK_OBS5		0x54
+
 /*
  * MII_CTRL block
  */
diff --git a/target/linux/ath79/image/lzma-loader/src/board.c b/target/linux/ath79/image/lzma-loader/src/board.c
index 7b1e110ee2..13926e9b1e 100644
--- a/target/linux/ath79/image/lzma-loader/src/board.c
+++ b/target/linux/ath79/image/lzma-loader/src/board.c
@@ -182,8 +182,34 @@ static inline void mr18_init(void)
 static inline void mr18_init(void) { }
 #endif
 
+#ifdef CONFIG_BOARD_HUAWEI_AP5030DN
+static inline void ap5030dn_init(void)
+{
+	const unsigned int ap5030dn_watchdog_gpio = 15;
+	unsigned int gpiobase, reg;
+
+	gpiobase = KSEG1ADDR(AR71XX_GPIO_BASE);
+
+	printf("Huawei AP5030DN\n");
+
+	reg = READREG(gpiobase + AR71XX_GPIO_REG_OE);
+	WRITEREG(gpiobase + AR71XX_GPIO_REG_OE,
+			reg & ~(1 << ap5030dn_watchdog_gpio));
+
+	/* Set GPIO15 MUX to output CLK_OBS5 (= CPU_CLK/4)
+	 * to keep the watchdog happy until wdt-gpio takes over
+	 */
+	reg = READREG(gpiobase + AR934X_GPIO_REG_OUT_FUNC3);
+	WRITEREG(gpiobase + AR934X_GPIO_REG_OUT_FUNC3,
+			reg | (QCA955X_GPIO_OUTSEL_CLK_OBS5 << 24));
+}
+#else
+static inline void ap5030dn_init(void) { }
+#endif
+
 void board_init(void)
 {
 	tlwr1043nd_init();
 	mr18_init();
+	ap5030dn_init();
 }
diff --git a/target/linux/generic/backport-5.15/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch b/target/linux/generic/backport-5.15/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch
new file mode 100644
index 0000000000..4fc9571a33
--- /dev/null
+++ b/target/linux/generic/backport-5.15/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch
@@ -0,0 +1,27 @@
+From 380b50ae3a04222334a3779b3787eba844b1177f Mon Sep 17 00:00:00 2001
+From: Marco von Rosenberg <marcovr at selfnet.de>
+Date: Thu, 16 Nov 2023 20:32:31 +0100
+Subject: net: phy: broadcom: Wire suspend/resume for BCM54612E
+
+The BCM54612E ethernet PHY supports IDDQ-SR.
+Therefore wire-up the suspend and resume callbacks
+to point to bcm54xx_suspend() and bcm54xx_resume().
+
+Signed-off-by: Marco von Rosenberg <marcovr at selfnet.de>
+Acked-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/phy/broadcom.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -795,6 +795,8 @@ static struct phy_driver broadcom_driver
+ 	.config_init	= bcm54xx_config_init,
+ 	.config_intr	= bcm_phy_config_intr,
+ 	.handle_interrupt = bcm_phy_handle_interrupt,
++	.suspend	= genphy_suspend,
++	.resume		= bcm54xx_resume,
+ }, {
+ 	.phy_id		= PHY_ID_BCM54616S,
+ 	.phy_id_mask	= 0xfffffff0,




More information about the lede-commits mailing list