[OpenWrt-Devel,3/3] ipq806x: add Netgear EX6100v2/EX6150v2 support

Message ID 881f89b9b0053dffda04da4320868c5ef1e92c3d.1515579309.git.tommyhebb@gmail.com
State Superseded
Delegated to: John Crispin
Headers show
Series
  • [OpenWrt-Devel,1/3] build: allow custom config names in mkits.sh
Related show

Commit Message

Thomas Hebb Jan. 10, 2018, 10:15 a.m.
This patch adds support for the Netgear EX6100v2 and EX6150v2 Wi-Fi
range extenders.

Hardware:

SoC:    Qualcomm IPQ4018
RAM:    256 MiB
FLASH:  16 MiB Winbond W25Q128
ETH:    Qualcomm IPQ4018 Gigabit PHY, 1 port
WLAN1:  Qualcomm Atheros QCA4018 2.4GHz 802.11b/g/n 2x2
WLAN2:  Qualcomm Atheros QCA4018 5GHz 802.11n/ac 1x1 (EX6100v2)
WLAN2:  Qualcomm Atheros QCA4018 5GHz 802.11n/ac 2x2 (EX6150v2)
INPUT:  Power, WPS, factory reset buttons, AP/extender mode toggle switch
LEDS:   Power, router, client (dual color red/green)
        Router activity, client activity (blue)
        WPS (green)
SERIAL: 3.3V unpopulated serial header connected to ttyMSM0. 11520n8.
        Serial access is not required to install OpenWRT on the device.

        To access, unscrew the four Torx T10 screws on the back of the
        unit and unclip the faceplate. Then, unclip the power supply
        board (to which the logic board is mounted using four large
        standoffs) from the large clips on the top and bottom that hold
        it in place. Flip over the boards so the power supply board is
        on top, making sure not to damage the Wi-Fi antenna wires.
        Unscrew the four Phillips #1 screws connecting the power supply
        board to the standoffs and carefully lift it off, unplugging the
        eight-pin connector that supplies power to the logic board. Then
        unscrew the four hexagonal standoffs from the logic board, flip
        the board over again, and lift off the metal shield (watch out
        for thermal compound). The unpopulated header is located at the
        bottom edge of the logic board, with pins 1 (square pad), 2, 3,
        and 4 carrying VDD (3.3V), TX, RX, and GND respectively.

To install, upload openwrt-ipq806x-EX61x0v2-squashfs-factory.img to the
Netgear web interface as a firmware update and ensure that the listed
update version matches that of the OpenWRT image you're trying to
install. Note that OpenWRT will not bring up the wireless interfaces by
default, so you must be able to connect to Ethernet for initial
configuration.

Features, tested and working:
 - Serial
 - Flash
 - Ethernet
 - Wi-Fi, 2.4GHz and 5GHz
 - Buttons (WPS and factory reset, which acts as restart)
 - LEDs (most of which are driven by a shift register connected to SoC GPIOs)
 - Factory OpenWRT install from Netgear firmware
 - OpenWRT sysupgrade

Features, untested but should work:
 - All above on the EX6150v2. I only own an EX6100v2 and so could not
   verify the other device.

Features, not planned:
 - AP/extender toggle switch

These two boards are unusual in that they both run the same stock image
and share the same official update binaries. As far as I can tell, the
only difference between the two units is the 5GHz MIMO configuration:
1x1 for the EX6100v2 and 2x2 for the EX6150v2. Since the boards are so
similar, both are supported by a single OpenWRT image, which determines
the board it's running on at runtime by reading the flash. The only
runtime differences between the two boards are the board name, the model
name, and the Wi-Fi calibration data that gets loaded.

U-Boot on this device is device-tree aware, and the stock firmware
provides the kernel and device tree in a FIT image. We do the same
because, even though this version of U-Boot ought to be able to boot a
uImage with appended DTB, I was unable to make that configuration work
for unknown reasons.

