aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-3.18
diff options
context:
space:
mode:
authorJohn Crispin <john@openwrt.org>2015-05-29 12:26:01 +0000
committerJohn Crispin <john@openwrt.org>2015-05-29 12:26:01 +0000
commitd2a2eb7e48f66e82dee1bae444ecfaff2c526fe2 (patch)
treed7e9bc9023dd972b9cf62e879c3432a0bc319d58 /target/linux/ipq806x/patches-3.18
parent72369c297663730264c761dda32004277da918df (diff)
downloadupstream-d2a2eb7e48f66e82dee1bae444ecfaff2c526fe2.tar.gz
upstream-d2a2eb7e48f66e82dee1bae444ecfaff2c526fe2.tar.bz2
upstream-d2a2eb7e48f66e82dee1bae444ecfaff2c526fe2.zip
ipq806x: replace caf nss-gmac driver by upstream stmmac
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@codeaurora.org> SVN-Revision: 45831
Diffstat (limited to 'target/linux/ipq806x/patches-3.18')
-rw-r--r--target/linux/ipq806x/patches-3.18/022-add-db149-dts.patch127
-rw-r--r--target/linux/ipq806x/patches-3.18/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch17
-rw-r--r--target/linux/ipq806x/patches-3.18/124-regulator-rpm-add-support-for-RPM-controller-SMB208.patch11
-rw-r--r--target/linux/ipq806x/patches-3.18/125-regulator-qcom-rpm-Add-missing-state-flag-in-call-to.patch7
-rw-r--r--target/linux/ipq806x/patches-3.18/126-add-rpm-to-ipq8064-dts.patch6
-rw-r--r--target/linux/ipq806x/patches-3.18/130-clk_mux-Fix-set_parent-doing-the-wrong-thing-when-IN.patch7
-rw-r--r--target/linux/ipq806x/patches-3.18/132-clk-Add-clk_unregister_-divider-gate-mux-to-close-me.patch2
-rw-r--r--target/linux/ipq806x/patches-3.18/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch8
-rw-r--r--target/linux/ipq806x/patches-3.18/700-add-gmac-dts-suport.patch164
-rw-r--r--target/linux/ipq806x/patches-3.18/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch733
-rw-r--r--target/linux/ipq806x/patches-3.18/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch105
-rw-r--r--target/linux/ipq806x/patches-3.18/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch65
-rw-r--r--target/linux/ipq806x/patches-3.18/703-stmmac-add-fixed-link-device-tree-support.patch64
-rw-r--r--target/linux/ipq806x/patches-3.18/704-stmmac-add-ipq806x-glue-layer.patch427
-rw-r--r--target/linux/ipq806x/patches-3.18/705-net-stmmac-ipq806x-document-device-tree-bindings.patch52
-rw-r--r--target/linux/ipq806x/patches-3.18/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch171
-rw-r--r--target/linux/ipq806x/patches-3.18/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch145
-rw-r--r--target/linux/ipq806x/patches-3.18/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch210
18 files changed, 1994 insertions, 327 deletions
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 85a0f7246a..bd6ec1e94f 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@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@codeaurora.org>
+ linux,stdout-path = "serial0:115200n8";
+ };
+
-+ aliases {
-+ mdio-gpio0 = &mdio0;
-+ };
-+
+ soc {
+ pinmux@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@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@12480000 {
@@ -180,106 +156,5 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+ usb30@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@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@4 {
-+ device_type = "ethernet-phy";
-+ reg = <4>;
-+ };
-+
-+ phy6: ethernet-phy@6 {
-+ device_type = "ethernet-phy";
-+ reg = <6>;
-+ };
-+
-+ phy7: ethernet-phy@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@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@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@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@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 7bee560e39..80ac25faeb 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@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@codeaurora.org>
spi_pins: spi_pins {
mux {
pins = "gpio18", "gpio19", "gpio21";
-@@ -153,6 +177,27 @@
+@@ -128,5 +152,26 @@
+ usb30@1 {
status = "ok";
};
-
++
+ pcie0: pci@1b500000 {
+ status = "ok";
+ reset-gpio = <&qcom_pinmux 3 0>;
@@ -115,10 +116,8 @@ Signed-off-by: Mathieu Olivari <mathieu@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@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@codeaurora.org>
hs_phy_1: phy@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 c411c1ce84..e4f094c213 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@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 11a296af70..48921a8429 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@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 854131c7f6..7e4c5cb1f6 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@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 d943ad511d..29f74b760d 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@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 127afd265f..790f25d28d 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@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 9f8d8cb7e8..a3c3bbfc9e 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@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@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 3c81f8834d..0000000000
--- 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@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@16300000 {
-@@ -89,6 +115,7 @@
- #size-cells = <1>;
- spi-max-frequency = <50000000>;
- reg = <0>;
-+ m25p,fast-read;
-
- partition@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@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@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@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@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@37000000 {
-+ device_type = "network";
-+ compatible = "qcom,nss-gmac";
-+ reg = <0x37000000 0x200000>;
-+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-+ status = "disabled";
-+ };
-+
-+ gmac1: ethernet@37200000 {
-+ device_type = "network";
-+ compatible = "qcom,nss-gmac";
-+ reg = <0x37200000 0x200000>;
-+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-+ status = "disabled";
-+ };
-+
-+ gmac2: ethernet@37400000 {
-+ device_type = "network";
-+ compatible = "qcom,nss-gmac";
-+ reg = <0x37400000 0x200000>;
-+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
-+ status = "disabled";
-+ };
-+
-+ gmac3: ethernet@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 0000000000..d7d6b69d15
--- /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@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@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 0000000000..8e59b5c48c
--- /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@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@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 0000000000..e8f9b5c29a
--- /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@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@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 0000000000..3c20fe477e
--- /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@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@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 0000000000..fa6740476b
--- /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@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@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 0000000000..3144fa36fe
--- /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@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@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@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 0000000000..50127fdb08
--- /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@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@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 0000000000..809d74372b
--- /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@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@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@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@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@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@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@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@4 {
++ device_type = "ethernet-phy";
++ reg = <4>;
++ };
++
++ phy6: ethernet-phy@6 {
++ device_type = "ethernet-phy";
++ reg = <6>;
++ };
++
++ phy7: ethernet-phy@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 0000000000..cce30b09a2
--- /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@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@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@16300000 {
+@@ -201,5 +211,26 @@
+ reg = <4>;
+ };
+ };
++
++ gmac1: ethernet@37200000 {
++ status = "ok";
++ phy-mode = "rgmii";
++ phy-handle = <&phy4>;
++ qcom,id = <1>;
++
++ pinctrl-0 = <&rgmii2_pins>;
++ pinctrl-names = "default";
++ };
++
++ gmac2: ethernet@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@12480000 {
+@@ -222,5 +230,40 @@
+ reg = <7>;
+ };
+ };
++
++ gmac0: ethernet@37000000 {
++ status = "ok";
++ phy-mode = "rgmii";
++ qcom,id = <0>;
++ phy-handle = <&phy4>;
++
++ pinctrl-0 = <&rgmii0_pins>;
++ pinctrl-names = "default";
++ };
++
++ gmac1: ethernet@37200000 {
++ status = "ok";
++ phy-mode = "sgmii";
++ qcom,id = <1>;
++
++ fixed-link {
++ speed = <1000>;
++ full-duplex;
++ };
++ };
++
++ gmac2: ethernet@37400000 {
++ status = "ok";
++ phy-mode = "sgmii";
++ qcom,id = <2>;
++ phy-handle = <&phy6>;
++ };
++
++ gmac3: ethernet@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@03000000 {
++ compatible = "syscon";
++ reg = <0x03000000 0x0000FFFF>;
++ };
++
++ qsgmii_csr: syscon@1bb00000 {
++ compatible = "syscon";
++ reg = <0x1bb00000 0x000001FF>;
++ };
++
++ gmac0: ethernet@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@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@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@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";
++ };
+ };
+ };