From: Alice Guo <[email protected]>

Add support for initializing 1G SGMII speed mode for i.MX952.

Signed-off-by: Alice Guo <[email protected]>
---
 drivers/net/fsl_enetc_xpcs_phy.c | 278 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 278 insertions(+)

diff --git a/drivers/net/fsl_enetc_xpcs_phy.c b/drivers/net/fsl_enetc_xpcs_phy.c
index a8c720786a0..e832f320773 100644
--- a/drivers/net/fsl_enetc_xpcs_phy.c
+++ b/drivers/net/fsl_enetc_xpcs_phy.c
@@ -225,6 +225,35 @@
 #define L0_RX_VCO_OVRD_OUT_2                                   0x214
 #define L0_RX_VCO_OVRD_OUT_2_RX_ANA_CDR_FREQ_TUNE_CLK  BIT(0)
 
+/* i.MX952 PHY_CTRL_EX registers */
+#define GLOBAL_CTRL_EX_0_MPLLB_SEL                     BIT(7)
+
+#define GLOBAL_CTRL_EX_4                               0x124
+#define   GLOBAL_CTRL_EX_4_PHY_PCS_PWR_STABLE          BIT(8)
+#define   GLOBAL_CTRL_EX_4_PHY_PMA_PWR_STABLE          BIT(14)
+
+/* i.MX952 VR_MII_MP_12G_16G_MPLLA_CTRL2 */
+#define PMA_MPLLA_CTRL2_V2_MPLLA_DIV8_CLK_EN           BIT(8)
+#define PMA_MPLLA_CTRL2_V2_MPLLA_DIV10_CLK_EN          BIT(9)
+#define PMA_MPLLA_CTRL2_V2_MPLLA_TX_CLK_DIV_MASK       GENMASK(13, 11)
+#define PMA_MPLLA_CTRL2_V2_MPLLA_DIV16P5_CLK_EN        BIT(14)
+#define PMA_MPLLA_CTRL2_V2_MPLLA_WRD_DIV2_EN           BIT(15)
+
+/* i.MX952 VR_MII_MP_12G_AFE_DFE_EN_CTRL */
+#define PMA_MP_12G_AFE_DFE_EN_CTRL                     0x100BA
+#define   PMA_AFE_DFE_EN_CTRL_AFE_EN_0                 BIT(0)
+#define   PMA_AFE_DFE_EN_CTRL_DFE_EN_0                 BIT(4)
+
+/* i.MX952 VR_MII_MP_12G_16G_25G_RX_CDR_CTRLL */
+#define PMA_RX_CDR_CTRL_VCO_LOW_FREQ_0                 BIT(8)
+
+/* i.MX952 VR_MII_MP_12G_VCO_CAL_REF0 */
+#define PMA_VCO_CAL_REF0_V2_VCO_REF_LD_0_MASK          GENMASK(5, 0)
+#define PMA_VCO_CAL_REF0_V2_VCO_REF_LD_0(x)            ((x) & GENMASK(5, 0))
+
+/* i.MX952 VR_MII_DIG_CTRL1 */
+#define MII_DIG_CTRL1_VR_RST                           BIT(15)
+
 static int enetc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg);
 static int enetc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, 
u16 val);
 
@@ -1479,6 +1508,255 @@ int imx95_xpcs_phy_sgmii_1g_config(struct udevice *dev)
        return 0;
 }
 
