[PATCH v1 2/3] net: fsl_enetc_xpcs_phy: Add 1G SGMII speed mode for i.MX952
alice.guo at oss.nxp.com
alice.guo at oss.nxp.com
Tue Jul 7 06:00:26 CEST 2026
From: Alice Guo <alice.guo at nxp.com>
Add support for initializing 1G SGMII speed mode for i.MX952.
Signed-off-by: Alice Guo <alice.guo at nxp.com>
---
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
More information about the U-Boot
mailing list