-From 9a89cb300c1ed5b90bae5684c88c85895a15c849 Mon Sep 17 00:00:00 2001
+From d46502279a11b48ede1d8bf65a229c8231bf0602 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>
+Date: Fri, 13 Jun 2025 05:55:08 +0400
+Subject: net: phy: qcom: at803x: Add Qualcomm IPQ5018 Internal PHY support
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.
+The PHY supports 10BASE-T/100BASE-TX/1000BASE-T link modes in SGMII
+interface mode, 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.
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
+Link: https://patch.msgid.link/20250613-ipq5018-ge-phy-v5-2-9af06e34ea6b@outlook.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
- drivers/net/phy/qcom/Kconfig | 2 +-
- drivers/net/phy/qcom/at803x.c | 185 ++++++++++++++++++++++++++++++++++++++++--
- 2 files changed, 178 insertions(+), 9 deletions(-)
+ drivers/net/phy/qcom/at803x.c | 167 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 167 insertions(+)
+
+(limited to 'drivers/net/phy/qcom/at803x.c')
---- 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>
+@@ -19,6 +19,7 @@
+ #include <linux/regulator/consumer.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"
-@@ -93,6 +98,8 @@
+@@ -93,6 +94,8 @@
#define ATH8035_PHY_ID 0x004dd072
#define AT8030_PHY_ID_MASK 0xffffffef
#define QCA9561_PHY_ID 0x004dd042
#define AT803X_PAGE_FIBER 0
-@@ -105,6 +112,50 @@
+@@ -105,6 +108,48 @@
/* disable hibernation mode */
#define AT803X_DISABLE_HIBERNATION_MODE BIT(2)
+
+#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_EEE_TX_TIMER 0x8008
++#define IPQ5018_PHY_PCS_EEE_RX_TIMER 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_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_EEE_TX_TIMER_VAL 0x7880
++#define IPQ5018_PHY_PCS_EEE_RX_TIMER_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_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");
-@@ -130,6 +181,11 @@ struct at803x_context {
+@@ -130,6 +175,11 @@ struct at803x_context {
u16 led_control;
};
static int at803x_write_page(struct phy_device *phydev, int page)
{
int mask;
-@@ -960,6 +1016,105 @@ static int at8035_probe(struct phy_devic
+@@ -960,6 +1010,109 @@ static int at8035_probe(struct phy_devic
return at8035_parse_dt(phydev);
}
+static int ipq5018_config_init(struct phy_device *phydev)
+{
+ struct ipq5018_priv *priv = phydev->priv;
-+ u16 val = 0;
++ u16 val;
+
+ /*
+ * set LDO efuse: first temporarily store ANA_DAC_FILTER value from
+ 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 8023AZ EEE TX and RX timer values */
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_TX_TIMER,
++ IPQ5018_PHY_PCS_EEE_TX_TIMER_VAL);
++ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_RX_TIMER,
++ IPQ5018_PHY_PCS_EEE_RX_TIMER_VAL);
+
+ /* set MSE threshold values */
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH1,
+
+static void ipq5018_link_change_notify(struct phy_device *phydev)
+{
++ /*
++ * Reset the FIFO buffer upon link disconnects to clear any residual data
++ * which may cause issues with the FIFO which it cannot recover from.
++ */
+ mdiobus_modify_changed(phydev->mdio.bus, phydev->mdio.addr,
+ IPQ5018_PHY_FIFO_CONTROL, IPQ5018_PHY_FIFO_RESET,
+ phydev->link ? IPQ5018_PHY_FIFO_RESET : 0);
+ "qcom,dac-preset-short-cable");
+
+ priv->rst = devm_reset_control_array_get_exclusive(dev);
-+ if (IS_ERR_OR_NULL(priv->rst))
++ if (IS_ERR(priv->rst))
+ return dev_err_probe(dev, PTR_ERR(priv->rst),
+ "failed to acquire reset\n");
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
-@@ -1052,6 +1207,19 @@ static struct phy_driver at803x_driver[]
+@@ -1052,6 +1205,19 @@ static struct phy_driver at803x_driver[]
.soft_reset = genphy_soft_reset,
.config_aneg = at803x_config_aneg,
}, {
/* Qualcomm Atheros QCA9561 */
PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
.name = "Qualcomm Atheros QCA9561 built-in PHY",
-@@ -1077,6 +1245,7 @@ static const struct mdio_device_id __may
+@@ -1077,6 +1243,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) },