1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2021, Intel Corporation. */ 3 4 #include "ice_common.h" 5 #include "ice_ptp_hw.h" 6 7 /* Low level functions for interacting with and managing the device clock used 8 * for the Precision Time Protocol. 9 * 10 * The ice hardware represents the current time using three registers: 11 * 12 * GLTSYN_TIME_H GLTSYN_TIME_L GLTSYN_TIME_R 13 * +---------------+ +---------------+ +---------------+ 14 * | 32 bits | | 32 bits | | 32 bits | 15 * +---------------+ +---------------+ +---------------+ 16 * 17 * The registers are incremented every clock tick using a 40bit increment 18 * value defined over two registers: 19 * 20 * GLTSYN_INCVAL_H GLTSYN_INCVAL_L 21 * +---------------+ +---------------+ 22 * | 8 bit s | | 32 bits | 23 * +---------------+ +---------------+ 24 * 25 * The increment value is added to the GLSTYN_TIME_R and GLSTYN_TIME_L 26 * registers every clock source tick. Depending on the specific device 27 * configuration, the clock source frequency could be one of a number of 28 * values. 29 * 30 * For E810 devices, the increment frequency is 812.5 MHz 31 * 32 * The hardware captures timestamps in the PHY for incoming packets, and for 33 * outgoing packets on request. To support this, the PHY maintains a timer 34 * that matches the lower 64 bits of the global source timer. 35 * 36 * In order to ensure that the PHY timers and the source timer are equivalent, 37 * shadow registers are used to prepare the desired initial values. A special 38 * sync command is issued to trigger copying from the shadow registers into 39 * the appropriate source and PHY registers simultaneously. 40 */ 41 42 /** 43 * ice_get_ptp_src_clock_index - determine source clock index 44 * @hw: pointer to HW struct 45 * 46 * Determine the source clock index currently in use, based on device 47 * capabilities reported during initialization. 48 */ 49 u8 ice_get_ptp_src_clock_index(struct ice_hw *hw) 50 { 51 return hw->func_caps.ts_func_info.tmr_index_assoc; 52 } 53 54 /* E810 functions 55 * 56 * The following functions operate on the E810 series devices which use 57 * a separate external PHY. 58 */ 59 60 /** 61 * ice_read_phy_reg_e810 - Read register from external PHY on E810 62 * @hw: pointer to the HW struct 63 * @addr: the address to read from 64 * @val: On return, the value read from the PHY 65 * 66 * Read a register from the external PHY on the E810 device. 67 */ 68 static int ice_read_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 *val) 69 { 70 struct ice_sbq_msg_input msg = {0}; 71 int status; 72 73 msg.msg_addr_low = lower_16_bits(addr); 74 msg.msg_addr_high = upper_16_bits(addr); 75 msg.opcode = ice_sbq_msg_rd; 76 msg.dest_dev = rmn_0; 77 78 status = ice_sbq_rw_reg(hw, &msg); 79 if (status) { 80 ice_debug(hw, ICE_DBG_PTP, "Failed to send message to PHY, status %d\n", 81 status); 82 return status; 83 } 84 85 *val = msg.data; 86 87 return 0; 88 } 89 90 /** 91 * ice_write_phy_reg_e810 - Write register on external PHY on E810 92 * @hw: pointer to the HW struct 93 * @addr: the address to writem to 94 * @val: the value to write to the PHY 95 * 96 * Write a value to a register of the external PHY on the E810 device. 97 */ 98 static int ice_write_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 val) 99 { 100 struct ice_sbq_msg_input msg = {0}; 101 int status; 102 103 msg.msg_addr_low = lower_16_bits(addr); 104 msg.msg_addr_high = upper_16_bits(addr); 105 msg.opcode = ice_sbq_msg_wr; 106 msg.dest_dev = rmn_0; 107 msg.data = val; 108 109 status = ice_sbq_rw_reg(hw, &msg); 110 if (status) { 111 ice_debug(hw, ICE_DBG_PTP, "Failed to send message to PHY, status %d\n", 112 status); 113 return status; 114 } 115 116 return 0; 117 } 118 119 /** 120 * ice_read_phy_tstamp_e810 - Read a PHY timestamp out of the external PHY 121 * @hw: pointer to the HW struct 122 * @lport: the lport to read from 123 * @idx: the timestamp index to read 124 * @tstamp: on return, the 40bit timestamp value 125 * 126 * Read a 40bit timestamp value out of the timestamp block of the external PHY 127 * on the E810 device. 128 */ 129 static int 130 ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp) 131 { 132 u32 lo_addr, hi_addr, lo, hi; 133 int status; 134 135 lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx); 136 hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx); 137 138 status = ice_read_phy_reg_e810(hw, lo_addr, &lo); 139 if (status) { 140 ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, status %d\n", 141 status); 142 return status; 143 } 144 145 status = ice_read_phy_reg_e810(hw, hi_addr, &hi); 146 if (status) { 147 ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, status %d\n", 148 status); 149 return status; 150 } 151 152 /* For E810 devices, the timestamp is reported with the lower 32 bits 153 * in the low register, and the upper 8 bits in the high register. 154 */ 155 *tstamp = ((u64)hi) << TS_HIGH_S | ((u64)lo & TS_LOW_M); 156 157 return 0; 158 } 159 160 /** 161 * ice_clear_phy_tstamp_e810 - Clear a timestamp from the external PHY 162 * @hw: pointer to the HW struct 163 * @lport: the lport to read from 164 * @idx: the timestamp index to reset 165 * 166 * Clear a timestamp, resetting its valid bit, from the timestamp block of the 167 * external PHY on the E810 device. 168 */ 169 static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx) 170 { 171 u32 lo_addr, hi_addr; 172 int status; 173 174 lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx); 175 hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx); 176 177 status = ice_write_phy_reg_e810(hw, lo_addr, 0); 178 if (status) { 179 ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, status %d\n", 180 status); 181 return status; 182 } 183 184 status = ice_write_phy_reg_e810(hw, hi_addr, 0); 185 if (status) { 186 ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, status %d\n", 187 status); 188 return status; 189 } 190 191 return 0; 192 } 193 194 /** 195 * ice_ptp_init_phy_e810 - Enable PTP function on the external PHY 196 * @hw: pointer to HW struct 197 * 198 * Enable the timesync PTP functionality for the external PHY connected to 199 * this function. 200 */ 201 int ice_ptp_init_phy_e810(struct ice_hw *hw) 202 { 203 int status; 204 u8 tmr_idx; 205 206 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 207 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_ENA(tmr_idx), 208 GLTSYN_ENA_TSYN_ENA_M); 209 if (status) 210 ice_debug(hw, ICE_DBG_PTP, "PTP failed in ena_phy_time_syn %d\n", 211 status); 212 213 return status; 214 } 215 216 /** 217 * ice_ptp_prep_phy_time_e810 - Prepare PHY port with initial time 218 * @hw: Board private structure 219 * @time: Time to initialize the PHY port clock to 220 * 221 * Program the PHY port ETH_GLTSYN_SHTIME registers in preparation setting the 222 * initial clock time. The time will not actually be programmed until the 223 * driver issues an INIT_TIME command. 224 * 225 * The time value is the upper 32 bits of the PHY timer, usually in units of 226 * nominal nanoseconds. 227 */ 228 static int ice_ptp_prep_phy_time_e810(struct ice_hw *hw, u32 time) 229 { 230 int status; 231 u8 tmr_idx; 232 233 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 234 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_0(tmr_idx), 0); 235 if (status) { 236 ice_debug(hw, ICE_DBG_PTP, "Failed to write SHTIME_0, status %d\n", 237 status); 238 return status; 239 } 240 241 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_L(tmr_idx), time); 242 if (status) { 243 ice_debug(hw, ICE_DBG_PTP, "Failed to write SHTIME_L, status %d\n", 244 status); 245 return status; 246 } 247 248 return 0; 249 } 250 251 /** 252 * ice_ptp_prep_phy_adj_e810 - Prep PHY port for a time adjustment 253 * @hw: pointer to HW struct 254 * @adj: adjustment value to program 255 * 256 * Prepare the PHY port for an atomic adjustment by programming the PHY 257 * ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual adjustment 258 * is completed by issuing an ADJ_TIME sync command. 259 * 260 * The adjustment value only contains the portion used for the upper 32bits of 261 * the PHY timer, usually in units of nominal nanoseconds. Negative 262 * adjustments are supported using 2s complement arithmetic. 263 */ 264 static int ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj) 265 { 266 int status; 267 u8 tmr_idx; 268 269 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 270 271 /* Adjustments are represented as signed 2's complement values in 272 * nanoseconds. Sub-nanosecond adjustment is not supported. 273 */ 274 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_L(tmr_idx), 0); 275 if (status) { 276 ice_debug(hw, ICE_DBG_PTP, "Failed to write adj to PHY SHADJ_L, status %d\n", 277 status); 278 return status; 279 } 280 281 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_H(tmr_idx), adj); 282 if (status) { 283 ice_debug(hw, ICE_DBG_PTP, "Failed to write adj to PHY SHADJ_H, status %d\n", 284 status); 285 return status; 286 } 287 288 return 0; 289 } 290 291 /** 292 * ice_ptp_prep_phy_incval_e810 - Prep PHY port increment value change 293 * @hw: pointer to HW struct 294 * @incval: The new 40bit increment value to prepare 295 * 296 * Prepare the PHY port for a new increment value by programming the PHY 297 * ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual change is 298 * completed by issuing an INIT_INCVAL command. 299 */ 300 static int ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval) 301 { 302 u32 high, low; 303 int status; 304 u8 tmr_idx; 305 306 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 307 low = lower_32_bits(incval); 308 high = upper_32_bits(incval); 309 310 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_L(tmr_idx), low); 311 if (status) { 312 ice_debug(hw, ICE_DBG_PTP, "Failed to write incval to PHY SHADJ_L, status %d\n", 313 status); 314 return status; 315 } 316 317 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_H(tmr_idx), high); 318 if (status) { 319 ice_debug(hw, ICE_DBG_PTP, "Failed to write incval PHY SHADJ_H, status %d\n", 320 status); 321 return status; 322 } 323 324 return 0; 325 } 326 327 /** 328 * ice_ptp_port_cmd_e810 - Prepare all external PHYs for a timer command 329 * @hw: pointer to HW struct 330 * @cmd: Command to be sent to the port 331 * 332 * Prepare the external PHYs connected to this device for a timer sync 333 * command. 334 */ 335 static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) 336 { 337 u32 cmd_val, val; 338 int status; 339 340 switch (cmd) { 341 case INIT_TIME: 342 cmd_val = GLTSYN_CMD_INIT_TIME; 343 break; 344 case INIT_INCVAL: 345 cmd_val = GLTSYN_CMD_INIT_INCVAL; 346 break; 347 case ADJ_TIME: 348 cmd_val = GLTSYN_CMD_ADJ_TIME; 349 break; 350 case READ_TIME: 351 cmd_val = GLTSYN_CMD_READ_TIME; 352 break; 353 case ADJ_TIME_AT_TIME: 354 cmd_val = GLTSYN_CMD_ADJ_INIT_TIME; 355 break; 356 } 357 358 /* Read, modify, write */ 359 status = ice_read_phy_reg_e810(hw, ETH_GLTSYN_CMD, &val); 360 if (status) { 361 ice_debug(hw, ICE_DBG_PTP, "Failed to read GLTSYN_CMD, status %d\n", status); 362 return status; 363 } 364 365 /* Modify necessary bits only and perform write */ 366 val &= ~TS_CMD_MASK_E810; 367 val |= cmd_val; 368 369 status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_CMD, val); 370 if (status) { 371 ice_debug(hw, ICE_DBG_PTP, "Failed to write back GLTSYN_CMD, status %d\n", status); 372 return status; 373 } 374 375 return 0; 376 } 377 378 /* Device agnostic functions 379 * 380 * The following functions implement useful behavior to hide the differences 381 * between E810 and other devices. They call the device-specific 382 * implementations where necessary. 383 * 384 * Currently, the driver only supports E810, but future work will enable 385 * support for E822-based devices. 386 */ 387 388 /** 389 * ice_ptp_lock - Acquire PTP global semaphore register lock 390 * @hw: pointer to the HW struct 391 * 392 * Acquire the global PTP hardware semaphore lock. Returns true if the lock 393 * was acquired, false otherwise. 394 * 395 * The PFTSYN_SEM register sets the busy bit on read, returning the previous 396 * value. If software sees the busy bit cleared, this means that this function 397 * acquired the lock (and the busy bit is now set). If software sees the busy 398 * bit set, it means that another function acquired the lock. 399 * 400 * Software must clear the busy bit with a write to release the lock for other 401 * functions when done. 402 */ 403 bool ice_ptp_lock(struct ice_hw *hw) 404 { 405 u32 hw_lock; 406 int i; 407 408 #define MAX_TRIES 5 409 410 for (i = 0; i < MAX_TRIES; i++) { 411 hw_lock = rd32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id)); 412 hw_lock = hw_lock & PFTSYN_SEM_BUSY_M; 413 if (hw_lock) { 414 /* Somebody is holding the lock */ 415 usleep_range(10000, 20000); 416 continue; 417 } else { 418 break; 419 } 420 } 421 422 return !hw_lock; 423 } 424 425 /** 426 * ice_ptp_unlock - Release PTP global semaphore register lock 427 * @hw: pointer to the HW struct 428 * 429 * Release the global PTP hardware semaphore lock. This is done by writing to 430 * the PFTSYN_SEM register. 431 */ 432 void ice_ptp_unlock(struct ice_hw *hw) 433 { 434 wr32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), 0); 435 } 436 437 /** 438 * ice_ptp_src_cmd - Prepare source timer for a timer command 439 * @hw: pointer to HW structure 440 * @cmd: Timer command 441 * 442 * Prepare the source timer for an upcoming timer sync command. 443 */ 444 static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) 445 { 446 u32 cmd_val; 447 u8 tmr_idx; 448 449 tmr_idx = ice_get_ptp_src_clock_index(hw); 450 cmd_val = tmr_idx << SEL_CPK_SRC; 451 452 switch (cmd) { 453 case INIT_TIME: 454 cmd_val |= GLTSYN_CMD_INIT_TIME; 455 break; 456 case INIT_INCVAL: 457 cmd_val |= GLTSYN_CMD_INIT_INCVAL; 458 break; 459 case ADJ_TIME: 460 cmd_val |= GLTSYN_CMD_ADJ_TIME; 461 break; 462 case ADJ_TIME_AT_TIME: 463 cmd_val |= GLTSYN_CMD_ADJ_INIT_TIME; 464 break; 465 case READ_TIME: 466 cmd_val |= GLTSYN_CMD_READ_TIME; 467 break; 468 } 469 470 wr32(hw, GLTSYN_CMD, cmd_val); 471 } 472 473 /** 474 * ice_ptp_tmr_cmd - Prepare and trigger a timer sync command 475 * @hw: pointer to HW struct 476 * @cmd: the command to issue 477 * 478 * Prepare the source timer and PHY timers and then trigger the requested 479 * command. This causes the shadow registers previously written in preparation 480 * for the command to be synchronously applied to both the source and PHY 481 * timers. 482 */ 483 static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) 484 { 485 int status; 486 487 /* First, prepare the source timer */ 488 ice_ptp_src_cmd(hw, cmd); 489 490 /* Next, prepare the ports */ 491 status = ice_ptp_port_cmd_e810(hw, cmd); 492 if (status) { 493 ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY ports for timer command %u, status %d\n", 494 cmd, status); 495 return status; 496 } 497 498 /* Write the sync command register to drive both source and PHY timer commands 499 * synchronously 500 */ 501 wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD); 502 503 return 0; 504 } 505 506 /** 507 * ice_ptp_init_time - Initialize device time to provided value 508 * @hw: pointer to HW struct 509 * @time: 64bits of time (GLTSYN_TIME_L and GLTSYN_TIME_H) 510 * 511 * Initialize the device to the specified time provided. This requires a three 512 * step process: 513 * 514 * 1) write the new init time to the source timer shadow registers 515 * 2) write the new init time to the PHY timer shadow registers 516 * 3) issue an init_time timer command to synchronously switch both the source 517 * and port timers to the new init time value at the next clock cycle. 518 */ 519 int ice_ptp_init_time(struct ice_hw *hw, u64 time) 520 { 521 int status; 522 u8 tmr_idx; 523 524 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 525 526 /* Source timers */ 527 wr32(hw, GLTSYN_SHTIME_L(tmr_idx), lower_32_bits(time)); 528 wr32(hw, GLTSYN_SHTIME_H(tmr_idx), upper_32_bits(time)); 529 wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0); 530 531 /* PHY timers */ 532 /* Fill Rx and Tx ports and send msg to PHY */ 533 status = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF); 534 if (status) 535 return status; 536 537 return ice_ptp_tmr_cmd(hw, INIT_TIME); 538 } 539 540 /** 541 * ice_ptp_write_incval - Program PHC with new increment value 542 * @hw: pointer to HW struct 543 * @incval: Source timer increment value per clock cycle 544 * 545 * Program the PHC with a new increment value. This requires a three-step 546 * process: 547 * 548 * 1) Write the increment value to the source timer shadow registers 549 * 2) Write the increment value to the PHY timer shadow registers 550 * 3) Issue an INIT_INCVAL timer command to synchronously switch both the 551 * source and port timers to the new increment value at the next clock 552 * cycle. 553 */ 554 int ice_ptp_write_incval(struct ice_hw *hw, u64 incval) 555 { 556 int status; 557 u8 tmr_idx; 558 559 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 560 561 /* Shadow Adjust */ 562 wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval)); 563 wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval)); 564 565 status = ice_ptp_prep_phy_incval_e810(hw, incval); 566 if (status) 567 return status; 568 569 return ice_ptp_tmr_cmd(hw, INIT_INCVAL); 570 } 571 572 /** 573 * ice_ptp_write_incval_locked - Program new incval while holding semaphore 574 * @hw: pointer to HW struct 575 * @incval: Source timer increment value per clock cycle 576 * 577 * Program a new PHC incval while holding the PTP semaphore. 578 */ 579 int ice_ptp_write_incval_locked(struct ice_hw *hw, u64 incval) 580 { 581 int status; 582 583 if (!ice_ptp_lock(hw)) 584 return -EBUSY; 585 586 status = ice_ptp_write_incval(hw, incval); 587 588 ice_ptp_unlock(hw); 589 590 return status; 591 } 592 593 /** 594 * ice_ptp_adj_clock - Adjust PHC clock time atomically 595 * @hw: pointer to HW struct 596 * @adj: Adjustment in nanoseconds 597 * 598 * Perform an atomic adjustment of the PHC time by the specified number of 599 * nanoseconds. This requires a three-step process: 600 * 601 * 1) Write the adjustment to the source timer shadow registers 602 * 2) Write the adjustment to the PHY timer shadow registers 603 * 3) Issue an ADJ_TIME timer command to synchronously apply the adjustment to 604 * both the source and port timers at the next clock cycle. 605 */ 606 int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj) 607 { 608 int status; 609 u8 tmr_idx; 610 611 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; 612 613 /* Write the desired clock adjustment into the GLTSYN_SHADJ register. 614 * For an ADJ_TIME command, this set of registers represents the value 615 * to add to the clock time. It supports subtraction by interpreting 616 * the value as a 2's complement integer. 617 */ 618 wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0); 619 wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj); 620 621 status = ice_ptp_prep_phy_adj_e810(hw, adj); 622 if (status) 623 return status; 624 625 return ice_ptp_tmr_cmd(hw, ADJ_TIME); 626 } 627 628 /** 629 * ice_read_phy_tstamp - Read a PHY timestamp from the timestamo block 630 * @hw: pointer to the HW struct 631 * @block: the block to read from 632 * @idx: the timestamp index to read 633 * @tstamp: on return, the 40bit timestamp value 634 * 635 * Read a 40bit timestamp value out of the timestamp block. 636 */ 637 int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp) 638 { 639 return ice_read_phy_tstamp_e810(hw, block, idx, tstamp); 640 } 641 642 /** 643 * ice_clear_phy_tstamp - Clear a timestamp from the timestamp block 644 * @hw: pointer to the HW struct 645 * @block: the block to read from 646 * @idx: the timestamp index to reset 647 * 648 * Clear a timestamp, resetting its valid bit, from the timestamp block. 649 */ 650 int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) 651 { 652 return ice_clear_phy_tstamp_e810(hw, block, idx); 653 } 654