The Wi-Fi calibration data (board-2.dat) for both boards was taken from
an official Netgear firmware update.

Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---
 package/firmware/ipq-wifi/Makefile                 |   4 +-
 package/firmware/ipq-wifi/board-ex6100v2.bin       | Bin 0 -> 24276 bytes
 package/firmware/ipq-wifi/board-ex6150v2.bin       | Bin 0 -> 24276 bytes
 .../ipq806x/base-files/etc/board.d/02_network      |   4 +
 .../etc/hotplug.d/firmware/11-ath10k-caldata       |   8 +-
 .../etc/hotplug.d/ieee80211/10_fix_wifi_mac        |  13 ++
 target/linux/ipq806x/base-files/lib/ipq806x.sh     |  24 +++
 target/linux/ipq806x/config-4.9                    |   2 +
 .../arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts    | 211 +++++++++++++++++++++
 target/linux/ipq806x/image/Makefile                |  41 +++-
 .../patches-4.9/0069-arm-boot-add-dts-files.patch  |   3 +-
 11 files changed, 300 insertions(+), 10 deletions(-)
 create mode 100644 package/firmware/ipq-wifi/board-ex6100v2.bin
 create mode 100644 package/firmware/ipq-wifi/board-ex6150v2.bin
 create mode 100644 target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts

Comments

Mathias Kresin Jan. 11, 2018, 6:35 a.m. | #1
Hey Thomas,

I only had a brief look at the patch. Might be there is more stuff to 
change. Find my comments inline.

