Adding support for Extreme ap-7612

Hello,
I have been working on porting an Extreme ap-7612 to openwrt. It boots the image to the ipq4029-ws-ap3915i, but the flash storage (MX30LF4G18AC-TI) does not mount. Here is my work on the .dts file, but iahve had no success. Any advice is appreciated.

// SPDX-License-Identifier: GPL-2.0-only OR MIT

#include "qcom-ipq4019.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/soc/qcom,tcsr.h>

/ {
	model = "Extreme Networks WS-AP3915i";
	compatible = "extreme-networks,ws-ap3915i";

	aliases {
		// TODO: Verify if the ethernet0 alias is needed
		ethernet0 = &gmac;
		led-boot = &led_system_green;
		led-failsafe = &led_system_amber;
		led-running = &led_system_green;
		led-upgrade = &led_system_amber;
	};

	soc {
		tcsr@1949000 {
			compatible = "qcom,tcsr";
			reg = <0x1949000 0x100>;
			qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
		};

		ess_tcsr@1953000 {
			compatible = "qcom,tcsr";
			reg = <0x1953000 0x1000>;
			qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
		};

		tcsr@1957000 {
			compatible = "qcom,tcsr";
			reg = <0x1957000 0x100>;
			qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
		};
	};

	leds {
		compatible = "gpio-leds";

		led_system_green: system_green {
			label = "green:system";
			gpios = <&tlmm 49 GPIO_ACTIVE_LOW>;
		};

		led_system_amber: system_amber {
			label = "amber:system";
			gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
		};

		led_wlan24_green: wlan24_green {
			label = "green:wlan24";
			gpios = <&tlmm 23 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy0tpt";
		};

		led_wlan24_amber: wlan24_amber {
			label = "amber:wlan24";
			gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
		};

		led_wlan5_green: wlan5_green {
			label = "green:wlan5";
			gpios = <&tlmm 22 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy1tpt";
		};

		led_wlan5_amber: wlan5_amber {
			label = "amber:wlan5";
			gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
		};

		iot {
			label = "blue:iot";
			gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
		};
	};

	keys {
		compatible = "gpio-keys";

		reset {
			label = "reset";
			gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_RESTART >;
		};
	};
};

&watchdog {
	status = "okay";
};

&prng {
	status = "okay";
};

&crypto {
	status = "okay";
};

&blsp_dma {
	status = "okay";
};

&blsp1_uart1 {
	pinctrl-0 = <&serial_pins>;
	pinctrl-names = "default";
	status = "okay";
};

&cryptobam {
	status = "okay";
};

&mdio {
	status = "okay";
	pinctrl-0 = <&mdio_pins>;
	pinctrl-names = "default";
};

&gmac {
	status = "okay";
};

&switch {
	status = "okay";
};

&swport5 {
	status = "okay";

	label = "lan";
};

&tlmm {
	mdio_pins: mdio_pinmux {
		mux_1 {
			pins = "gpio6";
			function = "mdio";
			bias-pull-up;
		};
		mux_2 {
			pins = "gpio7";
			function = "mdc";
			bias-pull-up;
		};
	};

	spi_0_pins: spi_0_pinmux {
		pin {
			function = "blsp_spi0";
			pins = "gpio13", "gpio14", "gpio15";
			drive-strength = <12>;
			bias-disable;
		};
		pin_cs {
			function = "gpio";
			pins = "gpio12";
			drive-strength = <2>;
			bias-disable;
			output-high;
		};
	};

	serial_pins: serial_0_pinmux {
		mux {
			pins = "gpio16", "gpio17";
			function = "blsp_uart0";
			bias-disable;
		};
	};
};

&wifi0 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&wifi1 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&blsp1_spi1 {
	pinctrl-0 = <&spi_0_pins>;
	pinctrl-names = "default";
	status = "okay";
	cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;

nand@0 {
    compatible = "mx30lf4g18ac"; /* Verify exact compatible string */
    reg = <0>;
    nand-bus-width = <8>;        /* Correct for x8 bus */
    nand-ecc-strength = <4>;     /* Matches 4-bit ECC requirement */
    nand-ecc-step-size = <512>;  /* Matches ECC per 512 bytes */
    nand-page-size = <2048>;     /* Correct for data area */
    nand-oob-size = <64>;        /* Correct for OOB area */
    nand-block-size = <0x20000>; /* 128 KiB block size (matches 128K+4K) */
	};

	};
};

Hello,
I have a bunch of Extreme ap-7612's from a donation to my organization. The AP has a IPQ-4029 cpu and a MX30LF4G18AC-TI NAND chip on the board. May I request expertise on with compiling an image for this device? I have gained experience compiled an image for a similar model, so it looks like I just need to write a new dts file.

Also I have successfully booted the AP up with the image for the OpenWRT ap3915i... but it does not mount the storage. Thank you!

Exactly this.

You need to gather some information first, most notably, the partition map of the original firmware, the GPIO layout, etc. Then you can adjust the dts. The WS-AP3915i has both, an SPI flash and a NAND flash.
There is also a universal WS-AP391x image available that supports more devices than the 3915i. Might be a good image to start as well.

Thank you. Does the storage section have any dependencies on the gpio? If not it seems easier to tackle that second. Here is what I gathered on storage:

NAND read: device 0 offset 0x1380000, size 0x800000
 8388608 bytes read: OK
