From: John Crispin Date: Fri, 29 May 2015 12:26:01 +0000 (+0000) Subject: ipq806x: replace caf nss-gmac driver by upstream stmmac X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=d2a2eb7e48f6;p=openwrt%2Fstaging%2Fsvanheule.git 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 SVN-Revision: 45831 --- diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile index f97db74fc3..da841a6314 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 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 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 + 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 + 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 + 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 }; --- 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 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 + 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 / { model = "Qualcomm IPQ8064"; -@@ -306,6 +307,129 @@ +@@ -306,6 +308,129 @@ #reset-cells = <1>; }; @@ -260,7 +259,7 @@ Signed-off-by: Mathieu Olivari 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 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 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 #include #include - -@@ -75,6 +76,63 @@ + #include +@@ -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 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 --- 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 = ; -+ status = "disabled"; -+ }; -+ -+ gmac1: ethernet@37200000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37200000 0x200000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac2: ethernet@37400000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37400000 0x200000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac3: ethernet@37600000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37600000 0x200000>; -+ interrupts = ; -+ 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 +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 +--- + 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 +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 +--- + 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 ++#include + + #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 + #include + #include ++#include + #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 +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 +--- + .../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 +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 +--- + 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 +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 +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 +--- + .../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 = ; ++ 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 = ; ++ 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 = ; ++ 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 = ; ++ 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 = ; ++ 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 a274f245d4..29631b2c28 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 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 --- 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 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 + 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 + 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 + 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-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 ad0a7401be..957b054b8c 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 }; --- 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 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 + 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 / { 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 b5a3f19b23..0000000000 --- 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@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"; -@@ -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@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 -@@ -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@37000000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37000000 0x200000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac1: ethernet@37200000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37200000 0x200000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac2: ethernet@37400000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37400000 0x200000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ gmac3: ethernet@37600000 { -+ device_type = "network"; -+ compatible = "qcom,nss-gmac"; -+ reg = <0x37600000 0x200000>; -+ interrupts = ; -+ 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 0000000000..1b9d47bf1b --- /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 +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 +--- + 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 0000000000..e94a746dcd --- /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 +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 +--- + 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 ++#include + + #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 + #include + #include ++#include + + #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 0000000000..3b2134ed3c --- /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 +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 +--- + .../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 0000000000..4b2c9b5b6d --- /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 +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 +--- + 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 0000000000..fecc958dc8 --- /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 +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 0000000000..3144fa36fe --- /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 +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 +--- + .../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 = ; ++ 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 0000000000..a9a2d556aa --- /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 +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 +--- + 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 "); + 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 0000000000..20d850287c --- /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 +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 +--- + 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 { +@@ -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@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-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 0000000000..6a14f9ff19 --- /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 +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 +--- + 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 { +@@ -177,5 +187,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 +@@ -540,5 +540,91 @@ + + status = "disabled"; + }; ++ ++ 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 = ; ++ 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 = ; ++ 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 = ; ++ 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 = ; ++ 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"; ++ }; + }; + };