10.01.2018 11:15, Thomas Hebb:
> This patch adds support for the Netgear EX6100v2 and EX6150v2 Wi-Fi
> range extenders.
> 
> Hardware:
> 
> SoC:    Qualcomm IPQ4018
> RAM:    256 MiB
> FLASH:  16 MiB Winbond W25Q128
> ETH:    Qualcomm IPQ4018 Gigabit PHY, 1 port
> WLAN1:  Qualcomm Atheros QCA4018 2.4GHz 802.11b/g/n 2x2
> WLAN2:  Qualcomm Atheros QCA4018 5GHz 802.11n/ac 1x1 (EX6100v2)
> WLAN2:  Qualcomm Atheros QCA4018 5GHz 802.11n/ac 2x2 (EX6150v2)
> INPUT:  Power, WPS, factory reset buttons, AP/extender mode toggle switch
> LEDS:   Power, router, client (dual color red/green)
>          Router activity, client activity (blue)
>          WPS (green)
> SERIAL: 3.3V unpopulated serial header connected to ttyMSM0. 11520n8.
>          Serial access is not required to install OpenWRT on the device.
> 
>          To access, unscrew the four Torx T10 screws on the back of the
>          unit and unclip the faceplate. Then, unclip the power supply
>          board (to which the logic board is mounted using four large
>          standoffs) from the large clips on the top and bottom that hold
>          it in place. Flip over the boards so the power supply board is
>          on top, making sure not to damage the Wi-Fi antenna wires.
>          Unscrew the four Phillips #1 screws connecting the power supply
>          board to the standoffs and carefully lift it off, unplugging the
>          eight-pin connector that supplies power to the logic board. Then
>          unscrew the four hexagonal standoffs from the logic board, flip
>          the board over again, and lift off the metal shield (watch out
>          for thermal compound). The unpopulated header is located at the
>          bottom edge of the logic board, with pins 1 (square pad), 2, 3,
>          and 4 carrying VDD (3.3V), TX, RX, and GND respectively.
> 
> To install, upload openwrt-ipq806x-EX61x0v2-squashfs-factory.img to the
> Netgear web interface as a firmware update and ensure that the listed
> update version matches that of the OpenWRT image you're trying to
> install. Note that OpenWRT will not bring up the wireless interfaces by
> default, so you must be able to connect to Ethernet for initial
> configuration.
> 
> Features, tested and working:
>   - Serial
>   - Flash
>   - Ethernet
>   - Wi-Fi, 2.4GHz and 5GHz
>   - Buttons (WPS and factory reset, which acts as restart)
>   - LEDs (most of which are driven by a shift register connected to SoC GPIOs)
>   - Factory OpenWRT install from Netgear firmware
>   - OpenWRT sysupgrade
> 
> Features, untested but should work:
>   - All above on the EX6150v2. I only own an EX6100v2 and so could not
>     verify the other device.
> 
> Features, not planned:
>   - AP/extender toggle switch
> 
> These two boards are unusual in that they both run the same stock image
> and share the same official update binaries. As far as I can tell, the
> only difference between the two units is the 5GHz MIMO configuration:
> 1x1 for the EX6100v2 and 2x2 for the EX6150v2. Since the boards are so
> similar, both are supported by a single OpenWRT image, which determines
> the board it's running on at runtime by reading the flash. The only
> runtime differences between the two boards are the board name, the model
> name, and the Wi-Fi calibration data that gets loaded.
> 
> U-Boot on this device is device-tree aware, and the stock firmware
> provides the kernel and device tree in a FIT image. We do the same
> because, even though this version of U-Boot ought to be able to boot a
> uImage with appended DTB, I was unable to make that configuration work
> for unknown reasons.
> 
> The Wi-Fi calibration data (board-2.dat) for both boards was taken from
> an official Netgear firmware update.
> 
> Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
> ---
>   package/firmware/ipq-wifi/Makefile                 |   4 +-
>   package/firmware/ipq-wifi/board-ex6100v2.bin       | Bin 0 -> 24276 bytes
>   package/firmware/ipq-wifi/board-ex6150v2.bin       | Bin 0 -> 24276 bytes
>   .../ipq806x/base-files/etc/board.d/02_network      |   4 +
>   .../etc/hotplug.d/firmware/11-ath10k-caldata       |   8 +-
>   .../etc/hotplug.d/ieee80211/10_fix_wifi_mac        |  13 ++
>   target/linux/ipq806x/base-files/lib/ipq806x.sh     |  24 +++
>   target/linux/ipq806x/config-4.9                    |   2 +
>   .../arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts    | 211 +++++++++++++++++++++
>   target/linux/ipq806x/image/Makefile                |  41 +++-
>   .../patches-4.9/0069-arm-boot-add-dts-files.patch  |   3 +-
>   11 files changed, 300 insertions(+), 10 deletions(-)
>   create mode 100644 package/firmware/ipq-wifi/board-ex6100v2.bin
>   create mode 100644 package/firmware/ipq-wifi/board-ex6150v2.bin
>   create mode 100644 target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts
> 
> diff --git a/target/linux/ipq806x/base-files/lib/ipq806x.sh b/target/linux/ipq806x/base-files/lib/ipq806x.sh
> index c4d2c8f258..1e011292eb 100644
> --- a/target/linux/ipq806x/base-files/lib/ipq806x.sh
> +++ b/target/linux/ipq806x/base-files/lib/ipq806x.sh
> @@ -7,6 +7,8 @@
>   IPQ806X_BOARD_NAME=
>   IPQ806X_MODEL=
>   
> +. /lib/functions.sh
> +
>   ipq806x_board_detect() {
>   	local machine
>   	local name
> @@ -50,6 +52,28 @@ ipq806x_board_detect() {
>   	*"VR2600v")
>   		name="vr2600v"
>   		;;
> +	*"EX61x0v2")
> +		# There are two models in this series, which have identical
> +		# hardware save for the number of 5G antennas. Since we run
> +		# the exact same image on both, we need to check the flash
> +		# to distinguish which we're running on.
> +		local hw_id="$(dd if="$(find_mtd_part dnidata)" \
> +			       bs=1 skip=41 count=25 2>/dev/null)"
> +
> +		case "$hw_id" in
> +		*"1x1")
> +			name="ex6100v2"
> +			IPQ806X_MODEL="Netgear EX6100v2"
> +			;;
> +		*"2x2")
> +			name="ex6150v2"
> +			IPQ806X_MODEL="Netgear EX6150v2"
> +			;;
> +		*)
> +			name="ex6100v2"
> +			IPQ806X_MODEL="Netgear EX61?0v2 (ERROR: failed to parse hw_id)"
> +		esac
> +		;;

Please don't do this kind of hackery. Create two images with two 
devicetree source files instead. Move common stuff to a dtsi and include 
the dtsi for both dts.

Please use the compatible string from the dts as boardname. Have a look 
at the ipq806x branch in my staging tree [0] for upcoming changes

