[v8,11/14] net: phy: at803x: add qca808x initial config sequence
Commit Message
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(-)
@@ -897,6 +897,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;
@@ -905,7 +983,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)