## Booting kernel from FIT Image at 80f00000 ...
   Using 'config@1' configuration
   Trying 'kernel@1' kernel subimage
     Description:  ARM OpenWrt Linux-3.14.43
     Type:         Kernel Image
     Compression:  gzip compressed
     Data Start:   0x80f000e4
     Data Size:    3426252 Bytes = 3.3 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x80208000
     Entry Point:  0x80208000
  Booting using the fdt blob at 0x812449cc

flash_type:             0x2
flash_index:            0x0
flash_chip_select:      0x0
flash_block_size:       0x20000
flash_density:          0x100000
partition table offset  0x0
No.: Name             Attributes            Start             Size
  0: 0:SBL1           0x0000ffff              0x0         0x100000
  1: 0:MIBIB          0x0000ffff         0x100000         0x100000
  2: 0:BOOTCONFIG     0x0000ffff         0x200000         0x100000
  3: 0:QSEE           0x0000ffff         0x300000         0x100000
  4: 0:QSEE_1         0x0000ffff         0x400000         0x100000
  5: 0:CDT            0x0000ffff         0x500000          0x80000
  6: 0:CDT_1          0x0000ffff         0x580000          0x80000
  7: 0:BOOTCONFIG1    0x0000ffff         0x600000          0x80000
  8: 0:APPSBLENV      0x0000ffff         0x680000          0x80000
  9: 0:APPSBL         0x0000ffff         0x700000         0x200000
 10: 0:APPSBL_1       0x0000ffff         0x900000         0x200000
 11: 0:ART            0x0000ffff         0xb00000          0x80000
 12: rootfs           0x0000ffff         0xb80000        0x4100000
 13: rootfs_1         0x0000ffff        0x4c80000        0x3300000


pc : [<87407cd0>]          lr : [<87407c8c>]
sp : 8735f870  ip : 8735fb1b     fp : 8735f91a
r10: 00000000  r9 : 8735f8b4     r8 : 8735ff60
r7 : 85000000  r6 : 00b80000     r5 : 00000001  r4 : 8735f8b4
r3 : 00b80001  r2 : 006ae129     r1 : 00000079  r0 : 84480000
Flags: Nzcv  IRQs off  FIQs off  Mode SVC_32



Creating 22 MTD partitions on "7980000.qcom,nand":
[    1.096501] 0x000000000000-0x000020000000 : "all_nand"
[    1.463729] 0x000000000000-0x000000100000 : "sbl1"
[    1.469220] 0x000000100000-0x000000200000 : "mibib"
[    1.474865] 0x000000200000-0x000000300000 : "bootcfg"
[    1.480606] 0x000000300000-0x000000400000 : "qsee"
[    1.486142] 0x000000400000-0x000000500000 : "qsee_alt"
[    1.491961] 0x000000500000-0x000000580000 : "cdt"
[    1.496968] 0x000000580000-0x000000600000 : "cdt_alt"
[    1.502305] 0x000000600000-0x000000680000 : "ddrparams"
[    1.507782] 0x000000680000-0x000000700000 : "appsblenv"
[    1.513220] 0x000000700000-0x000000900000 : "bootstrap"
[    1.519727] 0x000000900000-0x000000a00000 : "boot1"
[    1.525201] 0x000000a00000-0x000000b00000 : "boot2"
[    1.530634] 0x000000b00000-0x000000b80000 : "art"
[    1.535638] 0x000000b80000-0x000001380000 : "linux1"
[    1.546176] 0x000001380000-0x000001b80000 : "linux2"
[    1.556717] 0x000001b80000-0x00000a480000 : "rootfs1"
[    1.658287] 0x00000a480000-0x000012d80000 : "rootfs2"
[    1.759880] 0x000012d80000-0x000014f80000 : "var2"
[    1.788520] 0x000014f80000-0x000018f80000 : "etc2"
[    1.838342] 0x000018f80000-0x00001e380000 : "flash"
[    1.902316] 0x00001e380000-0x000020000000 : "panic"
[    1.927236] msm_nand_probe: NANDc phys addr 0x7980000, BAM phys addr 0x7984000, BAM IRQ 133


Looks like your system booted linux2 at 0x1380000. Now you need to adapt the Extreme Networks DTS to replace the NOR flash with the NAND flash and come up with a reasonable partition mapping. I would probably use linux1 for the kernel (about 8MB) and rootfs1 for the rootfs (about 28MB). The latter should be UBI, but judging from the boot log, it's not clear to me whether the bootloader can boot a kernel from UBI - if it can, this would be preferrable. In the latter case, you can even use an mtd-concat partition to span both linux1/rootfs1.
I would not touch any other partition to allow an easy way back to stock (the OEM firmware in linux2/rootfs2).

I'm not an expert on this target, the only devices with IPQ chipset that I worked on had an SPI NAND chip, that required a chip select GPIO. Yours seems to be using some integrated NAND controller, probably not requiring any GPIOs. But then again, I'm not an expert in this area.

I usually do the opposite, flashing the image is the very last thing that I implement. The reason is that sometimes the GPIOs need to be probed which leads to frequent lockups and the necessity to adapt the firmware several times. This is easiest done via a TFTP-booted initramfs image. Once I have everything working, I look into the flashing and installation procedure.

