[OpenWrt-Devel] [PATCH 5/6] ipq806x: replace caf nss-gmac driver by upstream stmmac

Mathieu Olivari mathieu at codeaurora.org
Tue May 26 17:27:56 EDT 2015


This driver has been cherry-picked and backported from the following
LKML thread:
*https://lkml.org/lkml/2015/5/26/744

It also updates the DT accordingly.

Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
---
 target/linux/ipq806x/Makefile                      |   2 +-
 .../ipq806x/patches-3.18/022-add-db149-dts.patch   | 127 +---
 ...-qcom-add-pcie-nodes-to-ipq806x-platforms.patch |  17 +-
 ...rpm-add-support-for-RPM-controller-SMB208.patch |  11 +-
 ...com-rpm-Add-missing-state-flag-in-call-to.patch |   7 +-
 .../patches-3.18/126-add-rpm-to-ipq8064-dts.patch  |   6 +-
 ...-set_parent-doing-the-wrong-thing-when-IN.patch |   7 +-
 ..._unregister_-divider-gate-mux-to-close-me.patch |   2 +-
 ...m-Add-necessary-DT-data-for-Krait-cpufreq.patch |   8 +-
 .../patches-3.18/700-add-gmac-dts-suport.patch     | 164 -----
 ...dd-support-for-NSS-GMAC-clocks-and-resets.patch | 733 +++++++++++++++++++++
 ...-phy-handle-support-to-the-platform-layer.patch | 105 +++
 ...-error-path-at-the-end-of-stmmac_probe_co.patch |  65 ++
 ...stmmac-add-fixed-link-device-tree-support.patch |  64 ++
 .../704-stmmac-add-ipq806x-glue-layer.patch        | 427 ++++++++++++
 ...mac-ipq806x-document-device-tree-bindings.patch |  52 ++
 ...mac-create-one-debugfs-dir-per-net-device.patch | 171 +++++
 ...RM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch | 145 ++++
 ...-qcom-add-gmac-nodes-to-ipq806x-platforms.patch | 210 ++++++
 .../ipq806x/patches-4.0/022-add-db149-dts.patch    | 133 +---
 ...-qcom-add-pcie-nodes-to-ipq806x-platforms.patch |  15 +-
 .../patches-4.0/700-add-gmac-dts-suport.patch      | 164 -----
 ...dd-support-for-NSS-GMAC-clocks-and-resets.patch | 733 +++++++++++++++++++++
 ...-phy-handle-support-to-the-platform-layer.patch | 105 +++
 ...-error-path-at-the-end-of-stmmac_probe_co.patch |  65 ++
 ...stmmac-add-fixed-link-device-tree-support.patch |  64 ++
 .../704-stmmac-add-ipq806x-glue-layer.patch        | 407 ++++++++++++
 ...mac-ipq806x-document-device-tree-bindings.patch |  52 ++
 ...mac-create-one-debugfs-dir-per-net-device.patch | 175 +++++
 ...RM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch | 145 ++++
 ...-qcom-add-gmac-nodes-to-ipq806x-platforms.patch | 210 ++++++
 31 files changed, 3962 insertions(+), 629 deletions(-)
 delete mode 100644 target/linux/ipq806x/patches-3.18/700-add-gmac-dts-suport.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/703-stmmac-add-fixed-link-device-tree-support.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/704-stmmac-add-ipq806x-glue-layer.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
 create mode 100644 target/linux/ipq806x/patches-3.18/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
 delete mode 100644 target/linux/ipq806x/patches-4.0/700-add-gmac-dts-suport.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
 create mode 100644 target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch

diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile
index f97db74..da841a6 100644
--- a/target/linux/ipq806x/Makefile
+++ b/target/linux/ipq806x/Makefile
@@ -15,7 +15,7 @@ KERNELNAME:=zImage Image dtbs
 
 include $(INCLUDE_DIR)/target.mk
 DEFAULT_PACKAGES += \
-	kmod-leds-gpio kmod-gpio-button-hotplug kmod-qca-nss-gmac swconfig \
+	kmod-leds-gpio kmod-gpio-button-hotplug kmod-stmmac swconfig \
 	kmod-ata-core kmod-ata-ahci kmod-ata-ahci-platform
 
 
diff --git a/target/linux/ipq806x/patches-3.18/022-add-db149-dts.patch b/target/linux/ipq806x/patches-3.18/022-add-db149-dts.patch
index 85a0f72..bd6ec1e 100644
--- a/target/linux/ipq806x/patches-3.18/022-add-db149-dts.patch
+++ b/target/linux/ipq806x/patches-3.18/022-add-db149-dts.patch
@@ -25,7 +25,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  	qcom-msm8974-sony-xperia-honami.dtb
 --- /dev/null
 +++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -0,0 +1,257 @@
+@@ -0,0 +1,132 @@
 +#include "qcom-ipq8064-v1.0.dtsi"
 +
 +/ {
@@ -50,15 +50,8 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +		linux,stdout-path = "serial0:115200n8";
 +	};
 +
-+	aliases {
-+		mdio-gpio0 = &mdio0;
-+	};
-+
 +	soc {
 +		pinmux at 800000 {
-+			pinctrl-0 = <&mdio0_pins &rgmii0_pinmux>;
-+			pinctrl-names = "default";
-+
 +			i2c4_pins: i2c4_pinmux {
 +				pins = "gpio12", "gpio13";
 +				function = "gsbi4";
@@ -73,23 +66,6 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +					bias-none;
 +				};
 +			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
-+
-+			rgmii0_pinmux: rgmii0_pinmux {
-+				mux {
-+					pins = "gpio2", "gpio66";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
 +		};
 +
 +		gsbi2: gsbi at 12480000 {
@@ -180,106 +156,5 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +		usb30 at 1 {
 +			status = "ok";
 +		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+
-+			phy0: ethernet-phy at 0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+				>;
-+			};
-+
-+			phy4: ethernet-phy at 4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+
-+			phy6: ethernet-phy at 6 {
-+				device_type = "ethernet-phy";
-+				reg = <6>;
-+			};
-+
-+			phy7: ethernet-phy at 7 {
-+				device_type = "ethernet-phy";
-+				reg = <7>;
-+			};
-+		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac0: ethernet at 37000000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			qcom,id = <0>;
-+			qcom,phy_mdio_addr = <4>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <1>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <1>;
-+			qcom,phy_mdio_addr = <0>;
-+			qcom,poll_required = <0>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+			qcom,phy_mdio_addr = <6>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <0>;
-+			qcom,forced_duplex = <0>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac3: ethernet at 37600000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <3>;
-+			qcom,phy_mdio_addr = <7>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <0>;
-+			qcom,forced_duplex = <0>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
 +	};
 +};
diff --git a/target/linux/ipq806x/patches-3.18/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-3.18/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
index 7bee560..80ac25f 100644
--- a/target/linux/ipq806x/patches-3.18/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
+++ b/target/linux/ipq806x/patches-3.18/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
@@ -60,7 +60,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  };
 --- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
 +++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -37,6 +37,30 @@
+@@ -30,6 +30,30 @@
  				bias-disable;
  			};
  
@@ -91,10 +91,11 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  			spi_pins: spi_pins {
  				mux {
  					pins = "gpio18", "gpio19", "gpio21";
-@@ -153,6 +177,27 @@
+@@ -128,5 +152,26 @@
+ 		usb30 at 1 {
  			status = "ok";
  		};
- 
++
 +		pcie0: pci at 1b500000 {
 +			status = "ok";
 +			reset-gpio = <&qcom_pinmux 3 0>;
@@ -115,10 +116,8 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +			pinctrl-0 = <&pcie3_pins>;
 +			pinctrl-names = "default";
 +		};
-+
- 		mdio0: mdio {
- 			compatible = "virtual,mdio-gpio";
- 			#address-cells = <1>;
+ 	};
+ };
 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
 +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
 @@ -3,6 +3,8 @@
@@ -130,7 +129,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  
  / {
  	model = "Qualcomm IPQ8064";
-@@ -306,6 +307,129 @@
+@@ -306,6 +308,129 @@
  			#reset-cells = <1>;
  		};
  
@@ -260,7 +259,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  		hs_phy_1: phy at 100f8800 {
  			compatible = "qcom,dwc3-hs-usb-phy";
  			reg = <0x100f8800 0x30>;
-@@ -389,6 +513,5 @@
+@@ -389,6 +514,5 @@
  				dr_mode = "host";
  			};
  		};
diff --git a/target/linux/ipq806x/patches-3.18/124-regulator-rpm-add-support-for-RPM-controller-SMB208.patch b/target/linux/ipq806x/patches-3.18/124-regulator-rpm-add-support-for-RPM-controller-SMB208.patch
index c411c1c..e4f094c 100644
--- a/target/linux/ipq806x/patches-3.18/124-regulator-rpm-add-support-for-RPM-controller-SMB208.patch
+++ b/target/linux/ipq806x/patches-3.18/124-regulator-rpm-add-support-for-RPM-controller-SMB208.patch
@@ -14,11 +14,9 @@ Signed-off-by: Mark Brown <broonie at kernel.org>
  drivers/regulator/qcom_rpm-regulator.c | 19 +++++++++++++++++++
  1 file changed, 19 insertions(+)
 
-diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
-index b55cd5b..fbcbd3f 100644
 --- a/drivers/regulator/qcom_rpm-regulator.c
 +++ b/drivers/regulator/qcom_rpm-regulator.c
-@@ -183,6 +183,13 @@ static const struct regulator_linear_range ftsmps_ranges[] = {
+@@ -183,6 +183,13 @@ static const struct regulator_linear_ran
  	REGULATOR_LINEAR_RANGE(1500000,  64, 100, 50000),
  };
  
@@ -32,7 +30,7 @@ index b55cd5b..fbcbd3f 100644
  static const struct regulator_linear_range ncp_ranges[] = {
  	REGULATOR_LINEAR_RANGE(1500000,   0,  31, 50000),
  };
-@@ -559,6 +566,16 @@ static const struct qcom_rpm_reg pm8921_switch = {
+@@ -559,6 +566,16 @@ static const struct qcom_rpm_reg pm8921_
  	.parts = &rpm8960_switch_parts,
  };
  