+static int imx952_xpcs_phy_mpll_sel(struct udevice *dev)
+{
+       ulong begin;
+       u16 val;
+
+       val = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, 
XPCS_PHY_REG(GLOBAL_CTRL_EX_4));
+       val |= GLOBAL_CTRL_EX_4_PHY_PCS_PWR_STABLE;
+       xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_4), 
val);
+
+       val = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, 
XPCS_PHY_REG(GLOBAL_CTRL_EX_4));
+       val |= GLOBAL_CTRL_EX_4_PHY_PMA_PWR_STABLE;
+       xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_4), 
val);
+
+       /* MPLLA - SGMII 1G; MPLLB - SGMII 2.5G */
+       val = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, 
XPCS_PHY_REG(GLOBAL_CTRL_EX_0));
+       val &= ~GLOBAL_CTRL_EX_0_MPLLB_SEL;
+       xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_0), 
val);
+
+       mdelay(1);
+
+       /* Poll for SRAM initialization done */
+       begin = get_timer(0);
+       do {
+               val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_SRAM));
+               if (get_timer(begin) > 500) {
+                       dev_err(dev, "Polling timeout, line: %d\n", __LINE__);
+                       goto timeout;
+               }
+               mdelay(10);
+       } while (!(val & PMA_SRAM_INIT_DN));
+
+       mdelay(1);
+
+       val = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, 
XPCS_PHY_REG(GLOBAL_CTRL_EX_0));
+       val |= GLOBAL_CTRL_EX_0_PHY_SRAM_BYPASS;
+       xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_0), 
val);
+
+       /*
+        * This bit is self-cleared when PSEQ_STATE in VR_XS_PCS_DIG_STS is 
equal
+        * to 3'b100, that is, Tx/Rx clocks are stable and in Power_Good state.
+        */
+       begin = get_timer(0);
+       do {
+               val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(PCS_CTRL1));
+               if (get_timer(begin) > 500) {
+                       dev_err(dev, "Polling timeout, line: %d\n", __LINE__);
+                       goto timeout;
+               }
+               mdelay(10);
+       } while (val & PCS_CTRL1_RESET);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val = u16_replace_bits(val, 0x2, 
PMA_MPLLA_CTRL2_V2_MPLLA_TX_CLK_DIV_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       return 0;
+
+timeout:
+       return -ETIMEDOUT;
+}
+
+static int imx952_xpcs_phy_mplla_configuration_sgmii(struct udevice *dev)
+{
+       ulong begin;
+       u16 val;
+
+       /* Disable 2.5G SGMII mode */
+       val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_DIG_CTRL1));
+       val &= ~MII_DIG_CTRL1_EN_2_5G_MODE;
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_DIG_CTRL1), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL));
+       val &= ~MII_CTRL_SS13;
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL));
+       val |= MII_CTRL_SS6;
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL), val);
+
+       /* Program various registers for 1G SGMII mode */
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_MPLL_CMN_CTRL));
+       val &= ~PMA_MPLL_CMN_CTRL_MPLLB_SEL_0;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_MPLL_CMN_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL));
+       val = u16_replace_bits(val, 2, PMA_REF_CLK_CTRL_REF_RANGE_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL));
+       val |= PMA_REF_CLK_CTRL_REF_CLK_DIV2;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL));
+       val |= PMA_REF_CLK_CTRL_REF_MPLLA_DIV2;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_REF_CLK_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL0));
+       val = u16_replace_bits(val, 0x50, 
PMA_MPLLA_CTRL0_MPLLA_MULTIPLIER_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_MPLLA_CTRL1));
+       val &= ~PMA_MPLLA_CTRL1_MPLLA_FRACN_CTRL_MASK;
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(PMA_MP_16G_MPLLA_CTRL1), 
val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val &= ~PMA_MPLLA_CTRL2_V2_MPLLA_DIV16P5_CLK_EN;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val = u16_replace_bits(val, 0x2, 
PMA_MPLLA_CTRL2_V2_MPLLA_TX_CLK_DIV_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val |= PMA_MPLLA_CTRL2_V2_MPLLA_DIV10_CLK_EN;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val &= ~PMA_MPLLA_CTRL2_V2_MPLLA_DIV8_CLK_EN;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2));
+       val &= ~PMA_MPLLA_CTRL2_V2_MPLLA_WRD_DIV2_EN;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_MPLLA_CTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_MPLLA_CTRL3));
+       val = u16_replace_bits(val, 0x3f, PMA_MPLLA_CTRL3_MPLLA_BANDWIDTH_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(PMA_MP_16G_MPLLA_CTRL3), 
val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_VCO_CAL_LD0));
+       val = u16_replace_bits(val, 0x550, PMA_VCO_CAL_LD0_VCO_LD_VAL_0_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_VCO_CAL_LD0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_25G_VCO_CAL_REF0));
+       val = u16_replace_bits(val, 0x11, 
PMA_VCO_CAL_REF0_V2_VCO_REF_LD_0_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_25G_VCO_CAL_REF0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_GENCTRL1));
+       val &= ~PMA_RX_GENCTRL1_RX_DIV16P5_CLK_EN_0;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_GENCTRL1), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_RATE_CTRL));
+       val = u16_replace_bits(val, 0x1, PMA_TX_RATE_CTRL_TX0_RATE_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_RATE_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_RATE_CTRL));
+       val = u16_replace_bits(val, 0x3, PMA_RX_RATE_CTRL_RX0_RATE_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_RATE_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_TX_GENCTRL2));
+       val = u16_replace_bits(val, 0x1, PMA_TX_GENCTRL2_TX0_WIDTH_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_TX_GENCTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_RX_GENCTRL2));
+       val = u16_replace_bits(val, 0x1, PMA_RX_GENCTRL2_RX0_WIDTH_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_RX_GENCTRL2), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_AFE_DFE_EN_CTRL));
+       val &= ~PMA_AFE_DFE_EN_CTRL_AFE_EN_0;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_AFE_DFE_EN_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_AFE_DFE_EN_CTRL));
+       val &= ~PMA_AFE_DFE_EN_CTRL_DFE_EN_0;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_AFE_DFE_EN_CTRL), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_25G_RX_EQ_CTRL0));
+       val = u16_replace_bits(val, 0x7, PMA_RX_EQ_CTRL0_CTLE_BOOST_0_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_16G_25G_RX_EQ_CTRL0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_DFE_TAP_CTRL0));
+       val = u16_replace_bits(val, 0x0, PMA_DFE_TAP_CTRL0_DFE_TAP1_0_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_DFE_TAP_CTRL0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_CDR_CTRL));
+       val &= ~PMA_RX_CDR_CTRL_VCO_LOW_FREQ_0;
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_RX_CDR_CTRL), val);
+
+       /* Initiate the soft reset */
+       val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_DIG_CTRL1));
+       val |= MII_DIG_CTRL1_VR_RST;
+       xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_DIG_CTRL1), val);
+
+       /* Poll for SRAM initialization done */
+       begin = get_timer(0);
+       do {
+               val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_SRAM));
+               if (get_timer(begin) > 500) {
+                       dev_err(dev, "Polling timeout, line: %d\n", __LINE__);
+                       goto timeout;
+               }
+               mdelay(10);
+       } while (!(val & PMA_SRAM_INIT_DN));
+
+       mdelay(1);
+
+       val = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, 
XPCS_PHY_REG(GLOBAL_CTRL_EX_0));
+       val |= GLOBAL_CTRL_EX_0_PHY_SRAM_BYPASS;
+       xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_0), 
val);
+
+       begin = get_timer(0);
+       do {
+               val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(MII_DIG_CTRL1));
+               if (get_timer(begin) > 500) {
+                       dev_err(dev, "Polling timeout, line: %d\n", __LINE__);
+                       goto timeout;
+               }
+               mdelay(10);
+       } while (val & MII_DIG_CTRL1_VR_RST);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL0));
+       val = u16_replace_bits(val, 0x0, PMA_TX_EQ_CTRL0_TX_EQ_PRE_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL0));
+       val = u16_replace_bits(val, 20, PMA_TX_EQ_CTRL0_TX_EQ_MAIN_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL0), val);
+
+       val = xpcs_read(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL1));
+       val = u16_replace_bits(val, 0x0, PMA_TX_EQ_CTRL1_TX_EQ_POST_MASK);
+       xpcs_write(dev, MDIO_MMD_VEND2, 
XPCS_PHY_REG(PMA_MP_12G_16G_25G_TX_EQ_CTRL1), val);
+
+       return 0;
+
+timeout:
+       return -ETIMEDOUT;
+}
+
+int imx952_xpcs_phy_sgmii_config(struct udevice *dev)
+{
+       int ret;
+
+       ret = imx952_xpcs_phy_mpll_sel(dev);
+       if (ret)
+               return ret;
+
+       ret = xpcs_phy_common_init_seq_1(dev);
+       if (ret)
+               return ret;
+
+       ret = imx952_xpcs_phy_mplla_configuration_sgmii(dev);
+       if (ret)
+               return ret;
+
+       ret = xpcs_phy_common_init_seq_2(dev, true);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 u32 xpcs_phy_get_id(struct udevice *dev)
 {
        int ret;

-- 
2.34.1

Reply via email to