Surely this can't be as easy as ask an AI, right? Can I just replace the 391x Nor flash code with this? Your expertise to verifying this code/ its concept is appreciated.

&nand0 {
    status = "okay";

    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        partition@0 {
            label = "u-boot";
            reg = <0x0000000 0x0020000>;   // 128KB for bootloader
            read-only;
        };

        partition@20000 {
            label = "u-boot-env";
            reg = <0x0020000 0x0020000>;   // 128KB for environment
        };

        partition@40000 {
            label = "linux1";
            reg = <0x0040000 0x00800000>;  // 8MB for kernel
        };

        partition@840000 {
            label = "rootfs1";
            reg = <0x0840000 0x01C00000>;  // 28MB for rootfs
        };

        partition@2400000 {
            label = "data";
            reg = <0x02400000 0x00C00000>; // Remaining space for data/config
        };
    };
};

The principle, yes, but the partition map is not correct. You are missing all partitions before and afterwards, i.e. you need to map the offsets and sizes from the OEM partition map.

Great! Here is the dts file code. I could not get make menuconfig to recognize it as a new device so I just overwrote the code to the 3915i.

// SPDX-License-Identifier: GPL-2.0-only OR MIT

#include "qcom-ipq4019.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/soc/qcom,tcsr.h>

/ {
	model = "Extreme Networks WS-AP7612";
	compatible = "extreme-networks,ws-ap7612";

	aliases {
		// TODO: Verify if the ethernet0 alias is needed
		ethernet0 = &gmac;
		led-boot = &led_system_green;
		led-failsafe = &led_system_amber;
		led-running = &led_system_green;
		led-upgrade = &led_system_amber;
	};

	soc {
		tcsr@1949000 {
			compatible = "qcom,tcsr";
			reg = <0x1949000 0x100>;
			qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
		};

		ess_tcsr@1953000 {
			compatible = "qcom,tcsr";
			reg = <0x1953000 0x1000>;
			qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
		};

		tcsr@1957000 {
			compatible = "qcom,tcsr";
			reg = <0x1957000 0x100>;
			qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
		};
	};

	leds {
		compatible = "gpio-leds";

		led_system_green: system_green {
			label = "green:system";
			gpios = <&tlmm 49 GPIO_ACTIVE_LOW>;
		};

		led_system_amber: system_amber {
			label = "amber:system";
			gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
		};

		led_wlan24_green: wlan24_green {
			label = "green:wlan24";
			gpios = <&tlmm 23 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy0tpt";
		};

		led_wlan24_amber: wlan24_amber {
			label = "amber:wlan24";
			gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
		};

		led_wlan5_green: wlan5_green {
			label = "green:wlan5";
			gpios = <&tlmm 22 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy1tpt";
		};

		led_wlan5_amber: wlan5_amber {
			label = "amber:wlan5";
			gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
		};

		iot {
			label = "blue:iot";
			gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
		};
	};

	keys {
		compatible = "gpio-keys";

		reset {
			label = "reset";
			gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_RESTART >;
		};
	};
};

&watchdog {
	status = "okay";
};

&prng {
	status = "okay";
};

&crypto {
	status = "okay";
};

&blsp_dma {
	status = "okay";
};

&blsp1_uart1 {
	pinctrl-0 = <&serial_pins>;
	pinctrl-names = "default";
	status = "okay";
};

&cryptobam {
	status = "okay";
};

&mdio {
	status = "okay";
	pinctrl-0 = <&mdio_pins>;
	pinctrl-names = "default";
};

&gmac {
	status = "okay";
};

&switch {
	status = "okay";
};

&swport5 {
	status = "okay";

	label = "lan";
};

&tlmm {
	mdio_pins: mdio_pinmux {
		mux_1 {
			pins = "gpio6";
			function = "mdio";
			bias-pull-up;
		};
		mux_2 {
			pins = "gpio7";
			function = "mdc";
			bias-pull-up;
		};
	};

	spi_0_pins: spi_0_pinmux {
		pin {
			function = "blsp_spi0";
			pins = "gpio13", "gpio14", "gpio15";
			drive-strength = <12>;
			bias-disable;
		};
		pin_cs {
			function = "gpio";
			pins = "gpio12";
			drive-strength = <2>;
			bias-disable;
			output-high;
		};
	};

	serial_pins: serial_0_pinmux {
		mux {
			pins = "gpio16", "gpio17";
			function = "blsp_uart0";
			bias-disable;
		};
	};
};

&wifi0 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&wifi1 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&blsp1_spi1 {
	pinctrl-0 = <&spi_0_pins>;
	pinctrl-names = "default";
	status = "okay";
	cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;
	};