>   	esac
>   
>   	[ -z "$name" ] && name="unknown"
> diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts
> new file mode 100644
> index 0000000000..a2ae64a1dc
> --- /dev/null
> +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts
> @@ -0,0 +1,211 @@
> +#include "qcom-ipq4019-ap.dk01.1.dtsi"

Don't include qcom-ipq4019-ap.dk01.1.dtsi here. It is an common file for 
the QCA ap.dk01 eval board and your board isn't an eval board. Copy 
relevant parts to your own dts.

> +#include "qcom-ipq4019-bus.dtsi"
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "Netgear EX61x0v2";
> +	compatible = "netgear,ex61x0v2", "qcom,ipq4019";
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0x80000000 0x10000000>;
> +	};
> +
> +	reserved-memory {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;
> +
> +		rsvd@87E00000 {
> +			reg = <0x87E00000 0x0200000>;
> +			no-map;
> +		};
> +	};
> +
> +	aliases {
> +		led-boot = &power_amber;
> +		led-failsafe = &power_amber;
> +		led-running = &power_green;
> +		led-upgrade = &power_amber;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	led_spi {
> +		compatible = "spi-gpio";
> +		#address-cells = <1>;
> +		ranges;
> +
> +		gpio-sck = <&tlmm 5 GPIO_ACTIVE_HIGH>;
> +		gpio-mosi = <&tlmm 4 GPIO_ACTIVE_HIGH>;
> +		num-chipselects = <0>;
> +
> +		led_gpio: led_gpio@0 {
> +			compatible = "fairchild,74hc595";
> +			reg = <0>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			registers-number = <1>;
> +			spi-max-frequency = <1000000>;
> +		};
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		wps {
> +			label = "wps";
> +			gpios = <&tlmm 0 GPIO_ACTIVE_LOW>;
> +			linux,code = <KEY_WPS_BUTTON>;
> +		};
> +
> +		reset {
> +			label = "reset";
> +			gpios = <&tlmm 63 GPIO_ACTIVE_LOW>;
> +			linux,code = <KEY_RESTART>;
> +		};
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +
> +		power_amber: power_amber {
> +			label = "ex61x0v2:amber:power";
> +			gpios = <&led_gpio 7 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		power_green: power_green {
> +			label = "ex61x0v2:green:power";
> +			gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		right {
> +			label = "ex61x0v2:blue:right";
> +			gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		left {
> +			label = "ex61x0v2:blue:left";
> +			gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		client_green {
> +			label = "ex61x0v2:green:client";
> +			gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		client_red {
> +			label = "ex61x0v2:red:client";
> +			gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		router_green {
> +			label = "ex61x0v2:green:router";
> +			gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		router_red {
> +			label = "ex61x0v2:red:router";
> +			gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		wps {
> +			label = "ex61x0v2:green:wps";
> +			gpios = <&tlmm 1 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +};
> +
> +&spi_0 {
> +	flash@0 {
> +		compatible = "winbond,w25q128", "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <24000000>;
> +
> +		partitions {
> +			compatible = "fixed-partitions";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			partition0@0 {
> +				label = "SBL1";
> +				reg = <0x00000000 0x00040000>;
> +				read-only;
> +			};
> +
> +			partition1@40000 {
> +				label = "MIBIB";
> +				reg = <0x00040000 0x00020000>;
> +				read-only;
> +			};
> +
> +			partition2@60000 {
> +				label = "QSEE";
> +				reg = <0x00060000 0x00060000>;
> +				read-only;
> +			};
> +
> +			partition3@c0000 {
> +				label = "CDT";
> +				reg = <0x000c0000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition4@d0000 {
> +				label = "DDRPARAMS";
> +				reg = <0x000d0000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition5@e0000 {
> +				label = "APPSBLENV";
> +				reg = <0x000e0000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition6@f0000 {
> +				label = "APPSBL";
> +				reg = <0x000f0000 0x00080000>;
> +				read-only;
> +			};
> +
> +			partition7@170000 {
> +				label = "ART";
> +				reg = <0x00170000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition8@180000 {
> +				label = "config";
> +				reg = <0x00180000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition9@190000 {
> +				label = "pot";
> +				reg = <0x00190000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition10@1a0000 {
> +				label = "dnidata";
> +				reg = <0x001a0000 0x00010000>;
> +				read-only;
> +			};
> +
> +			partition11@1b0000 {
> +				label = "firmware";
> +				reg = <0x001b0000 0x00e10000>;
> +			};
> +
> +			partition12@fc0000 {
> +				label = "language";
> +				reg = <0x00fc0000 0x00040000>;
> +				read-only;
> +			};
> +		};
> +	};
> +};


Mathias

[0] https://git.openwrt.org/?p=openwrt/staging/mkresin.git;a=summary

Patch

diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile
index f2b705e13a..7d26938e97 100644
--- a/package/firmware/ipq-wifi/Makefile
+++ b/package/firmware/ipq-wifi/Makefile
@@ -13,7 +13,7 @@  endef
 define Build/Compile
 endef
 
-ALLWIFIBOARDS:=rt-ac58u fritz4040 nbg6617
+ALLWIFIBOARDS:=rt-ac58u fritz4040 nbg6617 ex6100v2 ex6150v2
 ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD))
 
 define Package/ipq-wifi-default
@@ -44,5 +44,7 @@  endef
 $(eval $(call generate-ipq-wifi-package,rt-ac58u,ASUS RT-AC58U/RT-ACRH13))
 $(eval $(call generate-ipq-wifi-package,fritz4040,AVM FRITZBox 4040))
 $(eval $(call generate-ipq-wifi-package,nbg6617,ZyXEL NBG6617))
+$(eval $(call generate-ipq-wifi-package,ex6100v2,Netgear EX6100v2))
+$(eval $(call generate-ipq-wifi-package,ex6150v2,Netgear EX6150v2))
 
 $(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE))))
diff --git a/package/firmware/ipq-wifi/board-ex6100v2.bin b/package/firmware/ipq-wifi/board-ex6100v2.bin
new file mode 100644
index 0000000000000000000000000000000000000000..5bb224b244140a1da38b5eaf12cdacf1cccd4fd1
GIT binary patch
literal 24276
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
ak0#zL7=AqolsiBkI>WD@?oZ8$`~M&E1DN~(

literal 0
HcmV?d00001

diff --git a/package/firmware/ipq-wifi/board-ex6150v2.bin b/package/firmware/ipq-wifi/board-ex6150v2.bin
new file mode 100644
index 0000000000000000000000000000000000000000..930b87053969674534134d0ccf3e5820ccd47d50
GIT binary patch
literal 24276
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
P&>4RHWWQ^UKmPv#T2ht@

literal 0
HcmV?d00001

diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network
index ad357b7363..6587b9309d 100755
--- a/target/linux/ipq806x/base-files/etc/board.d/02_network
+++ b/target/linux/ipq806x/base-files/etc/board.d/02_network
@@ -50,6 +50,10 @@  nbg6817)
 	ucidef_set_interface_macaddr "lan" "$(macaddr_add $hw_mac_addr 2)"
 	ucidef_set_interface_macaddr "wan" "$(macaddr_add $hw_mac_addr 3)"
 	;;
+ex6100v2 |\
+ex6150v2)
+	ucidef_set_interface_lan "eth0"
+	;;
 *)
 	echo "Unsupported hardware. Network interfaces not intialized"
 	;;
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index 4c5b55bc53..b16b637911 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -47,7 +47,9 @@  board=$(board_name)
 case "$FIRMWARE" in
 "ath10k/pre-cal-ahb-a000000.wifi.bin")
 	case "$board" in
-	ap-dk01.1-c1)
+	ap-dk01.1-c1 |\
+	ex6100v2 |\
+	ex6150v2)
 		ath10kcal_extract "ART" 4096 12064
 		;;
 	fritz4040)
@@ -57,7 +59,9 @@  case "$FIRMWARE" in
 	;;
 "ath10k/pre-cal-ahb-a800000.wifi.bin")
 	case "$board" in
-	ap-dk01.1-c1)
+	ap-dk01.1-c1 |\
+	ex6100v2 |\
+	ex6150v2)
 		ath10kcal_extract "ART" 20480 12064
 		;;
 	fritz4040)
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
index 7884f5117a..0f3231323a 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
@@ -29,6 +29,19 @@  case "$board" in
 	vr2600v)
 		echo $(macaddr_add $(mtd_get_mac_binary default-mac 0)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
 		;;
+	ex6100v2 |\
+	ex6150v2)
+		case "$PHYNBR" in
+		0)
+			# 2.4G
+			echo $(mtd_get_mac_binary dnidata 0) > /sys${DEVPATH}/macaddress
+			;;
+		1)
+			# 5G
+			echo $(mtd_get_mac_binary dnidata 12) > /sys${DEVPATH}/macaddress
+			;;
+		esac
+		;;
 	*)
 		;;
 esac
