cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mscc_serdes.c (16994B)


      1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
      2/*
      3 * Driver for Microsemi VSC85xx PHYs
      4 *
      5 * Author: Bjarni Jonasson <bjarni.jonassoni@microchip.com>
      6 * License: Dual MIT/GPL
      7 * Copyright (c) 2021 Microsemi Corporation
      8 */
      9
     10#include <linux/phy.h>
     11#include "mscc_serdes.h"
     12#include "mscc.h"
     13
     14static int pll5g_detune(struct phy_device *phydev)
     15{
     16	u32 rd_dat;
     17	int ret;
     18
     19	rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2);
     20	rd_dat &= ~PHY_S6G_PLL5G_CFG2_GAIN_MASK;
     21	rd_dat |= PHY_S6G_PLL5G_CFG2_ENA_GAIN;
     22	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
     23				PHY_S6G_PLL5G_CFG2, rd_dat);
     24	if (ret)
     25		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
     26	return ret;
     27}
     28
     29static int pll5g_tune(struct phy_device *phydev)
     30{
     31	u32 rd_dat;
     32	int ret;
     33
     34	rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2);
     35	rd_dat &= ~PHY_S6G_PLL5G_CFG2_ENA_GAIN;
     36	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
     37				PHY_S6G_PLL5G_CFG2, rd_dat);
     38	if (ret)
     39		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
     40	return ret;
     41}
     42
     43static int vsc85xx_sd6g_pll_cfg_wr(struct phy_device *phydev,
     44				   const u32 pll_ena_offs,
     45				   const u32 pll_fsm_ctrl_data,
     46				   const u32 pll_fsm_ena)
     47{
     48	int ret;
     49
     50	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
     51				PHY_S6G_PLL_CFG,
     52				(pll_fsm_ena << PHY_S6G_PLL_ENA_OFFS_POS) |
     53				(pll_fsm_ctrl_data << PHY_S6G_PLL_FSM_CTRL_DATA_POS) |
     54				(pll_ena_offs << PHY_S6G_PLL_FSM_ENA_POS));
     55	if (ret)
     56		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
     57	return ret;
     58}
     59
     60static int vsc85xx_sd6g_common_cfg_wr(struct phy_device *phydev,
     61				      const u32 sys_rst,
     62				      const u32 ena_lane,
     63				      const u32 ena_loop,
     64				      const u32 qrate,
     65				      const u32 if_mode,
     66				      const u32 pwd_tx)
     67{
     68	/* ena_loop = 8 for eloop */
     69	/*          = 4 for floop */
     70	/*          = 2 for iloop */
     71	/*          = 1 for ploop */
     72	/* qrate    = 1 for SGMII, 0 for QSGMII */
     73	/* if_mode  = 1 for SGMII, 3 for QSGMII */
     74
     75	int ret;
     76
     77	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
     78				PHY_S6G_COMMON_CFG,
     79				(sys_rst << PHY_S6G_SYS_RST_POS) |
     80				(ena_lane << PHY_S6G_ENA_LANE_POS) |
     81				(ena_loop << PHY_S6G_ENA_LOOP_POS) |
     82				(qrate << PHY_S6G_QRATE_POS) |
     83				(if_mode << PHY_S6G_IF_MODE_POS));
     84	if (ret)
     85		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
     86	return ret;
     87}
     88
     89static int vsc85xx_sd6g_des_cfg_wr(struct phy_device *phydev,
     90				   const u32 des_phy_ctrl,
     91				   const u32 des_mbtr_ctrl,
     92				   const u32 des_bw_hyst,
     93				   const u32 des_bw_ana,
     94				   const u32 des_cpmd_sel)
     95{
     96	u32 reg_val;
     97	int ret;
     98
     99	/* configurable terms */
    100	reg_val = (des_phy_ctrl << PHY_S6G_DES_PHY_CTRL_POS) |
    101		  (des_mbtr_ctrl << PHY_S6G_DES_MBTR_CTRL_POS) |
    102		  (des_cpmd_sel << PHY_S6G_DES_CPMD_SEL_POS) |
    103		  (des_bw_hyst << PHY_S6G_DES_BW_HYST_POS) |
    104		  (des_bw_ana << PHY_S6G_DES_BW_ANA_POS);
    105	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    106				PHY_S6G_DES_CFG,
    107				reg_val);
    108	if (ret)
    109		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    110	return ret;
    111}
    112
    113static int vsc85xx_sd6g_ib_cfg0_wr(struct phy_device *phydev,
    114				   const u32 ib_rtrm_adj,
    115				   const u32 ib_sig_det_clk_sel,
    116				   const u32 ib_reg_pat_sel_offset,
    117				   const u32 ib_cal_ena)
    118{
    119	u32 base_val;
    120	u32 reg_val;
    121	int ret;
    122
    123	/* constant terms */
    124	base_val = 0x60a85837;
    125	/* configurable terms */
    126	reg_val = base_val | (ib_rtrm_adj << 25) |
    127		  (ib_sig_det_clk_sel << 16) |
    128		  (ib_reg_pat_sel_offset << 8) |
    129		  (ib_cal_ena << 3);
    130	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    131				PHY_S6G_IB_CFG0,
    132				reg_val);
    133	if (ret)
    134		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    135	return ret;
    136}
    137
    138static int vsc85xx_sd6g_ib_cfg1_wr(struct phy_device *phydev,
    139				   const u32 ib_tjtag,
    140				   const u32 ib_tsdet,
    141				   const u32 ib_scaly,
    142				   const u32 ib_frc_offset,
    143				   const u32 ib_filt_offset)
    144{
    145	u32 ib_filt_val;
    146	u32 reg_val = 0;
    147	int ret;
    148
    149	/* constant terms */
    150	ib_filt_val = 0xe0;
    151	/* configurable terms */
    152	reg_val  = (ib_tjtag << 17) + (ib_tsdet << 12) + (ib_scaly << 8) +
    153		   ib_filt_val + (ib_filt_offset << 4) + (ib_frc_offset << 0);
    154	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    155				PHY_S6G_IB_CFG1,
    156				reg_val);
    157	if (ret)
    158		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    159	return ret;
    160}
    161
    162static int vsc85xx_sd6g_ib_cfg2_wr(struct phy_device *phydev,
    163				   const u32 ib_tinfv,
    164				   const u32 ib_tcalv,
    165				   const u32 ib_ureg)
    166{
    167	u32 ib_cfg2_val;
    168	u32 base_val;
    169	int ret;
    170
    171	/* constant terms */
    172	base_val = 0x0f878010;
    173	/* configurable terms */
    174	ib_cfg2_val = base_val | ((ib_tinfv) << 28) | ((ib_tcalv) << 5) |
    175		      (ib_ureg << 0);
    176	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    177				PHY_S6G_IB_CFG2,
    178				ib_cfg2_val);
    179	if (ret)
    180		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    181	return ret;
    182}
    183
    184static int vsc85xx_sd6g_ib_cfg3_wr(struct phy_device *phydev,
    185				   const u32 ib_ini_hp,
    186				   const u32 ib_ini_mid,
    187				   const u32 ib_ini_lp,
    188				   const u32 ib_ini_offset)
    189{
    190	u32 reg_val;
    191	int ret;
    192
    193	reg_val  = (ib_ini_hp << 24) + (ib_ini_mid << 16) +
    194		   (ib_ini_lp << 8) + (ib_ini_offset << 0);
    195	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    196				PHY_S6G_IB_CFG3,
    197				reg_val);
    198	if (ret)
    199		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    200	return ret;
    201}
    202
    203static int vsc85xx_sd6g_ib_cfg4_wr(struct phy_device *phydev,
    204				   const u32 ib_max_hp,
    205				   const u32 ib_max_mid,
    206				   const u32 ib_max_lp,
    207				   const u32 ib_max_offset)
    208{
    209	u32 reg_val;
    210	int ret;
    211
    212	reg_val  = (ib_max_hp << 24) + (ib_max_mid << 16) +
    213		   (ib_max_lp << 8) + (ib_max_offset << 0);
    214	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    215				PHY_S6G_IB_CFG4,
    216				reg_val);
    217	if (ret)
    218		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    219	return ret;
    220}
    221
    222static int vsc85xx_sd6g_misc_cfg_wr(struct phy_device *phydev,
    223				    const u32 lane_rst)
    224{
    225	int ret;
    226
    227	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    228				PHY_S6G_MISC_CFG,
    229				lane_rst);
    230	if (ret)
    231		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    232	return ret;
    233}
    234
    235static int vsc85xx_sd6g_gp_cfg_wr(struct phy_device *phydev, const u32 gp_cfg_val)
    236{
    237	int ret;
    238
    239	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    240				PHY_S6G_GP_CFG,
    241				gp_cfg_val);
    242	if (ret)
    243		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    244	return ret;
    245}
    246
    247static int vsc85xx_sd6g_dft_cfg2_wr(struct phy_device *phydev,
    248				    const u32 rx_ji_ampl,
    249				    const u32 rx_step_freq,
    250				    const u32 rx_ji_ena,
    251				    const u32 rx_waveform_sel,
    252				    const u32 rx_freqoff_dir,
    253				    const u32 rx_freqoff_ena)
    254{
    255	u32 reg_val;
    256	int ret;
    257
    258	/* configurable terms */
    259	reg_val = (rx_ji_ampl << 8) | (rx_step_freq << 4) |
    260		  (rx_ji_ena << 3) | (rx_waveform_sel << 2) |
    261		  (rx_freqoff_dir << 1) | rx_freqoff_ena;
    262	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    263				PHY_S6G_IB_DFT_CFG2,
    264				reg_val);
    265	if (ret)
    266		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    267	return ret;
    268}
    269
    270static int vsc85xx_sd6g_dft_cfg0_wr(struct phy_device *phydev,
    271				    const u32 prbs_sel,
    272				    const u32 test_mode,
    273				    const u32 rx_dft_ena)
    274{
    275	u32 reg_val;
    276	int ret;
    277
    278	/* configurable terms */
    279	reg_val = (prbs_sel << 20) | (test_mode << 16) | (rx_dft_ena << 2);
    280	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    281				PHY_S6G_DFT_CFG0,
    282				reg_val);
    283	if (ret)
    284		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    285	return ret;
    286}
    287
    288/* Access LCPLL Cfg_0 */
    289static int vsc85xx_pll5g_cfg0_wr(struct phy_device *phydev,
    290				 const u32 selbgv820)
    291{
    292	u32 base_val;
    293	u32 reg_val;
    294	int ret;
    295
    296	/* constant terms */
    297	base_val = 0x7036f145;
    298	/* configurable terms */
    299	reg_val = base_val | (selbgv820 << 23);
    300	ret = vsc85xx_csr_write(phydev, MACRO_CTRL,
    301				PHY_S6G_PLL5G_CFG0, reg_val);
    302	if (ret)
    303		dev_err(&phydev->mdio.dev, "%s: write error\n", __func__);
    304	return ret;
    305}
    306
    307int vsc85xx_sd6g_config_v2(struct phy_device *phydev)
    308{
    309	u32 ib_sig_det_clk_sel_cal = 0;
    310	u32 ib_sig_det_clk_sel_mm  = 7;
    311	u32 pll_fsm_ctrl_data = 60;
    312	unsigned long deadline;
    313	u32 des_bw_ana_val = 3;
    314	u32 ib_tsdet_cal = 16;
    315	u32 ib_tsdet_mm  = 5;
    316	u32 ib_rtrm_adj;
    317	u32 if_mode = 1;
    318	u32 gp_iter = 5;
    319	u32 val32 = 0;
    320	u32 qrate = 1;
    321	u32 iter;
    322	int val = 0;
    323	int ret;
    324
    325	phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
    326
    327	/* Detune/Unlock LCPLL */
    328	ret = pll5g_detune(phydev);
    329	if (ret)
    330		return ret;
    331
    332	/* 0. Reset RCPLL */
    333	ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0);
    334	if (ret)
    335		return ret;
    336	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 0, 0, qrate, if_mode, 0);
    337	if (ret)
    338		return ret;
    339	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    340	if (ret)
    341		return ret;
    342	ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
    343	if (ret)
    344		return ret;
    345
    346	/* 1. Configure sd6g for SGMII prior to sd6g_IB_CAL */
    347	ib_rtrm_adj = 13;
    348	ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 0);
    349	if (ret)
    350		return ret;
    351	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
    352	if (ret)
    353		return ret;
    354	ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5);
    355	if (ret)
    356		return ret;
    357	ret = vsc85xx_sd6g_ib_cfg3_wr(phydev,  0, 31, 1, 31);
    358	if (ret)
    359		return ret;
    360	ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63);
    361	if (ret)
    362		return ret;
    363	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
    364	if (ret)
    365		return ret;
    366	ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1);
    367	if (ret)
    368		return ret;
    369	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    370	if (ret)
    371		return ret;
    372
    373	/* 2. Start rcpll_fsm */
    374	ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1);
    375	if (ret)
    376		return ret;
    377	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    378	if (ret)
    379		return ret;
    380
    381	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
    382	do {
    383		usleep_range(500, 1000);
    384		ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    385		if (ret)
    386			return ret;
    387		val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
    388					 PHY_S6G_PLL_STATUS);
    389		/* wait for bit 12 to clear */
    390	} while (time_before(jiffies, deadline) && (val32 & BIT(12)));
    391
    392	if (val32 & BIT(12))
    393		return -ETIMEDOUT;
    394
    395	/* 4. Release digital reset and disable transmitter */
    396	ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0);
    397	if (ret)
    398		return ret;
    399	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 1);
    400	if (ret)
    401		return ret;
    402	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    403	if (ret)
    404		return ret;
    405
    406	/* 5. Apply a frequency offset on RX-side (using internal FoJi logic) */
    407	ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768);
    408	if (ret)
    409		return ret;
    410	ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 2, 0, 0, 0, 1);
    411	if (ret)
    412		return ret;
    413	ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 1);
    414	if (ret)
    415		return ret;
    416	ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 2);
    417	if (ret)
    418		return ret;
    419	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    420	if (ret)
    421		return ret;
    422
    423	/* 6. Prepare required settings for IBCAL */
    424	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 0);
    425	if (ret)
    426		return ret;
    427	ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_cal, 0, 0);
    428	if (ret)
    429		return ret;
    430	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    431	if (ret)
    432		return ret;
    433
    434	/* 7. Start IB_CAL */
    435	ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj,
    436				      ib_sig_det_clk_sel_cal, 0, 1);
    437	if (ret)
    438		return ret;
    439	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    440	if (ret)
    441		return ret;
    442	/* 11 cycles (for ViperA) or 5 cycles (for ViperB & Elise) w/ SW clock */
    443	for (iter = 0; iter < gp_iter; iter++) {
    444		/* set gp(0) */
    445		ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 769);
    446		if (ret)
    447			return ret;
    448		ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    449		if (ret)
    450			return ret;
    451		/* clear gp(0) */
    452		ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768);
    453		if (ret)
    454			return ret;
    455		ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    456		if (ret)
    457			return ret;
    458	}
    459
    460	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 1);
    461	if (ret)
    462		return ret;
    463	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    464	if (ret)
    465		return ret;
    466	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 0, 1);
    467	if (ret)
    468		return ret;
    469	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    470	if (ret)
    471		return ret;
    472
    473	/* 8. Wait for IB cal to complete */
    474	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
    475	do {
    476		usleep_range(500, 1000);
    477		ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    478		if (ret)
    479			return ret;
    480		val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
    481					 PHY_S6G_IB_STATUS0);
    482		/* wait for bit 8 to set */
    483	} while (time_before(jiffies, deadline) && (~val32 & BIT(8)));
    484
    485	if (~val32 & BIT(8))
    486		return -ETIMEDOUT;
    487
    488	/* 9. Restore cfg values for mission mode */
    489	ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1);
    490	if (ret)
    491		return ret;
    492	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
    493	if (ret)
    494		return ret;
    495	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    496	if (ret)
    497		return ret;
    498
    499	/* 10. Re-enable transmitter */
    500	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
    501	if (ret)
    502		return ret;
    503	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    504	if (ret)
    505		return ret;
    506
    507	/* 11. Disable frequency offset generation (using internal FoJi logic) */
    508	ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 0, 0, 0, 0, 0);
    509	if (ret)
    510		return ret;
    511	ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 0);
    512	if (ret)
    513		return ret;
    514	ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
    515	if (ret)
    516		return ret;
    517	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    518	if (ret)
    519		return ret;
    520
    521	/* Tune/Re-lock LCPLL */
    522	ret = pll5g_tune(phydev);
    523	if (ret)
    524		return ret;
    525
    526	/* 12. Configure for Final Configuration and Settings */
    527	/* a. Reset RCPLL */
    528	ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0);
    529	if (ret)
    530		return ret;
    531	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 1, 0, qrate, if_mode, 0);
    532	if (ret)
    533		return ret;
    534	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    535	if (ret)
    536		return ret;
    537
    538	/* b. Configure sd6g for desired operating mode */
    539	phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_GPIO);
    540	ret = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
    541	if ((ret & MAC_CFG_MASK) == MAC_CFG_QSGMII) {
    542		/* QSGMII */
    543		pll_fsm_ctrl_data = 120;
    544		qrate   = 0;
    545		if_mode = 3;
    546		des_bw_ana_val = 5;
    547		val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
    548			PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC;
    549
    550		ret = vsc8584_cmd(phydev, val);
    551		if (ret) {
    552			dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n",
    553				__func__, ret);
    554			return ret;
    555		}
    556
    557		phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
    558	} else if ((ret & MAC_CFG_MASK) == MAC_CFG_SGMII) {
    559		/* SGMII */
    560		pll_fsm_ctrl_data = 60;
    561		qrate   = 1;
    562		if_mode = 1;
    563		des_bw_ana_val = 3;
    564
    565		val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
    566			PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_SGMII_MAC;
    567
    568		ret = vsc8584_cmd(phydev, val);
    569		if (ret) {
    570			dev_err(&phydev->mdio.dev, "%s: SGMII error: %d\n",
    571				__func__, ret);
    572			return ret;
    573		}
    574
    575		phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
    576	} else {
    577		dev_err(&phydev->mdio.dev, "%s: invalid mac_if: %x\n",
    578			__func__, ret);
    579	}
    580
    581	ret = phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
    582	if (ret)
    583		return ret;
    584	ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    585	if (ret)
    586		return ret;
    587	ret = vsc85xx_pll5g_cfg0_wr(phydev, 4);
    588	if (ret)
    589		return ret;
    590	ret = phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
    591	if (ret)
    592		return ret;
    593	ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0);
    594	if (ret)
    595		return ret;
    596	ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1);
    597	if (ret)
    598		return ret;
    599	ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1);
    600	if (ret)
    601		return ret;
    602	ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0);
    603	if (ret)
    604		return ret;
    605	ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5);
    606	if (ret)
    607		return ret;
    608	ret = vsc85xx_sd6g_ib_cfg3_wr(phydev,  0, 31, 1, 31);
    609	if (ret)
    610		return ret;
    611	ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63);
    612	if (ret)
    613		return ret;
    614	ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1);
    615	if (ret)
    616		return ret;
    617	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    618	if (ret)
    619		return ret;
    620
    621	/* 13. Start rcpll_fsm */
    622	ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1);
    623	if (ret)
    624		return ret;
    625	ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    626	if (ret)
    627		return ret;
    628
    629	/* 14. Wait for PLL cal to complete */
    630	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
    631	do {
    632		usleep_range(500, 1000);
    633		ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    634		if (ret)
    635			return ret;
    636		val32 = vsc85xx_csr_read(phydev, MACRO_CTRL,
    637					 PHY_S6G_PLL_STATUS);
    638		/* wait for bit 12 to clear */
    639	} while (time_before(jiffies, deadline) && (val32 & BIT(12)));
    640
    641	if (val32 & BIT(12))
    642		return -ETIMEDOUT;
    643
    644	/* release lane reset */
    645	ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0);
    646	if (ret)
    647		return ret;
    648
    649	return phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
    650}