// IPQ5018 GE Phy -> QCA8337 PHY4
&ge_phy {
- qcom,dac = <0x10 0x10>;
+ qcom,dac-preset-short-cable;
};
&mdio1 {
sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
-@@ -182,6 +188,19 @@
+@@ -182,6 +188,17 @@
status = "disabled";
};
+ cmn_pll: clock-controller@9b000 {
+ compatible = "qcom,ipq9574-cmn-pll";
-+ reg = <0x0009b000 0x800>,
-+ <0x19475c4 0x4>;
-+ reg-names = "cmn",
-+ "tcsr";
++ reg = <0x0009b000 0x800>;
++ reg-names = "cmn";
+ clocks = <&cmn_pll_ref_clk>,
+ <&gcc GCC_CMN_BLK_AHB_CLK>,
+ <&gcc GCC_CMN_BLK_SYS_CLK>;
--- /dev/null
+From 19600588e6403ff9f6c1e985fc025afb9160a56f Mon Sep 17 00:00:00 2001
+From: George Moussalem <george.moussalem@outlook.com>
+Date: Wed, 28 May 2025 08:37:25 +0400
+Subject: [PATCH v2 2/5] clk: qcom: gcc-ipq5018: fix GE PHY reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+Message-Id: <20250528-ipq5018-ge-phy-v2-2-68fc3a8248dd@outlook.com>
+
+The MISC reset is supposed to trigger a resets across the MDC, DSP, and
+RX & TX clocks of the IPQ5018 internal GE PHY. So let's set the bitmask
+of the reset definition accordingly in the GCC as per the downstream
+driver.
+
+Link: https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/00743c3e82fa87cba4460e7a2ba32f473a9ce932
+
+Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+---
+ drivers/clk/qcom/gcc-ipq5018.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/clk/qcom/gcc-ipq5018.c
++++ b/drivers/clk/qcom/gcc-ipq5018.c
+@@ -3660,7 +3660,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 = GENMASK(3, 0) },
+ };
+
+ static const struct of_device_id gcc_ipq5018_match_table[] = {
+++ /dev/null
-From 77ad12b3a5e21cae859247c0b82cf9a5b661e531 Mon Sep 17 00:00:00 2001
-From: Ziyang Huang <hzyitc@outlook.com>
-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.
-
-Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
- 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");
-+MODULE_AUTHOR("Ziyang Huang <hzyitc@outlook.com>");
+++ /dev/null
-From d2cdc83fb2c7360856e598810b88211d815fc851 Mon Sep 17 00:00:00 2001
-From: Ziyang Huang <hzyitc@outlook.com>
-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.
-
-Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
- 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
-@@ -188,6 +188,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 9a89cb300c1ed5b90bae5684c88c85895a15c849 Mon Sep 17 00:00:00 2001
+From: George Moussalem <george.moussalem@outlook.com>
+Date: Mon, 02 Jun 2025 12:50:39 +0400
+Subject: [PATCH v3 3/5] net: phy: qcom: at803x: Add Qualcomm IPQ5018 Internal PHY support
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+Message-Id: <20250602-ipq5018-ge-phy-v3-3-0d8f39f402a6@outlook.com>
+
+The IPQ5018 SoC contains a single internal Gigabit Ethernet PHY which
+provides an MDI interface directly to an RJ45 connector or an external
+switch over a PHY to PHY link.
+
+The PHY supports 10/100/1000 mbps link modes, CDT, auto-negotiation and
+802.3az EEE.
+
+Let's add support for this PHY in the at803x driver as it falls within
+the Qualcomm Atheros OUI.
+
+Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+---
+ drivers/net/phy/qcom/Kconfig | 2 +-
+ drivers/net/phy/qcom/at803x.c | 185 ++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 178 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/phy/qcom/Kconfig
++++ b/drivers/net/phy/qcom/Kconfig
+@@ -7,7 +7,7 @@ config AT803X_PHY
+ select QCOM_NET_PHYLIB
+ depends on REGULATOR
+ help
+- Currently supports the AR8030, AR8031, AR8033, AR8035 model
++ Currently supports the AR8030, AR8031, AR8033, AR8035, IPQ5018 model
+
+ config QCA83XX_PHY
+ tristate "Qualcomm Atheros QCA833x PHYs"
+--- a/drivers/net/phy/qcom/at803x.c
++++ b/drivers/net/phy/qcom/at803x.c
+@@ -7,19 +7,24 @@
+ * Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
+ */
+
+-#include <linux/phy.h>
+-#include <linux/module.h>
+-#include <linux/string.h>
+-#include <linux/netdevice.h>
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
+ #include <linux/etherdevice.h>
+ #include <linux/ethtool_netlink.h>
+-#include <linux/bitfield.h>
+-#include <linux/regulator/of_regulator.h>
+-#include <linux/regulator/driver.h>
+-#include <linux/regulator/consumer.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/netdevice.h>
+ #include <linux/of.h>
++#include <linux/phy.h>
+ #include <linux/phylink.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/regulator/driver.h>
++#include <linux/regulator/of_regulator.h>
++#include <linux/reset.h>
+ #include <linux/sfp.h>
++#include <linux/string.h>
+ #include <dt-bindings/net/qca-ar803x.h>
+
+ #include "qcom.h"
+@@ -96,6 +101,8 @@
+ #define ATH8035_PHY_ID 0x004dd072
+ #define AT8030_PHY_ID_MASK 0xffffffef
+
++#define IPQ5018_PHY_ID 0x004dd0c0
++
+ #define QCA9561_PHY_ID 0x004dd042
+
+ #define AT803X_PAGE_FIBER 0
+@@ -108,6 +115,50 @@
+ /* disable hibernation mode */
+ #define AT803X_DISABLE_HIBERNATION_MODE BIT(2)
+
++#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)
++
++/* MDAC and EDAC values for short cable length */
++#define IPQ5018_PHY_DEBUG_EDAC_VAL 0x10
++#define IPQ5018_PHY_MMD1_MDAC_VAL 0x10
++
++#define IPQ5018_PHY_MMD1_MSE_THRESH1 0x1000
++#define IPQ5018_PHY_MMD1_MSE_THRESH2 0x1001
++#define IPQ5018_PHY_PCS_AZ_CTRL1 0x8008
++#define IPQ5018_PHY_PCS_AZ_CTRL2 0x8009
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL3 0x8074
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL4 0x8075
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL5 0x8076
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL6 0x8077
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL7 0x8078
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL9 0x807a
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL13 0x807e
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL14 0x807f
++
++#define IPQ5018_PHY_MMD1_MSE_THRESH1_VAL 0xf1
++#define IPQ5018_PHY_MMD1_MSE_THRESH2_VAL 0x1f6
++#define IPQ5018_PHY_PCS_AZ_CTRL1_VAL 0x7880
++#define IPQ5018_PHY_PCS_AZ_CTRL2_VAL 0xc8
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL3_VAL 0xc040
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL4_VAL 0xa060
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL5_VAL 0xc040
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL6_VAL 0xa060
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL7_VAL 0xc24c
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL9_VAL 0xc060
++#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL13_VAL 0xb060
++#define IPQ5018_PHY_PCS_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
++
++#define IPQ5018_TCSR_ETH_LDO_READY BIT(0)
++
+ MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
+ MODULE_AUTHOR("Matus Ujhelyi");
+ MODULE_LICENSE("GPL");
+@@ -133,6 +184,11 @@ struct at803x_context {
+ u16 led_control;
+ };
+
++struct ipq5018_priv {
++ struct reset_control *rst;
++ bool set_short_cable_dac;
++};
++
+ static int at803x_write_page(struct phy_device *phydev, int page)
+ {
+ int mask;
+@@ -987,6 +1043,105 @@ static int at8035_probe(struct phy_devic
+ return at8035_parse_dt(phydev);
+ }
+
++static int ipq5018_cable_test_start(struct phy_device *phydev)
++{
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL3,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL3_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL4,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL4_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL5,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL5_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL6,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL6_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL7,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL7_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL9,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL9_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL13,
++ IPQ5018_PHY_PCS_CDT_THRESH_CTRL13_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL3,
++ IPQ5018_PHY_PCS_NEAR_ECHO_THRESH_VAL);
++
++ /* we do all the (time consuming) work later */
++ return 0;
++}
++
++static int ipq5018_config_init(struct phy_device *phydev)
++{
++ struct ipq5018_priv *priv = phydev->priv;
++ u16 val = 0;
++
++ /*
++ * 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_PCS_AZ_CTRL1,
++ IPQ5018_PHY_PCS_AZ_CTRL1_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_AZ_CTRL2,
++ IPQ5018_PHY_PCS_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);
++
++ /* PHY DAC values are optional and only set in a PHY to PHY link architecture */
++ if (priv->set_short_cable_dac) {
++ /* setting MDAC (Multi-level Digital-to-Analog Converter) in MMD1 */
++ phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
++ IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_MMD1_MDAC_VAL);
++
++ /* setting EDAC (Error-detection and Correction) in debug register */
++ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
++ IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_DEBUG_EDAC_VAL);
++ }
++
++ return 0;
++}
++
++static void ipq5018_link_change_notify(struct phy_device *phydev)
++{
++ mdiobus_modify_changed(phydev->mdio.bus, phydev->mdio.addr,
++ IPQ5018_PHY_FIFO_CONTROL, IPQ5018_PHY_FIFO_RESET,
++ phydev->link ? IPQ5018_PHY_FIFO_RESET : 0);
++}
++
++static int ipq5018_probe(struct phy_device *phydev)
++{
++ struct device *dev = &phydev->mdio.dev;
++ struct ipq5018_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->set_short_cable_dac = of_property_read_bool(dev->of_node,
++ "qcom,dac-preset-short-cable");
++
++ 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");
++
++ phydev->priv = priv;
++
++ return 0;
++}
++
+ static struct phy_driver at803x_driver[] = {
+ {
+ /* Qualcomm Atheros AR8035 */
+@@ -1079,6 +1234,19 @@ static struct phy_driver at803x_driver[]
+ .soft_reset = genphy_soft_reset,
+ .config_aneg = at803x_config_aneg,
+ }, {
++ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
++ .name = "Qualcomm Atheros IPQ5018 internal PHY",
++ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
++ .probe = ipq5018_probe,
++ .config_init = ipq5018_config_init,
++ .link_change_notify = ipq5018_link_change_notify,
++ .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,
++ .soft_reset = genphy_soft_reset,
++}, {
+ /* Qualcomm Atheros QCA9561 */
+ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
+ .name = "Qualcomm Atheros QCA9561 built-in PHY",
+@@ -1104,6 +1272,7 @@ static const struct mdio_device_id __may
+ { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
+ { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
+ { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
++ { PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID) },
+ { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
+ { }
+ };
+++ /dev/null
-From 28490d95fe9e059c5ce74b2289d66e0d7ede2d50 Mon Sep 17 00:00:00 2001
-From: Ziyang Huang <hzyitc@outlook.com>
-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.
-
-Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
- 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
-@@ -198,6 +198,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 {
-@@ -394,8 +409,8 @@
- <&pcie0_phy>,
- <&pcie1_phy>,
- <0>,
-- <0>,
-- <0>,
-+ <&ge_phy 0>,
-+ <&ge_phy 1>,
- <0>,
- <0>;
- #clock-cells = <1>;
--- /dev/null
+From 97a159dd7747724619e54cb3460d9b8d4ed08be7 Mon Sep 17 00:00:00 2001
+From: George Moussalem <george.moussalem@outlook.com>
+Date: Mon, 02 Jun 2025 12:50:40 +0400
+Subject: [PATCH v3 4/5] arm64: dts: qcom: ipq5018: Add MDIO buses
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+Message-Id: <20250602-ipq5018-ge-phy-v3-4-0d8f39f402a6@outlook.com>
+
+IPQ5018 contains two mdio buses of which one bus is used to control the
+SoC's internal GE PHY, while the other bus is connected to external PHYs
+or switches.
+
+There's already support for IPQ5018 in the mdio-ipq4019 driver, so let's
+simply add the mdio nodes for them.
+
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+---
+ arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+@@ -188,6 +188,30 @@
+ status = "disabled";
+ };
+
++ mdio0: mdio@88000 {
++ compatible = "qcom,ipq5018-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 1b733e878ac1292c6e0f2e9a49685b80c35619b0 Mon Sep 17 00:00:00 2001
+From: George Moussalem <george.moussalem@outlook.com>
+Date: Mon, 02 Jun 2025 12:50:41 +0400
+Subject: [PATCH v3 5/5] arm64: dts: qcom: ipq5018: Add GE PHY to internal mdio bus
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+Message-Id: <20250602-ipq5018-ge-phy-v3-5-0d8f39f402a6@outlook.com>
+
+The IPQ5018 SoC contains an internal GE PHY, always at phy address 7.
+As such, let's add the GE PHY node to the SoC dtsi.
+
+The LDO controller found in the SoC must be enabled to provide constant
+low voltages to the PHY. The mdio-ipq4019 driver already has support
+for this, so adding the appropriate TCSR register offset.
+
+In addition, the GE PHY outputs both the RX and TX clocks to the GCC
+which gate controls them and routes them back to the PHY itself.
+So let's create two DT fixed clocks and register them in the GCC node.
+
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+---
+ arch/arm64/boot/dts/qcom/ipq5018.dtsi | 26 +++++++++++++++++++++++---
+ 1 file changed, 23 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+@@ -22,6 +22,18 @@
+ #clock-cells = <0>;
+ };
+
++ gephy_rx_clk: gephy-rx-clk {
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ #clock-cells = <0>;
++ };
++
++ gephy_tx_clk: gephy-tx-clk {
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ #clock-cells = <0>;
++ };
++
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+@@ -190,7 +202,8 @@
+
+ mdio0: mdio@88000 {
+ compatible = "qcom,ipq5018-mdio";
+- reg = <0x00088000 0x64>;
++ reg = <0x00088000 0x64>,
++ <0x019475c4 0x4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+@@ -198,6 +211,13 @@
+ clock-names = "gcc_mdio_ahb_clk";
+
+ status = "disabled";
++
++ ge_phy: ethernet-phy@7 {
++ compatible = "ethernet-phy-id004d.d0c0";
++ reg = <7>;
++
++ resets = <&gcc GCC_GEPHY_MISC_ARES>;
++ };
+ };
+
+ mdio1: mdio@90000 {
+@@ -392,8 +412,8 @@
+ <&pcie0_phy>,
+ <&pcie1_phy>,
+ <0>,
+- <0>,
+- <0>,
++ <&gephy_rx_clk>,
++ <&gephy_tx_clk>,
+ <0>,
+ <0>;
+ #clock-cells = <1>;
+++ /dev/null
-From: George Moussalem <george.moussalem@outlook.com>
-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
-
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
---- 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
+From: George Moussalem <george.moussalem@outlook.com>
+Date: Wed, 28 May 2025 08:37:28 +0400
+Subject: [PATCH] arm64: dts: qcom: ipq5018: Add vendor compatible to mdio bus
+
+QCA SSDK needs to register the MDIO bus in its driver. Without a proper reference,
+it will crash. Since it tries to look up the MDIO bus using compatible strings that
+aren't upstreamed, add the vendor compatible.
+
+Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+@@ -201,7 +201,7 @@
+ };
+
+ mdio0: mdio@88000 {
+- compatible = "qcom,ipq5018-mdio";
++ compatible = "qcom,ipq5018-mdio", "qcom,ipq40xx-mdio";
+ reg = <0x00088000 0x64>,
+ <0x019475c4 0x4>;
+ #address-cells = <1>;
+++ /dev/null
-From: George Moussalem <george.moussalem@outlook.com>
-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.
-
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
---- 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,
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-@@ -694,6 +694,225 @@
+@@ -697,6 +697,225 @@
};
};
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
-@@ -111,6 +111,11 @@
+@@ -123,6 +123,11 @@
#size-cells = <2>;
ranges;