&nand0 {
    status = "okay";

    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

    partition@0 {
        label = "sbl1";
        reg = <0x000000000000 0x000000100000>;
        read-only;
    };

    partition@100000 {
        label = "mibib";
        reg = <0x000000100000 0x000000200000>;
    };

    partition@200000 {
        label = "bootcfg";
        reg = <0x000000200000 0x000000300000>;
    };

    partition@300000 {
        label = "qsee";
        reg = <0x000000300000 0x000000400000>;
    };

    partition@400000 {
        label = "qsee_alt";
        reg = <0x000000400000 0x000000500000>;
    };

    partition@500000 {
        label = "cdt";
        reg = <0x000000500000 0x000000580000>;
    };

    partition@580000 {
        label = "cdt_alt";
        reg = <0x000000580000 0x000000600000>;
    };

    partition@600000 {
        label = "ddrparams";
        reg = <0x000000600000 0x000000680000>;
    };

    partition@680000 {
        label = "appsblenv";
        reg = <0x000000680000 0x000000700000>;
    };

    partition@700000 {
        label = "bootstrap";
        reg = <0x000000700000 0x000000900000>;
    };

    partition@900000 {
        label = "boot1";
        reg = <0x000000900000 0x000000a00000>;
    };

    partition@a00000 {
        label = "boot2";
        reg = <0x000000a00000 0x000000b00000>;
    };

    partition@b00000 {
        label = "art";
        reg = <0x000000b00000 0x000000b80000>;
        read-only;
    };

    partition@b80000 {
        label = "linux1";
        reg = <0x000000b80000 0x000001380000>;
    };

    partition@1380000 {
        label = "linux2";
        reg = <0x000001380000 0x000001b80000>;
    };

    partition@1b80000 {
        label = "rootfs1";
        reg = <0x000001b80000 0x00000a480000>;
    };

    partition@a480000 {
        label = "rootfs2";
        reg = <0x00000a480000 0x000012d80000>;
    };

    partition@12d80000 {
        label = "var2";
        reg = <0x000012d80000 0x000014f80000>;
    };

    partition@14f80000 {
        label = "etc2";
        reg = <0x000014f80000 0x000018f80000>;
    };

    partition@18f80000 {
        label = "flash";
        reg = <0x000018f80000 0x00001e380000>;
    };

    partition@1e380000 {
        label = "panic";
        reg = <0x00001e380000 0x000020000000>;
    };
    };
};

Without going through the details, this looks better now.

Do not overwrite code, what you are looking for is here:

This might need adaptation as well since you have a NAND and not a NOR flash, i.e. all the UBI stuff needs to be added (check the other devices, there is somehwere a $(call Device/UbiFit) that looks promising). I can't give you more guidance on this right now, but usually I do the following:

  • Have a look at an OEM firmware ugprade image using binwalk and a hex editor to understand the layout
  • If no OEM firmware ugprade is available, do a full partition dump once initramfs boots up (a good idea for backup purposes anyway) and analyze this with a hex editor / binwalk
  • If there is UBI involved, make sure to also backup the /dev/ubi0_n partitions (n=0, 1, 2 ...).

For me, this is usually the hardest part to get right as there are so many variations out there.

Thank you. Your instructions worked well. So far, I have dumped firmware from the rootfs1 via uboot.

nand read 0x81000000 0x0840000 0x1C00000
tftpput 0x81000000 0x1C00000 rootfs1.bin




binwalk gave me this:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1051257       0x100A79        Certificate in DER format (x509 v3), header length: 4, sequence length: 1284
1051373       0x100AED        Certificate in DER format (x509 v3), header length: 4, sequence length: 1288
1102636       0x10D32C        U-Boot version string, "U-Boot 5.9.2.1-009R (Jun 26 2018 - 14:36:48)"
1103908       0x10D824        CRC32 polynomial table, little endian
1105596       0x10DEBC        CRC32 polynomial table, little endian
1116483       0x110943        Unix path: /usr/scripts/runmfg
1116976       0x110B30        U-Boot version string, "U-Boot 5.9.2.1-009R"
2099833       0x200A79        Certificate in DER format (x509 v3), header length: 4, sequence length: 1284
2099949       0x200AED        Certificate in DER format (x509 v3), header length: 4, sequence length: 1288
2151212       0x20D32C        U-Boot version string, "U-Boot 5.9.2.0-032R (May 02 2018 - 01:16:34)"
2152484       0x20D824        CRC32 polynomial table, little endian
2154172       0x20DEBC        CRC32 polynomial table, little endian
2165059       0x210943        Unix path: /usr/scripts/runmfg
2165552       0x210B30        U-Boot version string, "U-Boot 5.9.2.0-032R"
3407872       0x340000        Flattened device tree, size: 3460792 bytes, version: 17
3408100       0x3400E4        gzip compressed data, maximum compression, has original file name: "Image", from Unix, last modified: 2018-06-26 21:43:26
6834636       0x6849CC        Flattened device tree, size: 33223 bytes, version: 17
11796480      0xB40000        Flattened device tree, size: 3460828 bytes, version: 17
11796708      0xB400E4        gzip compressed data, maximum compression, has original file name: "Image", from Unix, last modified: 2018-05-02 08:22:51
15223280      0xE849F0        Flattened device tree, size: 33223 bytes, version: 17
20185088      0x1340000       JFFS2 filesystem, little endian

Then I ran: dd if=rootfs1.bin of=fdt_blob.dtb bs=1 skip=3407872 count=3460792

strings of the dtb hadthis juicy data:


!qcom,spi-qup-v2
spi_physical
spi_bam_physical
spi_irq
spi_bam_irq
core_clk
iface_clk
disabled
qcom,nand@7980000
!qcom,msm-nand
nand_phys
bam_phys
bam_irq
xqpic_nand
iface_clk
core_clk

Unless I am close to completion, too bad I can't just copy past the extracted ftd into the compiled open wrt image with dd or something.

