Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
0002 /*
0003  * Driver for Microsemi VSC85xx PHYs
0004  *
0005  * Author: Bjarni Jonasson <bjarni.jonassoni@microchip.com>
0006  * License: Dual MIT/GPL
0007  * Copyright (c) 2021 Microsemi Corporation
0008  */
0009 
0010 #include <linux/phy.h>
0011 #include "mscc_serdes.h"
0012 #include "mscc.h"
0013 
0014 static int pll5g_detune(struct phy_device *phydev)
0015 {
0016     u32 rd_dat;
0017     int ret;
0018 
0019     rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2);
0020     rd_dat &= ~PHY_S6G_PLL5G_CFG2_GAIN_MASK;
0021     rd_dat |= PHY_S6G_PLL5G_CFG2_ENA_GAIN;
0022     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0023                 PHY_S6G_PLL5G_CFG2, rd_dat);
0024     if (ret)
0025         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0026     return ret;
0027 }
0028 
0029 static int pll5g_tune(struct phy_device *phydev)
0030 {
0031     u32 rd_dat;
0032     int ret;
0033 
0034     rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2);
0035     rd_dat &= ~PHY_S6G_PLL5G_CFG2_ENA_GAIN;
0036     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0037                 PHY_S6G_PLL5G_CFG2, rd_dat);
0038     if (ret)
0039         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0040     return ret;
0041 }
0042 
0043 static int vsc85xx_sd6g_pll_cfg_wr(struct phy_device *phydev,
0044                    const u32 pll_ena_offs,
0045                    const u32 pll_fsm_ctrl_data,
0046                    const u32 pll_fsm_ena)
0047 {
0048     int ret;
0049 
0050     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0051                 PHY_S6G_PLL_CFG,
0052                 (pll_fsm_ena << PHY_S6G_PLL_ENA_OFFS_POS) |
0053                 (pll_fsm_ctrl_data << PHY_S6G_PLL_FSM_CTRL_DATA_POS) |
0054                 (pll_ena_offs << PHY_S6G_PLL_FSM_ENA_POS));
0055     if (ret)
0056         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0057     return ret;
0058 }
0059 
0060 static int vsc85xx_sd6g_common_cfg_wr(struct phy_device *phydev,
0061                       const u32 sys_rst,
0062                       const u32 ena_lane,
0063                       const u32 ena_loop,
0064                       const u32 qrate,
0065                       const u32 if_mode,
0066                       const u32 pwd_tx)
0067 {
0068     /* ena_loop = 8 for eloop */
0069     /*          = 4 for floop */
0070     /*          = 2 for iloop */
0071     /*          = 1 for ploop */
0072     /* qrate    = 1 for SGMII, 0 for QSGMII */
0073     /* if_mode  = 1 for SGMII, 3 for QSGMII */
0074 
0075     int ret;
0076 
0077     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0078                 PHY_S6G_COMMON_CFG,
0079                 (sys_rst << PHY_S6G_SYS_RST_POS) |
0080                 (ena_lane << PHY_S6G_ENA_LANE_POS) |
0081                 (ena_loop << PHY_S6G_ENA_LOOP_POS) |
0082                 (qrate << PHY_S6G_QRATE_POS) |
0083                 (if_mode << PHY_S6G_IF_MODE_POS));
0084     if (ret)
0085         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0086     return ret;
0087 }
0088 
0089 static int vsc85xx_sd6g_des_cfg_wr(struct phy_device *phydev,
0090                    const u32 des_phy_ctrl,
0091                    const u32 des_mbtr_ctrl,
0092                    const u32 des_bw_hyst,
0093                    const u32 des_bw_ana,
0094                    const u32 des_cpmd_sel)
0095 {
0096     u32 reg_val;
0097     int ret;
0098 
0099     /* configurable terms */
0100     reg_val = (des_phy_ctrl << PHY_S6G_DES_PHY_CTRL_POS) |
0101           (des_mbtr_ctrl << PHY_S6G_DES_MBTR_CTRL_POS) |
0102           (des_cpmd_sel << PHY_S6G_DES_CPMD_SEL_POS) |
0103           (des_bw_hyst << PHY_S6G_DES_BW_HYST_POS) |
0104           (des_bw_ana << PHY_S6G_DES_BW_ANA_POS);
0105     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0106                 PHY_S6G_DES_CFG,
0107                 reg_val);
0108     if (ret)
0109         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0110     return ret;
0111 }
0112 
0113 static int vsc85xx_sd6g_ib_cfg0_wr(struct phy_device *phydev,
0114                    const u32 ib_rtrm_adj,
0115                    const u32 ib_sig_det_clk_sel,
0116                    const u32 ib_reg_pat_sel_offset,
0117                    const u32 ib_cal_ena)
0118 {
0119     u32 base_val;
0120     u32 reg_val;
0121     int ret;
0122 
0123     /* constant terms */
0124     base_val = 0x60a85837;
0125     /* configurable terms */
0126     reg_val = base_val | (ib_rtrm_adj << 25) |
0127           (ib_sig_det_clk_sel << 16) |
0128           (ib_reg_pat_sel_offset << 8) |
0129           (ib_cal_ena << 3);
0130     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0131                 PHY_S6G_IB_CFG0,
0132                 reg_val);
0133     if (ret)
0134         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0135     return ret;
0136 }
0137 
0138 static int vsc85xx_sd6g_ib_cfg1_wr(struct phy_device *phydev,
0139                    const u32 ib_tjtag,
0140                    const u32 ib_tsdet,
0141                    const u32 ib_scaly,
0142                    const u32 ib_frc_offset,
0143                    const u32 ib_filt_offset)
0144 {
0145     u32 ib_filt_val;
0146     u32 reg_val = 0;
0147     int ret;
0148 
0149     /* constant terms */
0150     ib_filt_val = 0xe0;
0151     /* configurable terms */
0152     reg_val  = (ib_tjtag << 17) + (ib_tsdet << 12) + (ib_scaly << 8) +
0153            ib_filt_val + (ib_filt_offset << 4) + (ib_frc_offset << 0);
0154     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0155                 PHY_S6G_IB_CFG1,
0156                 reg_val);
0157     if (ret)
0158         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0159     return ret;
0160 }
0161 
0162 static int vsc85xx_sd6g_ib_cfg2_wr(struct phy_device *phydev,
0163                    const u32 ib_tinfv,
0164                    const u32 ib_tcalv,
0165                    const u32 ib_ureg)
0166 {
0167     u32 ib_cfg2_val;
0168     u32 base_val;
0169     int ret;
0170 
0171     /* constant terms */
0172     base_val = 0x0f878010;
0173     /* configurable terms */
0174     ib_cfg2_val = base_val | ((ib_tinfv) << 28) | ((ib_tcalv) << 5) |
0175               (ib_ureg << 0);
0176     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0177                 PHY_S6G_IB_CFG2,
0178                 ib_cfg2_val);
0179     if (ret)
0180         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0181     return ret;
0182 }
0183 
0184 static int vsc85xx_sd6g_ib_cfg3_wr(struct phy_device *phydev,
0185                    const u32 ib_ini_hp,
0186                    const u32 ib_ini_mid,
0187                    const u32 ib_ini_lp,
0188                    const u32 ib_ini_offset)
0189 {
0190     u32 reg_val;
0191     int ret;
0192 
0193     reg_val  = (ib_ini_hp << 24) + (ib_ini_mid << 16) +
0194            (ib_ini_lp << 8) + (ib_ini_offset << 0);
0195     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0196                 PHY_S6G_IB_CFG3,
0197                 reg_val);
0198     if (ret)
0199         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0200     return ret;
0201 }
0202 
0203 static int vsc85xx_sd6g_ib_cfg4_wr(struct phy_device *phydev,
0204                    const u32 ib_max_hp,
0205                    const u32 ib_max_mid,
0206                    const u32 ib_max_lp,
0207                    const u32 ib_max_offset)
0208 {
0209     u32 reg_val;
0210     int ret;
0211 
0212     reg_val  = (ib_max_hp << 24) + (ib_max_mid << 16) +
0213            (ib_max_lp << 8) + (ib_max_offset << 0);
0214     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0215                 PHY_S6G_IB_CFG4,
0216                 reg_val);
0217     if (ret)
0218         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0219     return ret;
0220 }
0221 
0222 static int vsc85xx_sd6g_misc_cfg_wr(struct phy_device *phydev,
0223                     const u32 lane_rst)
0224 {
0225     int ret;
0226 
0227     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0228                 PHY_S6G_MISC_CFG,
0229                 lane_rst);
0230     if (ret)
0231         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0232     return ret;
0233 }
0234 
0235 static int vsc85xx_sd6g_gp_cfg_wr(struct phy_device *phydev, const u32 gp_cfg_val)
0236 {
0237     int ret;
0238 
0239     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0240                 PHY_S6G_GP_CFG,
0241                 gp_cfg_val);
0242     if (ret)
0243         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0244     return ret;
0245 }
0246 
0247 static int vsc85xx_sd6g_dft_cfg2_wr(struct phy_device *phydev,
0248                     const u32 rx_ji_ampl,
0249                     const u32 rx_step_freq,
0250                     const u32 rx_ji_ena,
0251                     const u32 rx_waveform_sel,
0252                     const u32 rx_freqoff_dir,
0253                     const u32 rx_freqoff_ena)
0254 {
0255     u32 reg_val;
0256     int ret;
0257 
0258     /* configurable terms */
0259     reg_val = (rx_ji_ampl << 8) | (rx_step_freq << 4) |
0260           (rx_ji_ena << 3) | (rx_waveform_sel << 2) |
0261           (rx_freqoff_dir << 1) | rx_freqoff_ena;
0262     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0263                 PHY_S6G_IB_DFT_CFG2,
0264                 reg_val);
0265     if (ret)
0266         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0267     return ret;
0268 }
0269 
0270 static int vsc85xx_sd6g_dft_cfg0_wr(struct phy_device *phydev,
0271                     const u32 prbs_sel,
0272                     const u32 test_mode,
0273                     const u32 rx_dft_ena)
0274 {
0275     u32 reg_val;
0276     int ret;
0277 
0278     /* configurable terms */
0279     reg_val = (prbs_sel << 20) | (test_mode << 16) | (rx_dft_ena << 2);
0280     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0281                 PHY_S6G_DFT_CFG0,
0282                 reg_val);
0283     if (ret)
0284         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0285     return ret;
0286 }
0287 
0288 /* Access LCPLL Cfg_0 */
0289 static int vsc85xx_pll5g_cfg0_wr(struct phy_device *phydev,
0290                  const u32 selbgv820)
0291 {
0292     u32 base_val;
0293     u32 reg_val;
0294     int ret;
0295 
0296     /* constant terms */
0297     base_val = 0x7036f145;
0298     /* configurable terms */
0299     reg_val = base_val | (selbgv820 << 23);
0300     ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
0301                 PHY_S6G_PLL5G_CFG0, reg_val);
0302     if (ret)
0303         dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
0304     return ret;
0305 }
0306 
0307 int vsc85xx_sd6g_config_v2(struct phy_device *phydev)
0308 {
0309     u32 ib_sig_det_clk_sel_cal = 0;
0310     u32 ib_sig_det_clk_sel_mm  = 7;
0311     u32 pll_fsm_ctrl_data = 60;
0312     unsigned long deadline;
0313     u32 des_bw_ana_val = 3;
0314     u32 ib_tsdet_cal = 16;
0315     u32 ib_tsdet_mm  = 5;
0316     u32 ib_rtrm_adj;
0317     u32 if_mode = 1;
0318     u32 gp_iter = 5;
0319     u32 val32 = 0;
0320     u32 qrate = 1;
0321     u32 iter;
0322     int val = 0;
0323     int ret;
0324 
0325     phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
0326 
0327     /* Detune/Unlock LCPLL */
0328     ret = pll5g_detune(phydev);
0329     if (ret)
0330         return ret;
0331 
0332     /* 0. Reset RCPLL */
0333     ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0);
0334     if (ret)
0335         return ret;
0336     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 0, 0, qrate, if_mode, 0);
0337     if (ret)
0338         return ret;
0339     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0340     if (ret)
0341         return ret;
0342     ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
0343     if (ret)
0344         return ret;
0345 
0346     /* 1. Configure sd6g for SGMII prior to sd6g_IB_CAL */
0347     ib_rtrm_adj = 13;
0348     ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 0);
0349     if (ret)
0350         return ret;
0351     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
0352     if (ret)
0353         return ret;
0354     ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5);
0355     if (ret)
0356         return ret;
0357     ret = vsc85xx_sd6g_ib_cfg3_wr(phydev,  0, 31, 1, 31);
0358     if (ret)
0359         return ret;
0360     ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63);
0361     if (ret)
0362         return ret;
0363     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
0364     if (ret)
0365         return ret;
0366     ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1);
0367     if (ret)
0368         return ret;
0369     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0370     if (ret)
0371         return ret;
0372 
0373     /* 2. Start rcpll_fsm */
0374     ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1);
0375     if (ret)
0376         return ret;
0377     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0378     if (ret)
0379         return ret;
0380 
0381     deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
0382     do {
0383         usleep_range(500, 1000);
0384         ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0385         if (ret)
0386             return ret;
0387         val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
0388                      PHY_S6G_PLL_STATUS);
0389         /* wait for bit 12 to clear */
0390     } while (time_before(jiffies, deadline) && (val32 & BIT(12)));
0391 
0392     if (val32 & BIT(12))
0393         return -ETIMEDOUT;
0394 
0395     /* 4. Release digital reset and disable transmitter */
0396     ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0);
0397     if (ret)
0398         return ret;
0399     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 1);
0400     if (ret)
0401         return ret;
0402     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0403     if (ret)
0404         return ret;
0405 
0406     /* 5. Apply a frequency offset on RX-side (using internal FoJi logic) */
0407     ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768);
0408     if (ret)
0409         return ret;
0410     ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 2, 0, 0, 0, 1);
0411     if (ret)
0412         return ret;
0413     ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 1);
0414     if (ret)
0415         return ret;
0416     ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 2);
0417     if (ret)
0418         return ret;
0419     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0420     if (ret)
0421         return ret;
0422 
0423     /* 6. Prepare required settings for IBCAL */
0424     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 0);
0425     if (ret)
0426         return ret;
0427     ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_cal, 0, 0);
0428     if (ret)
0429         return ret;
0430     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0431     if (ret)
0432         return ret;
0433 
0434     /* 7. Start IB_CAL */
0435     ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj,
0436                       ib_sig_det_clk_sel_cal, 0, 1);
0437     if (ret)
0438         return ret;
0439     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0440     if (ret)
0441         return ret;
0442     /* 11 cycles (for ViperA) or 5 cycles (for ViperB & Elise) w/ SW clock */
0443     for (iter = 0; iter < gp_iter; iter++) {
0444         /* set gp(0) */
0445         ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 769);
0446         if (ret)
0447             return ret;
0448         ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0449         if (ret)
0450             return ret;
0451         /* clear gp(0) */
0452         ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768);
0453         if (ret)
0454             return ret;
0455         ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0456         if (ret)
0457             return ret;
0458     }
0459 
0460     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 1);
0461     if (ret)
0462         return ret;
0463     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0464     if (ret)
0465         return ret;
0466     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 0, 1);
0467     if (ret)
0468         return ret;
0469     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0470     if (ret)
0471         return ret;
0472 
0473     /* 8. Wait for IB cal to complete */
0474     deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
0475     do {
0476         usleep_range(500, 1000);
0477         ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0478         if (ret)
0479             return ret;
0480         val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
0481                      PHY_S6G_IB_STATUS0);
0482         /* wait for bit 8 to set */
0483     } while (time_before(jiffies, deadline) && (~val32 & BIT(8)));
0484 
0485     if (~val32 & BIT(8))
0486         return -ETIMEDOUT;
0487 
0488     /* 9. Restore cfg values for mission mode */
0489     ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1);
0490     if (ret)
0491         return ret;
0492     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
0493     if (ret)
0494         return ret;
0495     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0496     if (ret)
0497         return ret;
0498 
0499     /* 10. Re-enable transmitter */
0500     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
0501     if (ret)
0502         return ret;
0503     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0504     if (ret)
0505         return ret;
0506 
0507     /* 11. Disable frequency offset generation (using internal FoJi logic) */
0508     ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 0, 0, 0, 0, 0);
0509     if (ret)
0510         return ret;
0511     ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 0);
0512     if (ret)
0513         return ret;
0514     ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
0515     if (ret)
0516         return ret;
0517     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0518     if (ret)
0519         return ret;
0520 
0521     /* Tune/Re-lock LCPLL */
0522     ret = pll5g_tune(phydev);
0523     if (ret)
0524         return ret;
0525 
0526     /* 12. Configure for Final Configuration and Settings */
0527     /* a. Reset RCPLL */
0528     ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0);
0529     if (ret)
0530         return ret;
0531     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 1, 0, qrate, if_mode, 0);
0532     if (ret)
0533         return ret;
0534     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0535     if (ret)
0536         return ret;
0537 
0538     /* b. Configure sd6g for desired operating mode */
0539     phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_GPIO);
0540     ret = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
0541     if ((ret & MAC_CFG_MASK) == MAC_CFG_QSGMII) {
0542         /* QSGMII */
0543         pll_fsm_ctrl_data = 120;
0544         qrate   = 0;
0545         if_mode = 3;
0546         des_bw_ana_val = 5;
0547         val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
0548             PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC;
0549 
0550         ret = vsc8584_cmd(phydev, val);
0551         if (ret) {
0552             dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n",
0553                 __func__, ret);
0554             return ret;
0555         }
0556 
0557         phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
0558     } else if ((ret & MAC_CFG_MASK) == MAC_CFG_SGMII) {
0559         /* SGMII */
0560         pll_fsm_ctrl_data = 60;
0561         qrate   = 1;
0562         if_mode = 1;
0563         des_bw_ana_val = 3;
0564 
0565         val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
0566             PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_SGMII_MAC;
0567 
0568         ret = vsc8584_cmd(phydev, val);
0569         if (ret) {
0570             dev_err(&phydev->mdio.dev, "%s: SGMII error: %d\n",
0571                 __func__, ret);
0572             return ret;
0573         }
0574 
0575         phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
0576     } else {
0577         dev_err(&phydev->mdio.dev, "%s: invalid mac_if: %x\n",
0578             __func__, ret);
0579     }
0580 
0581     ret = phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
0582     if (ret)
0583         return ret;
0584     ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0585     if (ret)
0586         return ret;
0587     ret = vsc85xx_pll5g_cfg0_wr(phydev, 4);
0588     if (ret)
0589         return ret;
0590     ret = phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
0591     if (ret)
0592         return ret;
0593     ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
0594     if (ret)
0595         return ret;
0596     ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1);
0597     if (ret)
0598         return ret;
0599     ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
0600     if (ret)
0601         return ret;
0602     ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
0603     if (ret)
0604         return ret;
0605     ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5);
0606     if (ret)
0607         return ret;
0608     ret = vsc85xx_sd6g_ib_cfg3_wr(phydev,  0, 31, 1, 31);
0609     if (ret)
0610         return ret;
0611     ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63);
0612     if (ret)
0613         return ret;
0614     ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1);
0615     if (ret)
0616         return ret;
0617     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0618     if (ret)
0619         return ret;
0620 
0621     /* 13. Start rcpll_fsm */
0622     ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1);
0623     if (ret)
0624         return ret;
0625     ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0626     if (ret)
0627         return ret;
0628 
0629     /* 14. Wait for PLL cal to complete */
0630     deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
0631     do {
0632         usleep_range(500, 1000);
0633         ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0634         if (ret)
0635             return ret;
0636         val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
0637                      PHY_S6G_PLL_STATUS);
0638         /* wait for bit 12 to clear */
0639     } while (time_before(jiffies, deadline) && (val32 & BIT(12)));
0640 
0641     if (val32 & BIT(12))
0642         return -ETIMEDOUT;
0643 
0644     /* release lane reset */
0645     ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0);
0646     if (ret)
0647         return ret;
0648 
0649     return phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
0650 }