@@ -49,7 +47,7 @@ index b55cd5b..fbcbd3f 100644
  static const struct of_device_id rpm_of_match[] = {
  	{ .compatible = "qcom,rpm-pm8058-pldo",     .data = &pm8058_pldo },
  	{ .compatible = "qcom,rpm-pm8058-nldo",     .data = &pm8058_nldo },
-@@ -578,6 +595,8 @@ static const struct of_device_id rpm_of_match[] = {
+@@ -578,6 +595,8 @@ static const struct of_device_id rpm_of_
  	{ .compatible = "qcom,rpm-pm8921-ftsmps",   .data = &pm8921_ftsmps },
  	{ .compatible = "qcom,rpm-pm8921-ncp",      .data = &pm8921_ncp },
  	{ .compatible = "qcom,rpm-pm8921-switch",   .data = &pm8921_switch },
@@ -58,6 +56,3 @@ index b55cd5b..fbcbd3f 100644
  	{ }
  };
  MODULE_DEVICE_TABLE(of, rpm_of_match);
--- 
-2.1.4
-
diff --git a/target/linux/ipq806x/patches-3.18/125-regulator-qcom-rpm-Add-missing-state-flag-in-call-to.patch b/target/linux/ipq806x/patches-3.18/125-regulator-qcom-rpm-Add-missing-state-flag-in-call-to.patch
index 11a296a..48921a8 100644
--- a/target/linux/ipq806x/patches-3.18/125-regulator-qcom-rpm-Add-missing-state-flag-in-call-to.patch
+++ b/target/linux/ipq806x/patches-3.18/125-regulator-qcom-rpm-Add-missing-state-flag-in-call-to.patch
@@ -13,11 +13,9 @@ Signed-off-by: Lee Jones <lee.jones at linaro.org>
  drivers/regulator/qcom_rpm-regulator.c | 1 +
  1 file changed, 1 insertion(+)
 
-diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
-index 8364ff3..edd0a17 100644
 --- a/drivers/regulator/qcom_rpm-regulator.c
 +++ b/drivers/regulator/qcom_rpm-regulator.c
-@@ -205,6 +205,7 @@ static int rpm_reg_write(struct qcom_rpm_reg *vreg,
+@@ -205,6 +205,7 @@ static int rpm_reg_write(struct qcom_rpm
  	vreg->val[req->word] |= value << req->shift;
  
  	return qcom_rpm_write(vreg->rpm,
@@ -25,6 +23,3 @@ index 8364ff3..edd0a17 100644
  			      vreg->resource,
  			      vreg->val,
  			      vreg->parts->request_len);
--- 
-2.1.4
-
diff --git a/target/linux/ipq806x/patches-3.18/126-add-rpm-to-ipq8064-dts.patch b/target/linux/ipq806x/patches-3.18/126-add-rpm-to-ipq8064-dts.patch
index 854131c..7e4c5cb 100644
--- a/target/linux/ipq806x/patches-3.18/126-add-rpm-to-ipq8064-dts.patch
+++ b/target/linux/ipq806x/patches-3.18/126-add-rpm-to-ipq8064-dts.patch
@@ -7,8 +7,8 @@
 +#include <dt-bindings/mfd/qcom-rpm.h>
  #include <dt-bindings/soc/qcom,gsbi.h>
  #include <dt-bindings/reset/qcom,gcc-ipq806x.h>
- 
-@@ -75,6 +76,63 @@
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+@@ -76,6 +77,63 @@
  		ranges;
  		compatible = "simple-bus";
  
@@ -72,7 +72,7 @@
  		qcom_pinmux: pinmux at 800000 {
  			compatible = "qcom,ipq8064-pinctrl";
  			reg = <0x800000 0x4000>;
-@@ -119,6 +177,12 @@
+@@ -120,6 +178,12 @@
  			reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
  		};
  
diff --git a/target/linux/ipq806x/patches-3.18/130-clk_mux-Fix-set_parent-doing-the-wrong-thing-when-IN.patch b/target/linux/ipq806x/patches-3.18/130-clk_mux-Fix-set_parent-doing-the-wrong-thing-when-IN.patch
index d943ad5..29f74b7 100644
--- a/target/linux/ipq806x/patches-3.18/130-clk_mux-Fix-set_parent-doing-the-wrong-thing-when-IN.patch
+++ b/target/linux/ipq806x/patches-3.18/130-clk_mux-Fix-set_parent-doing-the-wrong-thing-when-IN.patch
@@ -42,11 +42,9 @@ Signed-off-by: Michael Turquette <mturquette at linaro.org>
  drivers/clk/clk-mux.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
-index 4f96ff3..6e1ecf9 100644
 --- a/drivers/clk/clk-mux.c
 +++ b/drivers/clk/clk-mux.c
-@@ -77,7 +77,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+@@ -77,7 +77,7 @@ static int clk_mux_set_parent(struct clk
  
  	else {
  		if (mux->flags & CLK_MUX_INDEX_BIT)
@@ -55,6 +53,3 @@ index 4f96ff3..6e1ecf9 100644
  
  		if (mux->flags & CLK_MUX_INDEX_ONE)
  			index++;
--- 
-2.1.4
-
diff --git a/target/linux/ipq806x/patches-3.18/132-clk-Add-clk_unregister_-divider-gate-mux-to-close-me.patch b/target/linux/ipq806x/patches-3.18/132-clk-Add-clk_unregister_-divider-gate-mux-to-close-me.patch
index 127afd2..790f25d 100644
--- a/target/linux/ipq806x/patches-3.18/132-clk-Add-clk_unregister_-divider-gate-mux-to-close-me.patch
+++ b/target/linux/ipq806x/patches-3.18/132-clk-Add-clk_unregister_-divider-gate-mux-to-close-me.patch
@@ -22,7 +22,7 @@ Signed-off-by: Michael Turquette <mturquette at linaro.org>
 
 --- a/drivers/clk/clk-divider.c
 +++ b/drivers/clk/clk-divider.c
-@@ -463,3 +463,19 @@ struct clk *clk_register_divider_table(s
+@@ -461,3 +461,19 @@ struct clk *clk_register_divider_table(s
  			width, clk_divider_flags, table, lock);
  }
  EXPORT_SYMBOL_GPL(clk_register_divider_table);
diff --git a/target/linux/ipq806x/patches-3.18/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch b/target/linux/ipq806x/patches-3.18/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
index 9f8d8cb..a3c3bbf 100644
--- a/target/linux/ipq806x/patches-3.18/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
+++ b/target/linux/ipq806x/patches-3.18/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
@@ -1,6 +1,6 @@
 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
 +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -23,6 +23,11 @@
+@@ -24,6 +24,11 @@
  			next-level-cache = <&L2>;
  			qcom,acc = <&acc0>;
  			qcom,saw = <&saw0>;
@@ -12,7 +12,7 @@
  		};
  
  		cpu at 1 {
-@@ -33,11 +38,24 @@
+@@ -34,11 +39,24 @@
  			next-level-cache = <&L2>;
  			qcom,acc = <&acc1>;
  			qcom,saw = <&saw1>;
@@ -37,7 +37,7 @@
  		};
  	};
  
-@@ -70,6 +88,46 @@
+@@ -71,6 +89,46 @@
  		};
  	};
  
@@ -84,7 +84,7 @@
  	soc: soc {
  		#address-cells = <1>;
  		#size-cells = <1>;
-@@ -170,11 +228,13 @@
+@@ -171,11 +229,13 @@
  		acc0: clock-controller at 2088000 {
  			compatible = "qcom,kpss-acc-v1";
  			reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
diff --git a/target/linux/ipq806x/patches-3.18/700-add-gmac-dts-suport.patch b/target/linux/ipq806x/patches-3.18/700-add-gmac-dts-suport.patch
deleted file mode 100644
index 3c81f88..0000000
--- a/target/linux/ipq806x/patches-3.18/700-add-gmac-dts-suport.patch
+++ /dev/null
@@ -1,164 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -22,8 +22,15 @@
- 		linux,stdout-path = "serial0:115200n8";
- 	};
- 
-+	aliases {
-+		mdio-gpio0 = &mdio0;
-+	};
-+
- 	soc {
- 		pinmux at 800000 {
-+			pinctrl-0 = <&mdio0_pins &rgmii2_pins>;
-+			pinctrl-names = "default";
-+
- 			i2c4_pins: i2c4_pinmux {
- 				pins = "gpio12", "gpio13";
- 				function = "gsbi4";
-@@ -54,6 +61,25 @@
- 					bias-none;
- 				};
- 			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
-+
-+			rgmii2_pins: rgmii2_pins {
-+				mux {
-+					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-+					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
-+					function = "rgmii2";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi at 16300000 {
-@@ -89,6 +115,7 @@
- 					#size-cells = <1>;
- 					spi-max-frequency = <50000000>;
- 					reg = <0>;
-+					m25p,fast-read;
- 
- 					partition at 0 {
- 						label = "lowlevel_init";
-@@ -163,5 +190,66 @@
- 			pinctrl-0 = <&pcie2_pins>;
- 			pinctrl-names = "default";
- 		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+
-+			phy0: ethernet-phy at 0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+				>;
-+			};
-+
-+			phy4: ethernet-phy at 4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			qcom,id = <1>;
-+			qcom,phy_mdio_addr = <4>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+			qcom,phy_mdio_addr = <0>;
-+			qcom,poll_required = <0>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -637,5 +638,42 @@
- 				dr_mode = "host";
- 			};
- 		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac0: ethernet at 37000000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37000000 0x200000>;
-+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37200000 0x200000>;
-+			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37400000 0x200000>;
-+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac3: ethernet at 37600000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37600000 0x200000>;
-+			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
- 	};
- };
diff --git a/target/linux/ipq806x/patches-3.18/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches-3.18/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
new file mode 100644
index 0000000..d7d6b69
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
@@ -0,0 +1,733 @@
+From 2fbb18f85826a9ba308fedb2cf90d3a661a39fd7 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd at codeaurora.org>
+Date: Fri, 27 Mar 2015 00:16:14 -0700
+Subject: [PATCH] clk: qcom: Add support for NSS/GMAC clocks and resets
+
+Add the NSS/GMAC clocks and the TCM clock and NSS resets.
+
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+---
+ drivers/clk/qcom/gcc-ipq806x.c               | 594 ++++++++++++++++++++++++++-
+ drivers/clk/qcom/gcc-ipq806x.c.rej           |  50 +++
+ include/dt-bindings/clock/qcom,gcc-ipq806x.h |   2 +
+ include/dt-bindings/reset/qcom,gcc-ipq806x.h |  43 ++
+ 4 files changed, 688 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/qcom/gcc-ipq806x.c.rej
+
+--- a/drivers/clk/qcom/gcc-ipq806x.c
++++ b/drivers/clk/qcom/gcc-ipq806x.c
+@@ -209,11 +209,46 @@ static struct clk_regmap pll14_vote = {
+ 	},
+ };
+ 
++#define NSS_PLL_RATE(f, _l, _m, _n, i) \
++	{  \
++		.freq = f,  \
++		.l = _l, \
++		.m = _m, \
++		.n = _n, \
++		.ibits = i, \
++	}
++
++static struct pll_freq_tbl pll18_freq_tbl[] = {
++	NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625),
++	NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625),
++};
++
++static struct clk_pll pll18 = {
++	.l_reg = 0x31a4,
++	.m_reg = 0x31a8,
++	.n_reg = 0x31ac,
++	.config_reg = 0x31b4,
++	.mode_reg = 0x31a0,
++	.status_reg = 0x31b8,
++	.status_bit = 16,
++	.post_div_shift = 16,
++	.post_div_width = 1,
++	.freq_tbl = pll18_freq_tbl,
++	.clkr.hw.init = &(struct clk_init_data){
++		.name = "pll18",
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.ops = &clk_pll_ops,
++	},
++};
++
+ #define P_PXO	0
+ #define P_PLL8	1
+ #define P_PLL3	1
+ #define P_PLL0	2
+ #define P_CXO	2
++#define P_PLL14	3
++#define P_PLL18 4
+ 
+ static const u8 gcc_pxo_pll8_map[] = {
+ 	[P_PXO]		= 0,
+@@ -264,6 +299,22 @@ static const char *gcc_pxo_pll8_pll0_map
+ 	"pll0_vote",
+ };
+ 
++static const u8 gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
++	[P_PXO] = 0 ,
++	[P_PLL8] = 4,
++	[P_PLL0] = 2,
++	[P_PLL14] = 5,
++	[P_PLL18] = 1,
++};
++
++static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
++	"pxo",
++	"pll8_vote",
++	"pll0_vote",
++	"pll14",
++	"pll18",
++};
++
+ static struct freq_tbl clk_tbl_gsbi_uart[] = {
+ 	{  1843200, P_PLL8, 2,  6, 625 },
+ 	{  3686400, P_PLL8, 2, 12, 625 },
+@@ -2239,6 +2290,472 @@ static struct clk_branch usb_fs1_h_clk =
+ 	},
+ };
+ 
++static const struct freq_tbl clk_tbl_gmac[] = {
++	{ 133000000, P_PLL0, 1,  50, 301 },
++	{ 266000000, P_PLL0, 1, 127, 382 },
++	{ }
++};
++
++static struct clk_dyn_rcg gmac_core1_src = {
++	.ns_reg[0] = 0x3cac,
++	.ns_reg[1] = 0x3cb0,
++	.md_reg[0] = 0x3ca4,
++	.md_reg[1] = 0x3ca8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ca0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core1_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 4,
++	.hwcg_reg = 0x3cb4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cb4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_clk",
++			.parent_names = (const char *[]){
++				"gmac_core1_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core2_src = {
++	.ns_reg[0] = 0x3ccc,
++	.ns_reg[1] = 0x3cd0,
++	.md_reg[0] = 0x3cc4,
++	.md_reg[1] = 0x3cc8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3cc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core2_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 5,
++	.hwcg_reg = 0x3cd4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cd4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_clk",
++			.parent_names = (const char *[]){
++				"gmac_core2_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core3_src = {
++	.ns_reg[0] = 0x3cec,
++	.ns_reg[1] = 0x3cf0,
++	.md_reg[0] = 0x3ce4,
++	.md_reg[1] = 0x3ce8,
++	.bank_reg = 0x3ce0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ce0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core3_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 6,
++	.hwcg_reg = 0x3cf4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cf4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_clk",
++			.parent_names = (const char *[]){
++				"gmac_core3_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core4_src = {
++	.ns_reg[0] = 0x3d0c,
++	.ns_reg[1] = 0x3d10,
++	.md_reg[0] = 0x3d04,
++	.md_reg[1] = 0x3d08,
++	.bank_reg = 0x3d00,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3d00,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core4_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 7,
++	.hwcg_reg = 0x3d14,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3d14,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_clk",
++			.parent_names = (const char *[]){
++				"gmac_core4_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss_tcm[] = {
++	{ 266000000, P_PLL0, 3, 0, 0 },
++	{ 400000000, P_PLL0, 2, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg nss_tcm_src = {
++	.ns_reg[0] = 0x3dc4,
++	.ns_reg[1] = 0x3dc8,
++	.bank_reg = 0x3dc0,
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss_tcm,
++	.clkr = {
++		.enable_reg = 0x3dc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch nss_tcm_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 14,
++	.clkr = {
++		.enable_reg = 0x3dd0,
++		.enable_mask = BIT(6) | BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_clk",
++			.parent_names = (const char *[]){
++				"nss_tcm_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss[] = {
++	{ 110000000, P_PLL18, 1, 1, 5 },
++	{ 275000000, P_PLL18, 2, 0, 0 },
++	{ 550000000, P_PLL18, 1, 0, 0 },
++	{ 733000000, P_PLL18, 1, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg ubi32_core1_src_clk = {
++	.ns_reg[0] = 0x3d2c,
++	.ns_reg[1] = 0x3d30,
++	.md_reg[0] = 0x3d24,
++	.md_reg[1] = 0x3d28,
++	.bank_reg = 0x3d20,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d20,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core1_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
++static struct clk_dyn_rcg ubi32_core2_src_clk = {
++	.ns_reg[0] = 0x3d4c,
++	.ns_reg[1] = 0x3d50,
++	.md_reg[0] = 0x3d44,
++	.md_reg[1] = 0x3d48,
++	.bank_reg = 0x3d40,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d40,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core2_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
+ static struct clk_regmap *gcc_ipq806x_clks[] = {
+ 	[PLL0] = &pll0.clkr,
+ 	[PLL0_VOTE] = &pll0_vote,
+@@ -2247,6 +2764,7 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL8_VOTE] = &pll8_vote,
+ 	[PLL14] = &pll14.clkr,
+ 	[PLL14_VOTE] = &pll14_vote,
++	[PLL18] = &pll18.clkr,
+ 	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+ 	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+ 	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+@@ -2344,6 +2862,18 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL9] = &hfpll0.clkr,
+ 	[PLL10] = &hfpll1.clkr,
+ 	[PLL12] = &hfpll_l2.clkr,
++	[GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr,
++	[GMAC_CORE1_CLK] = &gmac_core1_clk.clkr,
++	[GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr,
++	[GMAC_CORE2_CLK] = &gmac_core2_clk.clkr,
++	[GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr,
++	[GMAC_CORE3_CLK] = &gmac_core3_clk.clkr,
++	[GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr,
++	[GMAC_CORE4_CLK] = &gmac_core4_clk.clkr,
++	[UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr,
++	[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
++	[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
++	[NSSTCM_CLK] = &nss_tcm_clk.clkr,
+ };
+ 
+ static const struct qcom_reset_map gcc_ipq806x_resets[] = {
+@@ -2462,6 +2992,48 @@ static const struct qcom_reset_map gcc_i
+ 	[USB30_1_PHY_RESET] = { 0x3b58, 0 },
+ 	[NSSFB0_RESET] = { 0x3b60, 6 },
+ 	[NSSFB1_RESET] = { 0x3b60, 7 },
++	[UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3},
++	[UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 },
++	[UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 },
++	[UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 },
++	[UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 },
++	[UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 },
++	[UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 },
++	[UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 },
++	[GMAC_CORE1_RESET] = { 0x3cbc, 0 },
++	[GMAC_CORE2_RESET] = { 0x3cdc, 0 },
++	[GMAC_CORE3_RESET] = { 0x3cfc, 0 },
++	[GMAC_CORE4_RESET] = { 0x3d1c, 0 },
++	[GMAC_AHB_RESET] = { 0x3e24, 0 },
++	[NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 },
++	[NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 },
++	[NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 },
++	[NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 },
++	[NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 },
++	[NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 },
++	[NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 },
++	[NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 },
++	[NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 },
++	[NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 },
++	[NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 },
++	[NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 },
++	[NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 },
++	[NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 },
++	[NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 },
++	[NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 },
++	[NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 },
++	[NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 },
++	[NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 },
++	[NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 },
++	[NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 },
++	[NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 },
++	[NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 },
++	[NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 },
++	[NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 },
++	[NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 },
++	[NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 },
++	[NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 },
++	[NSS_SRDS_N_RESET] = { 0x3b60, 28 },
+ };
+ 
+ static const struct regmap_config gcc_ipq806x_regmap_config = {
+@@ -2490,6 +3062,8 @@ static int gcc_ipq806x_probe(struct plat
+ {
+ 	struct clk *clk;
+ 	struct device *dev = &pdev->dev;
++	struct regmap *regmap;
++	int ret;
+ 
+ 	/* Temporary until RPM clocks supported */
+ 	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
+@@ -2500,7 +3074,25 @@ static int gcc_ipq806x_probe(struct plat
+ 	if (IS_ERR(clk))
+ 		return PTR_ERR(clk);
+ 
+-	return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	if (ret)
++		return ret;
++
++	regmap = dev_get_regmap(dev, NULL);
++	if (!regmap)
++		return -ENODEV;
++
++	/* Setup PLL18 static bits */
++	regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400);
++	regmap_write(regmap, 0x31b0, 0x3080);
++
++	/* Set GMAC footswitch sleep/wakeup values */
++	regmap_write(regmap, 0x3cb8, 8);
++	regmap_write(regmap, 0x3cd8, 8);
++	regmap_write(regmap, 0x3cf8, 8);
++	regmap_write(regmap, 0x3d18, 8);
++
++	return 0;
+ }
+ 
+ static int gcc_ipq806x_remove(struct platform_device *pdev)
+--- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h
+@@ -289,5 +289,7 @@
+ #define UBI32_CORE2_CLK_SRC			278
+ #define UBI32_CORE1_CLK				279
+ #define UBI32_CORE2_CLK				280
++#define NSSTCM_CLK_SRC				281
++#define NSSTCM_CLK				282
+ 
+ #endif
+--- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h
+@@ -129,4 +129,47 @@
+ #define USB30_1_PHY_RESET				112
+ #define NSSFB0_RESET					113
+ #define NSSFB1_RESET					114
++#define UBI32_CORE1_CLKRST_CLAMP_RESET			115
++#define UBI32_CORE1_CLAMP_RESET				116
++#define UBI32_CORE1_AHB_RESET				117
++#define UBI32_CORE1_AXI_RESET				118
++#define UBI32_CORE2_CLKRST_CLAMP_RESET			119
++#define UBI32_CORE2_CLAMP_RESET				120
++#define UBI32_CORE2_AHB_RESET				121
++#define UBI32_CORE2_AXI_RESET				122
++#define GMAC_CORE1_RESET				123
++#define GMAC_CORE2_RESET				124
++#define GMAC_CORE3_RESET				125
++#define GMAC_CORE4_RESET				126
++#define GMAC_AHB_RESET					127
++#define NSS_CH0_RST_RX_CLK_N_RESET			128
++#define NSS_CH0_RST_TX_CLK_N_RESET			129
++#define NSS_CH0_RST_RX_125M_N_RESET			130
++#define NSS_CH0_HW_RST_RX_125M_N_RESET			131
++#define NSS_CH0_RST_TX_125M_N_RESET			132
++#define NSS_CH1_RST_RX_CLK_N_RESET			133
++#define NSS_CH1_RST_TX_CLK_N_RESET			134
++#define NSS_CH1_RST_RX_125M_N_RESET			135
++#define NSS_CH1_HW_RST_RX_125M_N_RESET			136
++#define NSS_CH1_RST_TX_125M_N_RESET			137
++#define NSS_CH2_RST_RX_CLK_N_RESET			138
++#define NSS_CH2_RST_TX_CLK_N_RESET			139
++#define NSS_CH2_RST_RX_125M_N_RESET			140
++#define NSS_CH2_HW_RST_RX_125M_N_RESET			141
++#define NSS_CH2_RST_TX_125M_N_RESET			142
++#define NSS_CH3_RST_RX_CLK_N_RESET			143
++#define NSS_CH3_RST_TX_CLK_N_RESET			144
++#define NSS_CH3_RST_RX_125M_N_RESET			145
++#define NSS_CH3_HW_RST_RX_125M_N_RESET			146
++#define NSS_CH3_RST_TX_125M_N_RESET			147
++#define NSS_RST_RX_250M_125M_N_RESET			148
++#define NSS_RST_TX_250M_125M_N_RESET			149
++#define NSS_QSGMII_TXPI_RST_N_RESET			150
++#define NSS_QSGMII_CDR_RST_N_RESET			151
++#define NSS_SGMII2_CDR_RST_N_RESET			152
++#define NSS_SGMII3_CDR_RST_N_RESET			153
++#define NSS_CAL_PRBS_RST_N_RESET			154
++#define NSS_LCKDT_RST_N_RESET				155
++#define NSS_SRDS_N_RESET				156
++
+ #endif
diff --git a/target/linux/ipq806x/patches-3.18/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch b/target/linux/ipq806x/patches-3.18/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
new file mode 100644
index 0000000..8e59b5c
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
@@ -0,0 +1,105 @@
+From 4f09499bc1d9bb095caccbcd73ff951ee631e521 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 15:42:40 -0700
+Subject: [PATCH 1/8] stmmac: add phy-handle support to the platform layer
+
+On stmmac driver, PHY specification in device-tree was done using the
+non-standard property "snps,phy-addr". Specifying a PHY on a different
+MDIO bus that the one within the stmmac controller doesn't seem to be
+possible when device-tree is used.
+
+This change adds support for the phy-handle property, as specified in
+Documentation/devicetree/bindings/net/ethernet.txt.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 28 ++++++++++++++--------
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |  6 ++++-
+ include/linux/stmmac.h                             |  1 +
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -52,6 +52,7 @@
+ #include "stmmac_ptp.h"
+ #include "stmmac.h"
+ #include <linux/reset.h>
++#include <linux/of_mdio.h>
+ 
+ #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
+ 
+@@ -818,18 +819,25 @@ static int stmmac_init_phy(struct net_de
+ 	priv->speed = 0;
+ 	priv->oldduplex = -1;
+ 
+-	if (priv->plat->phy_bus_name)
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
+-			 priv->plat->phy_bus_name, priv->plat->bus_id);
+-	else
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+-			 priv->plat->bus_id);
+-
+-	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+-		 priv->plat->phy_addr);
+-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
++	if (priv->plat->phy_node) {
++		phydev = of_phy_connect(dev, priv->plat->phy_node,
++					&stmmac_adjust_link, 0, interface);
++	} else {
++		if (priv->plat->phy_bus_name)
++			snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
++				 priv->plat->phy_bus_name, priv->plat->bus_id);
++		else
++			snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
++				 priv->plat->bus_id);
++
++		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
++			 priv->plat->phy_addr);
++		pr_debug("stmmac_init_phy:  trying to attach to %s\n",
++			 phy_id_fmt);
+ 
+-	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
++		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
++				     interface);
++	}
+ 
+ 	if (IS_ERR(phydev)) {
+ 		pr_err("%s: Could not attach to PHY\n", dev->name);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -27,6 +27,7 @@
+ #include <linux/of.h>
+ #include <linux/of_net.h>
+ #include <linux/of_device.h>
++#include <linux/of_mdio.h>
+ #include "stmmac.h"
+ 
+ static const struct of_device_id stmmac_dt_ids[] = {
+@@ -155,13 +156,16 @@ static int stmmac_probe_config_dt(struct
+ 	/* Default to phy auto-detection */
+ 	plat->phy_addr = -1;
+ 
++	/* If we find a phy-handle property, use it as the PHY */
++	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+ 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+ 
+-	if (plat->phy_bus_name)
++	if (plat->phy_node || plat->phy_bus_name)
+ 		plat->mdio_bus_data = NULL;
+ 	else
+ 		plat->mdio_bus_data =
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
+ 	int phy_addr;
+ 	int interface;
+ 	struct stmmac_mdio_bus_data *mdio_bus_data;
++	struct device_node *phy_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	int clk_csr;
+ 	int has_gmac;
diff --git a/target/linux/ipq806x/patches-3.18/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch b/target/linux/ipq806x/patches-3.18/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
new file mode 100644
index 0000000..e8f9b5c
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
@@ -0,0 +1,65 @@
+From 0149d275415cd1b2382ce94e5eb32641590097d0 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 15:57:12 -0700
+Subject: [PATCH 2/8] stmmac: move error path at the end of
+ stmmac_probe_config_dt()
+
+We will want to do additional clean-up on certain errors. Therefore,
+this change moves the error path at the end of the function for better
+code readability.
+
+This patch doesn't change anything functionally.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -117,13 +117,18 @@ static int stmmac_probe_config_dt(struct
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	const struct of_device_id *device;
++	int ret;
+ 
+-	if (!np)
+-		return -ENODEV;
++	if (!np) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	device = of_match_device(stmmac_dt_ids, &pdev->dev);
+-	if (!device)
+-		return -ENODEV;
++	if (!device) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	if (device->data) {
+ 		const struct stmmac_of_data *data = device->data;
+@@ -219,8 +224,10 @@ static int stmmac_probe_config_dt(struct
+ 	if (of_find_property(np, "snps,pbl", NULL)) {
+ 		dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
+ 				       GFP_KERNEL);
+-		if (!dma_cfg)
+-			return -ENOMEM;
++		if (!dma_cfg) {
++			ret = -ENOMEM;
++			goto err;
++		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ 		dma_cfg->fixed_burst =
+@@ -235,6 +242,9 @@ static int stmmac_probe_config_dt(struct
+ 	}
+ 
+ 	return 0;
++
++err:
++	return ret;
+ }
+ #else
+ static int stmmac_probe_config_dt(struct platform_device *pdev,
diff --git a/target/linux/ipq806x/patches-3.18/703-stmmac-add-fixed-link-device-tree-support.patch b/target/linux/ipq806x/patches-3.18/703-stmmac-add-fixed-link-device-tree-support.patch
new file mode 100644
index 0000000..3c20fe4
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/703-stmmac-add-fixed-link-device-tree-support.patch
@@ -0,0 +1,64 @@
+From 3a95f75867be562cb919ff23a738f70357188fbd Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:02:03 -0700
+Subject: [PATCH 3/8] stmmac: add fixed-link device-tree support
+
+In case DT is used, this change adds the ability to the stmmac driver to
+detect a fixed-link PHY, instanciate it, and use it during
+phy_connect().
+
+Fixed link PHYs DT usage is described in:
+Documentation/devicetree/bindings/net/fixed-link.txt
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     |  2 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 12 +++++++++++-
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -858,7 +858,7 @@ static int stmmac_init_phy(struct net_de
+ 	 * device as well.
+ 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
+ 	 */
+-	if (phydev->phy_id == 0) {
++	if (!priv->plat->phy_node && phydev->phy_id == 0) {
+ 		phy_disconnect(phydev);
+ 		return -ENODEV;
+ 	}
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -164,6 +164,14 @@ static int stmmac_probe_config_dt(struct
+ 	/* If we find a phy-handle property, use it as the PHY */
+ 	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ 
++	/* If phy-handle is not specified, check if we have a fixed-phy */
++	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
++		if ((of_phy_register_fixed_link(np) < 0))
++			return -ENODEV;
++
++		plat->phy_node = of_node_get(np);
++	}
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+@@ -226,7 +234,7 @@ static int stmmac_probe_config_dt(struct
+ 				       GFP_KERNEL);
+ 		if (!dma_cfg) {
+ 			ret = -ENOMEM;
+-			goto err;
++			goto err2;
+ 		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+@@ -243,6 +251,8 @@ static int stmmac_probe_config_dt(struct
+ 
+ 	return 0;
+ 
++err2:
++	of_node_put(np);
+ err:
+ 	return ret;
+ }
diff --git a/target/linux/ipq806x/patches-3.18/704-stmmac-add-ipq806x-glue-layer.patch b/target/linux/ipq806x/patches-3.18/704-stmmac-add-ipq806x-glue-layer.patch
new file mode 100644
index 0000000..fa67404
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/704-stmmac-add-ipq806x-glue-layer.patch
@@ -0,0 +1,427 @@
+From 69fb970ad3fe05af7cb99ea78230c69c7ca0d03b Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:10:22 -0700
+Subject: [PATCH 4/8] stmmac: add ipq806x glue layer
+
+The ethernet controller available in IPQ806x is a Synopsys DesignWare
+Gigabit MAC IP core, already supported by the stmmac driver.
+
+This glue layer implements some platform specific settings required to
+get the controller working on an IPQ806x based platform.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/Kconfig        |   1 +
+ drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c    | 324 +++++++++++++++++++++
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   1 +
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.h  |   1 +
+ 5 files changed, 328 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c
+
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -16,6 +16,7 @@ if STMMAC_ETH
+ config STMMAC_PLATFORM
+ 	bool "STMMAC Platform bus support"
+ 	depends on STMMAC_ETH
++	select MFD_SYSCON
+ 	default y
+ 	---help---
+ 	  This selects the platform specific bus support for
+@@ -26,6 +27,15 @@ config STMMAC_PLATFORM
+ 
+ 	  If unsure, say N.
+ 
++config DWMAC_IPQ806X
++	bool "QCA IPQ806x dwmac support"
++	depends on STMMAC_PLATFORM && ARCH_QCOM
++	help
++	  Support for Ethernet controller on QCA IPQ806x SoC.
++
++	  This selects the QCA IPQ806x SoC glue layer support for
++	  the stmmac device driver.
++
+ config DWMAC_MESON
+ 	bool "Amlogic Meson dwmac support"
+ 	depends on STMMAC_PLATFORM && ARCH_MESON
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -1,6 +1,7 @@
+ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
+ stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
+ stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
++stmmac-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
+ stmmac-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
+ stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
+ stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -46,6 +46,9 @@ static const struct of_device_id stmmac_
+ #ifdef CONFIG_DWMAC_SOCFPGA
+ 	{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
+ #endif
++#ifdef CONFIG_DWMAC_IPQ806X
++	{ .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data },
++#endif
+ 	/* SoC specific glue layers should come before generic bindings */
+ 	{ .compatible = "st,spear600-gmac"},
+ 	{ .compatible = "snps,dwmac-3.610"},
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+@@ -0,0 +1,343 @@
++/*
++ * Qualcomm Atheros IPQ806x GMAC glue layer
++ *
++ * Copyright (C) 2015 The Linux Foundation
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/phy.h>
++#include <linux/regmap.h>
++#include <linux/clk.h>
++#include <linux/reset.h>
++#include <linux/of_net.h>
++#include <linux/mfd/syscon.h>
++#include <linux/stmmac.h>
++#include <linux/of_mdio.h>
++
++#include "stmmac.h"
++
++#define NSS_COMMON_CLK_GATE			0x8
++#define NSS_COMMON_CLK_GATE_PTP_EN(x)		BIT(0x10 + x)
++#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x)	BIT(0x9 + (x * 2))
++#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x)	BIT(0x8 + (x * 2))
++#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x)	BIT(0x4 + x)
++#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x)	BIT(0x0 + x)
++
++#define NSS_COMMON_CLK_DIV0			0xC
++#define NSS_COMMON_CLK_DIV_OFFSET(x)		(x * 8)
++#define NSS_COMMON_CLK_DIV_MASK			0x7f
++
++#define NSS_COMMON_CLK_SRC_CTRL			0x14
++#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)	(1 << x)
++/* Mode is coded on 1 bit but is different depending on the MAC ID:
++ * MAC0: QSGMII=0 RGMII=1
++ * MAC1: QSGMII=0 SGMII=0 RGMII=1
++ * MAC2 & MAC3: QSGMII=0 SGMII=1
++ */
++#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x)	1
++#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x)	((x >= 2) ? 1 : 0)
++
++#define NSS_COMMON_MACSEC_CTL			0x28
++#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x)	(1 << x)
++
++#define NSS_COMMON_GMAC_CTL(x)			(0x30 + (x * 4))
++#define NSS_COMMON_GMAC_CTL_CSYS_REQ		BIT(19)
++#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL	BIT(16)
++#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET	8
++#define NSS_COMMON_GMAC_CTL_IFG_OFFSET		0
++#define NSS_COMMON_GMAC_CTL_IFG_MASK		0x3f
++
++#define NSS_COMMON_CLK_DIV_RGMII_1000		1
++#define NSS_COMMON_CLK_DIV_RGMII_100		9
++#define NSS_COMMON_CLK_DIV_RGMII_10		99
++#define NSS_COMMON_CLK_DIV_SGMII_1000		0
++#define NSS_COMMON_CLK_DIV_SGMII_100		4
++#define NSS_COMMON_CLK_DIV_SGMII_10		49
++
++#define QSGMII_PCS_MODE_CTL			0x68
++#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x)	BIT((x * 8) + 7)
++
++#define QSGMII_PCS_CAL_LCKDT_CTL		0x120
++#define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
++
++/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
++#define QSGMII_PHY_SGMII_CTL(x)			((x == 1) ? 0x134 : \
++						 (0x13c + (4 * (x - 2))))
++#define QSGMII_PHY_CDR_EN			BIT(0)
++#define QSGMII_PHY_RX_FRONT_EN			BIT(1)
++#define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
++#define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
++#define QSGMII_PHY_QSGMII_EN			BIT(7)
++#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
++#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		0x7
++#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
++#define QSGMII_PHY_RX_DC_BIAS_MASK		0x3
++#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
++#define QSGMII_PHY_RX_INPUT_EQU_MASK		0x3
++#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
++#define QSGMII_PHY_CDR_PI_SLEW_MASK		0x3
++#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
++#define QSGMII_PHY_TX_DRV_AMP_MASK		0xf
++
++struct ipq806x_gmac {
++	struct platform_device *pdev;
++	struct regmap *nss_common;
++	struct regmap *qsgmii_csr;
++	uint32_t id;
++	struct clk *core_clk;
++	phy_interface_t phy_mode;
++};
++
++static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_SGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_SGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_SGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_RGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_RGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_RGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	uint32_t clk_bits, val;
++	int div;
++
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		div = get_clk_div_rgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
++		break;
++
++	case PHY_INTERFACE_MODE_SGMII:
++		div = get_clk_div_sgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
++		break;
++
++	default:
++		dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return -EINVAL;
++	}
++
++	/* Disable the clocks */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val &= ~clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	/* Set the divider */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
++	val &= ~(NSS_COMMON_CLK_DIV_MASK
++		 << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
++	val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
++
++	/* Enable the clock back */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	return 0;
++}
++
++static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
++{
++	struct device *dev = &gmac->pdev->dev;
++
++	gmac->phy_mode = of_get_phy_mode(dev->of_node);
++	if (gmac->phy_mode < 0) {
++		dev_err(dev, "missing phy mode property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
++		dev_err(dev, "missing qcom id property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	/* The GMACs are called 1 to 4 in the documentation, but to simplify the
++	 * code and keep it consistent with the Linux convention, we'll number
++	 * them from 0 to 3 here.
++	 */
++	if (gmac->id < 0 || gmac->id > 3) {
++		dev_err(dev, "invalid gmac id\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	gmac->core_clk = devm_clk_get(dev, "stmmaceth");
++	if (IS_ERR(gmac->core_clk)) {
++		dev_err(dev, "missing stmmaceth clk property\n");
++		return gmac->core_clk;
++	}
++	clk_set_rate(gmac->core_clk, 266000000);
++
++	/* Setup the register map for the nss common registers */
++	gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,nss-common");
++	if (IS_ERR(gmac->nss_common)) {
++		dev_err(dev, "missing nss-common node\n");
++		return gmac->nss_common;
++	}
++
++	/* Setup the register map for the qsgmii csr registers */
++	gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,qsgmii-csr");
++	if (IS_ERR(gmac->qsgmii_csr)) {
++		dev_err(dev, "missing qsgmii-csr node\n");
++		return gmac->qsgmii_csr;
++	}
++
++	return NULL;
++}
++
++static void *ipq806x_gmac_setup(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct ipq806x_gmac *gmac;
++	int val;
++	void *err;
++
++	gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
++	if (!gmac)
++		return ERR_PTR(-ENOMEM);
++
++	gmac->pdev = pdev;
++
++	err = ipq806x_gmac_of_parse(gmac);
++	if (err) {
++		dev_err(dev, "device tree parsing error\n");
++		return err;
++	}
++
++	regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
++		     QSGMII_PCS_CAL_LCKDT_CTL_RST);
++
++	/* Inter frame gap is set to 12 */
++	val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
++	      12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
++	/* We also initiate an AXI low power exit request */
++	val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
++
++	/* Configure the clock src according to the mode */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
++	val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
++
++	/* Enable PTP clock */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
++		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
++			     QSGMII_PHY_CDR_EN |
++			     QSGMII_PHY_RX_FRONT_EN |
++			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
++			     QSGMII_PHY_TX_DRIVER_EN |
++			     QSGMII_PHY_QSGMII_EN |
++			     0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
++			     0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
++			     0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
++			     0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
++			     0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
++	}
++
++	return gmac;
++}
++
++static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
++{
++	struct ipq806x_gmac *gmac = priv;
++
++	ipq806x_gmac_set_speed(gmac, speed);
++}
++
++const struct stmmac_of_data ipq806x_gmac_data = {
++	.has_gmac	= 1,
++	.setup		= ipq806x_gmac_setup,
++	.fix_mac_speed	= ipq806x_gmac_fix_mac_speed,
++};
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -137,6 +137,9 @@ void stmmac_disable_eee_mode(struct stmm
+ bool stmmac_eee_init(struct stmmac_priv *priv);
+ 
+ #ifdef CONFIG_STMMAC_PLATFORM
++#ifdef CONFIG_DWMAC_IPQ806X
++extern const struct stmmac_of_data ipq806x_gmac_data;
++#endif
+ #ifdef CONFIG_DWMAC_MESON
+ extern const struct stmmac_of_data meson6_dwmac_data;
+ #endif
diff --git a/target/linux/ipq806x/patches-3.18/705-net-stmmac-ipq806x-document-device-tree-bindings.patch b/target/linux/ipq806x/patches-3.18/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
new file mode 100644
index 0000000..3144fa3
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
@@ -0,0 +1,52 @@
+From 0f9605d9409b77a89daef91cc68239fc2ff50457 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:51:25 -0700
+Subject: [PATCH 5/8] net: stmmac: ipq806x: document device tree bindings
+
+Add the device tree bindings documentation for the QCA IPQ806x
+variant of the Synopsys DesignWare MAC.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ .../devicetree/bindings/net/ipq806x-dwmac.txt      | 35 ++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+@@ -0,0 +1,35 @@
++* IPQ806x DWMAC Ethernet controller
++
++The device inherits all the properties of the dwmac/stmmac devices
++described in the file net/stmmac.txt with the following changes.
++
++Required properties:
++
++- compatible: should be "qcom,ipq806x-gmac" along with "snps,dwmac"
++	      and any applicable more detailed version number
++	      described in net/stmmac.txt
++
++- qcom,nss-common: should contain a phandle to a syscon device mapping the
++		   nss-common registers.
++
++- qcom,qsgmii-csr: should contain a phandle to a syscon device mapping the
++		   qsgmii-csr registers.
++
++Example:
++
++	gmac: ethernet at 37000000 {
++		device_type = "network";
++		compatible = "qcom,ipq806x-gmac";
++		reg = <0x37000000 0x200000>;
++		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++		interrupt-names = "macirq";
++
++		qcom,nss-common = <&nss_common>;
++		qcom,qsgmii-csr = <&qsgmii_csr>;
++
++		clocks = <&gcc GMAC_CORE1_CLK>;
++		clock-names = "stmmaceth";
++
++		resets = <&gcc GMAC_CORE1_RESET>;
++		reset-names = "stmmaceth";
++	};
diff --git a/target/linux/ipq806x/patches-3.18/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch b/target/linux/ipq806x/patches-3.18/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
new file mode 100644
index 0000000..50127fd
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
@@ -0,0 +1,171 @@
+From df944689d491e6af533173bf2ef448c3dd334f15 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 15:15:25 -0700
+Subject: [PATCH 6/8] net: stmmac: create one debugfs dir per net-device
+
+stmmac DebugFS entries are currently global to the driver. As a result,
+having more than one stmmac device in the system creates the following
+error:
+* ERROR stmmaceth, debugfs create directory failed
+* stmmac_hw_setup: failed debugFS registration
+
+This also results in being able to access the debugfs information for
+the first registered device only.
+
+This patch changes the debugfs structure to have one sub-directory per
+net-device. Files under "/sys/kernel/debug/stmmaceth" will now show-up
+under /sys/kernel/debug/stmmaceth/ethN/.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h      |  6 ++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 76 ++++++++++++++++-------
+ 2 files changed, 59 insertions(+), 23 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -116,6 +116,12 @@ struct stmmac_priv {
+ 	int use_riwt;
+ 	int irq_wake;
+ 	spinlock_t ptp_lock;
++
++#ifdef CONFIG_DEBUG_FS
++	struct dentry *dbgfs_dir;
++	struct dentry *dbgfs_rings_status;
++	struct dentry *dbgfs_dma_cap;
++#endif
+ };
+ 
+ int stmmac_mdio_unregister(struct net_device *ndev);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -119,7 +119,7 @@ static irqreturn_t stmmac_interrupt(int
+ 
+ #ifdef CONFIG_STMMAC_DEBUG_FS
+ static int stmmac_init_fs(struct net_device *dev);
+-static void stmmac_exit_fs(void);
++static void stmmac_exit_fs(struct net_device *dev);
+ #endif
+ 
+ #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+@@ -1879,7 +1879,7 @@ static int stmmac_release(struct net_dev
+ 	netif_carrier_off(dev);
+ 
+ #ifdef CONFIG_STMMAC_DEBUG_FS
+-	stmmac_exit_fs();
++	stmmac_exit_fs(dev);
+ #endif
+ 
+ 	stmmac_release_ptp(priv);
+@@ -2467,8 +2467,6 @@ static int stmmac_ioctl(struct net_devic
+ 
+ #ifdef CONFIG_STMMAC_DEBUG_FS
+ static struct dentry *stmmac_fs_dir;
+-static struct dentry *stmmac_rings_status;
+-static struct dentry *stmmac_dma_cap;
+ 
+ static void sysfs_display_ring(void *head, int size, int extend_desc,
+ 			       struct seq_file *seq)
+@@ -2607,36 +2605,39 @@ static const struct file_operations stmm
+ 
+ static int stmmac_init_fs(struct net_device *dev)
+ {
+-	/* Create debugfs entries */
+-	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
++	struct stmmac_priv *priv = netdev_priv(dev);
++
++	/* Create per netdev entries */
++	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
+ 
+-	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
+-		pr_err("ERROR %s, debugfs create directory failed\n",
+-		       STMMAC_RESOURCE_NAME);
++	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
++		pr_err("ERROR %s/%s, debugfs create directory failed\n",
++		       STMMAC_RESOURCE_NAME, dev->name);
+ 
+ 		return -ENOMEM;
+ 	}
+ 
+ 	/* Entry to report DMA RX/TX rings */
+-	stmmac_rings_status = debugfs_create_file("descriptors_status",
+-						  S_IRUGO, stmmac_fs_dir, dev,
+-						  &stmmac_rings_status_fops);
++	priv->dbgfs_rings_status =
++		debugfs_create_file("descriptors_status", S_IRUGO,
++				    priv->dbgfs_dir, dev,
++				    &stmmac_rings_status_fops);
+ 
+-	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
++	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
+ 		pr_info("ERROR creating stmmac ring debugfs file\n");
+-		debugfs_remove(stmmac_fs_dir);
++		debugfs_remove_recursive(priv->dbgfs_dir);
+ 
+ 		return -ENOMEM;
+ 	}
+ 
+ 	/* Entry to report the DMA HW features */
+-	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
+-					     dev, &stmmac_dma_cap_fops);
++	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
++					    priv->dbgfs_dir,
++					    dev, &stmmac_dma_cap_fops);
+ 
+-	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
++	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
+ 		pr_info("ERROR creating stmmac MMC debugfs file\n");
+-		debugfs_remove(stmmac_rings_status);
+-		debugfs_remove(stmmac_fs_dir);
++		debugfs_remove_recursive(priv->dbgfs_dir);
+ 
+ 		return -ENOMEM;
+ 	}
+@@ -2644,11 +2645,11 @@ static int stmmac_init_fs(struct net_dev
+ 	return 0;
+ }
+ 
+-static void stmmac_exit_fs(void)
++static void stmmac_exit_fs(struct net_device *dev)
+ {
+-	debugfs_remove(stmmac_rings_status);
+-	debugfs_remove(stmmac_dma_cap);
+-	debugfs_remove(stmmac_fs_dir);
++	struct stmmac_priv *priv = netdev_priv(dev);
++
++	debugfs_remove_recursive(priv->dbgfs_dir);
+ }
+ #endif /* CONFIG_STMMAC_DEBUG_FS */
+ 
+@@ -3032,6 +3033,21 @@ static int __init stmmac_init(void)
+ 	ret = stmmac_register_pci();
+ 	if (ret)
+ 		goto err_pci;
++
++#ifdef CONFIG_STMMAC_DEBUG_FS
++	/* Create debugfs main directory if it doesn't exist yet */
++	if (stmmac_fs_dir == NULL) {
++		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
++
++		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
++			pr_err("ERROR %s, debugfs create directory failed\n",
++			       STMMAC_RESOURCE_NAME);
++
++			return -ENOMEM;
++		}
++	}
++#endif
++
+ 	return 0;
+ err_pci:
+ 	stmmac_unregister_platform();
+@@ -3042,6 +3058,9 @@ err:
+ 
+ static void __exit stmmac_exit(void)
+ {
++#ifdef CONFIG_STMMAC_DEBUG_FS
++	debugfs_remove_recursive(stmmac_fs_dir);
++#endif
+ 	stmmac_unregister_platform();
+ 	stmmac_unregister_pci();
+ }
diff --git a/target/linux/ipq806x/patches-3.18/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch b/target/linux/ipq806x/patches-3.18/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
new file mode 100644
index 0000000..809d743
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
@@ -0,0 +1,145 @@
+From e81de9d28bd0421c236df322872e64edf4ee1852 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 16:32:09 -0700
+Subject: [PATCH 7/8] ARM: dts: qcom: add mdio nodes to ap148 & db149
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 40 ++++++++++++++++++++++++++-
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 46 ++++++++++++++++++++++++++++++++
+ 2 files changed, 85 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -14,8 +14,9 @@
+ 		};
+ 	};
+ 
+-	alias {
++	aliases {
+ 		serial0 = &uart4;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -54,6 +55,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi at 16300000 {
+@@ -163,5 +173,33 @@
+ 			pinctrl-0 = <&pcie2_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy at 0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++					>;
++			};
++
++			phy4: ethernet-phy at 4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -16,6 +16,7 @@
+ 
+ 	alias {
+ 		serial0 = &uart2;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -62,6 +63,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi at 12480000 {
+@@ -173,5 +183,44 @@
+ 			pinctrl-0 = <&pcie3_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy at 0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++				>;
++			};
++
++			phy4: ethernet-phy at 4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++
++			phy6: ethernet-phy at 6 {
++				device_type = "ethernet-phy";
++				reg = <6>;
++			};
++
++			phy7: ethernet-phy at 7 {
++				device_type = "ethernet-phy";
++				reg = <7>;
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/ipq806x/patches-3.18/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-3.18/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
new file mode 100644
index 0000000..cce30b0
--- /dev/null
+++ b/target/linux/ipq806x/patches-3.18/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
@@ -0,0 +1,210 @@
+From cab1f4720e82f2e17eaeed9a9ad9e4f07c742977 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 12:29:18 -0700
+Subject: [PATCH 8/8] ARM: dts: qcom: add gmac nodes to ipq806x platforms
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 31 ++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 43 ++++++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064.dtsi      | 86 ++++++++++++++++++++++++++++++++
+ 3 files changed, 160 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -64,6 +64,16 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii2_pins: rgmii2_pins {
++				mux {
++					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
++					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
++					function = "rgmii2";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi at 16300000 {
+@@ -201,5 +211,26 @@
+ 				reg = <4>;
+ 			};
+ 		};
++
++		gmac1: ethernet at 37200000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			phy-handle = <&phy4>;
++			qcom,id = <1>;
++
++			pinctrl-0 = <&rgmii2_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac2: ethernet at 37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -72,6 +72,14 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii0_pins: rgmii0_pins {
++				mux {
++					pins = "gpio2", "gpio66";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi at 12480000 {
+@@ -222,5 +230,40 @@
+ 				reg = <7>;
+ 			};
+ 		};
++
++		gmac0: ethernet at 37000000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			qcom,id = <0>;
++			phy-handle = <&phy4>;
++
++			pinctrl-0 = <&rgmii0_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac1: ethernet at 37200000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <1>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
++
++		gmac2: ethernet at 37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++			phy-handle = <&phy6>;
++		};
++
++		gmac3: ethernet at 37600000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <3>;
++			phy-handle = <&phy7>;
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -638,5 +638,91 @@
+ 				dr_mode = "host";
+ 			};
+ 		};
++
++		nss_common: syscon at 03000000 {
++			compatible = "syscon";
++			reg = <0x03000000 0x0000FFFF>;
++		};
++
++		qsgmii_csr: syscon at 1bb00000 {
++			compatible = "syscon";
++			reg = <0x1bb00000 0x000001FF>;
++		};
++
++		gmac0: ethernet at 37000000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37000000 0x200000>;
++			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE1_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE1_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac1: ethernet at 37200000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37200000 0x200000>;
++			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE2_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE2_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac2: ethernet at 37400000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37400000 0x200000>;
++			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE3_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE3_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac3: ethernet at 37600000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37600000 0x200000>;
++			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE4_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE4_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
+ 	};
+ };
diff --git a/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch b/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch
index a274f24..29631b2 100644
--- a/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch
+++ b/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch
@@ -1,4 +1,4 @@
-From a32d6e7c8fca6371a2614924b89981bc912b6378 Mon Sep 17 00:00:00 2001
+From f26cc3733bdd697bd81ae505fc133fa7c9b6ea19 Mon Sep 17 00:00:00 2001
 From: Mathieu Olivari <mathieu at codeaurora.org>
 Date: Tue, 7 Apr 2015 19:58:58 -0700
 Subject: [PATCH] ARM: dts: qcom: add initial DB149 device-tree
@@ -9,8 +9,8 @@ SATA, USB2, USB3 and NOR flash.
 Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 ---
  arch/arm/boot/dts/Makefile               |   1 +
- arch/arm/boot/dts/qcom-ipq8064-db149.dts | 257 +++++++++++++++++++++++++++++++
- 2 files changed, 258 insertions(+)
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 132 +++++++++++++++++++++++++++++++
+ 2 files changed, 133 insertions(+)
  create mode 100644 arch/arm/boot/dts/qcom-ipq8064-db149.dts
 
 --- a/arch/arm/boot/dts/Makefile
@@ -25,7 +25,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  	qcom-msm8974-sony-xperia-honami.dtb
 --- /dev/null
 +++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -0,0 +1,257 @@
+@@ -0,0 +1,132 @@
 +#include "qcom-ipq8064-v1.0.dtsi"
 +
 +/ {
@@ -50,15 +50,8 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +		linux,stdout-path = "serial0:115200n8";
 +	};
 +
-+	aliases {
-+		mdio-gpio0 = &mdio0;
-+	};
-+
 +	soc {
 +		pinmux at 800000 {
-+			pinctrl-0 = <&mdio0_pins &rgmii0_pinmux>;
-+			pinctrl-names = "default";
-+
 +			i2c4_pins: i2c4_pinmux {
 +				pins = "gpio12", "gpio13";
 +				function = "gsbi4";
@@ -73,23 +66,6 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +					bias-none;
 +				};
 +			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
-+
-+			rgmii0_pinmux: rgmii0_pinmux {
-+				mux {
-+					pins = "gpio2", "gpio66";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
 +		};
 +
 +		gsbi2: gsbi at 12480000 {
@@ -180,106 +156,5 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +		usb30 at 1 {
 +			status = "ok";
 +		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+
-+			phy0: ethernet-phy at 0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+				>;
-+			};
-+
-+			phy4: ethernet-phy at 4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+
-+			phy6: ethernet-phy at 6 {
-+				device_type = "ethernet-phy";
-+				reg = <6>;
-+			};
-+
-+			phy7: ethernet-phy at 7 {
-+				device_type = "ethernet-phy";
-+				reg = <7>;
-+			};
-+		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac0: ethernet at 37000000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			qcom,id = <0>;
-+			qcom,phy_mdio_addr = <4>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <1>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <1>;
-+			qcom,phy_mdio_addr = <0>;
-+			qcom,poll_required = <0>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+			qcom,phy_mdio_addr = <6>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <0>;
-+			qcom,forced_duplex = <0>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac3: ethernet at 37600000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <3>;
-+			qcom,phy_mdio_addr = <7>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <0>;
-+			qcom,forced_duplex = <0>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
 +	};
 +};
diff --git a/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
index ad0a740..957b054 100644
--- a/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
+++ b/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
@@ -60,7 +60,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  };
 --- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
 +++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -37,6 +37,30 @@
+@@ -30,6 +30,30 @@
  				bias-disable;
  			};
  
@@ -91,10 +91,11 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  			spi_pins: spi_pins {
  				mux {
  					pins = "gpio18", "gpio19", "gpio21";
-@@ -153,6 +177,27 @@
+@@ -128,5 +152,26 @@
+ 		usb30 at 1 {
  			status = "ok";
  		};
- 
++
 +		pcie0: pci at 1b500000 {
 +			status = "ok";
 +			reset-gpio = <&qcom_pinmux 3 0>;
@@ -115,10 +116,8 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
 +			pinctrl-0 = <&pcie3_pins>;
 +			pinctrl-names = "default";
 +		};
-+
- 		mdio0: mdio {
- 			compatible = "virtual,mdio-gpio";
- 			#address-cells = <1>;
+ 	};
+ };
 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
 +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
 @@ -3,6 +3,8 @@
@@ -130,7 +129,7 @@ Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
  
  / {
  	model = "Qualcomm IPQ8064";
-@@ -291,5 +292,128 @@
+@@ -291,5 +293,128 @@
  			#clock-cells = <1>;
  			#reset-cells = <1>;
  		};
diff --git a/target/linux/ipq806x/patches-4.0/700-add-gmac-dts-suport.patch b/target/linux/ipq806x/patches-4.0/700-add-gmac-dts-suport.patch
deleted file mode 100644
index b5a3f19..0000000
--- a/target/linux/ipq806x/patches-4.0/700-add-gmac-dts-suport.patch
+++ /dev/null
@@ -1,164 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -22,8 +22,15 @@
- 		linux,stdout-path = "serial0:115200n8";
- 	};
- 
-+	aliases {
-+		mdio-gpio0 = &mdio0;
-+	};
-+
- 	soc {
- 		pinmux at 800000 {
-+			pinctrl-0 = <&mdio0_pins &rgmii2_pins>;
-+			pinctrl-names = "default";
-+
- 			i2c4_pins: i2c4_pinmux {
- 				pins = "gpio12", "gpio13";
- 				function = "gsbi4";
-@@ -54,6 +61,25 @@
- 					bias-none;
- 				};
- 			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
-+
-+			rgmii2_pins: rgmii2_pins {
-+				mux {
-+					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-+					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
-+					function = "rgmii2";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi at 16300000 {
-@@ -89,6 +115,7 @@
- 					#size-cells = <1>;
- 					spi-max-frequency = <50000000>;
- 					reg = <0>;
-+					m25p,fast-read;
- 
- 					partition at 0 {
- 						label = "lowlevel_init";
-@@ -139,5 +166,66 @@
- 			pinctrl-0 = <&pcie2_pins>;
- 			pinctrl-names = "default";
- 		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+
-+			phy0: ethernet-phy at 0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+				>;
-+			};
-+
-+			phy4: ethernet-phy at 4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			qcom,id = <1>;
-+			qcom,phy_mdio_addr = <4>;
-+			qcom,poll_required = <1>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+			qcom,phy_mdio_addr = <0>;
-+			qcom,poll_required = <0>;
-+			qcom,rgmii_delay = <0>;
-+			qcom,emulation = <0>;
-+			qcom,forced_speed = <1000>;
-+			qcom,forced_duplex = <1>;
-+			qcom,socver = <0>;
-+			local-mac-address = [000000000000];
-+			mdiobus = <&mdio0>;
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -539,5 +540,42 @@
- 
- 			status = "disabled";
- 		};
-+
-+		nss-gmac-common {
-+			reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
-+			reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
-+		};
-+
-+		gmac0: ethernet at 37000000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37000000 0x200000>;
-+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac1: ethernet at 37200000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37200000 0x200000>;
-+			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac2: ethernet at 37400000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37400000 0x200000>;
-+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
-+
-+		gmac3: ethernet at 37600000 {
-+			device_type = "network";
-+			compatible = "qcom,nss-gmac";
-+			reg = <0x37600000 0x200000>;
-+			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
-+			status = "disabled";
-+		};
- 	};
- };
diff --git a/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
new file mode 100644
index 0000000..1b9d47b
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
@@ -0,0 +1,733 @@
+From 2fbb18f85826a9ba308fedb2cf90d3a661a39fd7 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd at codeaurora.org>
+Date: Fri, 27 Mar 2015 00:16:14 -0700
+Subject: [PATCH] clk: qcom: Add support for NSS/GMAC clocks and resets
+
+Add the NSS/GMAC clocks and the TCM clock and NSS resets.
+
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+---
+ drivers/clk/qcom/gcc-ipq806x.c               | 594 ++++++++++++++++++++++++++-
+ drivers/clk/qcom/gcc-ipq806x.c.rej           |  50 +++
+ include/dt-bindings/clock/qcom,gcc-ipq806x.h |   2 +
+ include/dt-bindings/reset/qcom,gcc-ipq806x.h |  43 ++
+ 4 files changed, 688 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/qcom/gcc-ipq806x.c.rej
+
+--- a/drivers/clk/qcom/gcc-ipq806x.c
++++ b/drivers/clk/qcom/gcc-ipq806x.c
+@@ -220,11 +220,46 @@ static struct clk_regmap pll14_vote = {
+ 	},
+ };
+ 
++#define NSS_PLL_RATE(f, _l, _m, _n, i) \
++	{  \
++		.freq = f,  \
++		.l = _l, \
++		.m = _m, \
++		.n = _n, \
++		.ibits = i, \
++	}
++
++static struct pll_freq_tbl pll18_freq_tbl[] = {
++	NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625),
++	NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625),
++};
++
++static struct clk_pll pll18 = {
++	.l_reg = 0x31a4,
++	.m_reg = 0x31a8,
++	.n_reg = 0x31ac,
++	.config_reg = 0x31b4,
++	.mode_reg = 0x31a0,
++	.status_reg = 0x31b8,
++	.status_bit = 16,
++	.post_div_shift = 16,
++	.post_div_width = 1,
++	.freq_tbl = pll18_freq_tbl,
++	.clkr.hw.init = &(struct clk_init_data){
++		.name = "pll18",
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.ops = &clk_pll_ops,
++	},
++};
++
+ #define P_PXO	0
+ #define P_PLL8	1
+ #define P_PLL3	1
+ #define P_PLL0	2
+ #define P_CXO	2
++#define P_PLL14	3
++#define P_PLL18 4
+ 
+ static const u8 gcc_pxo_pll8_map[] = {
+ 	[P_PXO]		= 0,
+@@ -275,6 +310,22 @@ static const char *gcc_pxo_pll8_pll0_map
+ 	"pll0_vote",
+ };
+ 
++static const u8 gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
++	[P_PXO] = 0 ,
++	[P_PLL8] = 4,
++	[P_PLL0] = 2,
++	[P_PLL14] = 5,
++	[P_PLL18] = 1,
++};
++
++static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
++	"pxo",
++	"pll8_vote",
++	"pll0_vote",
++	"pll14",
++	"pll18",
++};
++
+ static struct freq_tbl clk_tbl_gsbi_uart[] = {
+ 	{  1843200, P_PLL8, 2,  6, 625 },
+ 	{  3686400, P_PLL8, 2, 12, 625 },
+@@ -2250,6 +2301,472 @@ static struct clk_branch usb_fs1_h_clk =
+ 	},
+ };
+ 
++static const struct freq_tbl clk_tbl_gmac[] = {
++	{ 133000000, P_PLL0, 1,  50, 301 },
++	{ 266000000, P_PLL0, 1, 127, 382 },
++	{ }
++};
++
++static struct clk_dyn_rcg gmac_core1_src = {
++	.ns_reg[0] = 0x3cac,
++	.ns_reg[1] = 0x3cb0,
++	.md_reg[0] = 0x3ca4,
++	.md_reg[1] = 0x3ca8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ca0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core1_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 4,
++	.hwcg_reg = 0x3cb4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cb4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_clk",
++			.parent_names = (const char *[]){
++				"gmac_core1_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core2_src = {
++	.ns_reg[0] = 0x3ccc,
++	.ns_reg[1] = 0x3cd0,
++	.md_reg[0] = 0x3cc4,
++	.md_reg[1] = 0x3cc8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3cc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core2_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 5,
++	.hwcg_reg = 0x3cd4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cd4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_clk",
++			.parent_names = (const char *[]){
++				"gmac_core2_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core3_src = {
++	.ns_reg[0] = 0x3cec,
++	.ns_reg[1] = 0x3cf0,
++	.md_reg[0] = 0x3ce4,
++	.md_reg[1] = 0x3ce8,
++	.bank_reg = 0x3ce0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ce0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core3_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 6,
++	.hwcg_reg = 0x3cf4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cf4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_clk",
++			.parent_names = (const char *[]){
++				"gmac_core3_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core4_src = {
++	.ns_reg[0] = 0x3d0c,
++	.ns_reg[1] = 0x3d10,
++	.md_reg[0] = 0x3d04,
++	.md_reg[1] = 0x3d08,
++	.bank_reg = 0x3d00,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3d00,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core4_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 7,
++	.hwcg_reg = 0x3d14,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3d14,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_clk",
++			.parent_names = (const char *[]){
++				"gmac_core4_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss_tcm[] = {
++	{ 266000000, P_PLL0, 3, 0, 0 },
++	{ 400000000, P_PLL0, 2, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg nss_tcm_src = {
++	.ns_reg[0] = 0x3dc4,
++	.ns_reg[1] = 0x3dc8,
++	.bank_reg = 0x3dc0,
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss_tcm,
++	.clkr = {
++		.enable_reg = 0x3dc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch nss_tcm_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 14,
++	.clkr = {
++		.enable_reg = 0x3dd0,
++		.enable_mask = BIT(6) | BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_clk",
++			.parent_names = (const char *[]){
++				"nss_tcm_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss[] = {
++	{ 110000000, P_PLL18, 1, 1, 5 },
++	{ 275000000, P_PLL18, 2, 0, 0 },
++	{ 550000000, P_PLL18, 1, 0, 0 },
++	{ 733000000, P_PLL18, 1, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg ubi32_core1_src_clk = {
++	.ns_reg[0] = 0x3d2c,
++	.ns_reg[1] = 0x3d30,
++	.md_reg[0] = 0x3d24,
++	.md_reg[1] = 0x3d28,
++	.bank_reg = 0x3d20,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d20,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core1_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
++static struct clk_dyn_rcg ubi32_core2_src_clk = {
++	.ns_reg[0] = 0x3d4c,
++	.ns_reg[1] = 0x3d50,
++	.md_reg[0] = 0x3d44,
++	.md_reg[1] = 0x3d48,
++	.bank_reg = 0x3d40,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d40,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core2_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
+ static struct clk_regmap *gcc_ipq806x_clks[] = {
+ 	[PLL0] = &pll0.clkr,
+ 	[PLL0_VOTE] = &pll0_vote,
+@@ -2259,6 +2776,7 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL8_VOTE] = &pll8_vote,
+ 	[PLL14] = &pll14.clkr,
+ 	[PLL14_VOTE] = &pll14_vote,
++	[PLL18] = &pll18.clkr,
+ 	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+ 	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+ 	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+@@ -2356,6 +2874,18 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL9] = &hfpll0.clkr,
+ 	[PLL10] = &hfpll1.clkr,
+ 	[PLL12] = &hfpll_l2.clkr,
++	[GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr,
++	[GMAC_CORE1_CLK] = &gmac_core1_clk.clkr,
++	[GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr,
++	[GMAC_CORE2_CLK] = &gmac_core2_clk.clkr,
++	[GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr,
++	[GMAC_CORE3_CLK] = &gmac_core3_clk.clkr,
++	[GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr,
++	[GMAC_CORE4_CLK] = &gmac_core4_clk.clkr,
++	[UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr,
++	[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
++	[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
++	[NSSTCM_CLK] = &nss_tcm_clk.clkr,
+ };
+ 
+ static const struct qcom_reset_map gcc_ipq806x_resets[] = {
+@@ -2474,6 +3004,48 @@ static const struct qcom_reset_map gcc_i
+ 	[USB30_1_PHY_RESET] = { 0x3b58, 0 },
+ 	[NSSFB0_RESET] = { 0x3b60, 6 },
+ 	[NSSFB1_RESET] = { 0x3b60, 7 },
++	[UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3},
++	[UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 },
++	[UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 },
++	[UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 },
++	[UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 },
++	[UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 },
++	[UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 },
++	[UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 },
++	[GMAC_CORE1_RESET] = { 0x3cbc, 0 },
++	[GMAC_CORE2_RESET] = { 0x3cdc, 0 },
++	[GMAC_CORE3_RESET] = { 0x3cfc, 0 },
++	[GMAC_CORE4_RESET] = { 0x3d1c, 0 },
++	[GMAC_AHB_RESET] = { 0x3e24, 0 },
++	[NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 },
++	[NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 },
++	[NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 },
++	[NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 },
++	[NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 },
++	[NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 },
++	[NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 },
++	[NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 },
++	[NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 },
++	[NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 },
++	[NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 },
++	[NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 },
++	[NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 },
++	[NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 },
++	[NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 },
++	[NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 },
++	[NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 },
++	[NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 },
++	[NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 },
++	[NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 },
++	[NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 },
++	[NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 },
++	[NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 },
++	[NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 },
++	[NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 },
++	[NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 },
++	[NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 },
++	[NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 },
++	[NSS_SRDS_N_RESET] = { 0x3b60, 28 },
+ };
+ 
+ static const struct regmap_config gcc_ipq806x_regmap_config = {
+@@ -2502,6 +3074,8 @@ static int gcc_ipq806x_probe(struct plat
+ {
+ 	struct clk *clk;
+ 	struct device *dev = &pdev->dev;
++	struct regmap *regmap;
++	int ret;
+ 
+ 	/* Temporary until RPM clocks supported */
+ 	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
+@@ -2512,7 +3086,25 @@ static int gcc_ipq806x_probe(struct plat
+ 	if (IS_ERR(clk))
+ 		return PTR_ERR(clk);
+ 
+-	return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	if (ret)
++		return ret;
++
++	regmap = dev_get_regmap(dev, NULL);
++	if (!regmap)
++		return -ENODEV;
++
++	/* Setup PLL18 static bits */
++	regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400);
++	regmap_write(regmap, 0x31b0, 0x3080);
++
++	/* Set GMAC footswitch sleep/wakeup values */
++	regmap_write(regmap, 0x3cb8, 8);
++	regmap_write(regmap, 0x3cd8, 8);
++	regmap_write(regmap, 0x3cf8, 8);
++	regmap_write(regmap, 0x3d18, 8);
++
++	return 0;
+ }
+ 
+ static int gcc_ipq806x_remove(struct platform_device *pdev)
+--- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h
+@@ -288,5 +288,7 @@
+ #define UBI32_CORE2_CLK_SRC			278
+ #define UBI32_CORE1_CLK				279
+ #define UBI32_CORE2_CLK				280
++#define NSSTCM_CLK_SRC				281
++#define NSSTCM_CLK				282
+ 
+ #endif
+--- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h
+@@ -129,4 +129,47 @@
+ #define USB30_1_PHY_RESET				112
+ #define NSSFB0_RESET					113
+ #define NSSFB1_RESET					114
++#define UBI32_CORE1_CLKRST_CLAMP_RESET			115
++#define UBI32_CORE1_CLAMP_RESET				116
++#define UBI32_CORE1_AHB_RESET				117
++#define UBI32_CORE1_AXI_RESET				118
++#define UBI32_CORE2_CLKRST_CLAMP_RESET			119
++#define UBI32_CORE2_CLAMP_RESET				120
++#define UBI32_CORE2_AHB_RESET				121
++#define UBI32_CORE2_AXI_RESET				122
++#define GMAC_CORE1_RESET				123
++#define GMAC_CORE2_RESET				124
++#define GMAC_CORE3_RESET				125
++#define GMAC_CORE4_RESET				126
++#define GMAC_AHB_RESET					127
++#define NSS_CH0_RST_RX_CLK_N_RESET			128
++#define NSS_CH0_RST_TX_CLK_N_RESET			129
++#define NSS_CH0_RST_RX_125M_N_RESET			130
++#define NSS_CH0_HW_RST_RX_125M_N_RESET			131
++#define NSS_CH0_RST_TX_125M_N_RESET			132
++#define NSS_CH1_RST_RX_CLK_N_RESET			133
++#define NSS_CH1_RST_TX_CLK_N_RESET			134
++#define NSS_CH1_RST_RX_125M_N_RESET			135
++#define NSS_CH1_HW_RST_RX_125M_N_RESET			136
++#define NSS_CH1_RST_TX_125M_N_RESET			137
++#define NSS_CH2_RST_RX_CLK_N_RESET			138
++#define NSS_CH2_RST_TX_CLK_N_RESET			139
++#define NSS_CH2_RST_RX_125M_N_RESET			140
++#define NSS_CH2_HW_RST_RX_125M_N_RESET			141
++#define NSS_CH2_RST_TX_125M_N_RESET			142
++#define NSS_CH3_RST_RX_CLK_N_RESET			143
++#define NSS_CH3_RST_TX_CLK_N_RESET			144
++#define NSS_CH3_RST_RX_125M_N_RESET			145
++#define NSS_CH3_HW_RST_RX_125M_N_RESET			146
++#define NSS_CH3_RST_TX_125M_N_RESET			147
++#define NSS_RST_RX_250M_125M_N_RESET			148
++#define NSS_RST_TX_250M_125M_N_RESET			149
++#define NSS_QSGMII_TXPI_RST_N_RESET			150
++#define NSS_QSGMII_CDR_RST_N_RESET			151
++#define NSS_SGMII2_CDR_RST_N_RESET			152
++#define NSS_SGMII3_CDR_RST_N_RESET			153
++#define NSS_CAL_PRBS_RST_N_RESET			154
++#define NSS_LCKDT_RST_N_RESET				155
++#define NSS_SRDS_N_RESET				156
++
+ #endif
diff --git a/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch b/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
new file mode 100644
index 0000000..e94a746
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
@@ -0,0 +1,105 @@
+From 4f09499bc1d9bb095caccbcd73ff951ee631e521 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 15:42:40 -0700
+Subject: [PATCH 1/8] stmmac: add phy-handle support to the platform layer
+
+On stmmac driver, PHY specification in device-tree was done using the
+non-standard property "snps,phy-addr". Specifying a PHY on a different
+MDIO bus that the one within the stmmac controller doesn't seem to be
+possible when device-tree is used.
+
+This change adds support for the phy-handle property, as specified in
+Documentation/devicetree/bindings/net/ethernet.txt.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 28 ++++++++++++++--------
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |  6 ++++-
+ include/linux/stmmac.h                             |  1 +
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -52,6 +52,7 @@
+ #include "stmmac_ptp.h"
+ #include "stmmac.h"
+ #include <linux/reset.h>
++#include <linux/of_mdio.h>
+ 
+ #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
+ 
+@@ -816,18 +817,25 @@ static int stmmac_init_phy(struct net_de
+ 	priv->speed = 0;
+ 	priv->oldduplex = -1;
+ 
+-	if (priv->plat->phy_bus_name)
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
+-			 priv->plat->phy_bus_name, priv->plat->bus_id);
+-	else
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+-			 priv->plat->bus_id);
+-
+-	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+-		 priv->plat->phy_addr);
+-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
++	if (priv->plat->phy_node) {
++		phydev = of_phy_connect(dev, priv->plat->phy_node,
++					&stmmac_adjust_link, 0, interface);
++	} else {
++		if (priv->plat->phy_bus_name)
++			snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
++				 priv->plat->phy_bus_name, priv->plat->bus_id);
++		else
++			snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
++				 priv->plat->bus_id);
++
++		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
++			 priv->plat->phy_addr);
++		pr_debug("stmmac_init_phy:  trying to attach to %s\n",
++			 phy_id_fmt);
+ 
+-	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
++		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
++				     interface);
++	}
+ 
+ 	if (IS_ERR(phydev)) {
+ 		pr_err("%s: Could not attach to PHY\n", dev->name);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -27,6 +27,7 @@
+ #include <linux/of.h>
+ #include <linux/of_net.h>
+ #include <linux/of_device.h>
++#include <linux/of_mdio.h>
+ 
+ #include "stmmac.h"
+ #include "stmmac_platform.h"
+@@ -167,13 +168,16 @@ static int stmmac_probe_config_dt(struct
+ 	/* Default to phy auto-detection */
+ 	plat->phy_addr = -1;
+ 
++	/* If we find a phy-handle property, use it as the PHY */
++	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+ 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+ 
+-	if (plat->phy_bus_name)
++	if (plat->phy_node || plat->phy_bus_name)
+ 		plat->mdio_bus_data = NULL;
+ 	else
+ 		plat->mdio_bus_data =
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
+ 	int phy_addr;
+ 	int interface;
+ 	struct stmmac_mdio_bus_data *mdio_bus_data;
++	struct device_node *phy_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	int clk_csr;
+ 	int has_gmac;
diff --git a/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch b/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
new file mode 100644
index 0000000..3b2134e
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
@@ -0,0 +1,65 @@
+From 0149d275415cd1b2382ce94e5eb32641590097d0 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 15:57:12 -0700
+Subject: [PATCH 2/8] stmmac: move error path at the end of
+ stmmac_probe_config_dt()
+
+We will want to do additional clean-up on certain errors. Therefore,
+this change moves the error path at the end of the function for better
+code readability.
+
+This patch doesn't change anything functionally.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -129,13 +129,18 @@ static int stmmac_probe_config_dt(struct
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	const struct of_device_id *device;
++	int ret;
+ 
+-	if (!np)
+-		return -ENODEV;
++	if (!np) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	device = of_match_device(stmmac_dt_ids, &pdev->dev);
+-	if (!device)
+-		return -ENODEV;
++	if (!device) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	if (device->data) {
+ 		const struct stmmac_of_data *data = device->data;
+@@ -231,8 +236,10 @@ static int stmmac_probe_config_dt(struct
+ 	if (of_find_property(np, "snps,pbl", NULL)) {
+ 		dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
+ 				       GFP_KERNEL);
+-		if (!dma_cfg)
+-			return -ENOMEM;
++		if (!dma_cfg) {
++			ret = -ENOMEM;
++			goto err;
++		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ 		dma_cfg->fixed_burst =
+@@ -250,6 +257,9 @@ static int stmmac_probe_config_dt(struct
+ 	}
+ 
+ 	return 0;
++
++err:
++	return ret;
+ }
+ #else
+ static int stmmac_probe_config_dt(struct platform_device *pdev,
diff --git a/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch b/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch
new file mode 100644
index 0000000..4b2c9b5
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch
@@ -0,0 +1,64 @@
+From 3a95f75867be562cb919ff23a738f70357188fbd Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:02:03 -0700
+Subject: [PATCH 3/8] stmmac: add fixed-link device-tree support
+
+In case DT is used, this change adds the ability to the stmmac driver to
+detect a fixed-link PHY, instanciate it, and use it during
+phy_connect().
+
+Fixed link PHYs DT usage is described in:
+Documentation/devicetree/bindings/net/fixed-link.txt
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     |  2 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 12 +++++++++++-
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -856,7 +856,7 @@ static int stmmac_init_phy(struct net_de
+ 	 * device as well.
+ 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
+ 	 */
+-	if (phydev->phy_id == 0) {
++	if (!priv->plat->phy_node && phydev->phy_id == 0) {
+ 		phy_disconnect(phydev);
+ 		return -ENODEV;
+ 	}
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -176,6 +176,14 @@ static int stmmac_probe_config_dt(struct
+ 	/* If we find a phy-handle property, use it as the PHY */
+ 	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ 
++	/* If phy-handle is not specified, check if we have a fixed-phy */
++	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
++		if ((of_phy_register_fixed_link(np) < 0))
++			return -ENODEV;
++
++		plat->phy_node = of_node_get(np);
++	}
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+@@ -238,7 +246,7 @@ static int stmmac_probe_config_dt(struct
+ 				       GFP_KERNEL);
+ 		if (!dma_cfg) {
+ 			ret = -ENOMEM;
+-			goto err;
++			goto err2;
+ 		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+@@ -258,6 +266,8 @@ static int stmmac_probe_config_dt(struct
+ 
+ 	return 0;
+ 
++err2:
++	of_node_put(np);
+ err:
+ 	return ret;
+ }
diff --git a/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch b/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch
new file mode 100644
index 0000000..fecc958
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch
@@ -0,0 +1,407 @@
+From 69fb970ad3fe05af7cb99ea78230c69c7ca0d03b Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:10:22 -0700
+Subject: [PATCH 4/8] stmmac: add ipq806x glue layer
+
+The ethernet controller available in IPQ806x is a Synopsys DesignWare
+Gigabit MAC IP core, already supported by the stmmac driver.
+
+This glue layer implements some platform specific settings required to
+get the controller working on an IPQ806x based platform.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/Kconfig        |   1 +
+ drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c    | 324 +++++++++++++++++++++
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   1 +
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.h  |   1 +
+ 5 files changed, 328 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c
+
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -16,6 +16,7 @@ if STMMAC_ETH
+ config STMMAC_PLATFORM
+ 	tristate "STMMAC Platform bus support"
+ 	depends on STMMAC_ETH
++	select MFD_SYSCON
+ 	default y
+ 	---help---
+ 	  This selects the platform specific bus support for the stmmac driver.
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethto
+ 
+ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
+ stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o	\
+-		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o
++		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o dwmac-ipq806x.o
+ 
+ obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
+ stmmac-pci-objs:= stmmac_pci.o
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -42,6 +42,7 @@ static const struct of_device_id stmmac_
+ 	{ .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
+ 	{ .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
+ 	{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
++	{ .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data },
+ 	{ .compatible = "st,spear600-gmac"},
+ 	{ .compatible = "snps,dwmac-3.610"},
+ 	{ .compatible = "snps,dwmac-3.70a"},
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+@@ -25,5 +25,6 @@ extern const struct stmmac_of_data stih4
+ extern const struct stmmac_of_data stid127_dwmac_data;
+ extern const struct stmmac_of_data socfpga_gmac_data;
+ extern const struct stmmac_of_data rk3288_gmac_data;
++extern const struct stmmac_of_data ipq806x_gmac_data;
+ 
+ #endif /* __STMMAC_PLATFORM_H__ */
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+@@ -0,0 +1,343 @@
++/*
++ * Qualcomm Atheros IPQ806x GMAC glue layer
++ *
++ * Copyright (C) 2015 The Linux Foundation
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/phy.h>
++#include <linux/regmap.h>
++#include <linux/clk.h>
++#include <linux/reset.h>
++#include <linux/of_net.h>
++#include <linux/mfd/syscon.h>
++#include <linux/stmmac.h>
++#include <linux/of_mdio.h>
++
++#include "stmmac_platform.h"
++
++#define NSS_COMMON_CLK_GATE			0x8
++#define NSS_COMMON_CLK_GATE_PTP_EN(x)		BIT(0x10 + x)
++#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x)	BIT(0x9 + (x * 2))
++#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x)	BIT(0x8 + (x * 2))
++#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x)	BIT(0x4 + x)
++#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x)	BIT(0x0 + x)
++
++#define NSS_COMMON_CLK_DIV0			0xC
++#define NSS_COMMON_CLK_DIV_OFFSET(x)		(x * 8)
++#define NSS_COMMON_CLK_DIV_MASK			0x7f
++
++#define NSS_COMMON_CLK_SRC_CTRL			0x14
++#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)	(1 << x)
++/* Mode is coded on 1 bit but is different depending on the MAC ID:
++ * MAC0: QSGMII=0 RGMII=1
++ * MAC1: QSGMII=0 SGMII=0 RGMII=1
++ * MAC2 & MAC3: QSGMII=0 SGMII=1
++ */
++#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x)	1
++#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x)	((x >= 2) ? 1 : 0)
++
++#define NSS_COMMON_MACSEC_CTL			0x28
++#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x)	(1 << x)
++
++#define NSS_COMMON_GMAC_CTL(x)			(0x30 + (x * 4))
++#define NSS_COMMON_GMAC_CTL_CSYS_REQ		BIT(19)
++#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL	BIT(16)
++#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET	8
++#define NSS_COMMON_GMAC_CTL_IFG_OFFSET		0
++#define NSS_COMMON_GMAC_CTL_IFG_MASK		0x3f
++
++#define NSS_COMMON_CLK_DIV_RGMII_1000		1
++#define NSS_COMMON_CLK_DIV_RGMII_100		9
++#define NSS_COMMON_CLK_DIV_RGMII_10		99
++#define NSS_COMMON_CLK_DIV_SGMII_1000		0
++#define NSS_COMMON_CLK_DIV_SGMII_100		4
++#define NSS_COMMON_CLK_DIV_SGMII_10		49
++
++#define QSGMII_PCS_MODE_CTL			0x68
++#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x)	BIT((x * 8) + 7)
++
++#define QSGMII_PCS_CAL_LCKDT_CTL		0x120
++#define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
++
++/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
++#define QSGMII_PHY_SGMII_CTL(x)			((x == 1) ? 0x134 : \
++						 (0x13c + (4 * (x - 2))))
++#define QSGMII_PHY_CDR_EN			BIT(0)
++#define QSGMII_PHY_RX_FRONT_EN			BIT(1)
++#define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
++#define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
++#define QSGMII_PHY_QSGMII_EN			BIT(7)
++#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
++#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		0x7
++#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
++#define QSGMII_PHY_RX_DC_BIAS_MASK		0x3
++#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
++#define QSGMII_PHY_RX_INPUT_EQU_MASK		0x3
++#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
++#define QSGMII_PHY_CDR_PI_SLEW_MASK		0x3
++#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
++#define QSGMII_PHY_TX_DRV_AMP_MASK		0xf
++
++struct ipq806x_gmac {
++	struct platform_device *pdev;
++	struct regmap *nss_common;
++	struct regmap *qsgmii_csr;
++	uint32_t id;
++	struct clk *core_clk;
++	phy_interface_t phy_mode;
++};
++
++static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_SGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_SGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_SGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_RGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_RGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_RGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	uint32_t clk_bits, val;
++	int div;
++
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		div = get_clk_div_rgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
++		break;
++
++	case PHY_INTERFACE_MODE_SGMII:
++		div = get_clk_div_sgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
++		break;
++
++	default:
++		dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return -EINVAL;
++	}
++
++	/* Disable the clocks */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val &= ~clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	/* Set the divider */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
++	val &= ~(NSS_COMMON_CLK_DIV_MASK
++		 << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
++	val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
++
++	/* Enable the clock back */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	return 0;
++}
++
++static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
++{
++	struct device *dev = &gmac->pdev->dev;
++
++	gmac->phy_mode = of_get_phy_mode(dev->of_node);
++	if (gmac->phy_mode < 0) {
++		dev_err(dev, "missing phy mode property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
++		dev_err(dev, "missing qcom id property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	/* The GMACs are called 1 to 4 in the documentation, but to simplify the
++	 * code and keep it consistent with the Linux convention, we'll number
++	 * them from 0 to 3 here.
++	 */
++	if (gmac->id < 0 || gmac->id > 3) {
++		dev_err(dev, "invalid gmac id\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	gmac->core_clk = devm_clk_get(dev, "stmmaceth");
++	if (IS_ERR(gmac->core_clk)) {
++		dev_err(dev, "missing stmmaceth clk property\n");
++		return gmac->core_clk;
++	}
++	clk_set_rate(gmac->core_clk, 266000000);
++
++	/* Setup the register map for the nss common registers */
++	gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,nss-common");
++	if (IS_ERR(gmac->nss_common)) {
++		dev_err(dev, "missing nss-common node\n");
++		return gmac->nss_common;
++	}
++
++	/* Setup the register map for the qsgmii csr registers */
++	gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,qsgmii-csr");
++	if (IS_ERR(gmac->qsgmii_csr)) {
++		dev_err(dev, "missing qsgmii-csr node\n");
++		return gmac->qsgmii_csr;
++	}
++
++	return NULL;
++}
++
++static void *ipq806x_gmac_setup(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct ipq806x_gmac *gmac;
++	int val;
++	void *err;
++
++	gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
++	if (!gmac)
++		return ERR_PTR(-ENOMEM);
++
++	gmac->pdev = pdev;
++
++	err = ipq806x_gmac_of_parse(gmac);
++	if (err) {
++		dev_err(dev, "device tree parsing error\n");
++		return err;
++	}
++
++	regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
++		     QSGMII_PCS_CAL_LCKDT_CTL_RST);
++
++	/* Inter frame gap is set to 12 */
++	val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
++	      12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
++	/* We also initiate an AXI low power exit request */
++	val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
++
++	/* Configure the clock src according to the mode */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
++	val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
++
++	/* Enable PTP clock */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
++		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
++			     QSGMII_PHY_CDR_EN |
++			     QSGMII_PHY_RX_FRONT_EN |
++			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
++			     QSGMII_PHY_TX_DRIVER_EN |
++			     QSGMII_PHY_QSGMII_EN |
++			     0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
++			     0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
++			     0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
++			     0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
++			     0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
++	}
++
++	return gmac;
++}
++
++static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
++{
++	struct ipq806x_gmac *gmac = priv;
++
++	ipq806x_gmac_set_speed(gmac, speed);
++}
++
++const struct stmmac_of_data ipq806x_gmac_data = {
++	.has_gmac	= 1,
++	.setup		= ipq806x_gmac_setup,
++	.fix_mac_speed	= ipq806x_gmac_fix_mac_speed,
++};
diff --git a/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch b/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
new file mode 100644
index 0000000..3144fa3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
@@ -0,0 +1,52 @@
+From 0f9605d9409b77a89daef91cc68239fc2ff50457 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Fri, 8 May 2015 16:51:25 -0700
+Subject: [PATCH 5/8] net: stmmac: ipq806x: document device tree bindings
+
+Add the device tree bindings documentation for the QCA IPQ806x
+variant of the Synopsys DesignWare MAC.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ .../devicetree/bindings/net/ipq806x-dwmac.txt      | 35 ++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+@@ -0,0 +1,35 @@
++* IPQ806x DWMAC Ethernet controller
++
++The device inherits all the properties of the dwmac/stmmac devices
++described in the file net/stmmac.txt with the following changes.
++
++Required properties:
++
++- compatible: should be "qcom,ipq806x-gmac" along with "snps,dwmac"
++	      and any applicable more detailed version number
++	      described in net/stmmac.txt
++
++- qcom,nss-common: should contain a phandle to a syscon device mapping the
++		   nss-common registers.
++
++- qcom,qsgmii-csr: should contain a phandle to a syscon device mapping the
++		   qsgmii-csr registers.
++
++Example:
++
++	gmac: ethernet at 37000000 {
++		device_type = "network";
++		compatible = "qcom,ipq806x-gmac";
++		reg = <0x37000000 0x200000>;
++		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++		interrupt-names = "macirq";
++
++		qcom,nss-common = <&nss_common>;
++		qcom,qsgmii-csr = <&qsgmii_csr>;
++
++		clocks = <&gcc GMAC_CORE1_CLK>;
++		clock-names = "stmmaceth";
++
++		resets = <&gcc GMAC_CORE1_RESET>;
++		reset-names = "stmmaceth";
++	};
diff --git a/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch b/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
new file mode 100644
index 0000000..a9a2d55
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
@@ -0,0 +1,175 @@
+From df944689d491e6af533173bf2ef448c3dd334f15 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 15:15:25 -0700
+Subject: [PATCH 6/8] net: stmmac: create one debugfs dir per net-device
+
+stmmac DebugFS entries are currently global to the driver. As a result,
+having more than one stmmac device in the system creates the following
+error:
+* ERROR stmmaceth, debugfs create directory failed
+* stmmac_hw_setup: failed debugFS registration
+
+This also results in being able to access the debugfs information for
+the first registered device only.
+
+This patch changes the debugfs structure to have one sub-directory per
+net-device. Files under "/sys/kernel/debug/stmmaceth" will now show-up
+under /sys/kernel/debug/stmmaceth/ethN/.
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h      |  6 ++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 76 ++++++++++++++++-------
+ 2 files changed, 59 insertions(+), 23 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -116,6 +116,12 @@ struct stmmac_priv {
+ 	int use_riwt;
+ 	int irq_wake;
+ 	spinlock_t ptp_lock;
++
++#ifdef CONFIG_DEBUG_FS
++	struct dentry *dbgfs_dir;
++	struct dentry *dbgfs_rings_status;
++	struct dentry *dbgfs_dma_cap;
++#endif
+ };
+ 
+ int stmmac_mdio_unregister(struct net_device *ndev);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -119,7 +119,7 @@ static irqreturn_t stmmac_interrupt(int
+ 
+ #ifdef CONFIG_DEBUG_FS
+ static int stmmac_init_fs(struct net_device *dev);
+-static void stmmac_exit_fs(void);
++static void stmmac_exit_fs(struct net_device *dev);
+ #endif
+ 
+ #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+@@ -1918,7 +1918,7 @@ static int stmmac_release(struct net_dev
+ 	netif_carrier_off(dev);
+ 
+ #ifdef CONFIG_DEBUG_FS
+-	stmmac_exit_fs();
++	stmmac_exit_fs(dev);
+ #endif
+ 
+ 	stmmac_release_ptp(priv);
+@@ -2510,8 +2510,6 @@ static int stmmac_ioctl(struct net_devic
+ 
+ #ifdef CONFIG_DEBUG_FS
+ static struct dentry *stmmac_fs_dir;
+-static struct dentry *stmmac_rings_status;
+-static struct dentry *stmmac_dma_cap;
+ 
+ static void sysfs_display_ring(void *head, int size, int extend_desc,
+ 			       struct seq_file *seq)
+@@ -2650,36 +2648,39 @@ static const struct file_operations stmm
+ 
+ static int stmmac_init_fs(struct net_device *dev)
+ {
+-	/* Create debugfs entries */
+-	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
++	struct stmmac_priv *priv = netdev_priv(dev);
++
++	/* Create per netdev entries */
++	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
+ 
+-	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
+-		pr_err("ERROR %s, debugfs create directory failed\n",
+-		       STMMAC_RESOURCE_NAME);
++	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
++		pr_err("ERROR %s/%s, debugfs create directory failed\n",
++		       STMMAC_RESOURCE_NAME, dev->name);
+ 
+ 		return -ENOMEM;
+ 	}
+ 
+ 	/* Entry to report DMA RX/TX rings */
+-	stmmac_rings_status = debugfs_create_file("descriptors_status",
+-						  S_IRUGO, stmmac_fs_dir, dev,
+-						  &stmmac_rings_status_fops);
++	priv->dbgfs_rings_status =
++		debugfs_create_file("descriptors_status", S_IRUGO,
++				    priv->dbgfs_dir, dev,
++				    &stmmac_rings_status_fops);
+ 
+-	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
++	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
+ 		pr_info("ERROR creating stmmac ring debugfs file\n");
+-		debugfs_remove(stmmac_fs_dir);
++		debugfs_remove_recursive(priv->dbgfs_dir);
+ 
+ 		return -ENOMEM;
+ 	}
+ 
+ 	/* Entry to report the DMA HW features */
+-	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
+-					     dev, &stmmac_dma_cap_fops);
++	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
++					    priv->dbgfs_dir,
++					    dev, &stmmac_dma_cap_fops);
+ 
+-	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
++	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
+ 		pr_info("ERROR creating stmmac MMC debugfs file\n");
+-		debugfs_remove(stmmac_rings_status);
+-		debugfs_remove(stmmac_fs_dir);
++		debugfs_remove_recursive(priv->dbgfs_dir);
+ 
+ 		return -ENOMEM;
+ 	}
+@@ -2687,11 +2688,11 @@ static int stmmac_init_fs(struct net_dev
+ 	return 0;
+ }
+ 
+-static void stmmac_exit_fs(void)
++static void stmmac_exit_fs(struct net_device *dev)
+ {
+-	debugfs_remove(stmmac_rings_status);
+-	debugfs_remove(stmmac_dma_cap);
+-	debugfs_remove(stmmac_fs_dir);
++	struct stmmac_priv *priv = netdev_priv(dev);
++
++	debugfs_remove_recursive(priv->dbgfs_dir);
+ }
+ #endif /* CONFIG_DEBUG_FS */
+ 
+@@ -3136,6 +3137,35 @@ err:
+ __setup("stmmaceth=", stmmac_cmdline_opt);
+ #endif /* MODULE */
+ 
++static int __init stmmac_init(void)
++{
++#ifdef CONFIG_DEBUG_FS
++	/* Create debugfs main directory if it doesn't exist yet */
++	if (stmmac_fs_dir == NULL) {
++		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
++
++		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
++			pr_err("ERROR %s, debugfs create directory failed\n",
++			       STMMAC_RESOURCE_NAME);
++
++			return -ENOMEM;
++		}
++	}
++#endif
++
++	return 0;
++}
++
++static void __exit stmmac_exit(void)
++{
++#ifdef CONFIG_DEBUG_FS
++	debugfs_remove_recursive(stmmac_fs_dir);
++#endif
++}
++
++module_init(stmmac_init)
++module_exit(stmmac_exit)
++
+ MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
+ MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro at st.com>");
+ MODULE_LICENSE("GPL");
diff --git a/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch b/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
new file mode 100644
index 0000000..20d8502
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
@@ -0,0 +1,145 @@
+From e81de9d28bd0421c236df322872e64edf4ee1852 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 16:32:09 -0700
+Subject: [PATCH 7/8] ARM: dts: qcom: add mdio nodes to ap148 & db149
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 40 ++++++++++++++++++++++++++-
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 46 ++++++++++++++++++++++++++++++++
+ 2 files changed, 85 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -14,8 +14,9 @@
+ 		};
+ 	};
+ 
+-	alias {
++	aliases {
+ 		serial0 = &uart4;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -54,6 +55,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi at 16300000 {
+@@ -139,5 +149,33 @@
+ 			pinctrl-0 = <&pcie2_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy at 0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++					>;
++			};
++
++			phy4: ethernet-phy at 4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -16,6 +16,7 @@
+ 
+ 	alias {
+ 		serial0 = &uart2;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -62,6 +63,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi at 12480000 {
+@@ -173,5 +183,44 @@
+ 			pinctrl-0 = <&pcie3_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy at 0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++				>;
++			};
++
++			phy4: ethernet-phy at 4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++
++			phy6: ethernet-phy at 6 {
++				device_type = "ethernet-phy";
++				reg = <6>;
++			};
++
++			phy7: ethernet-phy at 7 {
++				device_type = "ethernet-phy";
++				reg = <7>;
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
new file mode 100644
index 0000000..6a14f9f
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
@@ -0,0 +1,210 @@
+From cab1f4720e82f2e17eaeed9a9ad9e4f07c742977 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu at codeaurora.org>
+Date: Mon, 11 May 2015 12:29:18 -0700
+Subject: [PATCH 8/8] ARM: dts: qcom: add gmac nodes to ipq806x platforms
+
+Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 31 ++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 43 ++++++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064.dtsi      | 86 ++++++++++++++++++++++++++++++++
+ 3 files changed, 160 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -64,6 +64,16 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii2_pins: rgmii2_pins {
++				mux {
++					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
++					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
++					function = "rgmii2";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi at 16300000 {
+@@ -177,5 +187,26 @@
+ 				reg = <4>;
+ 			};
+ 		};
++
++		gmac1: ethernet at 37200000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			phy-handle = <&phy4>;
++			qcom,id = <1>;
++
++			pinctrl-0 = <&rgmii2_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac2: ethernet at 37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -72,6 +72,14 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii0_pins: rgmii0_pins {
++				mux {
++					pins = "gpio2", "gpio66";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi at 12480000 {
+@@ -222,5 +230,40 @@
+ 				reg = <7>;
+ 			};
+ 		};
++
++		gmac0: ethernet at 37000000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			qcom,id = <0>;
++			phy-handle = <&phy4>;
++
++			pinctrl-0 = <&rgmii0_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac1: ethernet at 37200000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <1>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
++
++		gmac2: ethernet at 37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++			phy-handle = <&phy6>;
++		};
++
++		gmac3: ethernet at 37600000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <3>;
++			phy-handle = <&phy7>;
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -540,5 +540,91 @@
+ 
+ 			status = "disabled";
+ 		};
++
++		nss_common: syscon at 03000000 {
++			compatible = "syscon";
++			reg = <0x03000000 0x0000FFFF>;
++		};
++
++		qsgmii_csr: syscon at 1bb00000 {
++			compatible = "syscon";
++			reg = <0x1bb00000 0x000001FF>;
++		};
++
++		gmac0: ethernet at 37000000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37000000 0x200000>;
++			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE1_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE1_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac1: ethernet at 37200000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37200000 0x200000>;
++			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE2_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE2_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac2: ethernet at 37400000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37400000 0x200000>;
++			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE3_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE3_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac3: ethernet at 37600000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37600000 0x200000>;
++			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE4_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE4_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
+ 	};
+ };
-- 
2.1.4

_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list