It sounds like you're almost there. Because the extracted dtb file is already compiled, you can use the dtc (Device Tree Compiler) command to decompile it into a text-based format.

dtc -s -I dtb fdt_blob.dtb -O dts -o fdt_blob.dts

This will be really helpful for writing a dts file on your own.

Thank you. I decompiled it into a dts file. Unfortunately the compiled image using the dts file causes the AP to hang on boot at "Starting Kernel..."

## Flattened Device Tree from FIT Image at 85000000
   Using 'config@1' configuration
   Trying 'fdt-1' FDT blob subimage
     Description:  ARM OpenWrt extreme-networks_ws-ap7612 device tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x859e068c
     Data Size:    3460420 Bytes = 3.3 MiB
     Architecture: ARM
     Hash algo:    crc32
     Hash value:   4e8a5788
     Hash algo:    sha1
     Hash value:   88ecc3ac7d044bba4de58a0a3e5f4ddbe102aca0
   Verifying Hash Integrity ... crc32+ sha1+ OK
   Booting using the fdt blob at 0x859e068c
   Uncompressing Kernel Image ... OK
   Loading Device Tree to 86cb0000, end 86fffd43 ... OK
Device nand2 not found!
eth0 MAC Address from ART is not valid
eth1 MAC Address from ART is not valid
Using machid 0x8010001 from environment

Starting kernel ...

Can you share the dts file if you don't mind?

I wasn't expecting the dts file to be so huge, as the size of a dts file is usually around 10KB.
The fdt_blob.dts file structure looks like this:

/dts-v1/;

/ {
	#address-cells = <0x01>;
	description = "ARM OpenWrt FIT (Flattened Image Tree)";
	timestamp = <0x5b32b37f>;

	configurations {
		default = "config@1";

		config@1 {
			description = "OpenWrt";
			fdt = "fdt@1";
			kernel = "kernel@1";
		};
	};

	images {

		fdt@1 {
			arch = "arm";
			compression = "none";
			data = [ <fdt format data> ];
			description = "ARM OpenWrt qcom-ipq40xx-ap.dkxx device tree blob";
			type = "flat_dt";

			hash@1 {
				algo = "crc32";
				value = <0x8c0208a1>;
			};

			hash@2 {
				algo = "sha1";
				value = <0x11bc19cc 0xc487a971 0xbb666ea8 0x2b22137c 0x510d7fac>;
			};
		};

		kernel@1 {
			arch = "arm";
			compression = "gzip";
			data = [ <gzip compressed data> ];
			description = "ARM OpenWrt Linux-3.14.43";
			entry = <0x80208000>;
			load = <0x80208000>;
			os = "linux";
			type = "kernel";

			hash@1 {
				algo = "crc32";
				value = <0x2a4c52d>;
			};

			hash@2 {
				algo = "sha1";
				value = <0x1aab65e2 0x4880b0d8 0xeea6e7 0x91448009 0x855719d2>;
			};
		};
	};
};

You can see that the file contains two important pieces of data: fdt and kernel. The fdt data will be the one that you want to look into. I decompiled the fdt file to a dts file.

Here's what it looks like:
https://pastebin.com/S4FsL5dX

As a general practice, I rewrite a dts file myself and don't actually use the extracted version in OpenWrt, so I'm not really sure if it will work properly. But you can give it a try.

Good luck!

You absolutely have to rewrite the dts for OpenWrt. The vendor dts is usually only good to get an idea on the partition layout, the GPIO map ...

The reason is simple: The vendor bases its code usually on a proprietary SDK which differs often quite a lot from the Linux implementation.

I found that there is another router which uses the same NAND flash device (Netgear LBR20):

https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=07b9186e88a2e5b2bd842b87d7063645a23e3fcb

There is also a router which shares the same CPU (ipq4029), but uses smaller storage (Aruba AP-303):

https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=102c8c55f217606cdbdc9a449667e034676b3e75

Since I don't know the specifications of the AP-7612, I've modified the dts file based on your comments.

Here is the dts file I created:

// SPDX-License-Identifier: GPL-2.0-only OR MIT

#include "qcom-ipq4019.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/soc/qcom,tcsr.h>

/ {
	model = "Extreme Networks WS-AP3915i";
	compatible = "extreme-networks,ws-ap3915i";

	aliases {
		// TODO: Verify if the ethernet0 alias is needed
		ethernet0 = &gmac;
		led-boot = &led_system_green;
		led-failsafe = &led_system_amber;
		led-running = &led_system_green;
		led-upgrade = &led_system_amber;
	};

	soc {
		tcsr@1949000 {
			compatible = "qcom,tcsr";
			reg = <0x1949000 0x100>;
			qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
		};

		ess_tcsr@1953000 {
			compatible = "qcom,tcsr";
			reg = <0x1953000 0x1000>;
			qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
		};

		tcsr@1957000 {
			compatible = "qcom,tcsr";
			reg = <0x1957000 0x100>;
			qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
		};
	};

	leds {
		compatible = "gpio-leds";

		led_system_green: system_green {
			label = "green:system";
			gpios = <&tlmm 49 GPIO_ACTIVE_LOW>;
		};

		led_system_amber: system_amber {
			label = "amber:system";
			gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
		};

		led_wlan24_green: wlan24_green {
			label = "green:wlan24";
			gpios = <&tlmm 23 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy0tpt";
		};

		led_wlan24_amber: wlan24_amber {
			label = "amber:wlan24";
			gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
		};

		led_wlan5_green: wlan5_green {
			label = "green:wlan5";
			gpios = <&tlmm 22 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy1tpt";
		};

		led_wlan5_amber: wlan5_amber {
			label = "amber:wlan5";
			gpios = <&tlmm 26 GPIO_ACTIVE_LOW>;
		};

		iot {
			label = "blue:iot";
			gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
		};
	};

	keys {
		compatible = "gpio-keys";

		reset {
			label = "reset";
			gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_RESTART >;
		};
	};
};