diff --git a/target/linux/ipq806x/base-files/lib/ipq806x.sh b/target/linux/ipq806x/base-files/lib/ipq806x.sh
index c4d2c8f258..1e011292eb 100644
--- a/target/linux/ipq806x/base-files/lib/ipq806x.sh
+++ b/target/linux/ipq806x/base-files/lib/ipq806x.sh
@@ -7,6 +7,8 @@ 
 IPQ806X_BOARD_NAME=
 IPQ806X_MODEL=
 
+. /lib/functions.sh
+
 ipq806x_board_detect() {
 	local machine
 	local name
@@ -50,6 +52,28 @@  ipq806x_board_detect() {
 	*"VR2600v")
 		name="vr2600v"
 		;;
+	*"EX61x0v2")
+		# There are two models in this series, which have identical
+		# hardware save for the number of 5G antennas. Since we run
+		# the exact same image on both, we need to check the flash
+		# to distinguish which we're running on.
+		local hw_id="$(dd if="$(find_mtd_part dnidata)" \
+			       bs=1 skip=41 count=25 2>/dev/null)"
+
+		case "$hw_id" in
+		*"1x1")
+			name="ex6100v2"
+			IPQ806X_MODEL="Netgear EX6100v2"
+			;;
+		*"2x2")
+			name="ex6150v2"
+			IPQ806X_MODEL="Netgear EX6150v2"
+			;;
+		*)
+			name="ex6100v2"
+			IPQ806X_MODEL="Netgear EX61?0v2 (ERROR: failed to parse hw_id)"
+		esac
+		;;
 	esac
 
 	[ -z "$name" ] && name="unknown"
