linux/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
<<
>>
Prefs
   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 */
  49u8 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 */
  68static 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 */
  98static 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 */
 129static int
 130ice_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 */
 169static 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 */
 201int 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 */
 228static 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 */
 264static 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 */
 300static 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 */
 335static 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 */
 403bool 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                        break;
 415
 416                /* Somebody is holding the lock */
 417                usleep_range(10000, 20000);
 418        }
 419
 420        return !hw_lock;
 421}
 422
 423/**
 424 * ice_ptp_unlock - Release PTP global semaphore register lock
 425 * @hw: pointer to the HW struct
 426 *
 427 * Release the global PTP hardware semaphore lock. This is done by writing to
 428 * the PFTSYN_SEM register.
 429 */
 430void ice_ptp_unlock(struct ice_hw *hw)
 431{
 432        wr32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), 0);
 433}
 434
 435/**
 436 * ice_ptp_src_cmd - Prepare source timer for a timer command
 437 * @hw: pointer to HW structure
 438 * @cmd: Timer command
 439 *
 440 * Prepare the source timer for an upcoming timer sync command.
 441 */
 442static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
 443{
 444        u32 cmd_val;
 445        u8 tmr_idx;
 446
 447        tmr_idx = ice_get_ptp_src_clock_index(hw);
 448        cmd_val = tmr_idx << SEL_CPK_SRC;
 449
 450        switch (cmd) {
 451        case INIT_TIME:
 452                cmd_val |= GLTSYN_CMD_INIT_TIME;
 453                break;
 454        case INIT_INCVAL:
 455                cmd_val |= GLTSYN_CMD_INIT_INCVAL;
 456                break;
 457        case ADJ_TIME:
 458                cmd_val |= GLTSYN_CMD_ADJ_TIME;
 459                break;
 460        case ADJ_TIME_AT_TIME:
 461                cmd_val |= GLTSYN_CMD_ADJ_INIT_TIME;
 462                break;
 463        case READ_TIME:
 464                cmd_val |= GLTSYN_CMD_READ_TIME;
 465                break;
 466        }
 467
 468        wr32(hw, GLTSYN_CMD, cmd_val);
 469}
 470
 471/**
 472 * ice_ptp_tmr_cmd - Prepare and trigger a timer sync command
 473 * @hw: pointer to HW struct
 474 * @cmd: the command to issue
 475 *
 476 * Prepare the source timer and PHY timers and then trigger the requested
 477 * command. This causes the shadow registers previously written in preparation
 478 * for the command to be synchronously applied to both the source and PHY
 479 * timers.
 480 */
 481static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
 482{
 483        int status;
 484
 485        /* First, prepare the source timer */
 486        ice_ptp_src_cmd(hw, cmd);
 487
 488        /* Next, prepare the ports */
 489        status = ice_ptp_port_cmd_e810(hw, cmd);
 490        if (status) {
 491                ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY ports for timer command %u, status %d\n",
 492                          cmd, status);
 493                return status;
 494        }
 495
 496        /* Write the sync command register to drive both source and PHY timer commands
 497         * synchronously
 498         */
 499        wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
 500
 501        return 0;
 502}
 503
 504/**
 505 * ice_ptp_init_time - Initialize device time to provided value
 506 * @hw: pointer to HW struct
 507 * @time: 64bits of time (GLTSYN_TIME_L and GLTSYN_TIME_H)
 508 *
 509 * Initialize the device to the specified time provided. This requires a three
 510 * step process:
 511 *
 512 * 1) write the new init time to the source timer shadow registers
 513 * 2) write the new init time to the PHY timer shadow registers
 514 * 3) issue an init_time timer command to synchronously switch both the source
 515 *    and port timers to the new init time value at the next clock cycle.
 516 */
 517int ice_ptp_init_time(struct ice_hw *hw, u64 time)
 518{
 519        int status;
 520        u8 tmr_idx;
 521
 522        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
 523
 524        /* Source timers */
 525        wr32(hw, GLTSYN_SHTIME_L(tmr_idx), lower_32_bits(time));
 526        wr32(hw, GLTSYN_SHTIME_H(tmr_idx), upper_32_bits(time));
 527        wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
 528
 529        /* PHY timers */
 530        /* Fill Rx and Tx ports and send msg to PHY */
 531        status = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF);
 532        if (status)
 533                return status;
 534
 535        return ice_ptp_tmr_cmd(hw, INIT_TIME);
 536}
 537
 538/**
 539 * ice_ptp_write_incval - Program PHC with new increment value
 540 * @hw: pointer to HW struct
 541 * @incval: Source timer increment value per clock cycle
 542 *
 543 * Program the PHC with a new increment value. This requires a three-step
 544 * process:
 545 *
 546 * 1) Write the increment value to the source timer shadow registers
 547 * 2) Write the increment value to the PHY timer shadow registers
 548 * 3) Issue an INIT_INCVAL timer command to synchronously switch both the
 549 *    source and port timers to the new increment value at the next clock
 550 *    cycle.
 551 */
 552int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
 553{
 554        int status;
 555        u8 tmr_idx;
 556
 557        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
 558
 559        /* Shadow Adjust */
 560        wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
 561        wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
 562
 563        status = ice_ptp_prep_phy_incval_e810(hw, incval);
 564        if (status)
 565                return status;
 566
 567        return ice_ptp_tmr_cmd(hw, INIT_INCVAL);
 568}
 569
 570/**
 571 * ice_ptp_write_incval_locked - Program new incval while holding semaphore
 572 * @hw: pointer to HW struct
 573 * @incval: Source timer increment value per clock cycle
 574 *
 575 * Program a new PHC incval while holding the PTP semaphore.
 576 */
 577int ice_ptp_write_incval_locked(struct ice_hw *hw, u64 incval)
 578{
 579        int status;
 580
 581        if (!ice_ptp_lock(hw))
 582                return -EBUSY;
 583
 584        status = ice_ptp_write_incval(hw, incval);
 585
 586        ice_ptp_unlock(hw);
 587
 588        return status;
 589}
 590
 591/**
 592 * ice_ptp_adj_clock - Adjust PHC clock time atomically
 593 * @hw: pointer to HW struct
 594 * @adj: Adjustment in nanoseconds
 595 *
 596 * Perform an atomic adjustment of the PHC time by the specified number of
 597 * nanoseconds. This requires a three-step process:
 598 *
 599 * 1) Write the adjustment to the source timer shadow registers
 600 * 2) Write the adjustment to the PHY timer shadow registers
 601 * 3) Issue an ADJ_TIME timer command to synchronously apply the adjustment to
 602 *    both the source and port timers at the next clock cycle.
 603 */
 604int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
 605{
 606        int status;
 607        u8 tmr_idx;
 608
 609        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
 610
 611        /* Write the desired clock adjustment into the GLTSYN_SHADJ register.
 612         * For an ADJ_TIME command, this set of registers represents the value
 613         * to add to the clock time. It supports subtraction by interpreting
 614         * the value as a 2's complement integer.
 615         */
 616        wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
 617        wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
 618
 619        status = ice_ptp_prep_phy_adj_e810(hw, adj);
 620        if (status)
 621                return status;
 622
 623        return ice_ptp_tmr_cmd(hw, ADJ_TIME);
 624}
 625
 626/**
 627 * ice_read_phy_tstamp - Read a PHY timestamp from the timestamo block
 628 * @hw: pointer to the HW struct
 629 * @block: the block to read from
 630 * @idx: the timestamp index to read
 631 * @tstamp: on return, the 40bit timestamp value
 632 *
 633 * Read a 40bit timestamp value out of the timestamp block.
 634 */
 635int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
 636{
 637        return ice_read_phy_tstamp_e810(hw, block, idx, tstamp);
 638}
 639
 640/**
 641 * ice_clear_phy_tstamp - Clear a timestamp from the timestamp block
 642 * @hw: pointer to the HW struct
 643 * @block: the block to read from
 644 * @idx: the timestamp index to reset
 645 *
 646 * Clear a timestamp, resetting its valid bit, from the timestamp block.
 647 */
 648int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
 649{
 650        return ice_clear_phy_tstamp_e810(hw, block, idx);
 651}
 652