&watchdog {
	status = "okay";
};

&prng {
	status = "okay";
};

&crypto {
	status = "okay";
};

&blsp_dma {
	status = "okay";
};

&blsp1_uart1 {
	pinctrl-0 = <&serial_pins>;
	pinctrl-names = "default";
	status = "okay";
};

&cryptobam {
	status = "okay";
};

&mdio {
	status = "okay";
	pinctrl-0 = <&mdio_pins>;
	pinctrl-names = "default";
};

&gmac {
	status = "okay";
};

&switch {
	status = "okay";
};

&swport5 {
	status = "okay";

	label = "lan";
};

&tlmm {
	mdio_pins: mdio_pinmux {
		mux_1 {
			pins = "gpio6";
			function = "mdio";
			bias-pull-up;
		};
		mux_2 {
			pins = "gpio7";
			function = "mdc";
			bias-pull-up;
		};
	};

	serial_pins: serial_0_pinmux {
		mux {
			pins = "gpio16", "gpio17";
			function = "blsp_uart0";
			bias-disable;
		};
	};

	nand_pins: nand-pins {
		pullups {
			pins = "gpio52", "gpio53", "gpio58", "gpio59";
			function = "qpic";
			bias-pull-up;
		};

		pulldowns {
			pins = "gpio54", "gpio55", "gpio56",
			       "gpio57", "gpio60", "gpio61",
			       "gpio62", "gpio63", "gpio64",
			       "gpio65", "gpio66", "gpio67",
			       "gpio68", "gpio69";
			function = "qpic";
			bias-pull-down;
		};
	};
};

&wifi0 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&wifi1 {
	status = "okay";
	qcom,ath10k-calibration-variant = "Extreme-Networks-WS-AP3915i";
};

&nand {
	pinctrl-0 = <&nand_pins>;
	pinctrl-names = "default";
	status = "okay";

	nand@0 {
		partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			partition@0 {
				label = "sbl1";
				reg = <0x000000000000 0x000000100000>;
				read-only;
			};

			partition@100000 {
				label = "mibib";
				reg = <0x000000100000 0x000000100000>;
			};

			partition@200000 {
				label = "bootcfg";
				reg = <0x000000200000 0x000000100000>;
			};

			partition@300000 {
				label = "qsee";
				reg = <0x000000300000 0x000000100000>;
				read-only;
			};

			partition@400000 {
				label = "qsee_alt";
				reg = <0x000000400000 0x000000100000>;
			};

			partition@500000 {
				label = "cdt";
				reg = <0x000000500000 0x000000080000>;
			};

			partition@580000 {
				label = "cdt_alt";
				reg = <0x000000580000 0x000000080000>;
			};

			partition@600000 {
				label = "ddrparams";
				reg = <0x000000600000 0x000000080000>;
			};
            
            partition@680000 {
                label = "appsblenv";
                reg = <0x000000680000 0x000000080000>;
            };

            partition@700000 {
                label = "bootstrap";
                reg = <0x000000700000 0x000000200000>;
            };

            partition@900000 {
                label = "boot1";
                reg = <0x000000900000 0x000000100000>;
            };

            partition@a00000 {
                label = "boot2";
                reg = <0x000000a00000 0x000000100000>;
            };

            partition@b00000 {
                label = "art";
                reg = <0x000000b00000 0x000000080000>;
                read-only;
            };

            partition@b80000 {
                label = "linux1";
                reg = <0x000000b80000 0x000000800000>;
            };

            partition@1380000 {
                label = "linux2";
                reg = <0x000001380000 0x000000800000>;
            };

            partition@1b80000 {
                label = "rootfs1";
                reg = <0x000001b80000 0x000008900000>;
            };

            partition@a480000 {
                label = "rootfs2";
                reg = <0x00000a480000 0x000008900000>;
            };

            partition@12d80000 {
                label = "var2";
                reg = <0x000012d80000 0x000002200000>;
            };

            partition@14f80000 {
                label = "etc2";
                reg = <0x000014f80000 0x000004000000>;
            };

            partition@18f80000 {
                label = "flash";
                reg = <0x000018f80000 0x000005400000>;
            };

            partition@1e380000 {
                label = "panic";
                reg = <0x00001e380000 0x000001c80000>;
            };
		};
	};
};

I believe those two commits are a good starting point for adding support for Extreme AP-7612.

Thank you for the work. I am seeing how much deeper knowledge is required for a port. So to confirm, do I need to add some of the code you wrote to and existing file like the 3915i's bootable dts file?

My understanding is that you are building an image for Extreme Networks WS-AP3915i (ipq4029-ws-qp3915i), to test if it also works on your router. However, the WS-AP3915i uses SPI-NOR flash, while your router has NAND flash. With the current image, your router probably can't mount its flash, which is why you're trying to add support for it.