diff --git a/target/linux/ipq806x/config-4.9 b/target/linux/ipq806x/config-4.9
index bca4264c8f..6ba480d5a3 100644
--- a/target/linux/ipq806x/config-4.9
+++ b/target/linux/ipq806x/config-4.9
@@ -189,6 +189,7 @@  CONFIG_GENERIC_STRNLEN_USER=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_74X164=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_HANDLE_DOMAIN_IRQ=y
 CONFIG_HARDIRQS_SW_RESEND=y
@@ -452,6 +453,7 @@  CONFIG_SPARSE_IRQ=y
 CONFIG_SPI=y
 # CONFIG_SPI_CADENCE_QUADSPI is not set
 CONFIG_SPI_MASTER=y
+CONFIG_SPI_GPIO=y
 CONFIG_SPI_QUP=y
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts
new file mode 100644
index 0000000000..a2ae64a1dc
--- /dev/null
+++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-ex61x0v2.dts
@@ -0,0 +1,211 @@ 
+#include "qcom-ipq4019-ap.dk01.1.dtsi"
+#include "qcom-ipq4019-bus.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Netgear EX61x0v2";
+	compatible = "netgear,ex61x0v2", "qcom,ipq4019";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		rsvd@87E00000 {
+			reg = <0x87E00000 0x0200000>;
+			no-map;
+		};
+	};
+
+	aliases {
+		led-boot = &power_amber;
+		led-failsafe = &power_amber;
+		led-running = &power_green;
+		led-upgrade = &power_amber;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	led_spi {
+		compatible = "spi-gpio";
+		#address-cells = <1>;
+		ranges;
+
+		gpio-sck = <&tlmm 5 GPIO_ACTIVE_HIGH>;
+		gpio-mosi = <&tlmm 4 GPIO_ACTIVE_HIGH>;
+		num-chipselects = <0>;
+
+		led_gpio: led_gpio@0 {
+			compatible = "fairchild,74hc595";
+			reg = <0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			registers-number = <1>;
+			spi-max-frequency = <1000000>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		wps {
+			label = "wps";
+			gpios = <&tlmm 0 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WPS_BUTTON>;
+		};
+
+		reset {
+			label = "reset";
+			gpios = <&tlmm 63 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		power_amber: power_amber {
+			label = "ex61x0v2:amber:power";
+			gpios = <&led_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		power_green: power_green {
+			label = "ex61x0v2:green:power";
+			gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		right {
+			label = "ex61x0v2:blue:right";
+			gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		left {
+			label = "ex61x0v2:blue:left";
+			gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		client_green {
+			label = "ex61x0v2:green:client";
+			gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		client_red {
+			label = "ex61x0v2:red:client";
+			gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		router_green {
+			label = "ex61x0v2:green:router";
+			gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		router_red {
+			label = "ex61x0v2:red:router";
+			gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		wps {
+			label = "ex61x0v2:green:wps";
+			gpios = <&tlmm 1 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&spi_0 {
+	flash@0 {
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <24000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition0@0 {
+				label = "SBL1";
+				reg = <0x00000000 0x00040000>;
+				read-only;
+			};
+
+			partition1@40000 {
+				label = "MIBIB";
+				reg = <0x00040000 0x00020000>;
+				read-only;
+			};
+
+			partition2@60000 {
+				label = "QSEE";
+				reg = <0x00060000 0x00060000>;
+				read-only;
+			};
+
+			partition3@c0000 {
+				label = "CDT";
+				reg = <0x000c0000 0x00010000>;
+				read-only;
+			};
+
+			partition4@d0000 {
+				label = "DDRPARAMS";
+				reg = <0x000d0000 0x00010000>;
+				read-only;
+			};
+
+			partition5@e0000 {
+				label = "APPSBLENV";
+				reg = <0x000e0000 0x00010000>;
+				read-only;
+			};
+
+			partition6@f0000 {
+				label = "APPSBL";
+				reg = <0x000f0000 0x00080000>;
+				read-only;
+			};
+
+			partition7@170000 {
+				label = "ART";
+				reg = <0x00170000 0x00010000>;
+				read-only;
+			};
+
+			partition8@180000 {
+				label = "config";
+				reg = <0x00180000 0x00010000>;
+				read-only;
+			};
+
+			partition9@190000 {
+				label = "pot";
+				reg = <0x00190000 0x00010000>;
+				read-only;
+			};
+
+			partition10@1a0000 {
+				label = "dnidata";
+				reg = <0x001a0000 0x00010000>;
+				read-only;
+			};
+
+			partition11@1b0000 {
+				label = "firmware";
+				reg = <0x001b0000 0x00e10000>;
+			};
+
+			partition12@fc0000 {
+				label = "language";
+				reg = <0x00fc0000 0x00040000>;
+				read-only;
+			};
+		};
+	};
+};
diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile
index 2e6cb0922e..297062d8b2 100644
--- a/target/linux/ipq806x/image/Makefile
+++ b/target/linux/ipq806x/image/Makefile
@@ -58,7 +58,7 @@  define Device/UbiFit
 	IMAGE/nand-sysupgrade.tar := sysupgrade-tar | append-metadata
 endef
 
-define Device/DniImage
+define Device/DniNandImage
 	PROFILES += $$(DEVICE_NAME)
 	FILESYSTEMS := squashfs
 	KERNEL_SUFFIX := -uImage
@@ -71,7 +71,21 @@  define Device/DniImage
 	IMAGE/factory.img := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | pad-to $$$$(KERNEL_SIZE) | append-ubi | netgear-dni
 	IMAGE/sysupgrade.tar := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | sysupgrade-tar kernel=$$$$@ | append-metadata
 endef
-DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_HW_ID
+
+define Device/DniNorImage
+	PROFILES += $$(DEVICE_NAME)
+	FILESYSTEMS := squashfs
+	KERNEL_SUFFIX := -fit-uImage.itb
+	KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb $$(FIT_CFG_NAME)
+	KERNEL_NAME := Image
+	NETGEAR_BOARD_ID :=
+	NETGEAR_HW_ID :=
+	FIT_CFG_NAME :=
+	IMAGES := sysupgrade.bin factory.img
+	IMAGE/sysupgrade.bin := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | append-rootfs | pad-rootfs | append-metadata
+	IMAGE/factory.img := $$(IMAGE/sysupgrade.bin) | netgear-dni
+endef
+DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_HW_ID FIT_CFG_NAME
 
 define Device/TpSafeImage
 	PROFILES += $$(DEVICE_NAME)
@@ -136,7 +150,7 @@  endef
 TARGET_DEVICES += C2600
 
 define Device/D7800
-	$(call Device/DniImage)
+	$(call Device/DniNandImage)
 	DEVICE_DTS := qcom-ipq8064-d7800
 	KERNEL_SIZE := 2097152
 	NETGEAR_BOARD_ID := D7800
@@ -193,7 +207,7 @@  endef
 TARGET_DEVICES += FRITZ4040
 
 define Device/R7500
-	$(call Device/DniImage)
+	$(call Device/DniNandImage)
 	DEVICE_DTS := qcom-ipq8064-r7500
 	KERNEL_SIZE := 2097152
 	NETGEAR_BOARD_ID := R7500
@@ -207,7 +221,7 @@  endef
 TARGET_DEVICES += R7500
 
 define Device/R7500v2
-	$(call Device/DniImage)
+	$(call Device/DniNandImage)
 	DEVICE_DTS := qcom-ipq8064-r7500v2
 	KERNEL_SIZE := 2097152
 	NETGEAR_BOARD_ID := R7500v2
@@ -221,7 +235,7 @@  endef
 TARGET_DEVICES += R7500v2
 
 define Device/R7800
-	$(call Device/DniImage)
+	$(call Device/DniNandImage)
 	DEVICE_DTS := qcom-ipq8065-r7800
 	KERNEL_SIZE := 2097152
 	NETGEAR_BOARD_ID := R7800
@@ -294,4 +308,19 @@  define Device/AP-DK04.1-C1
 endef
 TARGET_DEVICES += AP-DK04.1-C1
 
+define Device/EX61x0v2
+	$(call Device/DniNorImage)
+	DEVICE_DTS := qcom-ipq4019-ex61x0v2
+	FIT_CFG_NAME := config@ap.dk01.1-c1
+	KERNEL_LOADADDR := 0x80208000
+	NETGEAR_BOARD_ID := EX6150v2series
+	NETGEAR_HW_ID := 29765285+16+0+128+2x2
+	BLOCKSIZE := 64k
+	PAGESIZE := 256
+	SUPPORTED_DEVICES := ex6100v2 ex6150v2
+	DEVICE_PACKAGES := ath10k-firmware-qca4019 ipq-wifi-ex6100v2 ipq-wifi-ex6150v2
+	DEVICE_TITLE := Netgear EX6100v2/EX6150v2
+endef
+TARGET_DEVICES += EX61x0v2
+
 $(eval $(call BuildImage))
diff --git a/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch
index bab2808789..c4915bdd6d 100644
--- a/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch
+++ b/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch
@@ -10,13 +10,14 @@  Signed-off-by: John Crispin <john@phrozen.org>
 
 --- a/arch/arm/boot/dts/Makefile
 +++ b/arch/arm/boot/dts/Makefile
-@@ -618,7 +618,18 @@ dtb-$(CONFIG_ARCH_QCOM) += \
+@@ -618,7 +618,19 @@ dtb-$(CONFIG_ARCH_QCOM) += \
  	qcom-apq8084-mtp.dtb \
  	qcom-ipq4019-ap.dk01.1-c1.dtb \
  	qcom-ipq4019-ap.dk04.1-c1.dtb \
 +	qcom-ipq4019-fritz4040.dtb \
 +	qcom-ipq4019-nbg6617.dtb \
 +	qcom-ipq4019-rt-ac58u.dtb \
++	qcom-ipq4019-ex61x0v2.dtb \
  	qcom-ipq8064-ap148.dtb \
 +	qcom-ipq8064-c2600.dtb \
 +	qcom-ipq8064-d7800.dtb \