1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025, Intel Corporation. */ 3 4 #include "ice.h" 5 #include "ice_lib.h" 6 #include "ice_ptp_hw.h" 7 8 static const struct 9 ice_tspll_params_e82x e82x_tspll_params[NUM_ICE_TSPLL_FREQ] = { 10 [ICE_TSPLL_FREQ_25_000] = { 11 .refclk_pre_div = 1, 12 .post_pll_div = 6, 13 .feedback_div = 197, 14 .frac_n_div = 2621440, 15 }, 16 [ICE_TSPLL_FREQ_122_880] = { 17 .refclk_pre_div = 5, 18 .post_pll_div = 7, 19 .feedback_div = 223, 20 .frac_n_div = 524288 21 }, 22 [ICE_TSPLL_FREQ_125_000] = { 23 .refclk_pre_div = 5, 24 .post_pll_div = 7, 25 .feedback_div = 223, 26 .frac_n_div = 524288 27 }, 28 [ICE_TSPLL_FREQ_153_600] = { 29 .refclk_pre_div = 5, 30 .post_pll_div = 6, 31 .feedback_div = 159, 32 .frac_n_div = 1572864 33 }, 34 [ICE_TSPLL_FREQ_156_250] = { 35 .refclk_pre_div = 5, 36 .post_pll_div = 6, 37 .feedback_div = 159, 38 .frac_n_div = 1572864 39 }, 40 [ICE_TSPLL_FREQ_245_760] = { 41 .refclk_pre_div = 10, 42 .post_pll_div = 7, 43 .feedback_div = 223, 44 .frac_n_div = 524288 45 }, 46 }; 47 48 /** 49 * ice_tspll_clk_freq_str - Convert time_ref_freq to string 50 * @clk_freq: Clock frequency 51 * 52 * Return: specified TIME_REF clock frequency converted to a string. 53 */ 54 static const char *ice_tspll_clk_freq_str(enum ice_tspll_freq clk_freq) 55 { 56 switch (clk_freq) { 57 case ICE_TSPLL_FREQ_25_000: 58 return "25 MHz"; 59 case ICE_TSPLL_FREQ_122_880: 60 return "122.88 MHz"; 61 case ICE_TSPLL_FREQ_125_000: 62 return "125 MHz"; 63 case ICE_TSPLL_FREQ_153_600: 64 return "153.6 MHz"; 65 case ICE_TSPLL_FREQ_156_250: 66 return "156.25 MHz"; 67 case ICE_TSPLL_FREQ_245_760: 68 return "245.76 MHz"; 69 default: 70 return "Unknown"; 71 } 72 } 73 74 /** 75 * ice_tspll_default_freq - Return default frequency for a MAC type 76 * @mac_type: MAC type 77 * 78 * Return: default TSPLL frequency for a correct MAC type, -ERANGE otherwise. 79 */ 80 static enum ice_tspll_freq ice_tspll_default_freq(enum ice_mac_type mac_type) 81 { 82 switch (mac_type) { 83 case ICE_MAC_GENERIC: 84 return ICE_TSPLL_FREQ_25_000; 85 case ICE_MAC_GENERIC_3K_E825: 86 return ICE_TSPLL_FREQ_156_250; 87 default: 88 return -ERANGE; 89 } 90 } 91 92 /** 93 * ice_tspll_check_params - Check if TSPLL params are correct 94 * @hw: Pointer to the HW struct 95 * @clk_freq: Clock frequency to program 96 * @clk_src: Clock source to select (TIME_REF or TCXO) 97 * 98 * Return: true if TSPLL params are correct, false otherwise. 99 */ 100 static bool ice_tspll_check_params(struct ice_hw *hw, 101 enum ice_tspll_freq clk_freq, 102 enum ice_clk_src clk_src) 103 { 104 if (clk_freq >= NUM_ICE_TSPLL_FREQ) { 105 dev_warn(ice_hw_to_dev(hw), "Invalid TSPLL frequency %u\n", 106 clk_freq); 107 return false; 108 } 109 110 if (clk_src >= NUM_ICE_CLK_SRC) { 111 dev_warn(ice_hw_to_dev(hw), "Invalid clock source %u\n", 112 clk_src); 113 return false; 114 } 115 116 if ((hw->mac_type == ICE_MAC_GENERIC_3K_E825 || 117 clk_src == ICE_CLK_SRC_TCXO) && 118 clk_freq != ice_tspll_default_freq(hw->mac_type)) { 119 dev_warn(ice_hw_to_dev(hw), "Unsupported frequency for this clock source\n"); 120 return false; 121 } 122 123 return true; 124 } 125 126 /** 127 * ice_tspll_clk_src_str - Convert time_ref_src to string 128 * @clk_src: Clock source 129 * 130 * Return: specified clock source converted to its string name 131 */ 132 static const char *ice_tspll_clk_src_str(enum ice_clk_src clk_src) 133 { 134 switch (clk_src) { 135 case ICE_CLK_SRC_TCXO: 136 return "TCXO"; 137 case ICE_CLK_SRC_TIME_REF: 138 return "TIME_REF"; 139 default: 140 return "Unknown"; 141 } 142 } 143 144 /** 145 * ice_tspll_log_cfg - Log current/new TSPLL configuration 146 * @hw: Pointer to the HW struct 147 * @enable: CGU enabled/disabled 148 * @clk_src: Current clock source 149 * @tspll_freq: Current clock frequency 150 * @lock: CGU lock status 151 * @new_cfg: true if this is a new config 152 */ 153 static void ice_tspll_log_cfg(struct ice_hw *hw, bool enable, u8 clk_src, 154 u8 tspll_freq, bool lock, bool new_cfg) 155 { 156 dev_dbg(ice_hw_to_dev(hw), 157 "%s TSPLL configuration -- %s, src %s, freq %s, PLL %s\n", 158 new_cfg ? "New" : "Current", str_enabled_disabled(enable), 159 ice_tspll_clk_src_str((enum ice_clk_src)clk_src), 160 ice_tspll_clk_freq_str((enum ice_tspll_freq)tspll_freq), 161 lock ? "locked" : "unlocked"); 162 } 163 164 /** 165 * ice_tspll_cfg_e82x - Configure the Clock Generation Unit TSPLL 166 * @hw: Pointer to the HW struct 167 * @clk_freq: Clock frequency to program 168 * @clk_src: Clock source to select (TIME_REF, or TCXO) 169 * 170 * Configure the Clock Generation Unit with the desired clock frequency and 171 * time reference, enabling the PLL which drives the PTP hardware clock. 172 * 173 * Return: 174 * * %0 - success 175 * * %-EINVAL - input parameters are incorrect 176 * * %-EBUSY - failed to lock TSPLL 177 * * %other - CGU read/write failure 178 */ 179 static int ice_tspll_cfg_e82x(struct ice_hw *hw, enum ice_tspll_freq clk_freq, 180 enum ice_clk_src clk_src) 181 { 182 u32 val, r9, r24; 183 int err; 184 185 err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9); 186 if (err) 187 return err; 188 189 err = ice_read_cgu_reg(hw, ICE_CGU_R24, &r24); 190 if (err) 191 return err; 192 193 err = ice_read_cgu_reg(hw, ICE_CGU_RO_BWM_LF, &val); 194 if (err) 195 return err; 196 197 ice_tspll_log_cfg(hw, !!FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r24), 198 FIELD_GET(ICE_CGU_R23_R24_TIME_REF_SEL, r24), 199 FIELD_GET(ICE_CGU_R9_TIME_REF_FREQ_SEL, r9), 200 !!FIELD_GET(ICE_CGU_RO_BWM_LF_TRUE_LOCK, val), 201 false); 202 203 /* Disable the PLL before changing the clock source or frequency */ 204 if (FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r24)) { 205 r24 &= ~ICE_CGU_R23_R24_TSPLL_ENABLE; 206 207 err = ice_write_cgu_reg(hw, ICE_CGU_R24, r24); 208 if (err) 209 return err; 210 } 211 212 /* Set the frequency */ 213 r9 &= ~ICE_CGU_R9_TIME_REF_FREQ_SEL; 214 r9 |= FIELD_PREP(ICE_CGU_R9_TIME_REF_FREQ_SEL, clk_freq); 215 err = ice_write_cgu_reg(hw, ICE_CGU_R9, r9); 216 if (err) 217 return err; 218 219 /* Configure the TSPLL feedback divisor */ 220 err = ice_read_cgu_reg(hw, ICE_CGU_R19, &val); 221 if (err) 222 return err; 223 224 val &= ~(ICE_CGU_R19_TSPLL_FBDIV_INTGR_E82X | ICE_CGU_R19_TSPLL_NDIVRATIO); 225 val |= FIELD_PREP(ICE_CGU_R19_TSPLL_FBDIV_INTGR_E82X, 226 e82x_tspll_params[clk_freq].feedback_div); 227 val |= FIELD_PREP(ICE_CGU_R19_TSPLL_NDIVRATIO, 1); 228 229 err = ice_write_cgu_reg(hw, ICE_CGU_R19, val); 230 if (err) 231 return err; 232 233 /* Configure the TSPLL post divisor */ 234 err = ice_read_cgu_reg(hw, ICE_CGU_R22, &val); 235 if (err) 236 return err; 237 238 val &= ~(ICE_CGU_R22_TIME1588CLK_DIV | 239 ICE_CGU_R22_TIME1588CLK_DIV2); 240 val |= FIELD_PREP(ICE_CGU_R22_TIME1588CLK_DIV, 241 e82x_tspll_params[clk_freq].post_pll_div); 242 243 err = ice_write_cgu_reg(hw, ICE_CGU_R22, val); 244 if (err) 245 return err; 246 247 /* Configure the TSPLL pre divisor and clock source */ 248 err = ice_read_cgu_reg(hw, ICE_CGU_R24, &r24); 249 if (err) 250 return err; 251 252 r24 &= ~(ICE_CGU_R23_R24_REF1588_CK_DIV | ICE_CGU_R24_FBDIV_FRAC | 253 ICE_CGU_R23_R24_TIME_REF_SEL); 254 r24 |= FIELD_PREP(ICE_CGU_R23_R24_REF1588_CK_DIV, 255 e82x_tspll_params[clk_freq].refclk_pre_div); 256 r24 |= FIELD_PREP(ICE_CGU_R24_FBDIV_FRAC, 257 e82x_tspll_params[clk_freq].frac_n_div); 258 r24 |= FIELD_PREP(ICE_CGU_R23_R24_TIME_REF_SEL, clk_src); 259 260 err = ice_write_cgu_reg(hw, ICE_CGU_R24, r24); 261 if (err) 262 return err; 263 264 /* Wait to ensure everything is stable */ 265 usleep_range(10, 20); 266 267 /* Finally, enable the PLL */ 268 r24 |= ICE_CGU_R23_R24_TSPLL_ENABLE; 269 270 err = ice_write_cgu_reg(hw, ICE_CGU_R24, r24); 271 if (err) 272 return err; 273 274 /* Wait at least 1 ms to verify if the PLL locks */ 275 usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); 276 277 err = ice_read_cgu_reg(hw, ICE_CGU_RO_BWM_LF, &val); 278 if (err) 279 return err; 280 281 if (!(val & ICE_CGU_RO_BWM_LF_TRUE_LOCK)) { 282 dev_warn(ice_hw_to_dev(hw), "CGU PLL failed to lock\n"); 283 return -EBUSY; 284 } 285 286 err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9); 287 if (err) 288 return err; 289 err = ice_read_cgu_reg(hw, ICE_CGU_R24, &r24); 290 if (err) 291 return err; 292 293 ice_tspll_log_cfg(hw, !!FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r24), 294 FIELD_GET(ICE_CGU_R23_R24_TIME_REF_SEL, r24), 295 FIELD_GET(ICE_CGU_R9_TIME_REF_FREQ_SEL, r9), 296 true, true); 297 298 return 0; 299 } 300 301 /** 302 * ice_tspll_dis_sticky_bits_e82x - disable TSPLL sticky bits 303 * @hw: Pointer to the HW struct 304 * 305 * Configure the Clock Generation Unit TSPLL sticky bits so they don't latch on 306 * losing TSPLL lock, but always show current state. 307 * 308 * Return: 0 on success, other error codes when failed to read/write CGU. 309 */ 310 static int ice_tspll_dis_sticky_bits_e82x(struct ice_hw *hw) 311 { 312 u32 val; 313 int err; 314 315 err = ice_read_cgu_reg(hw, ICE_CGU_CNTR_BIST, &val); 316 if (err) 317 return err; 318 319 val &= ~(ICE_CGU_CNTR_BIST_PLLLOCK_SEL_0 | 320 ICE_CGU_CNTR_BIST_PLLLOCK_SEL_1); 321 322 return ice_write_cgu_reg(hw, ICE_CGU_CNTR_BIST, val); 323 } 324 325 /** 326 * ice_tspll_cfg_e825c - Configure the TSPLL for E825-C 327 * @hw: Pointer to the HW struct 328 * @clk_freq: Clock frequency to program 329 * @clk_src: Clock source to select (TIME_REF, or TCXO) 330 * 331 * Configure the Clock Generation Unit with the desired clock frequency and 332 * time reference, enabling the PLL which drives the PTP hardware clock. 333 * 334 * Return: 335 * * %0 - success 336 * * %-EINVAL - input parameters are incorrect 337 * * %-EBUSY - failed to lock TSPLL 338 * * %other - CGU read/write failure 339 */ 340 static int ice_tspll_cfg_e825c(struct ice_hw *hw, enum ice_tspll_freq clk_freq, 341 enum ice_clk_src clk_src) 342 { 343 u32 val, r9, r23; 344 int err; 345 346 err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9); 347 if (err) 348 return err; 349 350 err = ice_read_cgu_reg(hw, ICE_CGU_R23, &r23); 351 if (err) 352 return err; 353 354 err = ice_read_cgu_reg(hw, ICE_CGU_RO_LOCK, &val); 355 if (err) 356 return err; 357 358 ice_tspll_log_cfg(hw, !!FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r23), 359 FIELD_GET(ICE_CGU_R23_R24_TIME_REF_SEL, r23), 360 FIELD_GET(ICE_CGU_R9_TIME_REF_FREQ_SEL, r9), 361 !!FIELD_GET(ICE_CGU_RO_LOCK_TRUE_LOCK, val), 362 false); 363 364 /* Disable the PLL before changing the clock source or frequency */ 365 if (FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r23)) { 366 r23 &= ~ICE_CGU_R23_R24_TSPLL_ENABLE; 367 368 err = ice_write_cgu_reg(hw, ICE_CGU_R23, r23); 369 if (err) 370 return err; 371 } 372 373 if (FIELD_GET(ICE_CGU_R9_TIME_SYNC_EN, r9)) { 374 r9 &= ~ICE_CGU_R9_TIME_SYNC_EN; 375 376 err = ice_write_cgu_reg(hw, ICE_CGU_R9, r9); 377 if (err) 378 return err; 379 } 380 381 /* Set the frequency and enable the correct receiver */ 382 r9 &= ~(ICE_CGU_R9_TIME_REF_FREQ_SEL | ICE_CGU_R9_CLK_EREF0_EN | 383 ICE_CGU_R9_TIME_REF_EN); 384 r9 |= FIELD_PREP(ICE_CGU_R9_TIME_REF_FREQ_SEL, clk_freq); 385 if (clk_src == ICE_CLK_SRC_TCXO) 386 r9 |= ICE_CGU_R9_CLK_EREF0_EN; 387 else 388 r9 |= ICE_CGU_R9_TIME_REF_EN; 389 r9 |= ICE_CGU_R9_TIME_SYNC_EN; 390 err = ice_write_cgu_reg(hw, ICE_CGU_R9, r9); 391 if (err) 392 return err; 393 394 /* Choose the referenced frequency */ 395 err = ice_read_cgu_reg(hw, ICE_CGU_R16, &val); 396 if (err) 397 return err; 398 val &= ~ICE_CGU_R16_TSPLL_CK_REFCLKFREQ; 399 val |= FIELD_PREP(ICE_CGU_R16_TSPLL_CK_REFCLKFREQ, 400 ICE_TSPLL_CK_REFCLKFREQ_E825); 401 err = ice_write_cgu_reg(hw, ICE_CGU_R16, val); 402 if (err) 403 return err; 404 405 /* Configure the TSPLL feedback divisor */ 406 err = ice_read_cgu_reg(hw, ICE_CGU_R19, &val); 407 if (err) 408 return err; 409 410 val &= ~(ICE_CGU_R19_TSPLL_FBDIV_INTGR_E825 | 411 ICE_CGU_R19_TSPLL_NDIVRATIO); 412 val |= FIELD_PREP(ICE_CGU_R19_TSPLL_FBDIV_INTGR_E825, 413 ICE_TSPLL_FBDIV_INTGR_E825); 414 val |= FIELD_PREP(ICE_CGU_R19_TSPLL_NDIVRATIO, 415 ICE_TSPLL_NDIVRATIO_E825); 416 417 err = ice_write_cgu_reg(hw, ICE_CGU_R19, val); 418 if (err) 419 return err; 420 421 /* Configure the TSPLL post divisor, these two are constant */ 422 err = ice_read_cgu_reg(hw, ICE_CGU_R22, &val); 423 if (err) 424 return err; 425 426 val &= ~(ICE_CGU_R22_TIME1588CLK_DIV | 427 ICE_CGU_R22_TIME1588CLK_DIV2); 428 val |= FIELD_PREP(ICE_CGU_R22_TIME1588CLK_DIV, 5); 429 430 err = ice_write_cgu_reg(hw, ICE_CGU_R22, val); 431 if (err) 432 return err; 433 434 /* Configure the TSPLL pre divisor (constant) and clock source */ 435 err = ice_read_cgu_reg(hw, ICE_CGU_R23, &r23); 436 if (err) 437 return err; 438 439 r23 &= ~(ICE_CGU_R23_R24_REF1588_CK_DIV | ICE_CGU_R23_R24_TIME_REF_SEL); 440 r23 |= FIELD_PREP(ICE_CGU_R23_R24_TIME_REF_SEL, clk_src); 441 442 err = ice_write_cgu_reg(hw, ICE_CGU_R23, r23); 443 if (err) 444 return err; 445 446 /* Clear the R24 register. */ 447 err = ice_write_cgu_reg(hw, ICE_CGU_R24, 0); 448 if (err) 449 return err; 450 451 /* Wait to ensure everything is stable */ 452 usleep_range(10, 20); 453 454 /* Finally, enable the PLL */ 455 r23 |= ICE_CGU_R23_R24_TSPLL_ENABLE; 456 457 err = ice_write_cgu_reg(hw, ICE_CGU_R23, r23); 458 if (err) 459 return err; 460 461 /* Wait at least 1 ms to verify if the PLL locks */ 462 usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); 463 464 err = ice_read_cgu_reg(hw, ICE_CGU_RO_LOCK, &val); 465 if (err) 466 return err; 467 468 if (!(val & ICE_CGU_RO_LOCK_TRUE_LOCK)) { 469 dev_warn(ice_hw_to_dev(hw), "CGU PLL failed to lock\n"); 470 return -EBUSY; 471 } 472 473 err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9); 474 if (err) 475 return err; 476 err = ice_read_cgu_reg(hw, ICE_CGU_R23, &r23); 477 if (err) 478 return err; 479 480 ice_tspll_log_cfg(hw, !!FIELD_GET(ICE_CGU_R23_R24_TSPLL_ENABLE, r23), 481 FIELD_GET(ICE_CGU_R23_R24_TIME_REF_SEL, r23), 482 FIELD_GET(ICE_CGU_R9_TIME_REF_FREQ_SEL, r9), 483 true, true); 484 485 return 0; 486 } 487 488 /** 489 * ice_tspll_dis_sticky_bits_e825c - disable TSPLL sticky bits for E825-C 490 * @hw: Pointer to the HW struct 491 * 492 * Configure the Clock Generation Unit TSPLL sticky bits so they don't latch on 493 * losing TSPLL lock, but always show current state. 494 * 495 * Return: 0 on success, other error codes when failed to read/write CGU. 496 */ 497 static int ice_tspll_dis_sticky_bits_e825c(struct ice_hw *hw) 498 { 499 u32 val; 500 int err; 501 502 err = ice_read_cgu_reg(hw, ICE_CGU_BW_TDC, &val); 503 if (err) 504 return err; 505 506 val &= ~ICE_CGU_BW_TDC_PLLLOCK_SEL; 507 508 return ice_write_cgu_reg(hw, ICE_CGU_BW_TDC, val); 509 } 510 511 /** 512 * ice_tspll_cfg_pps_out_e825c - Enable/disable 1PPS output and set amplitude 513 * @hw: pointer to the HW struct 514 * @enable: true to enable 1PPS output, false to disable it 515 * 516 * Return: 0 on success, other negative error code when CGU read/write failed. 517 */ 518 int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable) 519 { 520 u32 val; 521 int err; 522 523 err = ice_read_cgu_reg(hw, ICE_CGU_R9, &val); 524 if (err) 525 return err; 526 527 val &= ~(ICE_CGU_R9_ONE_PPS_OUT_EN | ICE_CGU_R9_ONE_PPS_OUT_AMP); 528 val |= FIELD_PREP(ICE_CGU_R9_ONE_PPS_OUT_EN, enable) | 529 ICE_CGU_R9_ONE_PPS_OUT_AMP; 530 531 return ice_write_cgu_reg(hw, ICE_CGU_R9, val); 532 } 533 534 /** 535 * ice_tspll_cfg - Configure the Clock Generation Unit TSPLL 536 * @hw: Pointer to the HW struct 537 * @clk_freq: Clock frequency to program 538 * @clk_src: Clock source to select (TIME_REF, or TCXO) 539 * 540 * Configure the Clock Generation Unit with the desired clock frequency and 541 * time reference, enabling the TSPLL which drives the PTP hardware clock. 542 * 543 * Return: 0 on success, -ERANGE on unsupported MAC type, other negative error 544 * codes when failed to configure CGU. 545 */ 546 static int ice_tspll_cfg(struct ice_hw *hw, enum ice_tspll_freq clk_freq, 547 enum ice_clk_src clk_src) 548 { 549 switch (hw->mac_type) { 550 case ICE_MAC_GENERIC: 551 return ice_tspll_cfg_e82x(hw, clk_freq, clk_src); 552 case ICE_MAC_GENERIC_3K_E825: 553 return ice_tspll_cfg_e825c(hw, clk_freq, clk_src); 554 default: 555 return -ERANGE; 556 } 557 } 558 559 /** 560 * ice_tspll_dis_sticky_bits - disable TSPLL sticky bits 561 * @hw: Pointer to the HW struct 562 * 563 * Configure the Clock Generation Unit TSPLL sticky bits so they don't latch on 564 * losing TSPLL lock, but always show current state. 565 * 566 * Return: 0 on success, -ERANGE on unsupported MAC type. 567 */ 568 static int ice_tspll_dis_sticky_bits(struct ice_hw *hw) 569 { 570 switch (hw->mac_type) { 571 case ICE_MAC_GENERIC: 572 return ice_tspll_dis_sticky_bits_e82x(hw); 573 case ICE_MAC_GENERIC_3K_E825: 574 return ice_tspll_dis_sticky_bits_e825c(hw); 575 default: 576 return -ERANGE; 577 } 578 } 579 580 /** 581 * ice_tspll_init - Initialize TSPLL with settings from firmware 582 * @hw: Pointer to the HW structure 583 * 584 * Initialize the Clock Generation Unit of the E82X/E825 device. 585 * 586 * Return: 0 on success, other error codes when failed to read/write/cfg CGU. 587 */ 588 int ice_tspll_init(struct ice_hw *hw) 589 { 590 struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info; 591 enum ice_tspll_freq tspll_freq; 592 enum ice_clk_src clk_src; 593 int err; 594 595 /* Only E822, E823 and E825 products support TSPLL */ 596 if (hw->mac_type != ICE_MAC_GENERIC && 597 hw->mac_type != ICE_MAC_GENERIC_3K_E825) 598 return 0; 599 600 tspll_freq = (enum ice_tspll_freq)ts_info->time_ref; 601 clk_src = (enum ice_clk_src)ts_info->clk_src; 602 if (!ice_tspll_check_params(hw, tspll_freq, clk_src)) 603 return -EINVAL; 604 605 /* Disable sticky lock detection so lock status reported is accurate */ 606 err = ice_tspll_dis_sticky_bits(hw); 607 if (err) 608 return err; 609 610 /* Configure the TSPLL using the parameters from the function 611 * capabilities. 612 */ 613 err = ice_tspll_cfg(hw, tspll_freq, clk_src); 614 if (err) { 615 dev_warn(ice_hw_to_dev(hw), "Failed to lock TSPLL to predefined frequency. Retrying with fallback frequency.\n"); 616 617 /* Try to lock to internal TCXO as a fallback. */ 618 tspll_freq = ice_tspll_default_freq(hw->mac_type); 619 clk_src = ICE_CLK_SRC_TCXO; 620 err = ice_tspll_cfg(hw, tspll_freq, clk_src); 621 if (err) 622 dev_warn(ice_hw_to_dev(hw), "Failed to lock TSPLL to fallback frequency.\n"); 623 } 624 625 return err; 626 } 627