lkml.org 
[lkml]   [2023]   [Dec]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v7 11/14] net: phy: at803x: add qca808x initial config sequence
Date
After GPIO reset, these Ethernet clock sequence needs to be
configured before reading the features of PHY, the Ethernet
system clock works on 25MHZ.

Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/phy/at803x.c | 84 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 6a7a7111ff68..204f5ca6001c 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1090,6 +1090,84 @@ static int qca8084_parse_dt(struct phy_device *phydev)
return 0;
}

+static int qca8084_clock_config(struct phy_device *phydev)
+{
+ struct at803x_priv *priv;
+ int ret = 0;
+
+ /* The ethernet clock IDs are only defined in one PHY device
+ * tree node, and these ethernet clocks only needs to be configured
+ * one time, which work on the clock rate 25MHZ.
+ */
+ priv = phydev->priv;
+ if (!priv->clk[SRDS0_SYS_CLK])
+ return 0;
+
+ ret = clk_set_rate(priv->clk[SRDS0_SYS_CLK], 25000000);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[SRDS0_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[SRDS1_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ /* Reset PCS system clocks */
+ reset_control_assert(priv->reset[SRDS0_SYS_RESET]);
+ reset_control_assert(priv->reset[SRDS1_SYS_RESET]);
+ fsleep(20000);
+
+ reset_control_deassert(priv->reset[SRDS0_SYS_RESET]);
+ reset_control_deassert(priv->reset[SRDS1_SYS_RESET]);
+
+ ret = clk_prepare_enable(priv->clk[GEPHY0_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY1_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY2_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY3_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ /* Reset ethernet system clocks */
+ reset_control_assert(priv->reset[GEPHY0_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY1_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY2_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY3_SYS_RESET]);
+ fsleep(20000);
+
+ reset_control_deassert(priv->reset[GEPHY0_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY1_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY2_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY3_SYS_RESET]);
+
+ /* Release ethernet DSP reset */
+ reset_control_deassert(priv->reset[GEPHY0_RESET]);
+ reset_control_deassert(priv->reset[GEPHY1_RESET]);
+ reset_control_deassert(priv->reset[GEPHY2_RESET]);
+ reset_control_deassert(priv->reset[GEPHY3_RESET]);
+ reset_control_deassert(priv->reset[GEPHY_DSP_RESET]);
+
+ /* Enable efuse loading into analog circuit */
+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG,
+ QCA8084_EPHY_LDO_EN, 0);
+ if (ret)
+ return ret;
+
+ fsleep(10000);
+ return 0;
+}
+
static int qca8084_probe(struct phy_device *phydev)
{
int ret;
@@ -1098,7 +1176,11 @@ static int qca8084_probe(struct phy_device *phydev)
if (ret)
return ret;

- return qca8084_parse_and_set_phyaddr(phydev);
+ ret = qca8084_parse_and_set_phyaddr(phydev);
+ if (ret)
+ return ret;
+
+ return qca8084_clock_config(phydev);
}

static int at803x_probe(struct phy_device *phydev)
--
2.42.0
\
 
 \ /
  Last update: 2023-12-14 10:50    [W:0.188 / U:0.016 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site