[PATCH v3 4/4] net: phy: at803x: add RX and TX clock management for IPQ5018 PHY
From: George Moussalem via B4 Relay
Date: Fri Jun 05 2026 - 08:50:20 EST
From: George Moussalem <george.moussalem@xxxxxxxxxxx>
Acquire and manage the RX and TX clocks for the IPQ5018 PHY.
These clocks are required for the PHY's datapath to function correctly.
Gate the clocks upon link state changes for improved power management.
Fixes: d46502279a11 ("net: phy: qcom: at803x: Add Qualcomm IPQ5018 Internal PHY support")
Signed-off-by: George Moussalem <george.moussalem@xxxxxxxxxxx>
---
drivers/net/phy/qcom/at803x.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/drivers/net/phy/qcom/at803x.c b/drivers/net/phy/qcom/at803x.c
index 63726cf98cd4..99bc710531a4 100644
--- a/drivers/net/phy/qcom/at803x.c
+++ b/drivers/net/phy/qcom/at803x.c
@@ -19,6 +19,8 @@
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/phylink.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/reset.h>
#include <linux/phy_port.h>
#include <dt-bindings/net/qca-ar803x.h>
@@ -176,6 +178,8 @@ struct at803x_context {
};
struct ipq5018_priv {
+ struct clk *rx_clk;
+ struct clk *tx_clk;
struct reset_control *rst;
bool set_short_cable_dac;
};
@@ -1062,6 +1066,35 @@ static int ipq5018_config_init(struct phy_device *phydev)
static void ipq5018_link_change_notify(struct phy_device *phydev)
{
+ struct ipq5018_priv *priv = phydev->priv;
+ int ret;
+
+ if (phydev->link) {
+ if (!__clk_is_enabled(priv->rx_clk)) {
+ ret = clk_prepare_enable(priv->rx_clk);
+ if (ret) {
+ dev_err(&phydev->mdio.dev,
+ "failed to enable RX clock\n");
+ goto reset_fifo;
+ }
+ }
+
+ if (!__clk_is_enabled(priv->tx_clk)) {
+ ret = clk_prepare_enable(priv->tx_clk);
+ if (ret) {
+ dev_err(&phydev->mdio.dev,
+ "failed to enable TX clock\n");
+ clk_disable_unprepare(priv->rx_clk);
+ }
+ }
+ } else {
+ if (__clk_is_enabled(priv->rx_clk))
+ clk_disable_unprepare(priv->rx_clk);
+ if (__clk_is_enabled(priv->tx_clk))
+ clk_disable_unprepare(priv->tx_clk);
+ }
+
+reset_fifo:
/*
* Reset the FIFO buffer upon link disconnects to clear any residual data
* which may cause issues with the FIFO which it cannot recover from.
@@ -1084,6 +1117,16 @@ static int ipq5018_probe(struct phy_device *phydev)
priv->set_short_cable_dac = of_property_read_bool(dev->of_node,
"qcom,dac-preset-short-cable");
+ priv->rx_clk = devm_clk_get(dev, "rx");
+ if (IS_ERR(priv->rx_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->rx_clk),
+ "failed to get RX clock\n");
+
+ priv->tx_clk = devm_clk_get(dev, "tx");
+ if (IS_ERR(priv->tx_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->tx_clk),
+ "failed to get TX clock\n");
+
priv->rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(priv->rst))
return dev_err_probe(dev, PTR_ERR(priv->rst),
--
2.53.0