Based on the comments, it looks like you're doing a "quick hack" by modifying the existing WS-AP3915i dts file to mount the NAND flash, rather than creating a new device profile. If you are taking this approach, you should overwrite the WS-AP3915i dts file with the one I shared with you.

Alternatively, if you are creating a new dts file from scratch, you'll need to add the following two sections:

  1. Add the nand_pins to the &tlmm section:
&tlmm {

...

	nand_pins: nand-pins {
		pullups {
			pins = "gpio52", "gpio53", "gpio58", "gpio59";
			function = "qpic";
			bias-pull-up;
		};

		pulldowns {
			pins = "gpio54", "gpio55", "gpio56",
			       "gpio57", "gpio60", "gpio61",
			       "gpio62", "gpio63", "gpio64",
			       "gpio65", "gpio66", "gpio67",
			       "gpio68", "gpio69";
			function = "qpic";
			bias-pull-down;
		};
	};

...

};
  1. Add the &nand section:
&nand {
	pinctrl-0 = <&nand_pins>;
	pinctrl-names = "default";
	status = "okay";

	nand@0 {
		partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			partition@0 {
				label = "sbl1";
				reg = <0x000000000000 0x000000100000>;
				read-only;
			};

			partition@100000 {
				label = "mibib";
				reg = <0x000000100000 0x000000100000>;
			};

			partition@200000 {
				label = "bootcfg";
				reg = <0x000000200000 0x000000100000>;
			};

			partition@300000 {
				label = "qsee";
				reg = <0x000000300000 0x000000100000>;
				read-only;
			};

			partition@400000 {
				label = "qsee_alt";
				reg = <0x000000400000 0x000000100000>;
			};

			partition@500000 {
				label = "cdt";
				reg = <0x000000500000 0x000000080000>;
			};

			partition@580000 {
				label = "cdt_alt";
				reg = <0x000000580000 0x000000080000>;
			};

			partition@600000 {
				label = "ddrparams";
				reg = <0x000000600000 0x000000080000>;
			};
            
            partition@680000 {
                label = "appsblenv";
                reg = <0x000000680000 0x000000080000>;
            };

            partition@700000 {
                label = "bootstrap";
                reg = <0x000000700000 0x000000200000>;
            };

            partition@900000 {
                label = "boot1";
                reg = <0x000000900000 0x000000100000>;
            };

            partition@a00000 {
                label = "boot2";
                reg = <0x000000a00000 0x000000100000>;
            };

            partition@b00000 {
                label = "art";
                reg = <0x000000b00000 0x000000080000>;
                read-only;
            };

            partition@b80000 {
                label = "linux1";
                reg = <0x000000b80000 0x000000800000>;
            };

            partition@1380000 {
                label = "linux2";
                reg = <0x000001380000 0x000000800000>;
            };

            partition@1b80000 {
                label = "rootfs1";
                reg = <0x000001b80000 0x000008900000>;
            };

            partition@a480000 {
                label = "rootfs2";
                reg = <0x00000a480000 0x000008900000>;
            };

            partition@12d80000 {
                label = "var2";
                reg = <0x000012d80000 0x000002200000>;
            };

            partition@14f80000 {
                label = "etc2";
                reg = <0x000014f80000 0x000004000000>;
            };

            partition@18f80000 {
                label = "flash";
                reg = <0x000018f80000 0x000005400000>;
            };

            partition@1e380000 {
                label = "panic";
                reg = <0x00001e380000 0x000001c80000>;
            };
		};
	};
};

Even if you're using the quick hack method for now, I would recommend creating a new device profile for your router. This keeps the changes cleaner, makes it easier to submit a pull request, and allows you to contribute your work back to the OpenWrt project in the future.

Thank you for all the help! I tweaked the firmware around until I got it to boot, mount the mtds, and interface with networking. From there I uploaded the squashfs.bin I compiled and ran mtd write /tmp/firmware.bin rootfs1. (as shown above there is no 'firmware' mtd). The flashed image partially boots until it tried to read the mtd as jffs2 for some reason. (I set the uboot boot-args to squashfs) Here is the context and error output:

[    0.996727] brd: module loaded
[    0.999008] at24 0-0057: 32768 byte 24c256 EEPROM, writable, 1 bytes/write
[    1.007210] sps: BAM device 0x07984000 is not registered yet.
[    1.011932] sps:BAM 0x07984000 is registered.
[    1.016146] msm_nand_bam_init: msm_nand_bam_init: BAM device registered: bam_handle 0xd7532200
[    1.025010] sps:BAM 0x07984000 (va:0xe0a60000) enabled: ver:0x19, number of pipes:7
[    1.032724] msm_nand_version_check: nand_major:1, nand_minor:4, qpic_major:1, qpic_minor:4
[    1.040796] msm_nand_scan: num ecc correctable bit not specified and defaults to 4 bit BCH
[    1.049061] msm_nand_scan: NAND Id: 0x9590dcc2 Buswidth: 8Bits Density: 512 MByte
[    1.056477] msm_nand_scan: pagesize: 2048 Erasesize: 131072 oobsize: 64 (in Bytes)
[    1.064021] msm_nand_scan: BCH ECC: 4 Bit
[    1.068010] msm_nand_scan: CFG0: 0x2a0408c0,      CFG1: 0x0804745c
[    1.068010]             RAWCFG0: 0x280420c0,   RAWCFG1: 0x0005045d
[    1.068010]           ECCBUFCFG: 0x00000203, ECCBCHCFG: 0x42040700
[    1.068010]      BAD BLOCK BYTE: 0x000001d1
[    1.090681] Creating 22 MTD partitions on "7980000.qcom,nand":
[    1.096494] 0x000000000000-0x000020000000 : "all_nand"
[    1.463837] 0x000000000000-0x000000100000 : "sbl1"
[    1.469333] 0x000000100000-0x000000200000 : "mibib"
[    1.474959] 0x000000200000-0x000000300000 : "bootcfg"
[    1.480697] 0x000000300000-0x000000400000 : "qsee"
[    1.486230] 0x000000400000-0x000000500000 : "qsee_alt"
[    1.492040] 0x000000500000-0x000000580000 : "cdt"
[    1.497046] 0x000000580000-0x000000600000 : "cdt_alt"
[    1.502372] 0x000000600000-0x000000680000 : "ddrparams"
[    1.507840] 0x000000680000-0x000000700000 : "appsblenv"
[    1.513269] 0x000000700000-0x000000900000 : "bootstrap"
[    1.519798] 0x000000900000-0x000000a00000 : "boot1"
[    1.525276] 0x000000a00000-0x000000b00000 : "boot2"
[    1.530727] 0x000000b00000-0x000000b80000 : "art"
[    1.535724] 0x000000b80000-0x000001380000 : "linux1"
[    1.546256] 0x000001380000-0x000001b80000 : "linux2"
[    1.556800] 0x000001b80000-0x00000a480000 : "rootfs1"
[    1.658420] 0x00000a480000-0x000012d80000 : "rootfs2"
[    1.760057] 0x000012d80000-0x000014f80000 : "var2"
[    1.788709] 0x000014f80000-0x000018f80000 : "etc2"
[    1.838540] 0x000018f80000-0x00001e380000 : "flash"
[    1.902533] 0x00001e380000-0x000020000000 : "panic"
[    1.927459] msm_nand_probe: NANDc phys addr 0x7980000, BAM phys addr 0x7984000, BAM IRQ 133
[    1.934804] msm_nand_probe: Allocated DMA buffer at virt_addr 0xe0a5a000, phys_addr 0x97550000
[    1.944389] libphy: ipq40xx_mdio: probed

[    4.054190] input: gpio_keys.7 as /devices/soc.0/gpio_keys.7/input/input0
[    4.060190] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[    4.069413] clk: Not disabling unused clocks
[    4.074045] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000000: 0x0dd0 instead
[    4.082499] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000004: 0x4b00 instead
[    4.092004] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000000c: 0x4b00 instead
[    4.101440] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000024: 0x4b00 instead
[    4.110900] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000004c: 0x4a68 instead
[    4.120375] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000005c: 0x5241 instead
[    4.129819] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000060: 0x704f instead
[    4.139289] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000064: 0x7257 instead
[    4.148743] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000068: 0x4946 instead
[    4.158203] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000006c: 0x4628 instead
[    4.167662] jffs2: Further such events for this erase block will not be printed
[    4.195132] jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00020000: 0xd4c1 instead
[   15.311782] jffs2_scan_eraseblock(): End of filesystem marker found at 0xb40000
[   15.407171] jffs2: Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes
[   15.414592] jffs2: empty_blocks 1005, bad_blocks 1, c->nr_blocks 1096
[   15.421162] VFS: Cannot open root device "mtdblock16" or unknown-block(31,16): error -5
[   15.429023] Please append a correct "root=" boot option; here are the available partitions:
[   15.437349] 1f00          524288 mtdblock0  (driver?)
[   15.442356] 1f01            1024 mtdblock1  (driver?)
[   15.447390] 1f02            1024 mtdblock2  (driver?)
[   15.452425] 1f03            1024 mtdblock3  (driver?)
[   15.457462] 1f04            1024 mtdblock4  (driver?)
[   15.462494] 1f05            1024 mtdblock5  (driver?)
[   15.467529] 1f06             512 mtdblock6  (driver?)
[   15.472564] 1f07             512 mtdblock7  (driver?)
[   15.477600] 1f08             512 mtdblock8  (driver?)
[   15.482633] 1f09             512 mtdblock9  (driver?)
[   15.487668] 1f0a            2048 mtdblock10  (driver?)
[   15.492789] 1f0b            1024 mtdblock11  (driver?)
[   15.497912] 1f0c            1024 mtdblock12  (driver?)
[   15.503032] 1f0d             512 mtdblock13  (driver?)
[   15.508156] 1f0e            8192 mtdblock14  (driver?)
[   15.513276] 1f0f            8192 mtdblock15  (driver?)
[   15.518399] 1f10          140288 mtdblock16  (driver?)
[   15.523536] 1f11          140288 mtdblock17  (driver?)
[   15.528640] 1f12           34816 mtdblock18  (driver?)
[   15.533777] 1f13           65536 mtdblock19  (driver?)
[   15.538884] 1f14           86016 mtdblock20  (driver?)
[   15.544021] 1f15           29184 mtdblock21  (driver?)
[   15.549126] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,16)