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 14 static 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 29 static 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 43 static 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 60 static 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 89 static 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 113 static 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 138 static 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 162 static 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 184 static 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 203 static 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 222 static 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 235 static 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 247 static 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 270 static 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 */ 289 static 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 307 int 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