+++ /dev/null
-From d2cdc83fb2c7360856e598810b88211d815fc851 Mon Sep 17 00:00:00 2001
-Date: Sun, 8 Sep 2024 16:40:12 +0800
-Subject: [PATCH 2/3] arm64: dts: qcom: ipq5018: add mdio node
-
-The IPQ5018 SoC contains two MDIO controllers. MDIO0 is used to control
-its internal GE Phy, while MDIO1 is wired to external PHYs/switch.
-
----
- arch/arm64/boot/dts/qcom/ipq5018.dtsi | 20 ++++++++++++++++++++
- 1 file changed, 20 insertions(+)
-
---- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-@@ -192,6 +192,30 @@
- status = "disabled";
- };
-
-+ mdio0: mdio@88000 {
-+ compatible = "qcom,ipq5018-mdio", "qcom,qca-mdio";
-+ reg = <0x00088000 0x64>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ clocks = <&gcc GCC_MDIO0_AHB_CLK>;
-+ clock-names = "gcc_mdio_ahb_clk";
-+
-+ status = "disabled";
-+ };
-+
-+ mdio1: mdio@90000 {
-+ compatible = "qcom,ipq5018-mdio";
-+ reg = <0x00090000 0x64>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ clocks = <&gcc GCC_MDIO1_AHB_CLK>;
-+ clock-names = "gcc_mdio_ahb_clk";
-+
-+ status = "disabled";
-+ };
-+
- cmn_pll: clock-controller@9b000 {
- compatible = "qcom,ipq9574-cmn-pll";
- reg = <0x0009b000 0x800>,
--- /dev/null
+From 77ad12b3a5e21cae859247c0b82cf9a5b661e531 Mon Sep 17 00:00:00 2001
+Date: Sun, 8 Sep 2024 16:40:11 +0800
+Subject: [PATCH 1/3] net: phy: qcom: Introduce IPQ5018 internal PHY driver
+
+Introduce the internal GE PHY driver, part of the Qualcomm IPQ50xx SoC.
+The driver registers two clock providers needed and referenced by the GCC
+using DT properties and phandles.
+
+---
+ drivers/net/phy/qcom/Kconfig | 6 ++
+ drivers/net/phy/qcom/Makefile | 1 +
+ drivers/net/phy/qcom/ipq5018.c | 138 +++++++++++++++++++++++++++++++++
+ 3 files changed, 145 insertions(+)
+ create mode 100644 drivers/net/phy/qcom/ipq5018.c
+
+--- a/drivers/net/phy/qcom/Kconfig
++++ b/drivers/net/phy/qcom/Kconfig
+@@ -9,6 +9,12 @@ config AT803X_PHY
+ help
+ Currently supports the AR8030, AR8031, AR8033, AR8035 model
+
++config IPQ5018_PHY
++ tristate "Qualcomm IPQ5018 internal PHYs"
++ select QCOM_NET_PHYLIB
++ help
++ Currently supports the Qualcomm IPQ5018 internal PHY
++
+ config QCA83XX_PHY
+ tristate "Qualcomm Atheros QCA833x PHYs"
+ select QCOM_NET_PHYLIB
+--- a/drivers/net/phy/qcom/Makefile
++++ b/drivers/net/phy/qcom/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o
+ obj-$(CONFIG_AT803X_PHY) += at803x.o
++obj-$(CONFIG_IPQ5018_PHY) += ipq5018.o
+ obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o
+ obj-$(CONFIG_QCA808X_PHY) += qca808x.o
+ obj-$(CONFIG_QCA807X_PHY) += qca807x.o
+--- /dev/null
++++ b/drivers/net/phy/qcom/ipq5018.c
+@@ -0,0 +1,138 @@
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/phy.h>
++#include <linux/reset.h>
++
++#include "qcom.h"
++
++#define IPQ5018_PHY_ID 0x004dd0c0
++
++#define TX_RX_CLK_RATE 125000000 /* 125M */
++
++#define IPQ5018_PHY_FIFO_CONTROL 0x19
++#define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
++
++struct ipq5018_phy {
++ int num_clks;
++ struct clk_bulk_data *clks;
++ struct reset_control *rst;
++
++ struct clk_hw *clk_rx, *clk_tx;
++ struct clk_hw_onecell_data *clk_data;
++};
++
++static int ipq5018_probe(struct phy_device *phydev)
++{
++ struct ipq5018_phy *priv;
++ struct device *dev = &phydev->mdio.dev;
++ char name[64];
++ int ret;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return dev_err_probe(dev, -ENOMEM,
++ "failed to allocate priv\n");
++
++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
++ if (priv->num_clks < 0)
++ return dev_err_probe(dev, priv->num_clks,
++ "failed to acquire clocks\n");
++
++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
++ if (ret)
++ return dev_err_probe(dev, ret,
++ "failed to enable clocks\n");
++
++ priv->rst = devm_reset_control_array_get_exclusive(dev);
++ if (IS_ERR_OR_NULL(priv->rst))
++ return dev_err_probe(dev, PTR_ERR(priv->rst),
++ "failed to acquire reset\n");
++
++ ret = reset_control_reset(priv->rst);
++ if (ret)
++ return dev_err_probe(dev, ret,
++ "failed to reset\n");
++
++ snprintf(name, sizeof(name), "%s#rx", dev_name(dev));
++ priv->clk_rx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
++ TX_RX_CLK_RATE);
++ if (IS_ERR_OR_NULL(priv->clk_rx))
++ return dev_err_probe(dev, PTR_ERR(priv->clk_rx),
++ "failed to register rx clock\n");
++
++ snprintf(name, sizeof(name), "%s#tx", dev_name(dev));
++ priv->clk_tx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
++ TX_RX_CLK_RATE);
++ if (IS_ERR_OR_NULL(priv->clk_tx))
++ return dev_err_probe(dev, PTR_ERR(priv->clk_tx),
++ "failed to register tx clock\n");
++
++ priv->clk_data = devm_kzalloc(dev,
++ struct_size(priv->clk_data, hws, 2),
++ GFP_KERNEL);
++ if (!priv->clk_data)
++ return dev_err_probe(dev, -ENOMEM,
++ "failed to allocate clk_data\n");
++
++ priv->clk_data->num = 2;
++ priv->clk_data->hws[0] = priv->clk_rx;
++ priv->clk_data->hws[1] = priv->clk_tx;
++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
++ priv->clk_data);
++ if (ret)
++ return dev_err_probe(dev, ret,
++ "fail to register clock provider\n");
++
++ return 0;
++}
++
++static int ipq5018_soft_reset(struct phy_device *phydev)
++{
++ int ret;
++
++ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
++ IPQ5018_PHY_FIFO_RESET, 0);
++ if (ret < 0)
++ return ret;
++
++ msleep(50);
++
++ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
++ IPQ5018_PHY_FIFO_RESET, IPQ5018_PHY_FIFO_RESET);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static int ipq5018_cable_test_start(struct phy_device *phydev)
++{
++ /* we do all the (time consuming) work later */
++ return 0;
++}
++
++static struct phy_driver ipq5018_internal_phy_driver[] = {
++ {
++ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
++ .name = "Qualcomm IPQ5018 internal PHY",
++ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
++ .probe = ipq5018_probe,
++ .soft_reset = ipq5018_soft_reset,
++ .read_status = at803x_read_status,
++ .config_intr = at803x_config_intr,
++ .handle_interrupt = at803x_handle_interrupt,
++ .cable_test_start = ipq5018_cable_test_start,
++ .cable_test_get_status = qca808x_cable_test_get_status,
++ },
++};
++module_phy_driver(ipq5018_internal_phy_driver);
++
++static struct mdio_device_id __maybe_unused ipq5018_internal_phy_ids[] = {
++ { PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID) },
++ { }
++};
++MODULE_DEVICE_TABLE(mdio, ipq5018_internal_phy_ids);
++
++MODULE_DESCRIPTION("Qualcomm IPQ5018 internal PHY driver");
--- /dev/null
+From d2cdc83fb2c7360856e598810b88211d815fc851 Mon Sep 17 00:00:00 2001
+Date: Sun, 8 Sep 2024 16:40:12 +0800
+Subject: [PATCH 2/3] arm64: dts: qcom: ipq5018: add mdio node
+
+The IPQ5018 SoC contains two MDIO controllers. MDIO0 is used to control
+its internal GE Phy, while MDIO1 is wired to external PHYs/switch.
+
+---
+ arch/arm64/boot/dts/qcom/ipq5018.dtsi | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+@@ -192,6 +192,30 @@
+ status = "disabled";
+ };
+
++ mdio0: mdio@88000 {
++ compatible = "qcom,ipq5018-mdio", "qcom,qca-mdio";
++ reg = <0x00088000 0x64>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ clocks = <&gcc GCC_MDIO0_AHB_CLK>;
++ clock-names = "gcc_mdio_ahb_clk";
++
++ status = "disabled";
++ };
++
++ mdio1: mdio@90000 {
++ compatible = "qcom,ipq5018-mdio";
++ reg = <0x00090000 0x64>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ clocks = <&gcc GCC_MDIO1_AHB_CLK>;
++ clock-names = "gcc_mdio_ahb_clk";
++
++ status = "disabled";
++ };
++
+ cmn_pll: clock-controller@9b000 {
+ compatible = "qcom,ipq9574-cmn-pll";
+ reg = <0x0009b000 0x800>,
+++ /dev/null
-From 77ad12b3a5e21cae859247c0b82cf9a5b661e531 Mon Sep 17 00:00:00 2001
-Date: Sun, 8 Sep 2024 16:40:11 +0800
-Subject: [PATCH 1/3] net: phy: qcom: Introduce IPQ5018 internal PHY driver
-
-Introduce the internal GE PHY driver, part of the Qualcomm IPQ50xx SoC.
-The driver registers two clock providers needed and referenced by the GCC
-using DT properties and phandles.
-
----
- drivers/net/phy/qcom/Kconfig | 6 ++
- drivers/net/phy/qcom/Makefile | 1 +
- drivers/net/phy/qcom/ipq5018.c | 138 +++++++++++++++++++++++++++++++++
- 3 files changed, 145 insertions(+)
- create mode 100644 drivers/net/phy/qcom/ipq5018.c
-
---- a/drivers/net/phy/qcom/Kconfig
-+++ b/drivers/net/phy/qcom/Kconfig
-@@ -9,6 +9,12 @@ config AT803X_PHY
- help
- Currently supports the AR8030, AR8031, AR8033, AR8035 model
-
-+config IPQ5018_PHY
-+ tristate "Qualcomm IPQ5018 internal PHYs"
-+ select QCOM_NET_PHYLIB
-+ help
-+ Currently supports the Qualcomm IPQ5018 internal PHY
-+
- config QCA83XX_PHY
- tristate "Qualcomm Atheros QCA833x PHYs"
- select QCOM_NET_PHYLIB
---- a/drivers/net/phy/qcom/Makefile
-+++ b/drivers/net/phy/qcom/Makefile
-@@ -1,6 +1,7 @@
- # SPDX-License-Identifier: GPL-2.0
- obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o
- obj-$(CONFIG_AT803X_PHY) += at803x.o
-+obj-$(CONFIG_IPQ5018_PHY) += ipq5018.o
- obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o
- obj-$(CONFIG_QCA808X_PHY) += qca808x.o
- obj-$(CONFIG_QCA807X_PHY) += qca807x.o
---- /dev/null
-+++ b/drivers/net/phy/qcom/ipq5018.c
-@@ -0,0 +1,138 @@
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/phy.h>
-+#include <linux/reset.h>
-+
-+#include "qcom.h"
-+
-+#define IPQ5018_PHY_ID 0x004dd0c0
-+
-+#define TX_RX_CLK_RATE 125000000 /* 125M */
-+
-+#define IPQ5018_PHY_FIFO_CONTROL 0x19
-+#define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
-+
-+struct ipq5018_phy {
-+ int num_clks;
-+ struct clk_bulk_data *clks;
-+ struct reset_control *rst;
-+
-+ struct clk_hw *clk_rx, *clk_tx;
-+ struct clk_hw_onecell_data *clk_data;
-+};
-+
-+static int ipq5018_probe(struct phy_device *phydev)
-+{
-+ struct ipq5018_phy *priv;
-+ struct device *dev = &phydev->mdio.dev;
-+ char name[64];
-+ int ret;
-+
-+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return dev_err_probe(dev, -ENOMEM,
-+ "failed to allocate priv\n");
-+
-+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
-+ if (priv->num_clks < 0)
-+ return dev_err_probe(dev, priv->num_clks,
-+ "failed to acquire clocks\n");
-+
-+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
-+ if (ret)
-+ return dev_err_probe(dev, ret,
-+ "failed to enable clocks\n");
-+
-+ priv->rst = devm_reset_control_array_get_exclusive(dev);
-+ if (IS_ERR_OR_NULL(priv->rst))
-+ return dev_err_probe(dev, PTR_ERR(priv->rst),
-+ "failed to acquire reset\n");
-+
-+ ret = reset_control_reset(priv->rst);
-+ if (ret)
-+ return dev_err_probe(dev, ret,
-+ "failed to reset\n");
-+
-+ snprintf(name, sizeof(name), "%s#rx", dev_name(dev));
-+ priv->clk_rx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
-+ TX_RX_CLK_RATE);
-+ if (IS_ERR_OR_NULL(priv->clk_rx))
-+ return dev_err_probe(dev, PTR_ERR(priv->clk_rx),
-+ "failed to register rx clock\n");
-+
-+ snprintf(name, sizeof(name), "%s#tx", dev_name(dev));
-+ priv->clk_tx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
-+ TX_RX_CLK_RATE);
-+ if (IS_ERR_OR_NULL(priv->clk_tx))
-+ return dev_err_probe(dev, PTR_ERR(priv->clk_tx),
-+ "failed to register tx clock\n");
-+
-+ priv->clk_data = devm_kzalloc(dev,
-+ struct_size(priv->clk_data, hws, 2),
-+ GFP_KERNEL);
-+ if (!priv->clk_data)
-+ return dev_err_probe(dev, -ENOMEM,
-+ "failed to allocate clk_data\n");
-+
-+ priv->clk_data->num = 2;
-+ priv->clk_data->hws[0] = priv->clk_rx;
-+ priv->clk_data->hws[1] = priv->clk_tx;
-+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-+ priv->clk_data);
-+ if (ret)
-+ return dev_err_probe(dev, ret,
-+ "fail to register clock provider\n");
-+
-+ return 0;
-+}
-+
-+static int ipq5018_soft_reset(struct phy_device *phydev)
-+{
-+ int ret;
-+
-+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
-+ IPQ5018_PHY_FIFO_RESET, 0);
-+ if (ret < 0)
-+ return ret;
-+
-+ msleep(50);
-+
-+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
-+ IPQ5018_PHY_FIFO_RESET, IPQ5018_PHY_FIFO_RESET);
-+ if (ret < 0)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static int ipq5018_cable_test_start(struct phy_device *phydev)
-+{
-+ /* we do all the (time consuming) work later */
-+ return 0;
-+}
-+
-+static struct phy_driver ipq5018_internal_phy_driver[] = {
-+ {
-+ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
-+ .name = "Qualcomm IPQ5018 internal PHY",
-+ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
-+ .probe = ipq5018_probe,
-+ .soft_reset = ipq5018_soft_reset,
-+ .read_status = at803x_read_status,
-+ .config_intr = at803x_config_intr,
-+ .handle_interrupt = at803x_handle_interrupt,
-+ .cable_test_start = ipq5018_cable_test_start,
-+ .cable_test_get_status = qca808x_cable_test_get_status,
-+ },
-+};
-+module_phy_driver(ipq5018_internal_phy_driver);
-+
-+static struct mdio_device_id __maybe_unused ipq5018_internal_phy_ids[] = {
-+ { PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID) },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(mdio, ipq5018_internal_phy_ids);
-+
-+MODULE_DESCRIPTION("Qualcomm IPQ5018 internal PHY driver");
--- /dev/null
+From 28490d95fe9e059c5ce74b2289d66e0d7ede2d50 Mon Sep 17 00:00:00 2001
+Date: Sun, 8 Sep 2024 16:40:12 +0800
+Subject: [PATCH 3/3] arm64: dts: qcom: ipq5018: add ge_phy node
+
+Add the GE PHY node and register the output clocks in the GCC node.
+
+---
+ arch/arm64/boot/dts/qcom/ipq5018.dtsi | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+@@ -202,6 +202,21 @@
+ clock-names = "gcc_mdio_ahb_clk";
+
+ status = "disabled";
++
++ ge_phy: ethernet-phy@7 {
++ compatible = "ethernet-phy-id004d.d0c0";
++ reg = <7>;
++ clocks = <&gcc GCC_GEPHY_RX_CLK>,
++ <&gcc GCC_GEPHY_TX_CLK>;
++
++ resets = <&gcc GCC_GEPHY_BCR>,
++ <&gcc GCC_GEPHY_MDC_SW_ARES>,
++ <&gcc GCC_GEPHY_DSP_HW_ARES>,
++ <&gcc GCC_GEPHY_RX_ARES>,
++ <&gcc GCC_GEPHY_TX_ARES>;
++
++ #clock-cells = <1>;
++ };
+ };
+
+ mdio1: mdio@90000 {
+@@ -398,8 +413,8 @@
+ <&pcie0_phy>,
+ <&pcie1_phy>,
+ <0>,
+- <0>,
+- <0>,
++ <&ge_phy 0>,
++ <&ge_phy 1>,
+ <0>,
+ <0>;
+ #clock-cells = <1>;
+++ /dev/null
-Date: Sun, 19 Jan 2025 11:25:27 +0400
-Subject: [PATCH] net: phy: qcom: ipq5018 enable configuration of DAC settings
-
-Allow setting amplitude and bias current as needed on the IPQ5018 Internal
-GE PHY. When the "qcom,dac" property is set in the DTS, the driver expects
-a pair of u32 values:
-
-(from QCA8337 datasheet)
-11: follow DSP setting
-10: bypass half amplitude and follow DSP half bias current
-01: half amplitude follow DSP and bypass half bias current
-00: full amplitude and full bias current
-
----
---- a/drivers/net/phy/qcom/ipq5018.c
-+++ b/drivers/net/phy/qcom/ipq5018.c
-@@ -13,6 +13,10 @@
- #define IPQ5018_PHY_FIFO_CONTROL 0x19
- #define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
-
-+#define IPQ5018_PHY_DEBUG_EDAC 0x4380
-+#define IPQ5018_PHY_MMD1_MDAC 0x8100
-+#define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
-+
- struct ipq5018_phy {
- int num_clks;
- struct clk_bulk_data *clks;
-@@ -20,20 +24,35 @@ struct ipq5018_phy {
-
- struct clk_hw *clk_rx, *clk_tx;
- struct clk_hw_onecell_data *clk_data;
-+
-+ u32 mdac;
-+ u32 edac;
- };
-
- static int ipq5018_probe(struct phy_device *phydev)
- {
-- struct ipq5018_phy *priv;
- struct device *dev = &phydev->mdio.dev;
-+ struct ipq5018_phy *priv;
-+ u32 mdac, edac = 0;
- char name[64];
-- int ret;
-+ int ret, cnt;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return dev_err_probe(dev, -ENOMEM,
- "failed to allocate priv\n");
-
-+ cnt = of_property_count_u32_elems(dev->of_node, "qcom,dac");
-+ if (cnt == 2) {
-+ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 0, &mdac);
-+ if (!ret)
-+ priv->mdac = mdac;
-+
-+ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 1, &edac);
-+ if (!ret)
-+ priv->edac = edac;
-+ }
-+
- priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
- if (priv->num_clks < 0)
- return dev_err_probe(dev, priv->num_clks,
-@@ -84,6 +103,8 @@ static int ipq5018_probe(struct phy_devi
- return dev_err_probe(dev, ret,
- "fail to register clock provider\n");
-
-+ phydev->priv = priv;
-+
- return 0;
- }
-
-@@ -112,12 +133,34 @@ static int ipq5018_cable_test_start(stru
- return 0;
- }
-
-+static int ipq5018_config_init(struct phy_device *phydev)
-+{
-+ struct ipq5018_phy *priv = phydev->priv;
-+ int ret;
-+
-+ /* setting mdac in MMD1 */
-+ if (priv->mdac) {
-+ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
-+ IPQ5018_PHY_DAC_MASK, priv->mdac);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ /* setting edac in debug register */
-+ if (priv->edac)
-+ return at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
-+ IPQ5018_PHY_DAC_MASK, priv->edac);
-+
-+ return 0;
-+}
-+
- static struct phy_driver ipq5018_internal_phy_driver[] = {
- {
- PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
- .name = "Qualcomm IPQ5018 internal PHY",
- .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
- .probe = ipq5018_probe,
-+ .config_init = ipq5018_config_init,
- .soft_reset = ipq5018_soft_reset,
- .read_status = at803x_read_status,
- .config_intr = at803x_config_intr,
--- /dev/null
+Date: Sun, 19 Jan 2025 11:25:27 +0400
+Subject: [PATCH] net: phy: qcom: ipq5018 enable configuration of DAC settings
+
+Allow setting amplitude and bias current as needed on the IPQ5018 Internal
+GE PHY. When the "qcom,dac" property is set in the DTS, the driver expects
+a pair of u32 values:
+
+(from QCA8337 datasheet)
+11: follow DSP setting
+10: bypass half amplitude and follow DSP half bias current
+01: half amplitude follow DSP and bypass half bias current
+00: full amplitude and full bias current
+
+---
+--- a/drivers/net/phy/qcom/ipq5018.c
++++ b/drivers/net/phy/qcom/ipq5018.c
+@@ -13,6 +13,10 @@
+ #define IPQ5018_PHY_FIFO_CONTROL 0x19
+ #define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
+
++#define IPQ5018_PHY_DEBUG_EDAC 0x4380
++#define IPQ5018_PHY_MMD1_MDAC 0x8100
++#define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
++
+ struct ipq5018_phy {
+ int num_clks;
+ struct clk_bulk_data *clks;
+@@ -20,20 +24,35 @@ struct ipq5018_phy {
+
+ struct clk_hw *clk_rx, *clk_tx;
+ struct clk_hw_onecell_data *clk_data;
++
++ u32 mdac;
++ u32 edac;
+ };
+
+ static int ipq5018_probe(struct phy_device *phydev)
+ {
+- struct ipq5018_phy *priv;
+ struct device *dev = &phydev->mdio.dev;
++ struct ipq5018_phy *priv;
++ u32 mdac, edac = 0;
+ char name[64];
+- int ret;
++ int ret, cnt;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to allocate priv\n");
+
++ cnt = of_property_count_u32_elems(dev->of_node, "qcom,dac");
++ if (cnt == 2) {
++ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 0, &mdac);
++ if (!ret)
++ priv->mdac = mdac;
++
++ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 1, &edac);
++ if (!ret)
++ priv->edac = edac;
++ }
++
+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
+ if (priv->num_clks < 0)
+ return dev_err_probe(dev, priv->num_clks,
+@@ -84,6 +103,8 @@ static int ipq5018_probe(struct phy_devi
+ return dev_err_probe(dev, ret,
+ "fail to register clock provider\n");
+
++ phydev->priv = priv;
++
+ return 0;
+ }
+
+@@ -112,12 +133,34 @@ static int ipq5018_cable_test_start(stru
+ return 0;
+ }
+
++static int ipq5018_config_init(struct phy_device *phydev)
++{
++ struct ipq5018_phy *priv = phydev->priv;
++ int ret;
++
++ /* setting mdac in MMD1 */
++ if (priv->mdac) {
++ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
++ IPQ5018_PHY_DAC_MASK, priv->mdac);
++ if (ret)
++ return ret;
++ }
++
++ /* setting edac in debug register */
++ if (priv->edac)
++ return at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
++ IPQ5018_PHY_DAC_MASK, priv->edac);
++
++ return 0;
++}
++
+ static struct phy_driver ipq5018_internal_phy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
+ .name = "Qualcomm IPQ5018 internal PHY",
+ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
+ .probe = ipq5018_probe,
++ .config_init = ipq5018_config_init,
+ .soft_reset = ipq5018_soft_reset,
+ .read_status = at803x_read_status,
+ .config_intr = at803x_config_intr,
+++ /dev/null
-Date: Fri, 24 Jan 2025 17:18:12 +0400
-Subject: [PATCH] net: phy: qcom: add IPQ5018 initvals and CDT feature
-
-The Cable Diagnostics Test for IPQ5018 follows the same logic as qca808x.
-However, the IPQ5018 GE PHY has its own threshold values. So let's set the
-CDT thresholds for the IPQ5018 internal GE PHY. While add it, add and set
-thesholds for MSE for signal quality measurement and 8023az for EEE.
-
----
---- a/drivers/net/phy/qcom/ipq5018.c
-+++ b/drivers/net/phy/qcom/ipq5018.c
-@@ -17,6 +17,38 @@
- #define IPQ5018_PHY_MMD1_MDAC 0x8100
- #define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
-
-+#define IPQ5018_PHY_MMD1_MSE_THRESH1 0x1000
-+#define IPQ5018_PHY_MMD1_MSE_THRESH2 0x1001
-+#define IPQ5018_PHY_MMD3_AZ_CTRL1 0x8008
-+#define IPQ5018_PHY_MMD3_AZ_CTRL2 0x8009
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3 0x8074
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4 0x8075
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5 0x8076
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6 0x8077
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7 0x8078
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9 0x807a
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13 0x807e
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL14 0x807f
-+
-+#define IPQ5018_PHY_MMD1_MSE_THRESH1_VAL 0xf1
-+#define IPQ5018_PHY_MMD1_MSE_THRESH2_VAL 0x1f6
-+#define IPQ5018_PHY_MMD3_AZ_CTRL1_VAL 0x7880
-+#define IPQ5018_PHY_MMD3_AZ_CTRL2_VAL 0xc8
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL 0xc040
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL 0xa060
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL 0xc040
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL 0xa060
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL 0xc24c
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL 0xc060
-+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL 0xb060
-+#define IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL 0x90b0
-+
-+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE 0x1
-+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK GENMASK(7,4)
-+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT 0x50
-+
-+#define IPQ5018_PHY_DEBUG_ANA_DAC_FILTER 0xa080
-+
- struct ipq5018_phy {
- int num_clks;
- struct clk_bulk_data *clks;
-@@ -129,6 +161,24 @@ static int ipq5018_soft_reset(struct phy
-
- static int ipq5018_cable_test_start(struct phy_device *phydev)
- {
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13,
-+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
-+ IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
-+
- /* we do all the (time consuming) work later */
- return 0;
- }
-@@ -136,8 +186,30 @@ static int ipq5018_cable_test_start(stru
- static int ipq5018_config_init(struct phy_device *phydev)
- {
- struct ipq5018_phy *priv = phydev->priv;
-+ u16 val = 0;
- int ret;
-
-+ /* set LDO efuse: first temporarily store ANA_DAC_FILTER value from
-+ debug register as it will be reset once the ANA_LDO_EFUSE register
-+ is written to */
-+ val = at803x_debug_reg_read(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER);
-+ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE,
-+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK,
-+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT);
-+ at803x_debug_reg_write(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER, val);
-+
-+ /* set 8023AZ CTRL values */
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL1,
-+ IPQ5018_PHY_MMD3_AZ_CTRL1_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL2,
-+ IPQ5018_PHY_MMD3_AZ_CTRL2_VAL);
-+
-+ /* set MSE threshold values */
-+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH1,
-+ IPQ5018_PHY_MMD1_MSE_THRESH1_VAL);
-+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH2,
-+ IPQ5018_PHY_MMD1_MSE_THRESH2_VAL);
-+
- /* setting mdac in MMD1 */
- if (priv->mdac) {
- ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
+++ /dev/null
-From f71366e0530db2c5cecbbbb6edfbf7344bd6f83b Mon Sep 17 00:00:00 2001
-Date: Sun, 8 Sep 2024 16:40:12 +0800
-Subject: [PATCH] clk: gcc-ipq5018: remove the unsupported clk
- combination for gmac
-
-Comment out the unsupported clock combination in the frequency table
-for GMAC1.
-
----
- drivers/clk/qcom/gcc-ipq5018.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/clk/qcom/gcc-ipq5018.c
-+++ b/drivers/clk/qcom/gcc-ipq5018.c
-@@ -677,7 +677,7 @@ static const struct freq_tbl ftbl_gmac1_
- F(2500000, P_UNIPHY_RX, 12.5, 0, 0),
- F(24000000, P_XO, 1, 0, 0),
- F(25000000, P_UNIPHY_RX, 2.5, 0, 0),
-- F(125000000, P_UNIPHY_RX, 2.5, 0, 0),
-+ /* F(125000000, P_UNIPHY_RX, 2.5, 0, 0), */
- F(125000000, P_UNIPHY_RX, 1, 0, 0),
- F(312500000, P_UNIPHY_RX, 1, 0, 0),
- { }
-@@ -717,7 +717,7 @@ static const struct freq_tbl ftbl_gmac1_
- F(2500000, P_UNIPHY_TX, 12.5, 0, 0),
- F(24000000, P_XO, 1, 0, 0),
- F(25000000, P_UNIPHY_TX, 2.5, 0, 0),
-- F(125000000, P_UNIPHY_TX, 2.5, 0, 0),
-+ /* F(125000000, P_UNIPHY_TX, 2.5, 0, 0), */
- F(125000000, P_UNIPHY_TX, 1, 0, 0),
- F(312500000, P_UNIPHY_TX, 1, 0, 0),
- { }
--- /dev/null
+Date: Fri, 24 Jan 2025 17:18:12 +0400
+Subject: [PATCH] net: phy: qcom: add IPQ5018 initvals and CDT feature
+
+The Cable Diagnostics Test for IPQ5018 follows the same logic as qca808x.
+However, the IPQ5018 GE PHY has its own threshold values. So let's set the
+CDT thresholds for the IPQ5018 internal GE PHY. While add it, add and set
+thesholds for MSE for signal quality measurement and 8023az for EEE.
+
+---
+--- a/drivers/net/phy/qcom/ipq5018.c
++++ b/drivers/net/phy/qcom/ipq5018.c
+@@ -17,6 +17,38 @@
+ #define IPQ5018_PHY_MMD1_MDAC 0x8100
+ #define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
+
++#define IPQ5018_PHY_MMD1_MSE_THRESH1 0x1000
++#define IPQ5018_PHY_MMD1_MSE_THRESH2 0x1001
++#define IPQ5018_PHY_MMD3_AZ_CTRL1 0x8008
++#define IPQ5018_PHY_MMD3_AZ_CTRL2 0x8009
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3 0x8074
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4 0x8075
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5 0x8076
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6 0x8077
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7 0x8078
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9 0x807a
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13 0x807e
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL14 0x807f
++
++#define IPQ5018_PHY_MMD1_MSE_THRESH1_VAL 0xf1
++#define IPQ5018_PHY_MMD1_MSE_THRESH2_VAL 0x1f6
++#define IPQ5018_PHY_MMD3_AZ_CTRL1_VAL 0x7880
++#define IPQ5018_PHY_MMD3_AZ_CTRL2_VAL 0xc8
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL 0xc040
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL 0xa060
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL 0xc040
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL 0xa060
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL 0xc24c
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL 0xc060
++#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL 0xb060
++#define IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL 0x90b0
++
++#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE 0x1
++#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK GENMASK(7,4)
++#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT 0x50
++
++#define IPQ5018_PHY_DEBUG_ANA_DAC_FILTER 0xa080
++
+ struct ipq5018_phy {
+ int num_clks;
+ struct clk_bulk_data *clks;
+@@ -129,6 +161,24 @@ static int ipq5018_soft_reset(struct phy
+
+ static int ipq5018_cable_test_start(struct phy_device *phydev)
+ {
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13,
++ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
++ IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
++
+ /* we do all the (time consuming) work later */
+ return 0;
+ }
+@@ -136,8 +186,30 @@ static int ipq5018_cable_test_start(stru
+ static int ipq5018_config_init(struct phy_device *phydev)
+ {
+ struct ipq5018_phy *priv = phydev->priv;
++ u16 val = 0;
+ int ret;
+
++ /* set LDO efuse: first temporarily store ANA_DAC_FILTER value from
++ debug register as it will be reset once the ANA_LDO_EFUSE register
++ is written to */
++ val = at803x_debug_reg_read(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER);
++ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE,
++ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK,
++ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT);
++ at803x_debug_reg_write(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER, val);
++
++ /* set 8023AZ CTRL values */
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL1,
++ IPQ5018_PHY_MMD3_AZ_CTRL1_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL2,
++ IPQ5018_PHY_MMD3_AZ_CTRL2_VAL);
++
++ /* set MSE threshold values */
++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH1,
++ IPQ5018_PHY_MMD1_MSE_THRESH1_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH2,
++ IPQ5018_PHY_MMD1_MSE_THRESH2_VAL);
++
+ /* setting mdac in MMD1 */
+ if (priv->mdac) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
+++ /dev/null
-From ce9e56a436e486690097cfbdda2d0c11b60db4c2 Mon Sep 17 00:00:00 2001
-Date: Sun, 8 Sep 2024 16:40:12 +0800
-Subject: [PATCH] clk: gcc-ipq5018: refer to GE PHY rx and tx clk providers by name
-
-QCA-SSDK does not register the output clocks of the onboard GE Phy and
-uniphy so the GCC and DTS can't reference them by their index.
-The SSDK references them by name, so let's change the GCC driver
-accordingly.
-
----
- drivers/clk/qcom/gcc-ipq5018.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
---- a/drivers/clk/qcom/gcc-ipq5018.c
-+++ b/drivers/clk/qcom/gcc-ipq5018.c
-@@ -335,8 +335,8 @@ static const struct parent_map gcc_xo_gp
-
- static const struct clk_parent_data gcc_xo_gephy_gcc_rx_gephy_gcc_tx_ubi32_pll_gpll0[] = {
- { .index = DT_XO },
-- { .index = DT_GEPHY_RX_CLK },
-- { .index = DT_GEPHY_TX_CLK },
-+ { .name = "gephy_gcc_rx", .index = -1 },
-+ { .name = "gephy_gcc_tx", .index = -1 },
- { .hw = &ubi32_pll.clkr.hw },
- { .hw = &gpll0.clkr.hw },
- };
-@@ -351,8 +351,8 @@ static const struct parent_map gcc_xo_ge
-
- static const struct clk_parent_data gcc_xo_gephy_gcc_tx_gephy_gcc_rx_ubi32_pll_gpll0[] = {
- { .index = DT_XO },
-- { .index = DT_GEPHY_TX_CLK },
-- { .index = DT_GEPHY_RX_CLK },
-+ { .name = "gephy_gcc_tx", .index = -1 },
-+ { .name = "gephy_gcc_rx", .index = -1 },
- { .hw = &ubi32_pll.clkr.hw },
- { .hw = &gpll0.clkr.hw },
- };
-@@ -367,8 +367,8 @@ static const struct parent_map gcc_xo_ge
-
- static const struct clk_parent_data gcc_xo_uniphy_gcc_rx_uniphy_gcc_tx_ubi32_pll_gpll0[] = {
- { .index = DT_XO },
-- { .index = DT_UNIPHY_RX_CLK },
-- { .index = DT_UNIPHY_TX_CLK },
-+ { .name = "uniphy_gcc_rx", .index = -1 },
-+ { .name = "uniphy_gcc_tx", .index = -1 },
- { .hw = &ubi32_pll.clkr.hw },
- { .hw = &gpll0.clkr.hw },
- };
-@@ -383,8 +383,8 @@ static const struct parent_map gcc_xo_un
-
- static const struct clk_parent_data gcc_xo_uniphy_gcc_tx_uniphy_gcc_rx_ubi32_pll_gpll0[] = {
- { .index = DT_XO },
-- { .index = DT_UNIPHY_TX_CLK },
-- { .index = DT_UNIPHY_RX_CLK },
-+ { .name = "uniphy_gcc_tx", .index = -1 },
-+ { .name = "uniphy_gcc_rx", .index = -1 },
- { .hw = &ubi32_pll.clkr.hw },
- { .hw = &gpll0.clkr.hw },
- };
+++ /dev/null
-Date: Tue, 29 Apr 2025 17:16:31 +0400
-Subject: [PATCH] clk: qcom: gcc-ipq5018: fix GE_PHY and Uniphy resets
-
-The resets for the GE PHY and Uniphy use bitmasks to assert multiple
-resets simultaneously. These bitmasks are missing and the reset is only
-performed partially against BIT(x) where x is the bit set in the GCC.
-So let's remove the single bit and replace them by the bitmasks as
-intended.
-
-Link: https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/00743c3e82fa87cba4460e7a2ba32f473a9ce932
-Link: https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/036bdc62aca561e8ff94a29c447fc400de2b7304
-
----
---- a/drivers/clk/qcom/gcc-ipq5018.c
-+++ b/drivers/clk/qcom/gcc-ipq5018.c
-@@ -3566,7 +3566,7 @@ static const struct qcom_reset_map gcc_i
- [GCC_DDRSS_BCR] = { 0x1e000, 0 },
- [GCC_EDPD_BCR] = { 0x3a000, 0 },
- [GCC_GEPHY_BCR] = { 0x56000, 0 },
-- [GCC_GEPHY_MDC_SW_ARES] = { 0x56004, 0 },
-+ [GCC_GEPHY_MDC_SW_ARES] = { 0x56004, .bitmask = 0x3 },
- [GCC_GEPHY_DSP_HW_ARES] = { 0x56004, 1 },
- [GCC_GEPHY_RX_ARES] = { 0x56004, 2 },
- [GCC_GEPHY_TX_ARES] = { 0x56004, 3 },
-@@ -3646,7 +3646,7 @@ static const struct qcom_reset_map gcc_i
- [GCC_UNIPHY_SYS_ARES] = { 0x56104, 1 },
- [GCC_UNIPHY_RX_ARES] = { 0x56104, 4 },
- [GCC_UNIPHY_TX_ARES] = { 0x56104, 5 },
-- [GCC_UNIPHY_SOFT_RESET] = {0x56104, 0 },
-+ [GCC_UNIPHY_SOFT_RESET] = {0x56104, .bitmask = 0x32 },
- [GCC_USB0_BCR] = { 0x3e070, 0 },
- [GCC_USB0_PHY_BCR] = { 0x3e034, 0 },
- [GCC_WCSS_BCR] = { 0x18000, 0 },
-@@ -3659,7 +3659,7 @@ static const struct qcom_reset_map gcc_i
- [GCC_WCSS_AXI_S_ARES] = { 0x59008, 6 },
- [GCC_WCSS_Q6_BCR] = { 0x18004, 0 },
- [GCC_WCSSAON_RESET] = { 0x59010, 0},
-- [GCC_GEPHY_MISC_ARES] = { 0x56004, 0 },
-+ [GCC_GEPHY_MISC_ARES] = { 0x56004, .bitmask = 0xf },
- };
-
- static const struct of_device_id gcc_ipq5018_match_table[] = {
+++ /dev/null
-From 28490d95fe9e059c5ce74b2289d66e0d7ede2d50 Mon Sep 17 00:00:00 2001
-Date: Sun, 8 Sep 2024 16:40:12 +0800
-Subject: [PATCH 3/3] arm64: dts: qcom: ipq5018: add ge_phy node
-
-Add the GE PHY node and register the output clocks in the GCC node.
-
----
- arch/arm64/boot/dts/qcom/ipq5018.dtsi | 16 ++++++++++++++--
- 1 file changed, 14 insertions(+), 2 deletions(-)
-
---- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-@@ -202,6 +202,19 @@
- clock-names = "gcc_mdio_ahb_clk";
-
- status = "disabled";
-+
-+ ge_phy: ethernet-phy@7 {
-+ compatible = "ethernet-phy-id004d.d0c0";
-+ reg = <7>;
-+
-+ clocks = <&gcc GCC_GEPHY_RX_CLK>,
-+ <&gcc GCC_GEPHY_TX_CLK>;
-+
-+ resets = <&gcc GCC_GEPHY_BCR>,
-+ <&gcc GCC_GEPHY_MISC_ARES>;
-+
-+ #clock-cells = <1>;
-+ };
- };
-
- mdio1: mdio@90000 {
-@@ -398,8 +411,8 @@
- <&pcie0_phy>,
- <&pcie1_phy>,
- <0>,
-- <0>,
-- <0>,
-+ <&ge_phy 0>,
-+ <&ge_phy 1>,
- <0>,
- <0>;
- #clock-cells = <1>;
--- /dev/null
+From f71366e0530db2c5cecbbbb6edfbf7344bd6f83b Mon Sep 17 00:00:00 2001
+Date: Sun, 8 Sep 2024 16:40:12 +0800
+Subject: [PATCH 1/2] clk: gcc-ipq5018: remove the unsupported clk
+ combination for gmac
+
+Comment out the unsupported clock combination in the frequency table
+for GMAC1.
+
+---
+ drivers/clk/qcom/gcc-ipq5018.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/qcom/gcc-ipq5018.c
++++ b/drivers/clk/qcom/gcc-ipq5018.c
+@@ -677,7 +677,7 @@ static const struct freq_tbl ftbl_gmac1_
+ F(2500000, P_UNIPHY_RX, 12.5, 0, 0),
+ F(24000000, P_XO, 1, 0, 0),
+ F(25000000, P_UNIPHY_RX, 2.5, 0, 0),
+- F(125000000, P_UNIPHY_RX, 2.5, 0, 0),
++ /* F(125000000, P_UNIPHY_RX, 2.5, 0, 0), */
+ F(125000000, P_UNIPHY_RX, 1, 0, 0),
+ F(312500000, P_UNIPHY_RX, 1, 0, 0),
+ { }
+@@ -717,7 +717,7 @@ static const struct freq_tbl ftbl_gmac1_
+ F(2500000, P_UNIPHY_TX, 12.5, 0, 0),
+ F(24000000, P_XO, 1, 0, 0),
+ F(25000000, P_UNIPHY_TX, 2.5, 0, 0),
+- F(125000000, P_UNIPHY_TX, 2.5, 0, 0),
++ /* F(125000000, P_UNIPHY_TX, 2.5, 0, 0), */
+ F(125000000, P_UNIPHY_TX, 1, 0, 0),
+ F(312500000, P_UNIPHY_TX, 1, 0, 0),
+ { }
--- /dev/null
+From ce9e56a436e486690097cfbdda2d0c11b60db4c2 Mon Sep 17 00:00:00 2001
+Date: Sun, 8 Sep 2024 16:40:12 +0800
+Subject: [PATCH] clk: gcc-ipq5018: refer to GE PHY rx and tx clk providers by name
+
+QCA-SSDK does not register the output clocks of the onboard GE Phy and
+uniphy so the GCC and DTS can't reference them by their index.
+The SSDK references them by name, so let's change the GCC driver
+accordingly.
+
+---
+ drivers/clk/qcom/gcc-ipq5018.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/qcom/gcc-ipq5018.c
++++ b/drivers/clk/qcom/gcc-ipq5018.c
+@@ -335,8 +335,8 @@ static const struct parent_map gcc_xo_gp
+
+ static const struct clk_parent_data gcc_xo_gephy_gcc_rx_gephy_gcc_tx_ubi32_pll_gpll0[] = {
+ { .index = DT_XO },
+- { .index = DT_GEPHY_RX_CLK },
+- { .index = DT_GEPHY_TX_CLK },
++ { .name = "gephy_gcc_rx", .index = -1 },
++ { .name = "gephy_gcc_tx", .index = -1 },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ };
+@@ -351,8 +351,8 @@ static const struct parent_map gcc_xo_ge
+
+ static const struct clk_parent_data gcc_xo_gephy_gcc_tx_gephy_gcc_rx_ubi32_pll_gpll0[] = {
+ { .index = DT_XO },
+- { .index = DT_GEPHY_TX_CLK },
+- { .index = DT_GEPHY_RX_CLK },
++ { .name = "gephy_gcc_tx", .index = -1 },
++ { .name = "gephy_gcc_rx", .index = -1 },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ };
+@@ -367,8 +367,8 @@ static const struct parent_map gcc_xo_ge
+
+ static const struct clk_parent_data gcc_xo_uniphy_gcc_rx_uniphy_gcc_tx_ubi32_pll_gpll0[] = {
+ { .index = DT_XO },
+- { .index = DT_UNIPHY_RX_CLK },
+- { .index = DT_UNIPHY_TX_CLK },
++ { .name = "uniphy_gcc_rx", .index = -1 },
++ { .name = "uniphy_gcc_tx", .index = -1 },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ };
+@@ -383,8 +383,8 @@ static const struct parent_map gcc_xo_un
+
+ static const struct clk_parent_data gcc_xo_uniphy_gcc_tx_uniphy_gcc_rx_ubi32_pll_gpll0[] = {
+ { .index = DT_XO },
+- { .index = DT_UNIPHY_TX_CLK },
+- { .index = DT_UNIPHY_RX_CLK },
++ { .name = "uniphy_gcc_tx", .index = -1 },
++ { .name = "uniphy_gcc_rx", .index = -1 },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ };
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-@@ -697,6 +697,225 @@
+@@ -699,6 +699,225 @@
};
};