brintos

brintos / linux-shallow public Read only

0
0
Text · 16.6 KiB · b3e854f Raw
651 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/*3 * Driver for Microsemi VSC85xx PHYs4 *5 * Author: Bjarni Jonasson <bjarni.jonassoni@microchip.com>6 * License: Dual MIT/GPL7 * Copyright (c) 2021 Microsemi Corporation8 */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}651