dpdk/drivers/net/ice/base/ice_ptp_hw.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2001-2022 Intel Corporation
   3 */
   4
   5#include "ice_type.h"
   6#include "ice_common.h"
   7#include "ice_ptp_hw.h"
   8#include "ice_ptp_consts.h"
   9#include "ice_cgu_regs.h"
  10
  11/* Low level functions for interacting with and managing the device clock used
  12 * for the Precision Time Protocol.
  13 *
  14 * The ice hardware represents the current time using three registers:
  15 *
  16 *    GLTSYN_TIME_H     GLTSYN_TIME_L     GLTSYN_TIME_R
  17 *  +---------------+ +---------------+ +---------------+
  18 *  |    32 bits    | |    32 bits    | |    32 bits    |
  19 *  +---------------+ +---------------+ +---------------+
  20 *
  21 * The registers are incremented every clock tick using a 40bit increment
  22 * value defined over two registers:
  23 *
  24 *                     GLTSYN_INCVAL_H   GLTSYN_INCVAL_L
  25 *                    +---------------+ +---------------+
  26 *                    |    8 bit s    | |    32 bits    |
  27 *                    +---------------+ +---------------+
  28 *
  29 * The increment value is added to the GLSTYN_TIME_R and GLSTYN_TIME_L
  30 * registers every clock source tick. Depending on the specific device
  31 * configuration, the clock source frequency could be one of a number of
  32 * values.
  33 *
  34 * For E810 devices, the increment frequency is 812.5 MHz
  35 *
  36 * For E822 devices the clock can be derived from different sources, and the
  37 * increment has an effective frequency of one of the following:
  38 * - 823.4375 MHz
  39 * - 783.36 MHz
  40 * - 796.875 MHz
  41 * - 816 MHz
  42 * - 830.078125 MHz
  43 * - 783.36 MHz
  44 *
  45 * The hardware captures timestamps in the PHY for incoming packets, and for
  46 * outgoing packets on request. To support this, the PHY maintains a timer
  47 * that matches the lower 64 bits of the global source timer.
  48 *
  49 * In order to ensure that the PHY timers and the source timer are equivalent,
  50 * shadow registers are used to prepare the desired initial values. A special
  51 * sync command is issued to trigger copying from the shadow registers into
  52 * the appropriate source and PHY registers simultaneously.
  53 *
  54 * The driver supports devices which have different PHYs with subtly different
  55 * mechanisms to program and control the timers. We divide the devices into
  56 * families named after the first major device, E810 and similar devices, and
  57 * E822 and similar devices.
  58 *
  59 * - E822 based devices have additional support for fine grained Vernier
  60 *   calibration which requires significant setup
  61 * - The layout of timestamp data in the PHY register blocks is different
  62 * - The way timer synchronization commands are issued is different.
  63 *
  64 * To support this, very low level functions have an e810 or e822 suffix
  65 * indicating what type of device they work on. Higher level abstractions for
  66 * tasks that can be done on both devices do not have the suffix and will
  67 * correctly look up the appropriate low level function when running.
  68 *
  69 * Functions which only make sense on a single device family may not have
  70 * a suitable generic implementation
  71 */
  72
  73/**
  74 * ice_get_ptp_src_clock_index - determine source clock index
  75 * @hw: pointer to HW struct
  76 *
  77 * Determine the source clock index currently in use, based on device
  78 * capabilities reported during initialization.
  79 */
  80u8 ice_get_ptp_src_clock_index(struct ice_hw *hw)
  81{
  82        return hw->func_caps.ts_func_info.tmr_index_assoc;
  83}
  84
  85/**
  86 * ice_ptp_read_src_incval - Read source timer increment value
  87 * @hw: pointer to HW struct
  88 *
  89 * Read the increment value of the source timer and return it.
  90 */
  91u64 ice_ptp_read_src_incval(struct ice_hw *hw)
  92{
  93        u32 lo, hi;
  94        u8 tmr_idx;
  95
  96        tmr_idx = ice_get_ptp_src_clock_index(hw);
  97
  98        lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
  99        hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
 100
 101        return ((u64)(hi & INCVAL_HIGH_M) << 32) | lo;
 102}
 103
 104/**
 105 * ice_read_cgu_reg_e822 - Read a CGU register
 106 * @hw: pointer to the HW struct
 107 * @addr: Register address to read
 108 * @val: storage for register value read
 109 *
 110 * Read the contents of a register of the Clock Generation Unit. Only
 111 * applicable to E822 devices.
 112 */
 113static enum ice_status
 114ice_read_cgu_reg_e822(struct ice_hw *hw, u16 addr, u32 *val)
 115{
 116        struct ice_sbq_msg_input cgu_msg;
 117        enum ice_status status;
 118
 119        cgu_msg.opcode = ice_sbq_msg_rd;
 120        cgu_msg.dest_dev = cgu;
 121        cgu_msg.msg_addr_low = addr;
 122        cgu_msg.msg_addr_high = 0x0;
 123
 124        status = ice_sbq_rw_reg_lp(hw, &cgu_msg, true);
 125        if (status) {
 126                ice_debug(hw, ICE_DBG_PTP, "Failed to read CGU register 0x%04x, status %d\n",
 127                          addr, status);
 128                return status;
 129        }
 130
 131        *val = cgu_msg.data;
 132
 133        return ICE_SUCCESS;
 134}
 135
 136/**
 137 * ice_write_cgu_reg_e822 - Write a CGU register
 138 * @hw: pointer to the HW struct
 139 * @addr: Register address to write
 140 * @val: value to write into the register
 141 *
 142 * Write the specified value to a register of the Clock Generation Unit. Only
 143 * applicable to E822 devices.
 144 */
 145static enum ice_status
 146ice_write_cgu_reg_e822(struct ice_hw *hw, u16 addr, u32 val)
 147{
 148        struct ice_sbq_msg_input cgu_msg;
 149        enum ice_status status;
 150
 151        cgu_msg.opcode = ice_sbq_msg_wr;
 152        cgu_msg.dest_dev = cgu;
 153        cgu_msg.msg_addr_low = addr;
 154        cgu_msg.msg_addr_high = 0x0;
 155        cgu_msg.data = val;
 156
 157        status = ice_sbq_rw_reg_lp(hw, &cgu_msg, true);
 158        if (status) {
 159                ice_debug(hw, ICE_DBG_PTP, "Failed to write CGU register 0x%04x, status %d\n",
 160                          addr, status);
 161                return status;
 162        }
 163
 164        return ICE_SUCCESS;
 165}
 166
 167/**
 168 * ice_clk_freq_str - Convert time_ref_freq to string
 169 * @clk_freq: Clock frequency
 170 *
 171 * Convert the specified TIME_REF clock frequency to a string.
 172 */
 173static const char *ice_clk_freq_str(u8 clk_freq)
 174{
 175        switch ((enum ice_time_ref_freq)clk_freq) {
 176        case ICE_TIME_REF_FREQ_25_000:
 177                return "25 MHz";
 178        case ICE_TIME_REF_FREQ_122_880:
 179                return "122.88 MHz";
 180        case ICE_TIME_REF_FREQ_125_000:
 181                return "125 MHz";
 182        case ICE_TIME_REF_FREQ_153_600:
 183                return "153.6 MHz";
 184        case ICE_TIME_REF_FREQ_156_250:
 185                return "156.25 MHz";
 186        case ICE_TIME_REF_FREQ_245_760:
 187                return "245.76 MHz";
 188        default:
 189                return "Unknown";
 190        }
 191}
 192
 193/**
 194 * ice_clk_src_str - Convert time_ref_src to string
 195 * @clk_src: Clock source
 196 *
 197 * Convert the specified clock source to its string name.
 198 */
 199static const char *ice_clk_src_str(u8 clk_src)
 200{
 201        switch ((enum ice_clk_src)clk_src) {
 202        case ICE_CLK_SRC_TCX0:
 203                return "TCX0";
 204        case ICE_CLK_SRC_TIME_REF:
 205                return "TIME_REF";
 206        default:
 207                return "Unknown";
 208        }
 209}
 210
 211/**
 212 * ice_cfg_cgu_pll_e822 - Configure the Clock Generation Unit
 213 * @hw: pointer to the HW struct
 214 * @clk_freq: Clock frequency to program
 215 * @clk_src: Clock source to select (TIME_REF, or TCX0)
 216 *
 217 * Configure the Clock Generation Unit with the desired clock frequency and
 218 * time reference, enabling the PLL which drives the PTP hardware clock.
 219 */
 220enum ice_status
 221ice_cfg_cgu_pll_e822(struct ice_hw *hw, enum ice_time_ref_freq clk_freq,
 222                     enum ice_clk_src clk_src)
 223{
 224        union tspll_ro_bwm_lf bwm_lf;
 225        union nac_cgu_dword19 dw19;
 226        union nac_cgu_dword22 dw22;
 227        union nac_cgu_dword24 dw24;
 228        union nac_cgu_dword9 dw9;
 229        enum ice_status status;
 230
 231        if (clk_freq >= NUM_ICE_TIME_REF_FREQ) {
 232                ice_warn(hw, "Invalid TIME_REF frequency %u\n", clk_freq);
 233                return ICE_ERR_PARAM;
 234        }
 235
 236        if (clk_src >= NUM_ICE_CLK_SRC) {
 237                ice_warn(hw, "Invalid clock source %u\n", clk_src);
 238                return ICE_ERR_PARAM;
 239        }
 240
 241        if (clk_src == ICE_CLK_SRC_TCX0 &&
 242            clk_freq != ICE_TIME_REF_FREQ_25_000) {
 243                ice_warn(hw, "TCX0 only supports 25 MHz frequency\n");
 244                return ICE_ERR_PARAM;
 245        }
 246
 247        status = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD9, &dw9.val);
 248        if (status)
 249                return status;
 250
 251        status = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val);
 252        if (status)
 253                return status;
 254
 255        status = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val);
 256        if (status)
 257                return status;
 258
 259        /* Log the current clock configuration */
 260        ice_debug(hw, ICE_DBG_PTP, "Current CGU configuration -- %s, clk_src %s, clk_freq %s, PLL %s\n",
 261                  dw24.field.ts_pll_enable ? "enabled" : "disabled",
 262                  ice_clk_src_str(dw24.field.time_ref_sel),
 263                  ice_clk_freq_str(dw9.field.time_ref_freq_sel),
 264                  bwm_lf.field.plllock_true_lock_cri ? "locked" : "unlocked");
 265
 266        /* Disable the PLL before changing the clock source or frequency */
 267        if (dw24.field.ts_pll_enable) {
 268                dw24.field.ts_pll_enable = 0;
 269
 270                status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val);
 271                if (status)
 272                        return status;
 273        }
 274
 275        /* Set the frequency */
 276        dw9.field.time_ref_freq_sel = clk_freq;
 277        status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD9, dw9.val);
 278        if (status)
 279                return status;
 280
 281        /* Configure the TS PLL feedback divisor */
 282        status = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD19, &dw19.val);
 283        if (status)
 284                return status;
 285
 286        dw19.field.tspll_fbdiv_intgr = e822_cgu_params[clk_freq].feedback_div;
 287        dw19.field.tspll_ndivratio = 1;
 288
 289        status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD19, dw19.val);
 290        if (status)
 291                return status;
 292
 293        /* Configure the TS PLL post divisor */
 294        status = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD22, &dw22.val);
 295        if (status)
 296                return status;
 297
 298        dw22.field.time1588clk_div = e822_cgu_params[clk_freq].post_pll_div;
 299        dw22.field.time1588clk_sel_div2 = 0;
 300
 301        status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD22, dw22.val);
 302        if (status)
 303                return status;
 304
 305        /* Configure the TS PLL pre divisor and clock source */
 306        status = ice_read_cgu_reg_e822(hw, NAC_CGU_DWORD24, &dw24.val);
 307        if (status)
 308                return status;
 309
 310        dw24.field.ref1588_ck_div = e822_cgu_params[clk_freq].refclk_pre_div;
 311        dw24.field.tspll_fbdiv_frac = e822_cgu_params[clk_freq].frac_n_div;
 312        dw24.field.time_ref_sel = clk_src;
 313
 314        status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val);
 315        if (status)
 316                return status;
 317
 318        /* Finally, enable the PLL */
 319        dw24.field.ts_pll_enable = 1;
 320
 321        status = ice_write_cgu_reg_e822(hw, NAC_CGU_DWORD24, dw24.val);
 322        if (status)
 323                return status;
 324
 325        /* Wait to verify if the PLL locks */
 326        ice_msec_delay(1, true);
 327
 328        status = ice_read_cgu_reg_e822(hw, TSPLL_RO_BWM_LF, &bwm_lf.val);
 329        if (status)
 330                return status;
 331
 332        if (!bwm_lf.field.plllock_true_lock_cri) {
 333                ice_warn(hw, "CGU PLL failed to lock\n");
 334                return ICE_ERR_NOT_READY;
 335        }
 336
 337        /* Log the current clock configuration */
 338        ice_debug(hw, ICE_DBG_PTP, "New CGU configuration -- %s, clk_src %s, clk_freq %s, PLL %s\n",
 339                  dw24.field.ts_pll_enable ? "enabled" : "disabled",
 340                  ice_clk_src_str(dw24.field.time_ref_sel),
 341                  ice_clk_freq_str(dw9.field.time_ref_freq_sel),
 342                  bwm_lf.field.plllock_true_lock_cri ? "locked" : "unlocked");
 343
 344        return ICE_SUCCESS;
 345}
 346
 347/**
 348 * ice_init_cgu_e822 - Initialize CGU with settings from firmware
 349 * @hw: pointer to the HW structure
 350 *
 351 * Initialize the Clock Generation Unit of the E822 device.
 352 */
 353static enum ice_status ice_init_cgu_e822(struct ice_hw *hw)
 354{
 355        struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info;
 356        union tspll_cntr_bist_settings cntr_bist;
 357        enum ice_status status;
 358
 359        status = ice_read_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS,
 360                                       &cntr_bist.val);
 361        if (status)
 362                return status;
 363
 364        /* Disable sticky lock detection so lock status reported is accurate */
 365        cntr_bist.field.i_plllock_sel_0 = 0;
 366        cntr_bist.field.i_plllock_sel_1 = 0;
 367
 368        status = ice_write_cgu_reg_e822(hw, TSPLL_CNTR_BIST_SETTINGS,
 369                                        cntr_bist.val);
 370        if (status)
 371                return status;
 372
 373        /* Configure the CGU PLL using the parameters from the function
 374         * capabilities.
 375         */
 376        status = ice_cfg_cgu_pll_e822(hw, ts_info->time_ref,
 377                                      (enum ice_clk_src)ts_info->clk_src);
 378        if (status)
 379                return status;
 380
 381        return ICE_SUCCESS;
 382}
 383
 384/**
 385 * ice_ptp_src_cmd - Prepare source timer for a timer command
 386 * @hw: pointer to HW structure
 387 * @cmd: Timer command
 388 *
 389 * Prepare the source timer for an upcoming timer sync command.
 390 */
 391void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
 392{
 393        u32 cmd_val;
 394        u8 tmr_idx;
 395
 396        tmr_idx = ice_get_ptp_src_clock_index(hw);
 397        cmd_val = tmr_idx << SEL_CPK_SRC;
 398
 399        switch (cmd) {
 400        case ICE_PTP_INIT_TIME:
 401                cmd_val |= GLTSYN_CMD_INIT_TIME;
 402                break;
 403        case ICE_PTP_INIT_INCVAL:
 404                cmd_val |= GLTSYN_CMD_INIT_INCVAL;
 405                break;
 406        case ICE_PTP_ADJ_TIME:
 407                cmd_val |= GLTSYN_CMD_ADJ_TIME;
 408                break;
 409        case ICE_PTP_ADJ_TIME_AT_TIME:
 410                cmd_val |= GLTSYN_CMD_ADJ_INIT_TIME;
 411                break;
 412        case ICE_PTP_READ_TIME:
 413                cmd_val |= GLTSYN_CMD_READ_TIME;
 414                break;
 415        case ICE_PTP_NOP:
 416                break;
 417        default:
 418                ice_warn(hw, "Unknown timer command %u\n", cmd);
 419                return;
 420        }
 421
 422        wr32(hw, GLTSYN_CMD, cmd_val);
 423}
 424
 425/**
 426 * ice_ptp_exec_tmr_cmd - Execute all prepared timer commands
 427 * @hw: pointer to HW struct
 428 *
 429 * Write the SYNC_EXEC_CMD bit to the GLTSYN_CMD_SYNC register, and flush the
 430 * write immediately. This triggers the hardware to begin executing all of the
 431 * source and PHY timer commands synchronously.
 432 */
 433static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw)
 434{
 435        wr32(hw, GLTSYN_CMD_SYNC, SYNC_EXEC_CMD);
 436        ice_flush(hw);
 437}
 438
 439/**
 440 * ice_ptp_clean_cmd - Clean the timer command register
 441 * @hw: pointer to HW struct
 442 *
 443 * Zero out the GLTSYN_CMD to avoid any residual command execution.
 444 */
 445static void ice_ptp_clean_cmd(struct ice_hw *hw)
 446{
 447        wr32(hw, GLTSYN_CMD, 0);
 448        ice_flush(hw);
 449}
 450
 451/* 56G PHY access functions */
 452static const u32 eth56g_port_base[ICE_NUM_PHY_PORTS] = {
 453        ICE_PHY0_BASE,
 454        ICE_PHY1_BASE,
 455        ICE_PHY2_BASE,
 456        ICE_PHY3_BASE,
 457        ICE_PHY4_BASE,
 458};
 459
 460/**
 461 * ice_write_phy_eth56g_raw_lp - Write a PHY port register with lock parameter
 462 * @hw: pointer to the HW struct
 463 * @reg_addr: PHY register address
 464 * @val: Value to write
 465 * @lock_sbq: true to lock the sideband queue
 466 */
 467static enum ice_status
 468ice_write_phy_eth56g_raw_lp(struct ice_hw *hw,  u32 reg_addr, u32 val,
 469                            bool lock_sbq)
 470{
 471        struct ice_sbq_msg_input phy_msg;
 472        enum ice_status status;
 473
 474        phy_msg.opcode = ice_sbq_msg_wr;
 475
 476        phy_msg.msg_addr_low = ICE_LO_WORD(reg_addr);
 477        phy_msg.msg_addr_high = ICE_HI_WORD(reg_addr);
 478
 479        phy_msg.data = val;
 480        phy_msg.dest_dev = phy_56g;
 481
 482        status = ice_sbq_rw_reg_lp(hw, &phy_msg, lock_sbq);
 483
 484        if (status)
 485                ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
 486                          status);
 487
 488        return status;
 489}
 490
 491/**
 492 * ice_read_phy_eth56g_raw_lp - Read a PHY port register with lock parameter
 493 * @hw: pointer to the HW struct
 494 * @reg_addr: PHY port register address
 495 * @val: Pointer to the value to read (out param)
 496 * @lock_sbq: true to lock the sideband queue
 497 */
 498static enum ice_status
 499ice_read_phy_eth56g_raw_lp(struct ice_hw *hw, u32 reg_addr, u32 *val,
 500                           bool lock_sbq)
 501{
 502        struct ice_sbq_msg_input phy_msg;
 503        enum ice_status status;
 504
 505        phy_msg.opcode = ice_sbq_msg_rd;
 506
 507        phy_msg.msg_addr_low = ICE_LO_WORD(reg_addr);
 508        phy_msg.msg_addr_high = ICE_HI_WORD(reg_addr);
 509
 510        phy_msg.dest_dev = phy_56g;
 511
 512        status = ice_sbq_rw_reg_lp(hw, &phy_msg, lock_sbq);
 513
 514        if (status)
 515                ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
 516                          status);
 517        else
 518                *val = phy_msg.data;
 519
 520        return status;
 521}
 522
 523/**
 524 * ice_phy_port_reg_address_eth56g - Calculate a PHY port register address
 525 * @port: Port number to be written
 526 * @offset: Offset from PHY port register base
 527 * @address: The result address
 528 */
 529static enum ice_status
 530ice_phy_port_reg_address_eth56g(u8 port, u16 offset, u32 *address)
 531{
 532        u8 phy, lane;
 533
 534        if (port >= ICE_NUM_EXTERNAL_PORTS)
 535                return ICE_ERR_OUT_OF_RANGE;
 536
 537        phy = port / ICE_PORTS_PER_QUAD;
 538        lane = port % ICE_PORTS_PER_QUAD;
 539
 540        *address = offset + eth56g_port_base[phy] +
 541                   PHY_PTP_LANE_ADDR_STEP * lane;
 542
 543        return ICE_SUCCESS;
 544}
 545
 546/**
 547 * ice_phy_port_mem_address_eth56g - Calculate a PHY port memory address
 548 * @port: Port number to be written
 549 * @offset: Offset from PHY port register base
 550 * @address: The result address
 551 */
 552static enum ice_status
 553ice_phy_port_mem_address_eth56g(u8 port, u16 offset, u32 *address)
 554{
 555        u8 phy, lane;
 556
 557        if (port >= ICE_NUM_EXTERNAL_PORTS)
 558                return ICE_ERR_OUT_OF_RANGE;
 559
 560        phy = port / ICE_PORTS_PER_QUAD;
 561        lane = port % ICE_PORTS_PER_QUAD;
 562
 563        *address = offset + eth56g_port_base[phy] +
 564                   PHY_PTP_MEM_START + PHY_PTP_MEM_LANE_STEP * lane;
 565
 566        return ICE_SUCCESS;
 567}
 568
 569/**
 570 * ice_write_phy_reg_eth56g_lp - Write a PHY port register with lock parameter
 571 * @hw: pointer to the HW struct
 572 * @port: Port number to be written
 573 * @offset: Offset from PHY port register base
 574 * @val: Value to write
 575 * @lock_sbq: true to lock the sideband queue
 576 */
 577static enum ice_status
 578ice_write_phy_reg_eth56g_lp(struct ice_hw *hw, u8 port, u16 offset, u32 val,
 579                            bool lock_sbq)
 580{
 581        enum ice_status status;
 582        u32 reg_addr;
 583
 584        status = ice_phy_port_reg_address_eth56g(port, offset, &reg_addr);
 585        if (status)
 586                return status;
 587
 588        return ice_write_phy_eth56g_raw_lp(hw, reg_addr, val, lock_sbq);
 589}
 590
 591/**
 592 * ice_write_phy_reg_eth56g - Write a PHY port register with sbq locked
 593 * @hw: pointer to the HW struct
 594 * @port: Port number to be written
 595 * @offset: Offset from PHY port register base
 596 * @val: Value to write
 597 */
 598enum ice_status
 599ice_write_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 offset, u32 val)
 600{
 601        return ice_write_phy_reg_eth56g_lp(hw, port, offset, val, true);
 602}
 603
 604/**
 605 * ice_read_phy_reg_eth56g_lp - Read a PHY port register with
 606 * lock parameter
 607 * @hw: pointer to the HW struct
 608 * @port: Port number to be read
 609 * @offset: Offset from PHY port register base
 610 * @val: Pointer to the value to read (out param)
 611 * @lock_sbq: true to lock the sideband queue
 612 */
 613static enum ice_status
 614ice_read_phy_reg_eth56g_lp(struct ice_hw *hw, u8 port, u16 offset, u32 *val,
 615                           bool lock_sbq)
 616{
 617        enum ice_status status;
 618        u32 reg_addr;
 619
 620        status = ice_phy_port_reg_address_eth56g(port, offset, &reg_addr);
 621        if (status)
 622                return status;
 623
 624        return ice_read_phy_eth56g_raw_lp(hw, reg_addr, val, lock_sbq);
 625}
 626
 627/**
 628 * ice_read_phy_reg_eth56g - Read a PHY port register with sbq locked
 629 * @hw: pointer to the HW struct
 630 * @port: Port number to be read
 631 * @offset: Offset from PHY port register base
 632 * @val: Pointer to the value to read (out param)
 633 */
 634enum ice_status
 635ice_read_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 offset, u32 *val)
 636{
 637        return ice_read_phy_reg_eth56g_lp(hw, port, offset, val, true);
 638}
 639
 640/**
 641 * ice_phy_port_mem_read_eth56g_lp - Read a PHY port memory location
 642 * with lock parameter
 643 * @hw: pointer to the HW struct
 644 * @port: Port number to be read
 645 * @offset: Offset from PHY port register base
 646 * @val: Pointer to the value to read (out param)
 647 * @lock_sbq: true to lock the sideband queue
 648 */
 649static enum ice_status
 650ice_phy_port_mem_read_eth56g_lp(struct ice_hw *hw, u8 port, u16 offset,
 651                                u32 *val, bool lock_sbq)
 652{
 653        enum ice_status status;
 654        u32 mem_addr;
 655
 656        status = ice_phy_port_mem_address_eth56g(port, offset, &mem_addr);
 657        if (status)
 658                return status;
 659
 660        return ice_read_phy_eth56g_raw_lp(hw, mem_addr, val, lock_sbq);
 661}
 662
 663/**
 664 * ice_phy_port_mem_read_eth56g - Read a PHY port memory location with
 665 * sbq locked
 666 * @hw: pointer to the HW struct
 667 * @port: Port number to be read
 668 * @offset: Offset from PHY port register base
 669 * @val: Pointer to the value to read (out param)
 670 */
 671static enum ice_status
 672ice_phy_port_mem_read_eth56g(struct ice_hw *hw, u8 port, u16 offset, u32 *val)
 673{
 674        return ice_phy_port_mem_read_eth56g_lp(hw, port, offset, val, true);
 675}
 676
 677/**
 678 * ice_phy_port_mem_write_eth56g_lp - Write a PHY port memory location with
 679 * lock parameter
 680 * @hw: pointer to the HW struct
 681 * @port: Port number to be read
 682 * @offset: Offset from PHY port register base
 683 * @val: Pointer to the value to read (out param)
 684 * @lock_sbq: true to lock the sideband queue
 685 */
 686static enum ice_status
 687ice_phy_port_mem_write_eth56g_lp(struct ice_hw *hw, u8 port, u16 offset,
 688                                 u32 val, bool lock_sbq)
 689{
 690        enum ice_status status;
 691        u32 mem_addr;
 692
 693        status = ice_phy_port_mem_address_eth56g(port, offset, &mem_addr);
 694        if (status)
 695                return status;
 696
 697        return ice_write_phy_eth56g_raw_lp(hw, mem_addr, val, lock_sbq);
 698}
 699
 700/**
 701 * ice_phy_port_mem_write_eth56g - Write a PHY port memory location with
 702 * sbq locked
 703 * @hw: pointer to the HW struct
 704 * @port: Port number to be read
 705 * @offset: Offset from PHY port register base
 706 * @val: Pointer to the value to read (out param)
 707 */
 708static enum ice_status
 709ice_phy_port_mem_write_eth56g(struct ice_hw *hw, u8 port, u16 offset, u32 val)
 710{
 711        return ice_phy_port_mem_write_eth56g_lp(hw, port, offset, val, true);
 712}
 713
 714/**
 715 * ice_is_64b_phy_reg_eth56g - Check if this is a 64bit PHY register
 716 * @low_addr: the low address to check
 717 *
 718 * Checks if the provided low address is one of the known 64bit PHY values
 719 * represented as two 32bit registers.
 720 */
 721static bool ice_is_64b_phy_reg_eth56g(u16 low_addr)
 722{
 723        switch (low_addr) {
 724        case PHY_REG_TX_TIMER_INC_PRE_L:
 725        case PHY_REG_RX_TIMER_INC_PRE_L:
 726        case PHY_REG_TX_CAPTURE_L:
 727        case PHY_REG_RX_CAPTURE_L:
 728        case PHY_REG_TOTAL_TX_OFFSET_L:
 729        case PHY_REG_TOTAL_RX_OFFSET_L:
 730                return true;
 731        default:
 732                return false;
 733        }
 734}
 735
 736/**
 737 * ice_is_40b_phy_reg_eth56g - Check if this is a 40bit PHY register
 738 * @low_addr: the low address to check
 739 *
 740 * Checks if the provided low address is one of the known 40bit PHY values
 741 * split into two registers with the lower 8 bits in the low register and the
 742 * upper 32 bits in the high register.
 743 */
 744static bool ice_is_40b_phy_reg_eth56g(u16 low_addr)
 745{
 746        switch (low_addr) {
 747        case PHY_REG_TIMETUS_L:
 748                return true;
 749        default:
 750                return false;
 751        }
 752}
 753
 754/**
 755 * ice_read_40b_phy_reg_eth56g - Read a 40bit value from PHY registers
 756 * @hw: pointer to the HW struct
 757 * @port: PHY port to read from
 758 * @low_addr: offset of the lower register to read from
 759 * @val: on return, the contents of the 40bit value from the PHY registers
 760 *
 761 * Reads the two registers associated with a 40bit value and returns it in the
 762 * val pointer.
 763 * This function checks that the caller has specified a known 40 bit register
 764 * offset
 765 */
 766static enum ice_status
 767ice_read_40b_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val)
 768{
 769        u16 high_addr = low_addr + sizeof(u32);
 770        enum ice_status status;
 771        u32 lo, hi;
 772
 773        if (!ice_is_40b_phy_reg_eth56g(low_addr))
 774                return ICE_ERR_PARAM;
 775
 776        status = ice_read_phy_reg_eth56g(hw, port, low_addr, &lo);
 777        if (status) {
 778                ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register %#08x\n, status %d",
 779                          (int)low_addr, status);
 780                return status;
 781        }
 782
 783        status = ice_read_phy_reg_eth56g(hw, port, low_addr + sizeof(u32), &hi);
 784        if (status) {
 785                ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register %08x\n, status %d",
 786                          high_addr, status);
 787                return status;
 788        }
 789
 790        *val = ((u64)hi << P_REG_40B_HIGH_S) | (lo & P_REG_40B_LOW_M);
 791
 792        return ICE_SUCCESS;
 793}
 794
 795/**
 796 * ice_read_64b_phy_reg_eth56g - Read a 64bit value from PHY registers
 797 * @hw: pointer to the HW struct
 798 * @port: PHY port to read from
 799 * @low_addr: offset of the lower register to read from
 800 * @val: on return, the contents of the 64bit value from the PHY registers
 801 *
 802 * Reads the two registers associated with a 64bit value and returns it in the
 803 * val pointer.
 804 * This function checks that the caller has specified a known 64 bit register
 805 * offset
 806 */
 807static enum ice_status
 808ice_read_64b_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val)
 809{
 810        u16 high_addr = low_addr + sizeof(u32);
 811        enum ice_status status;
 812        u32 lo, hi;
 813
 814        if (!ice_is_64b_phy_reg_eth56g(low_addr))
 815                return ICE_ERR_PARAM;
 816
 817        status = ice_read_phy_reg_eth56g(hw, port, low_addr, &lo);
 818        if (status) {
 819                ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register %#08x\n, status %d",
 820                          low_addr, status);
 821                return status;
 822        }
 823
 824        status = ice_read_phy_reg_eth56g(hw, port, high_addr, &hi);
 825        if (status) {
 826                ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register %#08x\n, status %d",
 827                          high_addr, status);
 828                return status;
 829        }
 830
 831        *val = ((u64)hi << 32) | lo;
 832
 833        return ICE_SUCCESS;
 834}
 835
 836/**
 837 * ice_write_40b_phy_reg_eth56g - Write a 40b value to the PHY
 838 * @hw: pointer to the HW struct
 839 * @port: port to write to
 840 * @low_addr: offset of the low register
 841 * @val: 40b value to write
 842 *
 843 * Write the provided 40b value to the two associated registers by splitting
 844 * it up into two chunks, the lower 8 bits and the upper 32 bits.
 845 * This function checks that the caller has specified a known 40 bit register
 846 * offset
 847 */
 848static enum ice_status
 849ice_write_40b_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 low_addr, u64 val)
 850{
 851        u16 high_addr = low_addr + sizeof(u32);
 852        enum ice_status status;
 853        u32 lo, hi;
 854
 855        if (!ice_is_40b_phy_reg_eth56g(low_addr))
 856                return ICE_ERR_PARAM;
 857
 858        lo = (u32)(val & P_REG_40B_LOW_M);
 859        hi = (u32)(val >> P_REG_40B_HIGH_S);
 860
 861        status = ice_write_phy_reg_eth56g(hw, port, low_addr, lo);
 862        if (status) {
 863                ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, status %d",
 864                          low_addr, status);
 865                return status;
 866        }
 867
 868        status = ice_write_phy_reg_eth56g(hw, port, high_addr, hi);
 869        if (status) {
 870                ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, status %d",
 871                          high_addr, status);
 872                return status;
 873        }
 874
 875        return ICE_SUCCESS;
 876}
 877
 878/**
 879 * ice_write_64b_phy_reg_eth56g - Write a 64bit value to PHY registers
 880 * @hw: pointer to the HW struct
 881 * @port: PHY port to read from
 882 * @low_addr: offset of the lower register to read from
 883 * @val: the contents of the 64bit value to write to PHY
 884 *
 885 * Write the 64bit value to the two associated 32bit PHY registers.
 886 * This function checks that the caller has specified a known 64 bit register
 887 * offset
 888 */
 889static enum ice_status
 890ice_write_64b_phy_reg_eth56g(struct ice_hw *hw, u8 port, u16 low_addr, u64 val)
 891{
 892        u16 high_addr = low_addr + sizeof(u32);
 893        enum ice_status status;
 894        u32 lo, hi;
 895
 896        if (!ice_is_64b_phy_reg_eth56g(low_addr))
 897                return ICE_ERR_PARAM;
 898
 899        lo = ICE_LO_DWORD(val);
 900        hi = ICE_HI_DWORD(val);
 901
 902        status = ice_write_phy_reg_eth56g(hw, port, low_addr, lo);
 903        if (status) {
 904                ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, status %d",
 905                          low_addr, status);
 906                return status;
 907        }
 908
 909        status = ice_write_phy_reg_eth56g(hw, port, high_addr, hi);
 910        if (status) {
 911                ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, status %d",
 912                          high_addr, status);
 913                return status;
 914        }
 915
 916        return ICE_SUCCESS;
 917}
 918
 919/**
 920 * ice_read_phy_tstamp_eth56g - Read a PHY timestamp out of the port memory
 921 * @hw: pointer to the HW struct
 922 * @port: the port to read from
 923 * @idx: the timestamp index to read
 924 * @tstamp: on return, the 40bit timestamp value
 925 *
 926 * Read a 40bit timestamp value out of the two associated entries in the
 927 * port memory block of the internal PHYs of the 56G devices.
 928 */
 929static enum ice_status
 930ice_read_phy_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx, u64 *tstamp)
 931{
 932        enum ice_status status;
 933        u16 lo_addr, hi_addr;
 934        u32 lo, hi;
 935
 936        lo_addr = (u16)PHY_TSTAMP_L(idx);
 937        hi_addr = (u16)PHY_TSTAMP_U(idx);
 938
 939        status = ice_phy_port_mem_read_eth56g(hw, port, lo_addr, &lo);
 940        if (status) {
 941                ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, status %d\n",
 942                          status);
 943                return status;
 944        }
 945
 946        status = ice_phy_port_mem_read_eth56g(hw, port, hi_addr, &hi);
 947        if (status) {
 948                ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, status %d\n",
 949                          status);
 950                return status;
 951        }
 952
 953        /* For 56G based internal PHYs, the timestamp is reported with the
 954         * lower 8 bits in the low register, and the upper 32 bits in the high
 955         * register.
 956         */
 957        *tstamp = ((u64)hi) << TS_PHY_HIGH_S | ((u64)lo & TS_PHY_LOW_M);
 958
 959        return ICE_SUCCESS;
 960}
 961
 962/**
 963 * ice_clear_phy_tstamp_eth56g - Clear a timestamp from the quad block
 964 * @hw: pointer to the HW struct
 965 * @port: the quad to read from
 966 * @idx: the timestamp index to reset
 967 *
 968 * Clear a timestamp, resetting its valid bit, in the PHY port memory of
 969 * internal PHYs of the 56G devices.
 970 */
 971static enum ice_status
 972ice_clear_phy_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx)
 973{
 974        enum ice_status status;
 975        u16 lo_addr;
 976
 977        lo_addr = (u16)PHY_TSTAMP_L(idx);
 978
 979        status = ice_phy_port_mem_write_eth56g(hw, port, lo_addr, 0);
 980        if (status) {
 981                ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, status %d\n",
 982                          status);
 983                return status;
 984        }
 985
 986        return ICE_SUCCESS;
 987}
 988
 989/**
 990 * ice_ptp_prep_port_phy_time_eth56g - Prepare one PHY port with initial time
 991 * @hw: pointer to the HW struct
 992 * @port: port number
 993 * @phy_time: time to initialize the PHY port clocks to
 994 *
 995 * Write a new initial time value into registers of a specific PHY port.
 996 */
 997static enum ice_status
 998ice_ptp_prep_port_phy_time_eth56g(struct ice_hw *hw, u8 port, u64 phy_time)
 999{
1000        enum ice_status status;
1001
1002        /* Tx case */
1003        status = ice_write_64b_phy_reg_eth56g(hw, port,
1004                                              PHY_REG_TX_TIMER_INC_PRE_L,
1005                                              phy_time);
1006        if (status)
1007                return status;
1008
1009        /* Rx case */
1010        return ice_write_64b_phy_reg_eth56g(hw, port,
1011                                            PHY_REG_RX_TIMER_INC_PRE_L,
1012                                            phy_time);
1013}
1014
1015/**
1016 * ice_ptp_prep_phy_time_eth56g - Prepare PHY port with initial time
1017 * @hw: pointer to the HW struct
1018 * @time: Time to initialize the PHY port clocks to
1019 *
1020 * Program the PHY port registers with a new initial time value. The port
1021 * clock will be initialized once the driver issues an ICE_PTP_INIT_TIME sync
1022 * command. The time value is the upper 32 bits of the PHY timer, usually in
1023 * units of nominal nanoseconds.
1024 */
1025static enum ice_status
1026ice_ptp_prep_phy_time_eth56g(struct ice_hw *hw, u32 time)
1027{
1028        enum ice_status status;
1029        u64 phy_time;
1030        u8 port;
1031
1032        /* The time represents the upper 32 bits of the PHY timer, so we need
1033         * to shift to account for this when programming.
1034         */
1035        phy_time = (u64)time << 32;
1036
1037        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1038                if (!(hw->ena_lports & BIT(port)))
1039                        continue;
1040                status = ice_ptp_prep_port_phy_time_eth56g(hw, port,
1041                                                           phy_time);
1042
1043                if (status) {
1044                        ice_debug(hw, ICE_DBG_PTP, "Failed to write init time for port %u, status %d\n",
1045                                  port, status);
1046                        return status;
1047                }
1048        }
1049
1050        return ICE_SUCCESS;
1051}
1052
1053/**
1054 * ice_ptp_prep_port_adj_eth56g - Prepare a single port for time adjust
1055 * @hw: pointer to HW struct
1056 * @port: Port number to be programmed
1057 * @time: time in cycles to adjust the port Tx and Rx clocks
1058 * @lock_sbq: true to lock the sbq sq_lock (the usual case); false if the
1059 *            sq_lock has already been locked at a higher level
1060 *
1061 * Program the port for an atomic adjustment by writing the Tx and Rx timer
1062 * registers. The atomic adjustment won't be completed until the driver issues
1063 * an ICE_PTP_ADJ_TIME command.
1064 *
1065 * Note that time is not in units of nanoseconds. It is in clock time
1066 * including the lower sub-nanosecond portion of the port timer.
1067 *
1068 * Negative adjustments are supported using 2s complement arithmetic.
1069 */
1070enum ice_status
1071ice_ptp_prep_port_adj_eth56g(struct ice_hw *hw, u8 port, s64 time,
1072                             bool lock_sbq)
1073{
1074        enum ice_status status;
1075        u32 l_time, u_time;
1076
1077        l_time = ICE_LO_DWORD(time);
1078        u_time = ICE_HI_DWORD(time);
1079
1080        /* Tx case */
1081        status = ice_write_phy_reg_eth56g_lp(hw, port,
1082                                             PHY_REG_TX_TIMER_INC_PRE_L,
1083                                             l_time, lock_sbq);
1084        if (status)
1085                goto exit_err;
1086
1087        status = ice_write_phy_reg_eth56g_lp(hw, port,
1088                                             PHY_REG_TX_TIMER_INC_PRE_U,
1089                                             u_time, lock_sbq);
1090        if (status)
1091                goto exit_err;
1092
1093        /* Rx case */
1094        status = ice_write_phy_reg_eth56g_lp(hw, port,
1095                                             PHY_REG_RX_TIMER_INC_PRE_L,
1096                                             l_time, lock_sbq);
1097        if (status)
1098                goto exit_err;
1099
1100        status = ice_write_phy_reg_eth56g_lp(hw, port,
1101                                             PHY_REG_RX_TIMER_INC_PRE_U,
1102                                             u_time, lock_sbq);
1103        if (status)
1104                goto exit_err;
1105
1106        return ICE_SUCCESS;
1107
1108exit_err:
1109        ice_debug(hw, ICE_DBG_PTP, "Failed to write time adjust for port %u, status %d\n",
1110                  port, status);
1111        return status;
1112}
1113
1114/**
1115 * ice_ptp_prep_phy_adj_eth56g - Prep PHY ports for a time adjustment
1116 * @hw: pointer to HW struct
1117 * @adj: adjustment in nanoseconds
1118 * @lock_sbq: true to lock the sbq sq_lock (the usual case); false if the
1119 *            sq_lock has already been locked at a higher level
1120 *
1121 * Prepare the PHY ports for an atomic time adjustment by programming the PHY
1122 * Tx and Rx port registers. The actual adjustment is completed by issuing an
1123 * ICE_PTP_ADJ_TIME or ICE_PTP_ADJ_TIME_AT_TIME sync command.
1124 */
1125static enum ice_status
1126ice_ptp_prep_phy_adj_eth56g(struct ice_hw *hw, s32 adj, bool lock_sbq)
1127{
1128        enum ice_status status = ICE_SUCCESS;
1129        s64 cycles;
1130        u8 port;
1131
1132        /* The port clock supports adjustment of the sub-nanosecond portion of
1133         * the clock. We shift the provided adjustment in nanoseconds to
1134         * calculate the appropriate adjustment to program into the PHY ports.
1135         */
1136        cycles = (s64)adj << 32;
1137
1138        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1139                if (!(hw->ena_lports & BIT(port)))
1140                        continue;
1141
1142                status = ice_ptp_prep_port_adj_eth56g(hw, port, cycles,
1143                                                      lock_sbq);
1144                if (status)
1145                        break;
1146        }
1147
1148        return status;
1149}
1150
1151/**
1152 * ice_ptp_prep_phy_incval_eth56g - Prepare PHY ports for time adjustment
1153 * @hw: pointer to HW struct
1154 * @incval: new increment value to prepare
1155 *
1156 * Prepare each of the PHY ports for a new increment value by programming the
1157 * port's TIMETUS registers. The new increment value will be updated after
1158 * issuing an ICE_PTP_INIT_INCVAL command.
1159 */
1160static enum ice_status
1161ice_ptp_prep_phy_incval_eth56g(struct ice_hw *hw, u64 incval)
1162{
1163        enum ice_status status;
1164        u8 port;
1165
1166        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1167                if (!(hw->ena_lports & BIT(port)))
1168                        continue;
1169                status = ice_write_40b_phy_reg_eth56g(hw, port,
1170                                                      PHY_REG_TIMETUS_L,
1171                                                      incval);
1172                if (status) {
1173                        ice_debug(hw, ICE_DBG_PTP, "Failed to write incval for port %u, status %d\n",
1174                                  port, status);
1175                        return status;
1176                }
1177        }
1178
1179        return ICE_SUCCESS;
1180}
1181
1182/**
1183 * ice_ptp_read_phy_incval_eth56g - Read a PHY port's current incval
1184 * @hw: pointer to the HW struct
1185 * @port: the port to read
1186 * @incval: on return, the time_clk_cyc incval for this port
1187 *
1188 * Read the time_clk_cyc increment value for a given PHY port.
1189 */
1190enum ice_status
1191ice_ptp_read_phy_incval_eth56g(struct ice_hw *hw, u8 port, u64 *incval)
1192{
1193        enum ice_status status;
1194
1195        status = ice_read_40b_phy_reg_eth56g(hw, port, PHY_REG_TIMETUS_L,
1196                                             incval);
1197        if (status) {
1198                ice_debug(hw, ICE_DBG_PTP, "Failed to read TIMETUS_L, status %d\n",
1199                          status);
1200                return status;
1201        }
1202
1203        ice_debug(hw, ICE_DBG_PTP, "read INCVAL = 0x%016llx\n",
1204                  (unsigned long long)*incval);
1205
1206        return ICE_SUCCESS;
1207}
1208
1209/**
1210 * ice_ptp_prep_phy_adj_target_eth56g - Prepare PHY for adjust at target time
1211 * @hw: pointer to HW struct
1212 * @target_time: target time to program
1213 *
1214 * Program the PHY port Tx and Rx TIMER_CNT_ADJ registers used for the
1215 * ICE_PTP_ADJ_TIME_AT_TIME command. This should be used in conjunction with
1216 * ice_ptp_prep_phy_adj_eth56g to program an atomic adjustment that is
1217 * delayed until a specified target time.
1218 *
1219 * Note that a target time adjustment is not currently supported on E810
1220 * devices.
1221 */
1222static enum ice_status
1223ice_ptp_prep_phy_adj_target_eth56g(struct ice_hw *hw, u32 target_time)
1224{
1225        enum ice_status status;
1226        u8 port;
1227
1228        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1229                if (!(hw->ena_lports & BIT(port)))
1230                        continue;
1231
1232                /* Tx case */
1233                /* No sub-nanoseconds data */
1234                status = ice_write_phy_reg_eth56g_lp(hw, port,
1235                                                     PHY_REG_TX_TIMER_CNT_ADJ_L,
1236                                                     0, true);
1237                if (status)
1238                        goto exit_err;
1239
1240                status = ice_write_phy_reg_eth56g_lp(hw, port,
1241                                                     PHY_REG_TX_TIMER_CNT_ADJ_U,
1242                                                     target_time, true);
1243                if (status)
1244                        goto exit_err;
1245
1246                /* Rx case */
1247                /* No sub-nanoseconds data */
1248                status = ice_write_phy_reg_eth56g_lp(hw, port,
1249                                                     PHY_REG_RX_TIMER_CNT_ADJ_L,
1250                                                     0, true);
1251                if (status)
1252                        goto exit_err;
1253
1254                status = ice_write_phy_reg_eth56g_lp(hw, port,
1255                                                     PHY_REG_RX_TIMER_CNT_ADJ_U,
1256                                                     target_time, true);
1257                if (status)
1258                        goto exit_err;
1259        }
1260
1261        return ICE_SUCCESS;
1262
1263exit_err:
1264        ice_debug(hw, ICE_DBG_PTP, "Failed to write target time for port %u, status %d\n",
1265                  port, status);
1266
1267        return status;
1268}
1269
1270/**
1271 * ice_ptp_read_port_capture_eth56g - Read a port's local time capture
1272 * @hw: pointer to HW struct
1273 * @port: Port number to read
1274 * @tx_ts: on return, the Tx port time capture
1275 * @rx_ts: on return, the Rx port time capture
1276 *
1277 * Read the port's Tx and Rx local time capture values.
1278 */
1279enum ice_status
1280ice_ptp_read_port_capture_eth56g(struct ice_hw *hw, u8 port, u64 *tx_ts,
1281                                 u64 *rx_ts)
1282{
1283        enum ice_status status;
1284
1285        /* Tx case */
1286        status = ice_read_64b_phy_reg_eth56g(hw, port, PHY_REG_TX_CAPTURE_L,
1287                                             tx_ts);
1288        if (status) {
1289                ice_debug(hw, ICE_DBG_PTP, "Failed to read REG_TX_CAPTURE, status %d\n",
1290                          status);
1291                return status;
1292        }
1293
1294        ice_debug(hw, ICE_DBG_PTP, "tx_init = %#016llx\n",
1295                  (unsigned long long)*tx_ts);
1296
1297        /* Rx case */
1298        status = ice_read_64b_phy_reg_eth56g(hw, port, PHY_REG_RX_CAPTURE_L,
1299                                             rx_ts);
1300        if (status) {
1301                ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_CAPTURE, status %d\n",
1302                          status);
1303                return status;
1304        }
1305
1306        ice_debug(hw, ICE_DBG_PTP, "rx_init = %#016llx\n",
1307                  (unsigned long long)*rx_ts);
1308
1309        return ICE_SUCCESS;
1310}
1311
1312/**
1313 * ice_ptp_one_port_cmd_eth56g - Prepare a single PHY port for a timer command
1314 * @hw: pointer to HW struct
1315 * @port: Port to which cmd has to be sent
1316 * @cmd: Command to be sent to the port
1317 * @lock_sbq: true if the sideband queue lock must be acquired
1318 *
1319 * Prepare the requested port for an upcoming timer sync command.
1320 */
1321enum ice_status
1322ice_ptp_one_port_cmd_eth56g(struct ice_hw *hw, u8 port,
1323                            enum ice_ptp_tmr_cmd cmd, bool lock_sbq)
1324{
1325        enum ice_status status;
1326        u32 cmd_val, val;
1327        u8 tmr_idx;
1328
1329        tmr_idx = ice_get_ptp_src_clock_index(hw);
1330        cmd_val = tmr_idx << SEL_PHY_SRC;
1331        switch (cmd) {
1332        case ICE_PTP_INIT_TIME:
1333                cmd_val |= PHY_CMD_INIT_TIME;
1334                break;
1335        case ICE_PTP_INIT_INCVAL:
1336                cmd_val |= PHY_CMD_INIT_INCVAL;
1337                break;
1338        case ICE_PTP_ADJ_TIME:
1339                cmd_val |= PHY_CMD_ADJ_TIME;
1340                break;
1341        case ICE_PTP_ADJ_TIME_AT_TIME:
1342                cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME;
1343                break;
1344        case ICE_PTP_READ_TIME:
1345                cmd_val |= PHY_CMD_READ_TIME;
1346                break;
1347        default:
1348                ice_warn(hw, "Unknown timer command %u\n", cmd);
1349                return ICE_ERR_PARAM;
1350        }
1351
1352        /* Tx case */
1353        /* Read, modify, write */
1354        status = ice_read_phy_reg_eth56g_lp(hw, port, PHY_REG_TX_TMR_CMD, &val,
1355                                            lock_sbq);
1356        if (status) {
1357                ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_TMR_CMD, status %d\n",
1358                          status);
1359                return status;
1360        }
1361
1362        /* Modify necessary bits only and perform write */
1363        val &= ~TS_CMD_MASK;
1364        val |= cmd_val;
1365
1366        status = ice_write_phy_reg_eth56g_lp(hw, port, PHY_REG_TX_TMR_CMD, val,
1367                                             lock_sbq);
1368        if (status) {
1369                ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_TMR_CMD, status %d\n",
1370                          status);
1371                return status;
1372        }
1373
1374        /* Rx case */
1375        /* Read, modify, write */
1376        status = ice_read_phy_reg_eth56g_lp(hw, port, PHY_REG_RX_TMR_CMD, &val,
1377                                            lock_sbq);
1378        if (status) {
1379                ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_TMR_CMD, status %d\n",
1380                          status);
1381                return status;
1382        }
1383
1384        /* Modify necessary bits only and perform write */
1385        val &= ~TS_CMD_MASK;
1386        val |= cmd_val;
1387
1388        status = ice_write_phy_reg_eth56g_lp(hw, port, PHY_REG_RX_TMR_CMD, val,
1389                                             lock_sbq);
1390        if (status) {
1391                ice_debug(hw, ICE_DBG_PTP, "Failed to write back RX_TMR_CMD, status %d\n",
1392                          status);
1393                return status;
1394        }
1395
1396        return ICE_SUCCESS;
1397}
1398
1399/**
1400 * ice_ptp_port_cmd_eth56g - Prepare all ports for a timer command
1401 * @hw: pointer to the HW struct
1402 * @cmd: timer command to prepare
1403 * @lock_sbq: true if the sideband queue lock must  be acquired
1404 *
1405 * Prepare all ports connected to this device for an upcoming timer sync
1406 * command.
1407 */
1408static enum ice_status
1409ice_ptp_port_cmd_eth56g(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
1410                        bool lock_sbq)
1411{
1412        enum ice_status status;
1413        u8 port;
1414
1415        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1416                if (!(hw->ena_lports & BIT(port)))
1417                        continue;
1418
1419                status = ice_ptp_one_port_cmd_eth56g(hw, port, cmd, lock_sbq);
1420                if (status)
1421                        return status;
1422        }
1423
1424        return ICE_SUCCESS;
1425}
1426
1427/**
1428 * ice_calc_fixed_tx_offset_eth56g - Calculated Fixed Tx offset for a port
1429 * @hw: pointer to the HW struct
1430 * @link_spd: the Link speed to calculate for
1431 *
1432 * Calculate the fixed offset due to known static latency data.
1433 */
1434static u64
1435ice_calc_fixed_tx_offset_eth56g(struct ice_hw *hw,
1436                                enum ice_ptp_link_spd link_spd)
1437{
1438        u64 fixed_offset = 0;
1439        return fixed_offset;
1440}
1441
1442/**
1443 * ice_phy_cfg_tx_offset_eth56g - Configure total Tx timestamp offset
1444 * @hw: pointer to the HW struct
1445 * @port: the PHY port to configure
1446 *
1447 * Program the PHY_REG_TOTAL_TX_OFFSET register with the total number of TUs to
1448 * adjust Tx timestamps by.
1449 *
1450 * To avoid overflow, when calculating the offset based on the known static
1451 * latency values, we use measurements in 1/100th of a nanosecond, and divide
1452 * the TUs per second up front. This avoids overflow while allowing
1453 * calculation of the adjustment using integer arithmetic.
1454 */
1455enum ice_status ice_phy_cfg_tx_offset_eth56g(struct ice_hw *hw, u8 port)
1456{
1457        enum ice_ptp_link_spd link_spd = ICE_PTP_LNK_SPD_10G;
1458        enum ice_status status;
1459        u64 total_offset;
1460
1461        total_offset = ice_calc_fixed_tx_offset_eth56g(hw, link_spd);
1462
1463        /* Now that the total offset has been calculated, program it to the
1464         * PHY and indicate that the Tx offset is ready. After this,
1465         * timestamps will be enabled.
1466         */
1467        status = ice_write_64b_phy_reg_eth56g(hw, port,
1468                                              PHY_REG_TOTAL_TX_OFFSET_L,
1469                                              total_offset);
1470        if (status)
1471                return status;
1472
1473        return ice_write_phy_reg_eth56g(hw, port, PHY_REG_TX_OFFSET_READY, 1);
1474}
1475
1476/**
1477 * ice_calc_fixed_rx_offset_eth56g - Calculated the fixed Rx offset for a port
1478 * @hw: pointer to HW struct
1479 * @link_spd: The Link speed to calculate for
1480 *
1481 * Determine the fixed Rx latency for a given link speed.
1482 */
1483static u64
1484ice_calc_fixed_rx_offset_eth56g(struct ice_hw *hw,
1485                                enum ice_ptp_link_spd link_spd)
1486{
1487        u64 fixed_offset = 0;
1488        return fixed_offset;
1489}
1490
1491/**
1492 * ice_phy_cfg_rx_offset_eth56g - Configure total Rx timestamp offset
1493 * @hw: pointer to the HW struct
1494 * @port: the PHY port to configure
1495 *
1496 * Program the PHY_REG_TOTAL_RX_OFFSET register with the number of Time Units to
1497 * adjust Rx timestamps by. This combines calculations from the Vernier offset
1498 * measurements taken in hardware with some data about known fixed delay as
1499 * well as adjusting for multi-lane alignment delay.
1500 *
1501 * This function must be called only after the offset registers are valid,
1502 * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
1503 * has measured the offset.
1504 *
1505 * To avoid overflow, when calculating the offset based on the known static
1506 * latency values, we use measurements in 1/100th of a nanosecond, and divide
1507 * the TUs per second up front. This avoids overflow while allowing
1508 * calculation of the adjustment using integer arithmetic.
1509 */
1510enum ice_status ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port)
1511{
1512        enum ice_status status;
1513        u64 total_offset;
1514
1515        total_offset = ice_calc_fixed_rx_offset_eth56g(hw, 0);
1516
1517        /* Now that the total offset has been calculated, program it to the
1518         * PHY and indicate that the Rx offset is ready. After this,
1519         * timestamps will be enabled.
1520         */
1521        status = ice_write_64b_phy_reg_eth56g(hw, port,
1522                                              PHY_REG_TOTAL_RX_OFFSET_L,
1523                                              total_offset);
1524        if (status)
1525                return status;
1526
1527        return ice_write_phy_reg_eth56g(hw, port, PHY_REG_RX_OFFSET_READY, 1);
1528}
1529
1530/**
1531 * ice_read_phy_and_phc_time_eth56g - Simultaneously capture PHC and PHY time
1532 * @hw: pointer to the HW struct
1533 * @port: the PHY port to read
1534 * @phy_time: on return, the 64bit PHY timer value
1535 * @phc_time: on return, the lower 64bits of PHC time
1536 *
1537 * Issue a ICE_PTP_READ_TIME timer command to simultaneously capture the PHY
1538 * and PHC timer values.
1539 */
1540static enum ice_status
1541ice_read_phy_and_phc_time_eth56g(struct ice_hw *hw, u8 port, u64 *phy_time,
1542                                 u64 *phc_time)
1543{
1544        enum ice_status status;
1545        u64 tx_time, rx_time;
1546        u32 zo, lo;
1547        u8 tmr_idx;
1548
1549        tmr_idx = ice_get_ptp_src_clock_index(hw);
1550
1551        /* Prepare the PHC timer for a ICE_PTP_READ_TIME capture command */
1552        ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
1553
1554        /* Prepare the PHY timer for a ICE_PTP_READ_TIME capture command */
1555        status = ice_ptp_one_port_cmd_eth56g(hw, port, ICE_PTP_READ_TIME, true);
1556        if (status)
1557                return status;
1558
1559        /* Issue the sync to start the ICE_PTP_READ_TIME capture */
1560        ice_ptp_exec_tmr_cmd(hw);
1561        ice_ptp_clean_cmd(hw);
1562
1563        /* Read the captured PHC time from the shadow time registers */
1564        zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
1565        lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
1566        *phc_time = (u64)lo << 32 | zo;
1567
1568        /* Read the captured PHY time from the PHY shadow registers */
1569        status = ice_ptp_read_port_capture_eth56g(hw, port, &tx_time, &rx_time);
1570        if (status)
1571                return status;
1572
1573        /* If the PHY Tx and Rx timers don't match, log a warning message.
1574         * Note that this should not happen in normal circumstances since the
1575         * driver always programs them together.
1576         */
1577        if (tx_time != rx_time)
1578                ice_warn(hw, "PHY port %u Tx and Rx timers do not match, tx_time 0x%016llX, rx_time 0x%016llX\n",
1579                         port, (unsigned long long)tx_time,
1580                         (unsigned long long)rx_time);
1581
1582        *phy_time = tx_time;
1583
1584        return ICE_SUCCESS;
1585}
1586
1587/**
1588 * ice_sync_phy_timer_eth56g - Synchronize the PHY timer with PHC timer
1589 * @hw: pointer to the HW struct
1590 * @port: the PHY port to synchronize
1591 *
1592 * Perform an adjustment to ensure that the PHY and PHC timers are in sync.
1593 * This is done by issuing a ICE_PTP_READ_TIME command which triggers a
1594 * simultaneous read of the PHY timer and PHC timer. Then we use the
1595 * difference to calculate an appropriate 2s complement addition to add
1596 * to the PHY timer in order to ensure it reads the same value as the
1597 * primary PHC timer.
1598 */
1599static enum ice_status ice_sync_phy_timer_eth56g(struct ice_hw *hw, u8 port)
1600{
1601        u64 phc_time, phy_time, difference;
1602        enum ice_status status;
1603
1604        if (!ice_ptp_lock(hw)) {
1605                ice_debug(hw, ICE_DBG_PTP, "Failed to acquire PTP semaphore\n");
1606                return ICE_ERR_NOT_READY;
1607        }
1608
1609        status = ice_read_phy_and_phc_time_eth56g(hw, port, &phy_time,
1610                                                  &phc_time);
1611        if (status)
1612                goto err_unlock;
1613
1614        /* Calculate the amount required to add to the port time in order for
1615         * it to match the PHC time.
1616         *
1617         * Note that the port adjustment is done using 2s complement
1618         * arithmetic. This is convenient since it means that we can simply
1619         * calculate the difference between the PHC time and the port time,
1620         * and it will be interpreted correctly.
1621         */
1622
1623        ice_ptp_src_cmd(hw, ICE_PTP_NOP);
1624        difference = phc_time - phy_time;
1625
1626        status = ice_ptp_prep_port_adj_eth56g(hw, port, (s64)difference, true);
1627        if (status)
1628                goto err_unlock;
1629
1630        status = ice_ptp_one_port_cmd_eth56g(hw, port, ICE_PTP_ADJ_TIME, true);
1631        if (status)
1632                goto err_unlock;
1633
1634        /* Issue the sync to activate the time adjustment */
1635        ice_ptp_exec_tmr_cmd(hw);
1636        ice_ptp_clean_cmd(hw);
1637
1638        /* Re-capture the timer values to flush the command registers and
1639         * verify that the time was properly adjusted.
1640         */
1641
1642        status = ice_read_phy_and_phc_time_eth56g(hw, port, &phy_time,
1643                                                  &phc_time);
1644        if (status)
1645                goto err_unlock;
1646
1647        ice_info(hw, "Port %u PHY time synced to PHC: 0x%016llX, 0x%016llX\n",
1648                 port, (unsigned long long)phy_time,
1649                 (unsigned long long)phc_time);
1650
1651err_unlock:
1652        ice_ptp_unlock(hw);
1653        return status;
1654}
1655
1656/**
1657 * ice_stop_phy_timer_eth56g - Stop the PHY clock timer
1658 * @hw: pointer to the HW struct
1659 * @port: the PHY port to stop
1660 * @soft_reset: if true, hold the SOFT_RESET bit of PHY_REG_PS
1661 *
1662 * Stop the clock of a PHY port. This must be done as part of the flow to
1663 * re-calibrate Tx and Rx timestamping offsets whenever the clock time is
1664 * initialized or when link speed changes.
1665 */
1666enum ice_status
1667ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset)
1668{
1669        enum ice_status status;
1670
1671        status = ice_write_phy_reg_eth56g(hw, port, PHY_REG_TX_OFFSET_READY, 0);
1672        if (status)
1673                return status;
1674
1675        status = ice_write_phy_reg_eth56g(hw, port, PHY_REG_RX_OFFSET_READY, 0);
1676        if (status)
1677                return status;
1678
1679        ice_debug(hw, ICE_DBG_PTP, "Disabled clock on PHY port %u\n", port);
1680
1681        return ICE_SUCCESS;
1682}
1683
1684/**
1685 * ice_start_phy_timer_eth56g - Start the PHY clock timer
1686 * @hw: pointer to the HW struct
1687 * @port: the PHY port to start
1688 * @bypass: unused, for compatibility
1689 *
1690 * Start the clock of a PHY port. This must be done as part of the flow to
1691 * re-calibrate Tx and Rx timestamping offsets whenever the clock time is
1692 * initialized or when link speed changes.
1693 *
1694 */
1695enum ice_status
1696ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool bypass)
1697{
1698        enum ice_status status;
1699        u32 lo, hi;
1700        u64 incval;
1701        u8 tmr_idx;
1702
1703        tmr_idx = ice_get_ptp_src_clock_index(hw);
1704
1705        status = ice_stop_phy_timer_eth56g(hw, port, false);
1706        if (status)
1707                return status;
1708
1709        ice_ptp_src_cmd(hw, ICE_PTP_NOP);
1710
1711        lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
1712        hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
1713        incval = (u64)hi << 32 | lo;
1714
1715        status = ice_write_40b_phy_reg_eth56g(hw, port, PHY_REG_TIMETUS_L,
1716                                              incval);
1717        if (status)
1718                return status;
1719
1720        status = ice_ptp_one_port_cmd_eth56g(hw, port, ICE_PTP_INIT_INCVAL,
1721                                             true);
1722        if (status)
1723                return status;
1724
1725        ice_ptp_exec_tmr_cmd(hw);
1726
1727        status = ice_sync_phy_timer_eth56g(hw, port);
1728        if (status)
1729                return status;
1730
1731        /* Program the Tx offset */
1732        status = ice_phy_cfg_tx_offset_eth56g(hw, port);
1733        if (status)
1734                return status;
1735
1736        /* Program the Rx offset */
1737        status = ice_phy_cfg_rx_offset_eth56g(hw, port);
1738        if (status)
1739                return status;
1740
1741        ice_debug(hw, ICE_DBG_PTP, "Enabled clock on PHY port %u\n", port);
1742
1743        return ICE_SUCCESS;
1744}
1745
1746/**
1747 * ice_ptp_init_phc_eth56g - Perform E822 specific PHC initialization
1748 * @hw: pointer to HW struct
1749 *
1750 * Perform PHC initialization steps specific to E822 devices.
1751 */
1752static enum ice_status ice_ptp_init_phc_eth56g(struct ice_hw *hw)
1753{
1754        enum ice_status status = ICE_SUCCESS;
1755        u32 regval;
1756
1757        /* Enable reading switch and PHY registers over the sideband queue */
1758#define PF_SB_REM_DEV_CTL_SWITCH_READ BIT(1)
1759#define PF_SB_REM_DEV_CTL_PHY0 BIT(2)
1760        regval = rd32(hw, PF_SB_REM_DEV_CTL);
1761        regval |= (PF_SB_REM_DEV_CTL_SWITCH_READ |
1762                   PF_SB_REM_DEV_CTL_PHY0);
1763        wr32(hw, PF_SB_REM_DEV_CTL, regval);
1764
1765        /* Initialize the Clock Generation Unit */
1766        status = ice_init_cgu_e822(hw);
1767
1768        return status;
1769}
1770
1771/**
1772 * ice_ptp_read_tx_hwtstamp_status_eth56g - Get the current TX timestamp
1773 * status mask. Returns the mask of ports where TX timestamps are available
1774 * @hw: pointer to the HW struct
1775 * @ts_status: the timestamp mask pointer
1776 */
1777enum ice_status
1778ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status)
1779{
1780        enum ice_status status;
1781
1782        status = ice_read_phy_eth56g_raw_lp(hw, PHY_PTP_INT_STATUS, ts_status,
1783                                            true);
1784        if (status)
1785                return status;
1786
1787        ice_debug(hw, ICE_DBG_PTP, "PHY interrupt status: %x\n", *ts_status);
1788
1789        return ICE_SUCCESS;
1790}
1791
1792/**
1793 * ice_ptp_init_phy_cfg - Get the current TX timestamp status
1794 * mask. Returns the mask of ports where TX timestamps are available
1795 * @hw: pointer to the HW struct
1796 */
1797enum ice_status
1798ice_ptp_init_phy_cfg(struct ice_hw *hw)
1799{
1800        enum ice_status status;
1801        u32 phy_rev;
1802
1803        status = ice_read_phy_eth56g_raw_lp(hw, PHY_REG_REVISION, &phy_rev,
1804                                            true);
1805        if (status)
1806                return status;
1807
1808        if (phy_rev == PHY_REVISION_ETH56G) {
1809                hw->phy_cfg = ICE_PHY_ETH56G;
1810                return ICE_SUCCESS;
1811        }
1812
1813        if (ice_is_e810(hw))
1814                hw->phy_cfg = ICE_PHY_E810;
1815        else
1816                hw->phy_cfg = ICE_PHY_E822;
1817
1818        return ICE_SUCCESS;
1819}
1820
1821/* ----------------------------------------------------------------------------
1822 * E822 family functions
1823 *
1824 * The following functions operate on the E822 family of devices.
1825 */
1826
1827/**
1828 * ice_fill_phy_msg_e822 - Fill message data for a PHY register access
1829 * @msg: the PHY message buffer to fill in
1830 * @port: the port to access
1831 * @offset: the register offset
1832 */
1833static void
1834ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset)
1835{
1836        int phy_port, phy, quadtype;
1837
1838        phy_port = port % ICE_PORTS_PER_PHY_E822;
1839        phy = port / ICE_PORTS_PER_PHY_E822;
1840        quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822;
1841
1842        if (quadtype == 0) {
1843                msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port);
1844                msg->msg_addr_high = P_Q0_H(P_0_BASE + offset, phy_port);
1845        } else {
1846                msg->msg_addr_low = P_Q1_L(P_4_BASE + offset, phy_port);
1847                msg->msg_addr_high = P_Q1_H(P_4_BASE + offset, phy_port);
1848        }
1849
1850        if (phy == 0)
1851                msg->dest_dev = rmn_0;
1852        else if (phy == 1)
1853                msg->dest_dev = rmn_1;
1854        else
1855                msg->dest_dev = rmn_2;
1856}
1857
1858/**
1859 * ice_is_64b_phy_reg_e822 - Check if this is a 64bit PHY register
1860 * @low_addr: the low address to check
1861 * @high_addr: on return, contains the high address of the 64bit register
1862 *
1863 * Checks if the provided low address is one of the known 64bit PHY values
1864 * represented as two 32bit registers. If it is, return the appropriate high
1865 * register offset to use.
1866 */
1867static bool ice_is_64b_phy_reg_e822(u16 low_addr, u16 *high_addr)
1868{
1869        switch (low_addr) {
1870        case P_REG_PAR_PCS_TX_OFFSET_L:
1871                *high_addr = P_REG_PAR_PCS_TX_OFFSET_U;
1872                return true;
1873        case P_REG_PAR_PCS_RX_OFFSET_L:
1874                *high_addr = P_REG_PAR_PCS_RX_OFFSET_U;
1875                return true;
1876        case P_REG_PAR_TX_TIME_L:
1877                *high_addr = P_REG_PAR_TX_TIME_U;
1878                return true;
1879        case P_REG_PAR_RX_TIME_L:
1880                *high_addr = P_REG_PAR_RX_TIME_U;
1881                return true;
1882        case P_REG_TOTAL_TX_OFFSET_L:
1883                *high_addr = P_REG_TOTAL_TX_OFFSET_U;
1884                return true;
1885        case P_REG_TOTAL_RX_OFFSET_L:
1886                *high_addr = P_REG_TOTAL_RX_OFFSET_U;
1887                return true;
1888        case P_REG_UIX66_10G_40G_L:
1889                *high_addr = P_REG_UIX66_10G_40G_U;
1890                return true;
1891        case P_REG_UIX66_25G_100G_L:
1892                *high_addr = P_REG_UIX66_25G_100G_U;
1893                return true;
1894        case P_REG_TX_CAPTURE_L:
1895                *high_addr = P_REG_TX_CAPTURE_U;
1896                return true;
1897        case P_REG_RX_CAPTURE_L:
1898                *high_addr = P_REG_RX_CAPTURE_U;
1899                return true;
1900        case P_REG_TX_TIMER_INC_PRE_L:
1901                *high_addr = P_REG_TX_TIMER_INC_PRE_U;
1902                return true;
1903        case P_REG_RX_TIMER_INC_PRE_L:
1904                *high_addr = P_REG_RX_TIMER_INC_PRE_U;
1905                return true;
1906        default:
1907                return false;
1908        }
1909}
1910
1911/**
1912 * ice_is_40b_phy_reg_e822 - Check if this is a 40bit PHY register
1913 * @low_addr: the low address to check
1914 * @high_addr: on return, contains the high address of the 40bit value
1915 *
1916 * Checks if the provided low address is one of the known 40bit PHY values
1917 * split into two registers with the lower 8 bits in the low register and the
1918 * upper 32 bits in the high register. If it is, return the appropriate high
1919 * register offset to use.
1920 */
1921static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr)
1922{
1923        switch (low_addr) {
1924        case P_REG_TIMETUS_L:
1925                *high_addr = P_REG_TIMETUS_U;
1926                return true;
1927        case P_REG_PAR_RX_TUS_L:
1928                *high_addr = P_REG_PAR_RX_TUS_U;
1929                return true;
1930        case P_REG_PAR_TX_TUS_L:
1931                *high_addr = P_REG_PAR_TX_TUS_U;
1932                return true;
1933        case P_REG_PCS_RX_TUS_L:
1934                *high_addr = P_REG_PCS_RX_TUS_U;
1935                return true;
1936        case P_REG_PCS_TX_TUS_L:
1937                *high_addr = P_REG_PCS_TX_TUS_U;
1938                return true;
1939        case P_REG_DESK_PAR_RX_TUS_L:
1940                *high_addr = P_REG_DESK_PAR_RX_TUS_U;
1941                return true;
1942        case P_REG_DESK_PAR_TX_TUS_L:
1943                *high_addr = P_REG_DESK_PAR_TX_TUS_U;
1944                return true;
1945        case P_REG_DESK_PCS_RX_TUS_L:
1946                *high_addr = P_REG_DESK_PCS_RX_TUS_U;
1947                return true;
1948        case P_REG_DESK_PCS_TX_TUS_L:
1949                *high_addr = P_REG_DESK_PCS_TX_TUS_U;
1950                return true;
1951        default:
1952                return false;
1953        }
1954}
1955
1956/**
1957 * ice_read_phy_reg_e822_lp - Read a PHY register
1958 * @hw: pointer to the HW struct
1959 * @port: PHY port to read from
1960 * @offset: PHY register offset to read
1961 * @val: on return, the contents read from the PHY
1962 * @lock_sbq: true if the sideband queue lock must be acquired
1963 *
1964 * Read a PHY register for the given port over the device sideband queue.
1965 */
1966static enum ice_status
1967ice_read_phy_reg_e822_lp(struct ice_hw *hw, u8 port, u16 offset, u32 *val,
1968                         bool lock_sbq)
1969{
1970        struct ice_sbq_msg_input msg = {0};
1971        enum ice_status status;
1972
1973        ice_fill_phy_msg_e822(&msg, port, offset);
1974        msg.opcode = ice_sbq_msg_rd;
1975
1976        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
1977        if (status) {
1978                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
1979                          status);
1980                return status;
1981        }
1982
1983        *val = msg.data;
1984
1985        return ICE_SUCCESS;
1986}
1987
1988enum ice_status
1989ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val)
1990{
1991        return ice_read_phy_reg_e822_lp(hw, port, offset, val, true);
1992}
1993
1994/**
1995 * ice_read_40b_phy_reg_e822 - Read a 40bit value from PHY registers
1996 * @hw: pointer to the HW struct
1997 * @port: PHY port to read from
1998 * @low_addr: offset of the lower register to read from
1999 * @val: on return, the contents of the 40bit value from the PHY registers
2000 *
2001 * Reads the two registers associated with a 40bit value and returns it in the
2002 * val pointer. The offset always specifies the lower register offset to use.
2003 * The high offset is looked up. This function only operates on registers
2004 * known to be split into a lower 8 bit chunk and an upper 32 bit chunk.
2005 */
2006static enum ice_status
2007ice_read_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val)
2008{
2009        enum ice_status status;
2010        u32 low, high;
2011        u16 high_addr;
2012
2013        /* Only operate on registers known to be split into two 32bit
2014         * registers.
2015         */
2016        if (!ice_is_40b_phy_reg_e822(low_addr, &high_addr)) {
2017                ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n",
2018                          low_addr);
2019                return ICE_ERR_PARAM;
2020        }
2021
2022        status = ice_read_phy_reg_e822(hw, port, low_addr, &low);
2023        if (status) {
2024                ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register 0x%08x\n, status %d",
2025                          low_addr, status);
2026                return status;
2027        }
2028
2029        status = ice_read_phy_reg_e822(hw, port, high_addr, &high);
2030        if (status) {
2031                ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register 0x%08x\n, status %d",
2032                          high_addr, status);
2033                return status;
2034        }
2035
2036        *val = (u64)high << P_REG_40B_HIGH_S | (low & P_REG_40B_LOW_M);
2037
2038        return ICE_SUCCESS;
2039}
2040
2041/**
2042 * ice_read_64b_phy_reg_e822 - Read a 64bit value from PHY registers
2043 * @hw: pointer to the HW struct
2044 * @port: PHY port to read from
2045 * @low_addr: offset of the lower register to read from
2046 * @val: on return, the contents of the 64bit value from the PHY registers
2047 *
2048 * Reads the two registers associated with a 64bit value and returns it in the
2049 * val pointer. The offset always specifies the lower register offset to use.
2050 * The high offset is looked up. This function only operates on registers
2051 * known to be two parts of a 64bit value.
2052 */
2053static enum ice_status
2054ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val)
2055{
2056        enum ice_status status;
2057        u32 low, high;
2058        u16 high_addr;
2059
2060        /* Only operate on registers known to be split into two 32bit
2061         * registers.
2062         */
2063        if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) {
2064                ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n",
2065                          low_addr);
2066                return ICE_ERR_PARAM;
2067        }
2068
2069        status = ice_read_phy_reg_e822(hw, port, low_addr, &low);
2070        if (status) {
2071                ice_debug(hw, ICE_DBG_PTP, "Failed to read from low register 0x%08x\n, status %d",
2072                          low_addr, status);
2073                return status;
2074        }
2075
2076        status = ice_read_phy_reg_e822(hw, port, high_addr, &high);
2077        if (status) {
2078                ice_debug(hw, ICE_DBG_PTP, "Failed to read from high register 0x%08x\n, status %d",
2079                          high_addr, status);
2080                return status;
2081        }
2082
2083        *val = (u64)high << 32 | low;
2084
2085        return ICE_SUCCESS;
2086}
2087
2088/**
2089 * ice_write_phy_reg_e822_lp - Write a PHY register
2090 * @hw: pointer to the HW struct
2091 * @port: PHY port to write to
2092 * @offset: PHY register offset to write
2093 * @val: The value to write to the register
2094 * @lock_sbq: true if the sideband queue lock must be acquired
2095 *
2096 * Write a PHY register for the given port over the device sideband queue.
2097 */
2098static enum ice_status
2099ice_write_phy_reg_e822_lp(struct ice_hw *hw, u8 port, u16 offset, u32 val,
2100                          bool lock_sbq)
2101{
2102        struct ice_sbq_msg_input msg = {0};
2103        enum ice_status status;
2104
2105        ice_fill_phy_msg_e822(&msg, port, offset);
2106        msg.opcode = ice_sbq_msg_wr;
2107        msg.data = val;
2108
2109        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
2110        if (status) {
2111                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
2112                          status);
2113                return status;
2114        }
2115
2116        return ICE_SUCCESS;
2117}
2118
2119enum ice_status
2120ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val)
2121{
2122        return ice_write_phy_reg_e822_lp(hw, port, offset, val, true);
2123}
2124
2125/**
2126 * ice_write_40b_phy_reg_e822 - Write a 40b value to the PHY
2127 * @hw: pointer to the HW struct
2128 * @port: port to write to
2129 * @low_addr: offset of the low register
2130 * @val: 40b value to write
2131 *
2132 * Write the provided 40b value to the two associated registers by splitting
2133 * it up into two chunks, the lower 8 bits and the upper 32 bits.
2134 */
2135static enum ice_status
2136ice_write_40b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val)
2137{
2138        enum ice_status status;
2139        u32 low, high;
2140        u16 high_addr;
2141
2142        /* Only operate on registers known to be split into a lower 8 bit
2143         * register and an upper 32 bit register.
2144         */
2145        if (!ice_is_40b_phy_reg_e822(low_addr, &high_addr)) {
2146                ice_debug(hw, ICE_DBG_PTP, "Invalid 40b register addr 0x%08x\n",
2147                          low_addr);
2148                return ICE_ERR_PARAM;
2149        }
2150
2151        low = (u32)(val & P_REG_40B_LOW_M);
2152        high = (u32)(val >> P_REG_40B_HIGH_S);
2153
2154        status = ice_write_phy_reg_e822(hw, port, low_addr, low);
2155        if (status) {
2156                ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, status %d",
2157                          low_addr, status);
2158                return status;
2159        }
2160
2161        status = ice_write_phy_reg_e822(hw, port, high_addr, high);
2162        if (status) {
2163                ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, status %d",
2164                          high_addr, status);
2165                return status;
2166        }
2167
2168        return ICE_SUCCESS;
2169}
2170
2171/**
2172 * ice_write_64b_phy_reg_e822 - Write a 64bit value to PHY registers
2173 * @hw: pointer to the HW struct
2174 * @port: PHY port to read from
2175 * @low_addr: offset of the lower register to read from
2176 * @val: the contents of the 64bit value to write to PHY
2177 *
2178 * Write the 64bit value to the two associated 32bit PHY registers. The offset
2179 * is always specified as the lower register, and the high address is looked
2180 * up. This function only operates on registers known to be two parts of
2181 * a 64bit value.
2182 */
2183static enum ice_status
2184ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val)
2185{
2186        enum ice_status status;
2187        u32 low, high;
2188        u16 high_addr;
2189
2190        /* Only operate on registers known to be split into two 32bit
2191         * registers.
2192         */
2193        if (!ice_is_64b_phy_reg_e822(low_addr, &high_addr)) {
2194                ice_debug(hw, ICE_DBG_PTP, "Invalid 64b register addr 0x%08x\n",
2195                          low_addr);
2196                return ICE_ERR_PARAM;
2197        }
2198
2199        low = ICE_LO_DWORD(val);
2200        high = ICE_HI_DWORD(val);
2201
2202        status = ice_write_phy_reg_e822(hw, port, low_addr, low);
2203        if (status) {
2204                ice_debug(hw, ICE_DBG_PTP, "Failed to write to low register 0x%08x\n, status %d",
2205                          low_addr, status);
2206                return status;
2207        }
2208
2209        status = ice_write_phy_reg_e822(hw, port, high_addr, high);
2210        if (status) {
2211                ice_debug(hw, ICE_DBG_PTP, "Failed to write to high register 0x%08x\n, status %d",
2212                          high_addr, status);
2213                return status;
2214        }
2215
2216        return ICE_SUCCESS;
2217}
2218
2219/**
2220 * ice_fill_quad_msg_e822 - Fill message data for quad register access
2221 * @msg: the PHY message buffer to fill in
2222 * @quad: the quad to access
2223 * @offset: the register offset
2224 *
2225 * Fill a message buffer for accessing a register in a quad shared between
2226 * multiple PHYs.
2227 */
2228static enum ice_status
2229ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset)
2230{
2231        u32 addr;
2232
2233        if (quad >= ICE_MAX_QUAD)
2234                return ICE_ERR_PARAM;
2235
2236        msg->dest_dev = rmn_0;
2237
2238        if ((quad % ICE_QUADS_PER_PHY_E822) == 0)
2239                addr = Q_0_BASE + offset;
2240        else
2241                addr = Q_1_BASE + offset;
2242
2243        msg->msg_addr_low = ICE_LO_WORD(addr);
2244        msg->msg_addr_high = ICE_HI_WORD(addr);
2245
2246        return ICE_SUCCESS;
2247}
2248
2249/**
2250 * ice_read_quad_reg_e822_lp - Read a PHY quad register
2251 * @hw: pointer to the HW struct
2252 * @quad: quad to read from
2253 * @offset: quad register offset to read
2254 * @val: on return, the contents read from the quad
2255 * @lock_sbq: true if the sideband queue lock must be acquired
2256 *
2257 * Read a quad register over the device sideband queue. Quad registers are
2258 * shared between multiple PHYs.
2259 */
2260static enum ice_status
2261ice_read_quad_reg_e822_lp(struct ice_hw *hw, u8 quad, u16 offset, u32 *val,
2262                          bool lock_sbq)
2263{
2264        struct ice_sbq_msg_input msg = {0};
2265        enum ice_status status;
2266
2267        status = ice_fill_quad_msg_e822(&msg, quad, offset);
2268        if (status)
2269                goto exit_err;
2270
2271        msg.opcode = ice_sbq_msg_rd;
2272
2273        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
2274exit_err:
2275        if (status)
2276                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
2277                          status);
2278        else
2279                *val = msg.data;
2280
2281        return status;
2282}
2283
2284enum ice_status
2285ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val)
2286{
2287        return ice_read_quad_reg_e822_lp(hw, quad, offset, val, true);
2288}
2289
2290/**
2291 * ice_write_quad_reg_e822_lp - Write a PHY quad register
2292 * @hw: pointer to the HW struct
2293 * @quad: quad to write to
2294 * @offset: quad register offset to write
2295 * @val: The value to write to the register
2296 * @lock_sbq: true if the sideband queue lock must be acquired
2297 *
2298 * Write a quad register over the device sideband queue. Quad registers are
2299 * shared between multiple PHYs.
2300 */
2301static enum ice_status
2302ice_write_quad_reg_e822_lp(struct ice_hw *hw, u8 quad, u16 offset, u32 val,
2303                           bool lock_sbq)
2304{
2305        struct ice_sbq_msg_input msg = {0};
2306        enum ice_status status;
2307
2308        status = ice_fill_quad_msg_e822(&msg, quad, offset);
2309        if (status)
2310                goto exit_err;
2311
2312        msg.opcode = ice_sbq_msg_wr;
2313        msg.data = val;
2314
2315        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
2316exit_err:
2317        if (status)
2318                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
2319                          status);
2320
2321        return status;
2322}
2323
2324enum ice_status
2325ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val)
2326{
2327        return ice_write_quad_reg_e822_lp(hw, quad, offset, val, true);
2328}
2329
2330/**
2331 * ice_read_phy_tstamp_e822 - Read a PHY timestamp out of the quad block
2332 * @hw: pointer to the HW struct
2333 * @quad: the quad to read from
2334 * @idx: the timestamp index to read
2335 * @tstamp: on return, the 40bit timestamp value
2336 *
2337 * Read a 40bit timestamp value out of the two associated registers in the
2338 * quad memory block that is shared between the internal PHYs of the E822
2339 * family of devices.
2340 */
2341static enum ice_status
2342ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp)
2343{
2344        enum ice_status status;
2345        u16 lo_addr, hi_addr;
2346        u32 lo, hi;
2347
2348        lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx);
2349        hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx);
2350
2351        status = ice_read_quad_reg_e822(hw, quad, lo_addr, &lo);
2352        if (status) {
2353                ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, status %d\n",
2354                          status);
2355                return status;
2356        }
2357
2358        status = ice_read_quad_reg_e822(hw, quad, hi_addr, &hi);
2359        if (status) {
2360                ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, status %d\n",
2361                          status);
2362                return status;
2363        }
2364
2365        /* For E822 based internal PHYs, the timestamp is reported with the
2366         * lower 8 bits in the low register, and the upper 32 bits in the high
2367         * register.
2368         */
2369        *tstamp = ((u64)hi) << TS_PHY_HIGH_S | ((u64)lo & TS_PHY_LOW_M);
2370
2371        return ICE_SUCCESS;
2372}
2373
2374/**
2375 * ice_clear_phy_tstamp_e822 - Clear a timestamp from the quad block
2376 * @hw: pointer to the HW struct
2377 * @quad: the quad to read from
2378 * @idx: the timestamp index to reset
2379 *
2380 * Clear a timestamp, resetting its valid bit, from the PHY quad block that is
2381 * shared between the internal PHYs on the E822 devices.
2382 */
2383static enum ice_status
2384ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx)
2385{
2386        enum ice_status status;
2387        u16 lo_addr, hi_addr;
2388
2389        lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx);
2390        hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx);
2391
2392        status = ice_write_quad_reg_e822(hw, quad, lo_addr, 0);
2393        if (status) {
2394                ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, status %d\n",
2395                          status);
2396                return status;
2397        }
2398
2399        status = ice_write_quad_reg_e822(hw, quad, hi_addr, 0);
2400        if (status) {
2401                ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, status %d\n",
2402                          status);
2403                return status;
2404        }
2405
2406        return ICE_SUCCESS;
2407}
2408
2409/**
2410 * ice_ptp_set_vernier_wl - Set the window length for vernier calibration
2411 * @hw: pointer to the HW struct
2412 *
2413 * Set the window length used for the vernier port calibration process.
2414 */
2415enum ice_status ice_ptp_set_vernier_wl(struct ice_hw *hw)
2416{
2417        u8 port;
2418
2419        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2420                enum ice_status status;
2421
2422                status = ice_write_phy_reg_e822_lp(hw, port, P_REG_WL,
2423                                                   PTP_VERNIER_WL, true);
2424                if (status) {
2425                        ice_debug(hw, ICE_DBG_PTP, "Failed to set vernier window length for port %u, status %d\n",
2426                                  port, status);
2427                        return status;
2428                }
2429        }
2430
2431        return ICE_SUCCESS;
2432}
2433
2434/**
2435 * ice_ptp_init_phc_e822 - Perform E822 specific PHC initialization
2436 * @hw: pointer to HW struct
2437 *
2438 * Perform PHC initialization steps specific to E822 devices.
2439 */
2440static enum ice_status ice_ptp_init_phc_e822(struct ice_hw *hw)
2441{
2442        enum ice_status status;
2443        u32 regval;
2444
2445        /* Enable reading switch and PHY registers over the sideband queue */
2446#define PF_SB_REM_DEV_CTL_SWITCH_READ BIT(1)
2447#define PF_SB_REM_DEV_CTL_PHY0 BIT(2)
2448        regval = rd32(hw, PF_SB_REM_DEV_CTL);
2449        regval |= (PF_SB_REM_DEV_CTL_SWITCH_READ |
2450                   PF_SB_REM_DEV_CTL_PHY0);
2451        wr32(hw, PF_SB_REM_DEV_CTL, regval);
2452
2453        /* Initialize the Clock Generation Unit */
2454        status = ice_init_cgu_e822(hw);
2455        if (status)
2456                return status;
2457
2458        /* Set window length for all the ports */
2459        return ice_ptp_set_vernier_wl(hw);
2460}
2461
2462/**
2463 * ice_ptp_prep_phy_time_e822 - Prepare PHY port with initial time
2464 * @hw: pointer to the HW struct
2465 * @time: Time to initialize the PHY port clocks to
2466 *
2467 * Program the PHY port registers with a new initial time value. The port
2468 * clock will be initialized once the driver issues an ICE_PTP_INIT_TIME sync
2469 * command. The time value is the upper 32 bits of the PHY timer, usually in
2470 * units of nominal nanoseconds.
2471 */
2472static enum ice_status
2473ice_ptp_prep_phy_time_e822(struct ice_hw *hw, u32 time)
2474{
2475        enum ice_status status;
2476        u64 phy_time;
2477        u8 port;
2478
2479        /* The time represents the upper 32 bits of the PHY timer, so we need
2480         * to shift to account for this when programming.
2481         */
2482        phy_time = (u64)time << 32;
2483
2484        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2485
2486                /* Tx case */
2487                status = ice_write_64b_phy_reg_e822(hw, port,
2488                                                    P_REG_TX_TIMER_INC_PRE_L,
2489                                                    phy_time);
2490                if (status)
2491                        goto exit_err;
2492
2493                /* Rx case */
2494                status = ice_write_64b_phy_reg_e822(hw, port,
2495                                                    P_REG_RX_TIMER_INC_PRE_L,
2496                                                    phy_time);
2497                if (status)
2498                        goto exit_err;
2499        }
2500
2501        return ICE_SUCCESS;
2502
2503exit_err:
2504        ice_debug(hw, ICE_DBG_PTP, "Failed to write init time for port %u, status %d\n",
2505                  port, status);
2506
2507        return status;
2508}
2509
2510/**
2511 * ice_ptp_prep_port_adj_e822 - Prepare a single port for time adjust
2512 * @hw: pointer to HW struct
2513 * @port: Port number to be programmed
2514 * @time: time in cycles to adjust the port Tx and Rx clocks
2515 * @lock_sbq: true to lock the sbq sq_lock (the usual case); false if the
2516 *            sq_lock has already been locked at a higher level
2517 *
2518 * Program the port for an atomic adjustment by writing the Tx and Rx timer
2519 * registers. The atomic adjustment won't be completed until the driver issues
2520 * an ICE_PTP_ADJ_TIME command.
2521 *
2522 * Note that time is not in units of nanoseconds. It is in clock time
2523 * including the lower sub-nanosecond portion of the port timer.
2524 *
2525 * Negative adjustments are supported using 2s complement arithmetic.
2526 */
2527enum ice_status
2528ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time,
2529                           bool lock_sbq)
2530{
2531        enum ice_status status;
2532        u32 l_time, u_time;
2533
2534        l_time = ICE_LO_DWORD(time);
2535        u_time = ICE_HI_DWORD(time);
2536
2537        /* Tx case */
2538        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_TX_TIMER_INC_PRE_L,
2539                                           l_time, lock_sbq);
2540        if (status)
2541                goto exit_err;
2542
2543        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_TX_TIMER_INC_PRE_U,
2544                                           u_time, lock_sbq);
2545        if (status)
2546                goto exit_err;
2547
2548        /* Rx case */
2549        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_RX_TIMER_INC_PRE_L,
2550                                           l_time, lock_sbq);
2551        if (status)
2552                goto exit_err;
2553
2554        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_RX_TIMER_INC_PRE_U,
2555                                           u_time, lock_sbq);
2556        if (status)
2557                goto exit_err;
2558
2559        return ICE_SUCCESS;
2560
2561exit_err:
2562        ice_debug(hw, ICE_DBG_PTP, "Failed to write time adjust for port %u, status %d\n",
2563                  port, status);
2564        return status;
2565}
2566
2567/**
2568 * ice_ptp_prep_phy_adj_e822 - Prep PHY ports for a time adjustment
2569 * @hw: pointer to HW struct
2570 * @adj: adjustment in nanoseconds
2571 * @lock_sbq: true to lock the sbq sq_lock (the usual case); false if the
2572 *            sq_lock has already been locked at a higher level
2573 *
2574 * Prepare the PHY ports for an atomic time adjustment by programming the PHY
2575 * Tx and Rx port registers. The actual adjustment is completed by issuing an
2576 * ICE_PTP_ADJ_TIME or ICE_PTP_ADJ_TIME_AT_TIME sync command.
2577 */
2578static enum ice_status
2579ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj, bool lock_sbq)
2580{
2581        s64 cycles;
2582        u8 port;
2583
2584        /* The port clock supports adjustment of the sub-nanosecond portion of
2585         * the clock. We shift the provided adjustment in nanoseconds to
2586         * calculate the appropriate adjustment to program into the PHY ports.
2587         */
2588        if (adj > 0)
2589                cycles = (s64)adj << 32;
2590        else
2591                cycles = -(((s64)-adj) << 32);
2592
2593        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2594                enum ice_status status;
2595
2596                status = ice_ptp_prep_port_adj_e822(hw, port, cycles,
2597                                                    lock_sbq);
2598                if (status)
2599                        return status;
2600        }
2601
2602        return ICE_SUCCESS;
2603}
2604
2605/**
2606 * ice_ptp_prep_phy_incval_e822 - Prepare PHY ports for time adjustment
2607 * @hw: pointer to HW struct
2608 * @incval: new increment value to prepare
2609 *
2610 * Prepare each of the PHY ports for a new increment value by programming the
2611 * port's TIMETUS registers. The new increment value will be updated after
2612 * issuing an ICE_PTP_INIT_INCVAL command.
2613 */
2614static enum ice_status
2615ice_ptp_prep_phy_incval_e822(struct ice_hw *hw, u64 incval)
2616{
2617        enum ice_status status;
2618        u8 port;
2619
2620        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2621                status = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L,
2622                                                    incval);
2623                if (status)
2624                        goto exit_err;
2625        }
2626
2627        return ICE_SUCCESS;
2628
2629exit_err:
2630        ice_debug(hw, ICE_DBG_PTP, "Failed to write incval for port %u, status %d\n",
2631                  port, status);
2632
2633        return status;
2634}
2635
2636/**
2637 * ice_ptp_read_phy_incval_e822 - Read a PHY port's current incval
2638 * @hw: pointer to the HW struct
2639 * @port: the port to read
2640 * @incval: on return, the time_clk_cyc incval for this port
2641 *
2642 * Read the time_clk_cyc increment value for a given PHY port.
2643 */
2644enum ice_status
2645ice_ptp_read_phy_incval_e822(struct ice_hw *hw, u8 port, u64 *incval)
2646{
2647        enum ice_status status;
2648
2649        status = ice_read_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, incval);
2650        if (status) {
2651                ice_debug(hw, ICE_DBG_PTP, "Failed to read TIMETUS_L, status %d\n",
2652                          status);
2653                return status;
2654        }
2655
2656        ice_debug(hw, ICE_DBG_PTP, "read INCVAL = 0x%016llx\n",
2657                  (unsigned long long)*incval);
2658
2659        return ICE_SUCCESS;
2660}
2661
2662/**
2663 * ice_ptp_prep_phy_adj_target_e822 - Prepare PHY for adjust at target time
2664 * @hw: pointer to HW struct
2665 * @target_time: target time to program
2666 *
2667 * Program the PHY port Tx and Rx TIMER_CNT_ADJ registers used for the
2668 * ICE_PTP_ADJ_TIME_AT_TIME command. This should be used in conjunction with
2669 * ice_ptp_prep_phy_adj_e822 to program an atomic adjustment that is
2670 * delayed until a specified target time.
2671 *
2672 * Note that a target time adjustment is not currently supported on E810
2673 * devices.
2674 */
2675static enum ice_status
2676ice_ptp_prep_phy_adj_target_e822(struct ice_hw *hw, u32 target_time)
2677{
2678        enum ice_status status;
2679        u8 port;
2680
2681        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2682
2683                /* Tx case */
2684                /* No sub-nanoseconds data */
2685                status = ice_write_phy_reg_e822_lp(hw, port,
2686                                                   P_REG_TX_TIMER_CNT_ADJ_L,
2687                                                   0, true);
2688                if (status)
2689                        goto exit_err;
2690
2691                status = ice_write_phy_reg_e822_lp(hw, port,
2692                                                   P_REG_TX_TIMER_CNT_ADJ_U,
2693                                                   target_time, true);
2694                if (status)
2695                        goto exit_err;
2696
2697                /* Rx case */
2698                /* No sub-nanoseconds data */
2699                status = ice_write_phy_reg_e822_lp(hw, port,
2700                                                   P_REG_RX_TIMER_CNT_ADJ_L,
2701                                                   0, true);
2702                if (status)
2703                        goto exit_err;
2704
2705                status = ice_write_phy_reg_e822_lp(hw, port,
2706                                                   P_REG_RX_TIMER_CNT_ADJ_U,
2707                                                   target_time, true);
2708                if (status)
2709                        goto exit_err;
2710        }
2711
2712        return ICE_SUCCESS;
2713
2714exit_err:
2715        ice_debug(hw, ICE_DBG_PTP, "Failed to write target time for port %u, status %d\n",
2716                  port, status);
2717
2718        return status;
2719}
2720
2721/**
2722 * ice_ptp_read_port_capture_e822 - Read a port's local time capture
2723 * @hw: pointer to HW struct
2724 * @port: Port number to read
2725 * @tx_ts: on return, the Tx port time capture
2726 * @rx_ts: on return, the Rx port time capture
2727 *
2728 * Read the port's Tx and Rx local time capture values.
2729 *
2730 * Note this has no equivalent for the E810 devices.
2731 */
2732enum ice_status
2733ice_ptp_read_port_capture_e822(struct ice_hw *hw, u8 port, u64 *tx_ts,
2734                               u64 *rx_ts)
2735{
2736        enum ice_status status;
2737
2738        /* Tx case */
2739        status = ice_read_64b_phy_reg_e822(hw, port, P_REG_TX_CAPTURE_L, tx_ts);
2740        if (status) {
2741                ice_debug(hw, ICE_DBG_PTP, "Failed to read REG_TX_CAPTURE, status %d\n",
2742                          status);
2743                return status;
2744        }
2745
2746        ice_debug(hw, ICE_DBG_PTP, "tx_init = 0x%016llx\n",
2747                  (unsigned long long)*tx_ts);
2748
2749        /* Rx case */
2750        status = ice_read_64b_phy_reg_e822(hw, port, P_REG_RX_CAPTURE_L, rx_ts);
2751        if (status) {
2752                ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_CAPTURE, status %d\n",
2753                          status);
2754                return status;
2755        }
2756
2757        ice_debug(hw, ICE_DBG_PTP, "rx_init = 0x%016llx\n",
2758                  (unsigned long long)*rx_ts);
2759
2760        return ICE_SUCCESS;
2761}
2762
2763/**
2764 * ice_ptp_one_port_cmd_e822 - Prepare a single PHY port for a timer command
2765 * @hw: pointer to HW struct
2766 * @port: Port to which cmd has to be sent
2767 * @cmd: Command to be sent to the port
2768 * @lock_sbq: true if the sideband queue lock must be acquired
2769 *
2770 * Prepare the requested port for an upcoming timer sync command.
2771 *
2772 * Note there is no equivalent of this operation on E810, as that device
2773 * always handles all external PHYs internally.
2774 */
2775enum ice_status
2776ice_ptp_one_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd,
2777                          bool lock_sbq)
2778{
2779        enum ice_status status;
2780        u32 cmd_val, val;
2781        u8 tmr_idx;
2782
2783        tmr_idx = ice_get_ptp_src_clock_index(hw);
2784        cmd_val = tmr_idx << SEL_PHY_SRC;
2785        switch (cmd) {
2786        case ICE_PTP_INIT_TIME:
2787                cmd_val |= PHY_CMD_INIT_TIME;
2788                break;
2789        case ICE_PTP_INIT_INCVAL:
2790                cmd_val |= PHY_CMD_INIT_INCVAL;
2791                break;
2792        case ICE_PTP_ADJ_TIME:
2793                cmd_val |= PHY_CMD_ADJ_TIME;
2794                break;
2795        case ICE_PTP_ADJ_TIME_AT_TIME:
2796                cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME;
2797                break;
2798        case ICE_PTP_READ_TIME:
2799                cmd_val |= PHY_CMD_READ_TIME;
2800                break;
2801        default:
2802                ice_warn(hw, "Unknown timer command %u\n", cmd);
2803                return ICE_ERR_PARAM;
2804        }
2805
2806        /* Tx case */
2807        /* Read, modify, write */
2808        status = ice_read_phy_reg_e822_lp(hw, port, P_REG_TX_TMR_CMD, &val,
2809                                          lock_sbq);
2810        if (status) {
2811                ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_TMR_CMD, status %d\n",
2812                          status);
2813                return status;
2814        }
2815
2816        /* Modify necessary bits only and perform write */
2817        val &= ~TS_CMD_MASK;
2818        val |= cmd_val;
2819
2820        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_TX_TMR_CMD, val,
2821                                           lock_sbq);
2822        if (status) {
2823                ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_TMR_CMD, status %d\n",
2824                          status);
2825                return status;
2826        }
2827
2828        /* Rx case */
2829        /* Read, modify, write */
2830        status = ice_read_phy_reg_e822_lp(hw, port, P_REG_RX_TMR_CMD, &val,
2831                                          lock_sbq);
2832        if (status) {
2833                ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_TMR_CMD, status %d\n",
2834                          status);
2835                return status;
2836        }
2837
2838        /* Modify necessary bits only and perform write */
2839        val &= ~TS_CMD_MASK;
2840        val |= cmd_val;
2841
2842        status = ice_write_phy_reg_e822_lp(hw, port, P_REG_RX_TMR_CMD, val,
2843                                           lock_sbq);
2844        if (status) {
2845                ice_debug(hw, ICE_DBG_PTP, "Failed to write back RX_TMR_CMD, status %d\n",
2846                          status);
2847                return status;
2848        }
2849
2850        return ICE_SUCCESS;
2851}
2852
2853/**
2854 * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command
2855 * @hw: pointer to the HW struct
2856 * @cmd: timer command to prepare
2857 * @lock_sbq: true if the sideband queue lock must  be acquired
2858 *
2859 * Prepare all ports connected to this device for an upcoming timer sync
2860 * command.
2861 */
2862static enum ice_status
2863ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
2864                      bool lock_sbq)
2865{
2866        u8 port;
2867
2868        for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
2869                enum ice_status status;
2870
2871                status = ice_ptp_one_port_cmd_e822(hw, port, cmd, lock_sbq);
2872                if (status)
2873                        return status;
2874        }
2875
2876        return ICE_SUCCESS;
2877}
2878
2879/* E822 Vernier calibration functions
2880 *
2881 * The following functions are used as part of the vernier calibration of
2882 * a port. This calibration increases the precision of the timestamps on the
2883 * port.
2884 */
2885
2886/**
2887 * ice_phy_get_speed_and_fec_e822 - Get link speed and FEC based on serdes mode
2888 * @hw: pointer to HW struct
2889 * @port: the port to read from
2890 * @link_out: if non-NULL, holds link speed on success
2891 * @fec_out: if non-NULL, holds FEC algorithm on success
2892 *
2893 * Read the serdes data for the PHY port and extract the link speed and FEC
2894 * algorithm.
2895 */
2896enum ice_status
2897ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port,
2898                               enum ice_ptp_link_spd *link_out,
2899                               enum ice_ptp_fec_mode *fec_out)
2900{
2901        enum ice_ptp_link_spd link;
2902        enum ice_ptp_fec_mode fec;
2903        enum ice_status status;
2904        u32 serdes;
2905
2906        status = ice_read_phy_reg_e822(hw, port, P_REG_LINK_SPEED, &serdes);
2907        if (status) {
2908                ice_debug(hw, ICE_DBG_PTP, "Failed to read serdes info\n");
2909                return status;
2910        }
2911
2912        /* Determine the FEC algorithm */
2913        fec = (enum ice_ptp_fec_mode)P_REG_LINK_SPEED_FEC_MODE(serdes);
2914
2915        serdes &= P_REG_LINK_SPEED_SERDES_M;
2916
2917        /* Determine the link speed */
2918        if (fec == ICE_PTP_FEC_MODE_RS_FEC) {
2919                switch (serdes) {
2920                case ICE_PTP_SERDES_25G:
2921                        link = ICE_PTP_LNK_SPD_25G_RS;
2922                        break;
2923                case ICE_PTP_SERDES_50G:
2924                        link = ICE_PTP_LNK_SPD_50G_RS;
2925                        break;
2926                case ICE_PTP_SERDES_100G:
2927                        link = ICE_PTP_LNK_SPD_100G_RS;
2928                        break;
2929                default:
2930                        return ICE_ERR_OUT_OF_RANGE;
2931                }
2932        } else {
2933                switch (serdes) {
2934                case ICE_PTP_SERDES_1G:
2935                        link = ICE_PTP_LNK_SPD_1G;
2936                        break;
2937                case ICE_PTP_SERDES_10G:
2938                        link = ICE_PTP_LNK_SPD_10G;
2939                        break;
2940                case ICE_PTP_SERDES_25G:
2941                        link = ICE_PTP_LNK_SPD_25G;
2942                        break;
2943                case ICE_PTP_SERDES_40G:
2944                        link = ICE_PTP_LNK_SPD_40G;
2945                        break;
2946                case ICE_PTP_SERDES_50G:
2947                        link = ICE_PTP_LNK_SPD_50G;
2948                        break;
2949                default:
2950                        return ICE_ERR_OUT_OF_RANGE;
2951                }
2952        }
2953
2954        if (link_out)
2955                *link_out = link;
2956        if (fec_out)
2957                *fec_out = fec;
2958
2959        return ICE_SUCCESS;
2960}
2961
2962/**
2963 * ice_phy_cfg_lane_e822 - Configure PHY quad for single/multi-lane timestamp
2964 * @hw: pointer to HW struct
2965 * @port: to configure the quad for
2966 */
2967void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port)
2968{
2969        enum ice_ptp_link_spd link_spd;
2970        enum ice_status status;
2971        u32 val;
2972        u8 quad;
2973
2974        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, NULL);
2975        if (status) {
2976                ice_debug(hw, ICE_DBG_PTP, "Failed to get PHY link speed, status %d\n",
2977                          status);
2978                return;
2979        }
2980
2981        quad = port / ICE_PORTS_PER_QUAD;
2982
2983        status = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, &val);
2984        if (status) {
2985                ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEM_GLB_CFG, status %d\n",
2986                          status);
2987                return;
2988        }
2989
2990        if (link_spd >= ICE_PTP_LNK_SPD_40G)
2991                val &= ~Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_M;
2992        else
2993                val |= Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_M;
2994
2995        status = ice_write_quad_reg_e822(hw, quad, Q_REG_TX_MEM_GBL_CFG, val);
2996        if (status) {
2997                ice_debug(hw, ICE_DBG_PTP, "Failed to write back TX_MEM_GBL_CFG, status %d\n",
2998                          status);
2999                return;
3000        }
3001}
3002
3003/**
3004 * ice_phy_cfg_uix_e822 - Configure Serdes UI to TU conversion for E822
3005 * @hw: pointer to the HW structure
3006 * @port: the port to configure
3007 *
3008 * Program the conversion ration of Serdes clock "unit intervals" (UIs) to PHC
3009 * hardware clock time units (TUs). That is, determine the number of TUs per
3010 * serdes unit interval, and program the UIX registers with this conversion.
3011 *
3012 * This conversion is used as part of the calibration process when determining
3013 * the additional error of a timestamp vs the real time of transmission or
3014 * receipt of the packet.
3015 *
3016 * Hardware uses the number of TUs per 66 UIs, written to the UIX registers
3017 * for the two main serdes clock rates, 10G/40G and 25G/100G serdes clocks.
3018 *
3019 * To calculate the conversion ratio, we use the following facts:
3020 *
3021 * a) the clock frequency in Hz (cycles per second)
3022 * b) the number of TUs per cycle (the increment value of the clock)
3023 * c) 1 second per 1 billion nanoseconds
3024 * d) the duration of 66 UIs in nanoseconds
3025 *
3026 * Given these facts, we can use the following table to work out what ratios
3027 * to multiply in order to get the number of TUs per 66 UIs:
3028 *
3029 * cycles |   1 second   | incval (TUs) | nanoseconds
3030 * -------+--------------+--------------+-------------
3031 * second | 1 billion ns |    cycle     |   66 UIs
3032 *
3033 * To perform the multiplication using integers without too much loss of
3034 * precision, we can take use the following equation:
3035 *
3036 * (freq * incval * 6600 LINE_UI ) / ( 100 * 1 billion)
3037 *
3038 * We scale up to using 6600 UI instead of 66 in order to avoid fractional
3039 * nanosecond UIs (66 UI at 10G/40G is 6.4 ns)
3040 *
3041 * The increment value has a maximum expected range of about 34 bits, while
3042 * the frequency value is about 29 bits. Multiplying these values shouldn't
3043 * overflow the 64 bits. However, we must then further multiply them again by
3044 * the Serdes unit interval duration. To avoid overflow here, we split the
3045 * overall divide by 1e11 into a divide by 256 (shift down by 8 bits) and
3046 * a divide by 390,625,000. This does lose some precision, but avoids
3047 * miscalculation due to arithmetic overflow.
3048 */
3049static enum ice_status ice_phy_cfg_uix_e822(struct ice_hw *hw, u8 port)
3050{
3051        u64 cur_freq, clk_incval, tu_per_sec, uix;
3052        enum ice_status status;
3053
3054        cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw));
3055        clk_incval = ice_ptp_read_src_incval(hw);
3056
3057        /* Calculate TUs per second divided by 256 */
3058        tu_per_sec = (cur_freq * clk_incval) >> 8;
3059
3060#define LINE_UI_10G_40G 640 /* 6600 UIs is 640 nanoseconds at 10Gb/40Gb */
3061#define LINE_UI_25G_100G 256 /* 6600 UIs is 256 nanoseconds at 25Gb/100Gb */
3062
3063        /* Program the 10Gb/40Gb conversion ratio */
3064        uix = DIV_U64(tu_per_sec * LINE_UI_10G_40G, 390625000);
3065
3066        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_10G_40G_L,
3067                                            uix);
3068        if (status) {
3069                ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_10G_40G, status %d\n",
3070                          status);
3071                return status;
3072        }
3073
3074        /* Program the 25Gb/100Gb conversion ratio */
3075        uix = DIV_U64(tu_per_sec * LINE_UI_25G_100G, 390625000);
3076
3077        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_UIX66_25G_100G_L,
3078                                            uix);
3079        if (status) {
3080                ice_debug(hw, ICE_DBG_PTP, "Failed to write UIX66_25G_100G, status %d\n",
3081                          status);
3082                return status;
3083        }
3084
3085        return ICE_SUCCESS;
3086}
3087
3088/**
3089 * ice_phy_cfg_parpcs_e822 - Configure TUs per PAR/PCS clock cycle
3090 * @hw: pointer to the HW struct
3091 * @port: port to configure
3092 *
3093 * Configure the number of TUs for the PAR and PCS clocks used as part of the
3094 * timestamp calibration process. This depends on the link speed, as the PHY
3095 * uses different markers depending on the speed.
3096 *
3097 * 1Gb/10Gb/25Gb:
3098 * - Tx/Rx PAR/PCS markers
3099 *
3100 * 25Gb RS:
3101 * - Tx/Rx Reed Solomon gearbox PAR/PCS markers
3102 *
3103 * 40Gb/50Gb:
3104 * - Tx/Rx PAR/PCS markers
3105 * - Rx Deskew PAR/PCS markers
3106 *
3107 * 50G RS and 100GB RS:
3108 * - Tx/Rx Reed Solomon gearbox PAR/PCS markers
3109 * - Rx Deskew PAR/PCS markers
3110 * - Tx PAR/PCS markers
3111 *
3112 * To calculate the conversion, we use the PHC clock frequency (cycles per
3113 * second), the increment value (TUs per cycle), and the related PHY clock
3114 * frequency to calculate the TUs per unit of the PHY link clock. The
3115 * following table shows how the units convert:
3116 *
3117 * cycles |  TUs  | second
3118 * -------+-------+--------
3119 * second | cycle | cycles
3120 *
3121 * For each conversion register, look up the appropriate frequency from the
3122 * e822 PAR/PCS table and calculate the TUs per unit of that clock. Program
3123 * this to the appropriate register, preparing hardware to perform timestamp
3124 * calibration to calculate the total Tx or Rx offset to adjust the timestamp
3125 * in order to calibrate for the internal PHY delays.
3126 *
3127 * Note that the increment value ranges up to ~34 bits, and the clock
3128 * frequency is ~29 bits, so multiplying them together should fit within the
3129 * 64 bit arithmetic.
3130 */
3131static enum ice_status ice_phy_cfg_parpcs_e822(struct ice_hw *hw, u8 port)
3132{
3133        u64 cur_freq, clk_incval, tu_per_sec, phy_tus;
3134        enum ice_ptp_link_spd link_spd;
3135        enum ice_ptp_fec_mode fec_mode;
3136        enum ice_status status;
3137
3138        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
3139        if (status)
3140                return status;
3141
3142        cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw));
3143        clk_incval = ice_ptp_read_src_incval(hw);
3144
3145        /* Calculate TUs per cycle of the PHC clock */
3146        tu_per_sec = cur_freq * clk_incval;
3147
3148        /* For each PHY conversion register, look up the appropriate link
3149         * speed frequency and determine the TUs per that clock's cycle time.
3150         * Split this into a high and low value and then program the
3151         * appropriate register. If that link speed does not use the
3152         * associated register, write zeros to clear it instead.
3153         */
3154
3155        /* P_REG_PAR_TX_TUS */
3156        if (e822_vernier[link_spd].tx_par_clk)
3157                phy_tus = DIV_U64(tu_per_sec,
3158                                  e822_vernier[link_spd].tx_par_clk);
3159        else
3160                phy_tus = 0;
3161
3162        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_TX_TUS_L,
3163                                            phy_tus);
3164        if (status)
3165                return status;
3166
3167        /* P_REG_PAR_RX_TUS */
3168        if (e822_vernier[link_spd].rx_par_clk)
3169                phy_tus = DIV_U64(tu_per_sec,
3170                                  e822_vernier[link_spd].rx_par_clk);
3171        else
3172                phy_tus = 0;
3173
3174        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_PAR_RX_TUS_L,
3175                                            phy_tus);
3176        if (status)
3177                return status;
3178
3179        /* P_REG_PCS_TX_TUS */
3180        if (e822_vernier[link_spd].tx_pcs_clk)
3181                phy_tus = DIV_U64(tu_per_sec,
3182                                  e822_vernier[link_spd].tx_pcs_clk);
3183        else
3184                phy_tus = 0;
3185
3186        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_TX_TUS_L,
3187                                            phy_tus);
3188        if (status)
3189                return status;
3190
3191        /* P_REG_PCS_RX_TUS */
3192        if (e822_vernier[link_spd].rx_pcs_clk)
3193                phy_tus = DIV_U64(tu_per_sec,
3194                                  e822_vernier[link_spd].rx_pcs_clk);
3195        else
3196                phy_tus = 0;
3197
3198        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_PCS_RX_TUS_L,
3199                                            phy_tus);
3200        if (status)
3201                return status;
3202
3203        /* P_REG_DESK_PAR_TX_TUS */
3204        if (e822_vernier[link_spd].tx_desk_rsgb_par)
3205                phy_tus = DIV_U64(tu_per_sec,
3206                                  e822_vernier[link_spd].tx_desk_rsgb_par);
3207        else
3208                phy_tus = 0;
3209
3210        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_TX_TUS_L,
3211                                            phy_tus);
3212        if (status)
3213                return status;
3214
3215        /* P_REG_DESK_PAR_RX_TUS */
3216        if (e822_vernier[link_spd].rx_desk_rsgb_par)
3217                phy_tus = DIV_U64(tu_per_sec,
3218                                  e822_vernier[link_spd].rx_desk_rsgb_par);
3219        else
3220                phy_tus = 0;
3221
3222        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PAR_RX_TUS_L,
3223                                            phy_tus);
3224        if (status)
3225                return status;
3226
3227        /* P_REG_DESK_PCS_TX_TUS */
3228        if (e822_vernier[link_spd].tx_desk_rsgb_pcs)
3229                phy_tus = DIV_U64(tu_per_sec,
3230                                  e822_vernier[link_spd].tx_desk_rsgb_pcs);
3231        else
3232                phy_tus = 0;
3233
3234        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_TX_TUS_L,
3235                                            phy_tus);
3236        if (status)
3237                return status;
3238
3239        /* P_REG_DESK_PCS_RX_TUS */
3240        if (e822_vernier[link_spd].rx_desk_rsgb_pcs)
3241                phy_tus = DIV_U64(tu_per_sec,
3242                                  e822_vernier[link_spd].rx_desk_rsgb_pcs);
3243        else
3244                phy_tus = 0;
3245
3246        return ice_write_40b_phy_reg_e822(hw, port, P_REG_DESK_PCS_RX_TUS_L,
3247                                          phy_tus);
3248}
3249
3250/**
3251 * ice_calc_fixed_tx_offset_e822 - Calculated Fixed Tx offset for a port
3252 * @hw: pointer to the HW struct
3253 * @link_spd: the Link speed to calculate for
3254 *
3255 * Calculate the fixed offset due to known static latency data.
3256 */
3257static u64
3258ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd)
3259{
3260        u64 cur_freq, clk_incval, tu_per_sec, fixed_offset;
3261
3262        cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw));
3263        clk_incval = ice_ptp_read_src_incval(hw);
3264
3265        /* Calculate TUs per second */
3266        tu_per_sec = cur_freq * clk_incval;
3267
3268        /* Calculate number of TUs to add for the fixed Tx latency. Since the
3269         * latency measurement is in 1/100th of a nanosecond, we need to
3270         * multiply by tu_per_sec and then divide by 1e11. This calculation
3271         * overflows 64 bit integer arithmetic, so break it up into two
3272         * divisions by 1e4 first then by 1e7.
3273         */
3274        fixed_offset = DIV_U64(tu_per_sec, 10000);
3275        fixed_offset *= e822_vernier[link_spd].tx_fixed_delay;
3276        fixed_offset = DIV_U64(fixed_offset, 10000000);
3277
3278        return fixed_offset;
3279}
3280
3281/**
3282 * ice_phy_cfg_tx_offset_e822 - Configure total Tx timestamp offset
3283 * @hw: pointer to the HW struct
3284 * @port: the PHY port to configure
3285 *
3286 * Program the P_REG_TOTAL_TX_OFFSET register with the total number of TUs to
3287 * adjust Tx timestamps by. This is calculated by combining some known static
3288 * latency along with the Vernier offset computations done by hardware.
3289 *
3290 * This function must be called only after the offset registers are valid,
3291 * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
3292 * has measured the offset.
3293 *
3294 * To avoid overflow, when calculating the offset based on the known static
3295 * latency values, we use measurements in 1/100th of a nanosecond, and divide
3296 * the TUs per second up front. This avoids overflow while allowing
3297 * calculation of the adjustment using integer arithmetic.
3298 */
3299enum ice_status ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
3300{
3301        enum ice_ptp_link_spd link_spd;
3302        enum ice_ptp_fec_mode fec_mode;
3303        enum ice_status status;
3304        u64 total_offset, val;
3305
3306        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
3307        if (status)
3308                return status;
3309
3310        total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd);
3311
3312        /* Read the first Vernier offset from the PHY register and add it to
3313         * the total offset.
3314         */
3315        if (link_spd == ICE_PTP_LNK_SPD_1G ||
3316            link_spd == ICE_PTP_LNK_SPD_10G ||
3317            link_spd == ICE_PTP_LNK_SPD_25G ||
3318            link_spd == ICE_PTP_LNK_SPD_25G_RS ||
3319            link_spd == ICE_PTP_LNK_SPD_40G ||
3320            link_spd == ICE_PTP_LNK_SPD_50G) {
3321                status = ice_read_64b_phy_reg_e822(hw, port,
3322                                                   P_REG_PAR_PCS_TX_OFFSET_L,
3323                                                   &val);
3324                if (status)
3325                        return status;
3326
3327                total_offset += val;
3328        }
3329
3330        /* For Tx, we only need to use the second Vernier offset for
3331         * multi-lane link speeds with RS-FEC. The lanes will always be
3332         * aligned.
3333         */
3334        if (link_spd == ICE_PTP_LNK_SPD_50G_RS ||
3335            link_spd == ICE_PTP_LNK_SPD_100G_RS) {
3336                status = ice_read_64b_phy_reg_e822(hw, port,
3337                                                   P_REG_PAR_TX_TIME_L,
3338                                                   &val);
3339                if (status)
3340                        return status;
3341
3342                total_offset += val;
3343        }
3344
3345        /* Now that the total offset has been calculated, program it to the
3346         * PHY and indicate that the Tx offset is ready. After this,
3347         * timestamps will be enabled.
3348         */
3349        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L,
3350                                            total_offset);
3351        if (status)
3352                return status;
3353
3354        status = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1);
3355        if (status)
3356                return status;
3357
3358        return ICE_SUCCESS;
3359}
3360
3361/**
3362 * ice_phy_cfg_fixed_tx_offset_e822 - Configure Tx offset for bypass mode
3363 * @hw: pointer to the HW struct
3364 * @port: the PHY port to configure
3365 *
3366 * Calculate and program the fixed Tx offset, and indicate that the offset is
3367 * ready. This can be used when operating in bypass mode.
3368 */
3369static enum ice_status
3370ice_phy_cfg_fixed_tx_offset_e822(struct ice_hw *hw, u8 port)
3371{
3372        enum ice_ptp_link_spd link_spd;
3373        enum ice_ptp_fec_mode fec_mode;
3374        enum ice_status status;
3375        u64 total_offset;
3376
3377        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
3378        if (status)
3379                return status;
3380
3381        total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd);
3382
3383        /* Program the fixed Tx offset into the P_REG_TOTAL_TX_OFFSET_L
3384         * register, then indicate that the Tx offset is ready. After this,
3385         * timestamps will be enabled.
3386         *
3387         * Note that this skips including the more precise offsets generated
3388         * by the Vernier calibration.
3389         */
3390        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L,
3391                                            total_offset);
3392        if (status)
3393                return status;
3394
3395        status = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1);
3396        if (status)
3397                return status;
3398
3399        return ICE_SUCCESS;
3400}
3401
3402/**
3403 * ice_phy_calc_pmd_adj_e822 - Calculate PMD adjustment for Rx
3404 * @hw: pointer to the HW struct
3405 * @port: the PHY port to adjust for
3406 * @link_spd: the current link speed of the PHY
3407 * @fec_mode: the current FEC mode of the PHY
3408 * @pmd_adj: on return, the amount to adjust the Rx total offset by
3409 *
3410 * Calculates the adjustment to Rx timestamps due to PMD alignment in the PHY.
3411 * This varies by link speed and FEC mode. The value calculated accounts for
3412 * various delays caused when receiving a packet.
3413 */
3414static enum ice_status
3415ice_phy_calc_pmd_adj_e822(struct ice_hw *hw, u8 port,
3416                          enum ice_ptp_link_spd link_spd,
3417                          enum ice_ptp_fec_mode fec_mode, u64 *pmd_adj)
3418{
3419        u64 cur_freq, clk_incval, tu_per_sec, mult, adj;
3420        u32 pmd_adj_divisor, val;
3421        enum ice_status status;
3422        u8 pmd_align;
3423
3424        status = ice_read_phy_reg_e822(hw, port, P_REG_PMD_ALIGNMENT, &val);
3425        if (status) {
3426                ice_debug(hw, ICE_DBG_PTP, "Failed to read PMD alignment, status %d\n",
3427                          status);
3428                return status;
3429        }
3430
3431        pmd_align = (u8)val;
3432
3433        cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw));
3434        clk_incval = ice_ptp_read_src_incval(hw);
3435
3436        /* Calculate TUs per second */
3437        tu_per_sec = cur_freq * clk_incval;
3438
3439        /* Get the link speed dependent PMD adjustment divisor */
3440        pmd_adj_divisor = e822_vernier[link_spd].pmd_adj_divisor;
3441
3442        /* The PMD alignment adjustment measurement depends on the link speed,
3443         * and whether FEC is enabled. For each link speed, the alignment
3444         * adjustment is calculated by dividing a value by the length of
3445         * a Time Unit in nanoseconds.
3446         *
3447         * 1G: align == 4 ? 10 * 0.8 : (align + 6 % 10) * 0.8
3448         * 10G: align == 65 ? 0 : (align * 0.1 * 32/33)
3449         * 10G w/FEC: align * 0.1 * 32/33
3450         * 25G: align == 65 ? 0 : (align * 0.4 * 32/33)
3451         * 25G w/FEC: align * 0.4 * 32/33
3452         * 40G: align == 65 ? 0 : (align * 0.1 * 32/33)
3453         * 40G w/FEC: align * 0.1 * 32/33
3454         * 50G: align == 65 ? 0 : (align * 0.4 * 32/33)
3455         * 50G w/FEC: align * 0.8 * 32/33
3456         *
3457         * For RS-FEC, if align is < 17 then we must also add 1.6 * 32/33.
3458         *
3459         * To allow for calculating this value using integer arithmetic, we
3460         * instead start with the number of TUs per second, (inverse of the
3461         * length of a Time Unit in nanoseconds), multiply by a value based
3462         * on the PMD alignment register, and then divide by the right value
3463         * calculated based on the table above. To avoid integer overflow this
3464         * division is broken up into a step of dividing by 125 first.
3465         */
3466        if (link_spd == ICE_PTP_LNK_SPD_1G) {
3467                if (pmd_align == 4)
3468                        mult = 10;
3469                else
3470                        mult = (pmd_align + 6) % 10;
3471        } else if (link_spd == ICE_PTP_LNK_SPD_10G ||
3472                   link_spd == ICE_PTP_LNK_SPD_25G ||
3473                   link_spd == ICE_PTP_LNK_SPD_40G ||
3474                   link_spd == ICE_PTP_LNK_SPD_50G) {
3475                /* If Clause 74 FEC, always calculate PMD adjust */
3476                if (pmd_align != 65 || fec_mode == ICE_PTP_FEC_MODE_CLAUSE74)
3477                        mult = pmd_align;
3478                else
3479                        mult = 0;
3480        } else if (link_spd == ICE_PTP_LNK_SPD_25G_RS ||
3481                   link_spd == ICE_PTP_LNK_SPD_50G_RS ||
3482                   link_spd == ICE_PTP_LNK_SPD_100G_RS) {
3483                if (pmd_align < 17)
3484                        mult = pmd_align + 40;
3485                else
3486                        mult = pmd_align;
3487        } else {
3488                ice_debug(hw, ICE_DBG_PTP, "Unknown link speed %d, skipping PMD adjustment\n",
3489                          link_spd);
3490                mult = 0;
3491        }
3492
3493        /* In some cases, there's no need to adjust for the PMD alignment */
3494        if (!mult) {
3495                *pmd_adj = 0;
3496                return ICE_SUCCESS;
3497        }
3498
3499        /* Calculate the adjustment by multiplying TUs per second by the
3500         * appropriate multiplier and divisor. To avoid overflow, we first
3501         * divide by 125, and then handle remaining divisor based on the link
3502         * speed pmd_adj_divisor value.
3503         */
3504        adj = DIV_U64(tu_per_sec, 125);
3505        adj *= mult;
3506        adj = DIV_U64(adj, pmd_adj_divisor);
3507
3508        /* Finally, for 25G-RS and 50G-RS, a further adjustment for the Rx
3509         * cycle count is necessary.
3510         */
3511        if (link_spd == ICE_PTP_LNK_SPD_25G_RS) {
3512                u64 cycle_adj;
3513                u8 rx_cycle;
3514
3515                status = ice_read_phy_reg_e822(hw, port, P_REG_RX_40_TO_160_CNT,
3516                                               &val);
3517                if (status) {
3518                        ice_debug(hw, ICE_DBG_PTP, "Failed to read 25G-RS Rx cycle count, status %d\n",
3519                                  status);
3520                        return status;
3521                }
3522
3523                rx_cycle = val & P_REG_RX_40_TO_160_CNT_RXCYC_M;
3524                if (rx_cycle) {
3525                        mult = (4 - rx_cycle) * 40;
3526
3527                        cycle_adj = DIV_U64(tu_per_sec, 125);
3528                        cycle_adj *= mult;
3529                        cycle_adj = DIV_U64(cycle_adj, pmd_adj_divisor);
3530
3531                        adj += cycle_adj;
3532                }
3533        } else if (link_spd == ICE_PTP_LNK_SPD_50G_RS) {
3534                u64 cycle_adj;
3535                u8 rx_cycle;
3536
3537                status = ice_read_phy_reg_e822(hw, port, P_REG_RX_80_TO_160_CNT,
3538                                               &val);
3539                if (status) {
3540                        ice_debug(hw, ICE_DBG_PTP, "Failed to read 50G-RS Rx cycle count, status %d\n",
3541                                  status);
3542                        return status;
3543                }
3544
3545                rx_cycle = val & P_REG_RX_80_TO_160_CNT_RXCYC_M;
3546                if (rx_cycle) {
3547                        mult = rx_cycle * 40;
3548
3549                        cycle_adj = DIV_U64(tu_per_sec, 125);
3550                        cycle_adj *= mult;
3551                        cycle_adj = DIV_U64(cycle_adj, pmd_adj_divisor);
3552
3553                        adj += cycle_adj;
3554                }
3555        }
3556
3557        /* Return the calculated adjustment */
3558        *pmd_adj = adj;
3559
3560        return ICE_SUCCESS;
3561}
3562
3563/**
3564 * ice_calc_fixed_rx_offset_e822 - Calculated the fixed Rx offset for a port
3565 * @hw: pointer to HW struct
3566 * @link_spd: The Link speed to calculate for
3567 *
3568 * Determine the fixed Rx latency for a given link speed.
3569 */
3570static u64
3571ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd)
3572{
3573        u64 cur_freq, clk_incval, tu_per_sec, fixed_offset;
3574
3575        cur_freq = ice_e822_pll_freq(ice_e822_time_ref(hw));
3576        clk_incval = ice_ptp_read_src_incval(hw);
3577
3578        /* Calculate TUs per second */
3579        tu_per_sec = cur_freq * clk_incval;
3580
3581        /* Calculate number of TUs to add for the fixed Rx latency. Since the
3582         * latency measurement is in 1/100th of a nanosecond, we need to
3583         * multiply by tu_per_sec and then divide by 1e11. This calculation
3584         * overflows 64 bit integer arithmetic, so break it up into two
3585         * divisions by 1e4 first then by 1e7.
3586         */
3587        fixed_offset = DIV_U64(tu_per_sec, 10000);
3588        fixed_offset *= e822_vernier[link_spd].rx_fixed_delay;
3589        fixed_offset = DIV_U64(fixed_offset, 10000000);
3590
3591        return fixed_offset;
3592}
3593
3594/**
3595 * ice_phy_cfg_rx_offset_e822 - Configure total Rx timestamp offset
3596 * @hw: pointer to the HW struct
3597 * @port: the PHY port to configure
3598 *
3599 * Program the P_REG_TOTAL_RX_OFFSET register with the number of Time Units to
3600 * adjust Rx timestamps by. This combines calculations from the Vernier offset
3601 * measurements taken in hardware with some data about known fixed delay as
3602 * well as adjusting for multi-lane alignment delay.
3603 *
3604 * This function must be called only after the offset registers are valid,
3605 * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
3606 * has measured the offset.
3607 *
3608 * To avoid overflow, when calculating the offset based on the known static
3609 * latency values, we use measurements in 1/100th of a nanosecond, and divide
3610 * the TUs per second up front. This avoids overflow while allowing
3611 * calculation of the adjustment using integer arithmetic.
3612 */
3613enum ice_status ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
3614{
3615        enum ice_ptp_link_spd link_spd;
3616        enum ice_ptp_fec_mode fec_mode;
3617        u64 total_offset, pmd, val;
3618        enum ice_status status;
3619
3620        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
3621        if (status)
3622                return status;
3623
3624        total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd);
3625
3626        /* Read the first Vernier offset from the PHY register and add it to
3627         * the total offset.
3628         */
3629        status = ice_read_64b_phy_reg_e822(hw, port,
3630                                           P_REG_PAR_PCS_RX_OFFSET_L,
3631                                           &val);
3632        if (status)
3633                return status;
3634
3635        total_offset += val;
3636
3637        /* For Rx, all multi-lane link speeds include a second Vernier
3638         * calibration, because the lanes might not be aligned.
3639         */
3640        if (link_spd == ICE_PTP_LNK_SPD_40G ||
3641            link_spd == ICE_PTP_LNK_SPD_50G ||
3642            link_spd == ICE_PTP_LNK_SPD_50G_RS ||
3643            link_spd == ICE_PTP_LNK_SPD_100G_RS) {
3644                status = ice_read_64b_phy_reg_e822(hw, port,
3645                                                   P_REG_PAR_RX_TIME_L,
3646                                                   &val);
3647                if (status)
3648                        return status;
3649
3650                total_offset += val;
3651        }
3652
3653        /* In addition, Rx must account for the PMD alignment */
3654        status = ice_phy_calc_pmd_adj_e822(hw, port, link_spd, fec_mode, &pmd);
3655        if (status)
3656                return status;
3657
3658        /* For RS-FEC, this adjustment adds delay, but for other modes, it
3659         * subtracts delay.
3660         */
3661        if (fec_mode == ICE_PTP_FEC_MODE_RS_FEC)
3662                total_offset += pmd;
3663        else
3664                total_offset -= pmd;
3665
3666        /* Now that the total offset has been calculated, program it to the
3667         * PHY and indicate that the Rx offset is ready. After this,
3668         * timestamps will be enabled.
3669         */
3670        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L,
3671                                            total_offset);
3672        if (status)
3673                return status;
3674
3675        status = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1);
3676        if (status)
3677                return status;
3678
3679        return ICE_SUCCESS;
3680}
3681
3682/**
3683 * ice_phy_cfg_fixed_rx_offset_e822 - Configure fixed Rx offset for bypass mode
3684 * @hw: pointer to the HW struct
3685 * @port: the PHY port to configure
3686 *
3687 * Calculate and program the fixed Rx offset, and indicate that the offset is
3688 * ready. This can be used when operating in bypass mode.
3689 */
3690static enum ice_status
3691ice_phy_cfg_fixed_rx_offset_e822(struct ice_hw *hw, u8 port)
3692{
3693        enum ice_ptp_link_spd link_spd;
3694        enum ice_ptp_fec_mode fec_mode;
3695        enum ice_status status;
3696        u64 total_offset;
3697
3698        status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
3699        if (status)
3700                return status;
3701
3702        total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd);
3703
3704        /* Program the fixed Rx offset into the P_REG_TOTAL_RX_OFFSET_L
3705         * register, then indicate that the Rx offset is ready. After this,
3706         * timestamps will be enabled.
3707         *
3708         * Note that this skips including the more precise offsets generated
3709         * by Vernier calibration.
3710         */
3711        status = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L,
3712                                            total_offset);
3713        if (status)
3714                return status;
3715
3716        status = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1);
3717        if (status)
3718                return status;
3719
3720        return ICE_SUCCESS;
3721}
3722
3723/**
3724 * ice_read_phy_and_phc_time_e822 - Simultaneously capture PHC and PHY time
3725 * @hw: pointer to the HW struct
3726 * @port: the PHY port to read
3727 * @phy_time: on return, the 64bit PHY timer value
3728 * @phc_time: on return, the lower 64bits of PHC time
3729 *
3730 * Issue a ICE_PTP_READ_TIME timer command to simultaneously capture the PHY
3731 * and PHC timer values.
3732 */
3733static enum ice_status
3734ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time,
3735                               u64 *phc_time)
3736{
3737        enum ice_status status;
3738        u64 tx_time, rx_time;
3739        u32 zo, lo;
3740        u8 tmr_idx;
3741
3742        tmr_idx = ice_get_ptp_src_clock_index(hw);
3743
3744        /* Prepare the PHC timer for a ICE_PTP_READ_TIME capture command */
3745        ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
3746
3747        /* Prepare the PHY timer for a ICE_PTP_READ_TIME capture command */
3748        status = ice_ptp_one_port_cmd_e822(hw, port, ICE_PTP_READ_TIME, true);
3749        if (status)
3750                return status;
3751
3752        /* Issue the sync to start the ICE_PTP_READ_TIME capture */
3753        ice_ptp_exec_tmr_cmd(hw);
3754        ice_ptp_clean_cmd(hw);
3755
3756        /* Read the captured PHC time from the shadow time registers */
3757        zo = rd32(hw, GLTSYN_SHTIME_0(tmr_idx));
3758        lo = rd32(hw, GLTSYN_SHTIME_L(tmr_idx));
3759        *phc_time = (u64)lo << 32 | zo;
3760
3761        /* Read the captured PHY time from the PHY shadow registers */
3762        status = ice_ptp_read_port_capture_e822(hw, port, &tx_time, &rx_time);
3763        if (status)
3764                return status;
3765
3766        /* If the PHY Tx and Rx timers don't match, log a warning message.
3767         * Note that this should not happen in normal circumstances since the
3768         * driver always programs them together.
3769         */
3770        if (tx_time != rx_time)
3771                ice_warn(hw, "PHY port %u Tx and Rx timers do not match, tx_time 0x%016llX, rx_time 0x%016llX\n",
3772                         port, (unsigned long long)tx_time,
3773                         (unsigned long long)rx_time);
3774
3775        *phy_time = tx_time;
3776
3777        return ICE_SUCCESS;
3778}
3779
3780/**
3781 * ice_sync_phy_timer_e822 - Synchronize the PHY timer with PHC timer
3782 * @hw: pointer to the HW struct
3783 * @port: the PHY port to synchronize
3784 *
3785 * Perform an adjustment to ensure that the PHY and PHC timers are in sync.
3786 * This is done by issuing a ICE_PTP_READ_TIME command which triggers a
3787 * simultaneous read of the PHY timer and PHC timer. Then we use the
3788 * difference to calculate an appropriate 2s complement addition to add
3789 * to the PHY timer in order to ensure it reads the same value as the
3790 * primary PHC timer.
3791 */
3792static enum ice_status ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
3793{
3794        u64 phc_time, phy_time, difference;
3795        enum ice_status status;
3796
3797        if (!ice_ptp_lock(hw)) {
3798                ice_debug(hw, ICE_DBG_PTP, "Failed to acquire PTP semaphore\n");
3799                return ICE_ERR_NOT_READY;
3800        }
3801
3802        status = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time);
3803        if (status)
3804                goto err_unlock;
3805
3806        /* Calculate the amount required to add to the port time in order for
3807         * it to match the PHC time.
3808         *
3809         * Note that the port adjustment is done using 2s complement
3810         * arithmetic. This is convenient since it means that we can simply
3811         * calculate the difference between the PHC time and the port time,
3812         * and it will be interpreted correctly.
3813         */
3814        difference = phc_time - phy_time;
3815
3816        status = ice_ptp_prep_port_adj_e822(hw, port, (s64)difference, true);
3817        if (status)
3818                goto err_unlock;
3819
3820        status = ice_ptp_one_port_cmd_e822(hw, port, ICE_PTP_ADJ_TIME, true);
3821        if (status)
3822                goto err_unlock;
3823
3824        /* Init PHC mstr/src cmd for exec during sync */
3825        ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
3826
3827        /* Issue the sync to activate the time adjustment */
3828        ice_ptp_exec_tmr_cmd(hw);
3829        ice_ptp_clean_cmd(hw);
3830
3831        /* Re-capture the timer values to flush the command registers and
3832         * verify that the time was properly adjusted.
3833         */
3834        status = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time);
3835        if (status)
3836                goto err_unlock;
3837
3838        ice_info(hw, "Port %u PHY time synced to PHC: 0x%016llX, 0x%016llX\n",
3839                 port, (unsigned long long)phy_time,
3840                 (unsigned long long)phc_time);
3841
3842        ice_ptp_unlock(hw);
3843
3844        return ICE_SUCCESS;
3845
3846err_unlock:
3847        ice_ptp_unlock(hw);
3848        return status;
3849}
3850
3851/**
3852 * ice_stop_phy_timer_e822 - Stop the PHY clock timer
3853 * @hw: pointer to the HW struct
3854 * @port: the PHY port to stop
3855 * @soft_reset: if true, hold the SOFT_RESET bit of P_REG_PS
3856 *
3857 * Stop the clock of a PHY port. This must be done as part of the flow to
3858 * re-calibrate Tx and Rx timestamping offsets whenever the clock time is
3859 * initialized or when link speed changes.
3860 */
3861enum ice_status
3862ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset)
3863{
3864        enum ice_status status;
3865        u32 val;
3866
3867        status = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 0);
3868        if (status)
3869                return status;
3870
3871        status = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 0);
3872        if (status)
3873                return status;
3874
3875        status = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
3876        if (status)
3877                return status;
3878
3879        val &= ~P_REG_PS_START_M;
3880        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3881        if (status)
3882                return status;
3883
3884        val &= ~P_REG_PS_ENA_CLK_M;
3885        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3886        if (status)
3887                return status;
3888
3889        if (soft_reset) {
3890                val |= P_REG_PS_SFT_RESET_M;
3891                status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3892                if (status)
3893                        return status;
3894        }
3895
3896        ice_debug(hw, ICE_DBG_PTP, "Disabled clock on PHY port %u\n", port);
3897
3898        return ICE_SUCCESS;
3899}
3900
3901/**
3902 * ice_start_phy_timer_e822 - Start the PHY clock timer
3903 * @hw: pointer to the HW struct
3904 * @port: the PHY port to start
3905 * @bypass: if true, start the PHY in bypass mode
3906 *
3907 * Start the clock of a PHY port. This must be done as part of the flow to
3908 * re-calibrate Tx and Rx timestamping offsets whenever the clock time is
3909 * initialized or when link speed changes.
3910 *
3911 * Bypass mode enables timestamps immediately without waiting for Vernier
3912 * calibration to complete. Hardware will still continue taking Vernier
3913 * measurements on Tx or Rx of packets, but they will not be applied to
3914 * timestamps. Use ice_phy_exit_bypass_e822 to exit bypass mode once hardware
3915 * has completed offset calculation.
3916 */
3917enum ice_status
3918ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass)
3919{
3920        enum ice_status status;
3921        u32 lo, hi, val;
3922        u64 incval;
3923        u8 tmr_idx;
3924
3925        ice_ptp_clean_cmd(hw);
3926        tmr_idx = ice_get_ptp_src_clock_index(hw);
3927
3928        status = ice_stop_phy_timer_e822(hw, port, false);
3929        if (status)
3930                return status;
3931
3932        ice_phy_cfg_lane_e822(hw, port);
3933
3934        status = ice_phy_cfg_uix_e822(hw, port);
3935        if (status)
3936                return status;
3937
3938        status = ice_phy_cfg_parpcs_e822(hw, port);
3939        if (status)
3940                return status;
3941
3942        lo = rd32(hw, GLTSYN_INCVAL_L(tmr_idx));
3943        hi = rd32(hw, GLTSYN_INCVAL_H(tmr_idx));
3944        incval = (u64)hi << 32 | lo;
3945
3946        status = ice_write_40b_phy_reg_e822(hw, port, P_REG_TIMETUS_L, incval);
3947        if (status)
3948                return status;
3949
3950        status = ice_ptp_one_port_cmd_e822(hw, port, ICE_PTP_INIT_INCVAL, true);
3951        if (status)
3952                return status;
3953
3954        /* Init PHC mstr/src cmd for exec during sync */
3955        ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
3956
3957        ice_ptp_exec_tmr_cmd(hw);
3958
3959        status = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
3960        if (status)
3961                return status;
3962
3963        val |= P_REG_PS_SFT_RESET_M;
3964        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3965        if (status)
3966                return status;
3967
3968        val |= P_REG_PS_START_M;
3969        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3970        if (status)
3971                return status;
3972
3973        val &= ~P_REG_PS_SFT_RESET_M;
3974        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3975        if (status)
3976                return status;
3977
3978        status = ice_ptp_one_port_cmd_e822(hw, port, ICE_PTP_INIT_INCVAL, true);
3979        if (status)
3980                return status;
3981
3982        ice_ptp_exec_tmr_cmd(hw);
3983
3984        val |= P_REG_PS_ENA_CLK_M;
3985        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3986        if (status)
3987                return status;
3988
3989        val |= P_REG_PS_LOAD_OFFSET_M;
3990        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
3991        if (status)
3992                return status;
3993
3994        ice_ptp_exec_tmr_cmd(hw);
3995
3996        status = ice_sync_phy_timer_e822(hw, port);
3997        if (status)
3998                return status;
3999
4000        if (bypass) {
4001                val |= P_REG_PS_BYPASS_MODE_M;
4002                /* Enter BYPASS mode, enabling timestamps immediately. */
4003                status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
4004                if (status)
4005                        return status;
4006
4007                /* Program the fixed Tx offset */
4008                status = ice_phy_cfg_fixed_tx_offset_e822(hw, port);
4009                if (status)
4010                        return status;
4011
4012                /* Program the fixed Rx offset */
4013                status = ice_phy_cfg_fixed_rx_offset_e822(hw, port);
4014                if (status)
4015                        return status;
4016        }
4017
4018        ice_debug(hw, ICE_DBG_PTP, "Enabled clock on PHY port %u\n", port);
4019
4020        return ICE_SUCCESS;
4021}
4022
4023/**
4024 * ice_phy_exit_bypass_e822 - Exit bypass mode, after vernier calculations
4025 * @hw: pointer to the HW struct
4026 * @port: the PHY port to configure
4027 *
4028 * After hardware finishes vernier calculations for the Tx and Rx offset, this
4029 * function can be used to exit bypass mode by updating the total Tx and Rx
4030 * offsets, and then disabling bypass. This will enable hardware to include
4031 * the more precise offset calibrations, increasing precision of the generated
4032 * timestamps.
4033 *
4034 * This cannot be done until hardware has measured the offsets, which requires
4035 * waiting until at least one packet has been sent and received by the device.
4036 */
4037enum ice_status ice_phy_exit_bypass_e822(struct ice_hw *hw, u8 port)
4038{
4039        enum ice_status status;
4040        u32 val;
4041
4042        status = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, &val);
4043        if (status) {
4044                ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, status %d\n",
4045                          port, status);
4046                return status;
4047        }
4048
4049        if (!(val & P_REG_TX_OV_STATUS_OV_M)) {
4050                ice_debug(hw, ICE_DBG_PTP, "Tx offset is not yet valid for port %u\n",
4051                          port);
4052                return ICE_ERR_NOT_READY;
4053        }
4054
4055        status = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, &val);
4056        if (status) {
4057                ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, status %d\n",
4058                          port, status);
4059                return status;
4060        }
4061
4062        if (!(val & P_REG_TX_OV_STATUS_OV_M)) {
4063                ice_debug(hw, ICE_DBG_PTP, "Rx offset is not yet valid for port %u\n",
4064                          port);
4065                return ICE_ERR_NOT_READY;
4066        }
4067
4068        status = ice_phy_cfg_tx_offset_e822(hw, port);
4069        if (status) {
4070                ice_debug(hw, ICE_DBG_PTP, "Failed to program total Tx offset for port %u, status %d\n",
4071                          port, status);
4072                return status;
4073        }
4074
4075        status = ice_phy_cfg_rx_offset_e822(hw, port);
4076        if (status) {
4077                ice_debug(hw, ICE_DBG_PTP, "Failed to program total Rx offset for port %u, status %d\n",
4078                          port, status);
4079                return status;
4080        }
4081
4082        /* Exit bypass mode now that the offset has been updated */
4083        status = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
4084        if (status) {
4085                ice_debug(hw, ICE_DBG_PTP, "Failed to read P_REG_PS for port %u, status %d\n",
4086                          port, status);
4087                return status;
4088        }
4089
4090        if (!(val & P_REG_PS_BYPASS_MODE_M))
4091                ice_debug(hw, ICE_DBG_PTP, "Port %u not in bypass mode\n",
4092                          port);
4093
4094        val &= ~P_REG_PS_BYPASS_MODE_M;
4095        status = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
4096        if (status) {
4097                ice_debug(hw, ICE_DBG_PTP, "Failed to disable bypass for port %u, status %d\n",
4098                          port, status);
4099                return status;
4100        }
4101
4102        ice_info(hw, "Exiting bypass mode on PHY port %u\n", port);
4103
4104        return ICE_SUCCESS;
4105}
4106
4107/* E810 functions
4108 *
4109 * The following functions operate on the E810 series devices which use
4110 * a separate external PHY.
4111 */
4112
4113/**
4114 * ice_read_phy_reg_e810_lp - Read register from external PHY on E810
4115 * @hw: pointer to the HW struct
4116 * @addr: the address to read from
4117 * @val: On return, the value read from the PHY
4118 * @lock_sbq: true if the sideband queue lock must be acquired
4119 *
4120 * Read a register from the external PHY on the E810 device.
4121 */
4122static enum ice_status
4123ice_read_phy_reg_e810_lp(struct ice_hw *hw, u32 addr, u32 *val, bool lock_sbq)
4124{
4125        struct ice_sbq_msg_input msg = {0};
4126        enum ice_status status;
4127
4128        msg.msg_addr_low = ICE_LO_WORD(addr);
4129        msg.msg_addr_high = ICE_HI_WORD(addr);
4130        msg.opcode = ice_sbq_msg_rd;
4131        msg.dest_dev = rmn_0;
4132
4133        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
4134        if (status) {
4135                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
4136                          status);
4137                return status;
4138        }
4139
4140        *val = msg.data;
4141
4142        return ICE_SUCCESS;
4143}
4144
4145static enum ice_status
4146ice_read_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 *val)
4147{
4148        return ice_read_phy_reg_e810_lp(hw, addr, val, true);
4149}
4150
4151/**
4152 * ice_write_phy_reg_e810_lp - Write register on external PHY on E810
4153 * @hw: pointer to the HW struct
4154 * @addr: the address to writem to
4155 * @val: the value to write to the PHY
4156 * @lock_sbq: true if the sideband queue lock must be acquired
4157 *
4158 * Write a value to a register of the external PHY on the E810 device.
4159 */
4160static enum ice_status
4161ice_write_phy_reg_e810_lp(struct ice_hw *hw, u32 addr, u32 val, bool lock_sbq)
4162{
4163        struct ice_sbq_msg_input msg = {0};
4164        enum ice_status status;
4165
4166        msg.msg_addr_low = ICE_LO_WORD(addr);
4167        msg.msg_addr_high = ICE_HI_WORD(addr);
4168        msg.opcode = ice_sbq_msg_wr;
4169        msg.dest_dev = rmn_0;
4170        msg.data = val;
4171
4172        status = ice_sbq_rw_reg_lp(hw, &msg, lock_sbq);
4173        if (status) {
4174                ice_debug(hw, ICE_DBG_PTP, "Failed to send message to phy, status %d\n",
4175                          status);
4176                return status;
4177        }
4178
4179        return ICE_SUCCESS;
4180}
4181
4182static enum ice_status
4183ice_write_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 val)
4184{
4185        return ice_write_phy_reg_e810_lp(hw, addr, val, true);
4186}
4187
4188/**
4189 * ice_read_phy_tstamp_ll_e810 - Read a PHY timestamp registers through the FW
4190 * @hw: pointer to the HW struct
4191 * @idx: the timestamp index to read
4192 * @hi: 8 bit timestamp high value
4193 * @lo: 32 bit timestamp low value
4194 *
4195 * Read a 8bit timestamp high value and 32 bit timestamp low value out of the
4196 * timestamp block of the external PHY on the E810 device using the low latency
4197 * timestamp read.
4198 */
4199static enum ice_status
4200ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
4201{
4202        u8 i;
4203
4204        /* Write TS index to read to the PF register so the FW can read it */
4205        wr32(hw, PF_SB_ATQBAL, TS_LL_READ_TS_IDX(idx));
4206
4207        /* Read the register repeatedly until the FW provides us the TS */
4208        for (i = TS_LL_READ_RETRIES; i > 0; i--) {
4209                u32 val = rd32(hw, PF_SB_ATQBAL);
4210
4211                /* When the bit is cleared, the TS is ready in the register */
4212                if (!(val & TS_LL_READ_TS)) {
4213                        /* High 8 bit value of the TS is on the bits 16:23 */
4214                        *hi = (u8)(val >> TS_LL_READ_TS_HIGH_S);
4215
4216                        /* Read the low 32 bit value and set the TS valid bit */
4217                        *lo = rd32(hw, PF_SB_ATQBAH) | TS_VALID;
4218                        return ICE_SUCCESS;
4219                }
4220
4221                ice_usec_delay(10, false);
4222        }
4223
4224        /* FW failed to provide the TS in time */
4225        ice_debug(hw, ICE_DBG_PTP, "Failed to read PTP timestamp using low latency read\n");
4226        return ICE_ERR_NOT_READY;
4227}
4228
4229/**
4230 * ice_read_phy_tstamp_sbq_e810 - Read a PHY timestamp registers through the sbq
4231 * @hw: pointer to the HW struct
4232 * @lport: the lport to read from
4233 * @idx: the timestamp index to read
4234 * @hi: 8 bit timestamp high value
4235 * @lo: 32 bit timestamp low value
4236 *
4237 * Read a 8bit timestamp high value and 32 bit timestamp low value out of the
4238 * timestamp block of the external PHY on the E810 device using sideband queue.
4239 */
4240static enum ice_status
4241ice_read_phy_tstamp_sbq_e810(struct ice_hw *hw, u8 lport, u8 idx, u8 *hi,
4242                             u32 *lo)
4243{
4244        u32 hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx);
4245        u32 lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx);
4246        enum ice_status status;
4247        u32 lo_val, hi_val;
4248
4249        status = ice_read_phy_reg_e810(hw, lo_addr, &lo_val);
4250        if (status) {
4251                ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, status %d\n",
4252                          status);
4253                return status;
4254        }
4255
4256        status = ice_read_phy_reg_e810(hw, hi_addr, &hi_val);
4257        if (status) {
4258                ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, status %d\n",
4259                          status);
4260                return status;
4261        }
4262
4263        *lo = lo_val;
4264        *hi = (u8)hi_val;
4265
4266        return ICE_SUCCESS;
4267}
4268
4269/**
4270 * ice_read_phy_tstamp_e810 - Read a PHY timestamp out of the external PHY
4271 * @hw: pointer to the HW struct
4272 * @lport: the lport to read from
4273 * @idx: the timestamp index to read
4274 * @tstamp: on return, the 40bit timestamp value
4275 *
4276 * Read a 40bit timestamp value out of the timestamp block of the external PHY
4277 * on the E810 device.
4278 */
4279static enum ice_status
4280ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
4281{
4282        enum ice_status status;
4283        u32 lo = 0;
4284        u8 hi = 0;
4285
4286        if (hw->dev_caps.ts_dev_info.ts_ll_read)
4287                status = ice_read_phy_tstamp_ll_e810(hw, idx, &hi, &lo);
4288        else
4289                status = ice_read_phy_tstamp_sbq_e810(hw, lport, idx, &hi, &lo);
4290
4291        if (status)
4292                return status;
4293
4294        /* For E810 devices, the timestamp is reported with the lower 32 bits
4295         * in the low register, and the upper 8 bits in the high register.
4296         */
4297        *tstamp = ((u64)hi) << TS_HIGH_S | ((u64)lo & TS_LOW_M);
4298
4299        return ICE_SUCCESS;
4300}
4301
4302/**
4303 * ice_clear_phy_tstamp_e810 - Clear a timestamp from the external PHY
4304 * @hw: pointer to the HW struct
4305 * @lport: the lport to read from
4306 * @idx: the timestamp index to reset
4307 *
4308 * Clear a timestamp, resetting its valid bit, from the timestamp block of the
4309 * external PHY on the E810 device.
4310 */
4311static enum ice_status
4312ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx)
4313{
4314        enum ice_status status;
4315        u32 lo_addr, hi_addr;
4316
4317        lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx);
4318        hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx);
4319
4320        status = ice_write_phy_reg_e810(hw, lo_addr, 0);
4321        if (status) {
4322                ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, status %d\n",
4323                          status);
4324                return status;
4325        }
4326
4327        status = ice_write_phy_reg_e810(hw, hi_addr, 0);
4328        if (status) {
4329                ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, status %d\n",
4330                          status);
4331                return status;
4332        }
4333
4334        return ICE_SUCCESS;
4335}
4336
4337/**
4338 * ice_ptp_init_phy_e810 - Enable PTP function on the external PHY
4339 * @hw: pointer to HW struct
4340 *
4341 * Enable the timesync PTP functionality for the external PHY connected to
4342 * this function.
4343 *
4344 * Note there is no equivalent function needed on E822 based devices.
4345 */
4346enum ice_status ice_ptp_init_phy_e810(struct ice_hw *hw)
4347{
4348        enum ice_status status;
4349        u8 tmr_idx;
4350
4351        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4352        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_ENA(tmr_idx),
4353                                        GLTSYN_ENA_TSYN_ENA_M);
4354        if (status)
4355                ice_debug(hw, ICE_DBG_PTP, "PTP failed in ena_phy_time_syn %d\n",
4356                          status);
4357
4358        return status;
4359}
4360
4361/**
4362 * ice_ptp_init_phc_e810 - Perform E810 specific PHC initialization
4363 * @hw: pointer to HW struct
4364 *
4365 * Perform E810-specific PTP hardware clock initialization steps.
4366 */
4367static enum ice_status ice_ptp_init_phc_e810(struct ice_hw *hw)
4368{
4369        /* Ensure synchronization delay is zero */
4370        wr32(hw, GLTSYN_SYNC_DLAY, 0);
4371
4372        /* Initialize the PHY */
4373        return ice_ptp_init_phy_e810(hw);
4374}
4375
4376/**
4377 * ice_ptp_prep_phy_time_e810 - Prepare PHY port with initial time
4378 * @hw: Board private structure
4379 * @time: Time to initialize the PHY port clock to
4380 *
4381 * Program the PHY port ETH_GLTSYN_SHTIME registers in preparation setting the
4382 * initial clock time. The time will not actually be programmed until the
4383 * driver issues an ICE_PTP_INIT_TIME command.
4384 *
4385 * The time value is the upper 32 bits of the PHY timer, usually in units of
4386 * nominal nanoseconds.
4387 */
4388static enum ice_status ice_ptp_prep_phy_time_e810(struct ice_hw *hw, u32 time)
4389{
4390        enum ice_status status;
4391        u8 tmr_idx;
4392
4393        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4394        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_0(tmr_idx), 0);
4395        if (status) {
4396                ice_debug(hw, ICE_DBG_PTP, "Failed to write SHTIME_0, status %d\n",
4397                          status);
4398                return status;
4399        }
4400
4401        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_L(tmr_idx), time);
4402        if (status) {
4403                ice_debug(hw, ICE_DBG_PTP, "Failed to write SHTIME_L, status %d\n",
4404                          status);
4405                return status;
4406        }
4407
4408        return ICE_SUCCESS;
4409}
4410
4411/**
4412 * ice_ptp_prep_phy_adj_e810 - Prep PHY port for a time adjustment
4413 * @hw: pointer to HW struct
4414 * @adj: adjustment value to program
4415 * @lock_sbq: true if the sideband queue luck must be acquired
4416 *
4417 * Prepare the PHY port for an atomic adjustment by programming the PHY
4418 * ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual adjustment
4419 * is completed by issuing an ICE_PTP_ADJ_TIME sync command.
4420 *
4421 * The adjustment value only contains the portion used for the upper 32bits of
4422 * the PHY timer, usually in units of nominal nanoseconds. Negative
4423 * adjustments are supported using 2s complement arithmetic.
4424 */
4425static enum ice_status
4426ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj, bool lock_sbq)
4427{
4428        enum ice_status status;
4429        u8 tmr_idx;
4430
4431        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4432
4433        /* Adjustments are represented as signed 2's complement values in
4434         * nanoseconds. Sub-nanosecond adjustment is not supported.
4435         */
4436        status = ice_write_phy_reg_e810_lp(hw, ETH_GLTSYN_SHADJ_L(tmr_idx),
4437                                           0, lock_sbq);
4438        if (status) {
4439                ice_debug(hw, ICE_DBG_PTP, "Failed to write adj to PHY SHADJ_L, status %d\n",
4440                          status);
4441                return status;
4442        }
4443
4444        status = ice_write_phy_reg_e810_lp(hw, ETH_GLTSYN_SHADJ_H(tmr_idx),
4445                                           adj, lock_sbq);
4446        if (status) {
4447                ice_debug(hw, ICE_DBG_PTP, "Failed to write adj to PHY SHADJ_H, status %d\n",
4448                          status);
4449                return status;
4450        }
4451
4452        return ICE_SUCCESS;
4453}
4454
4455/**
4456 * ice_ptp_prep_phy_incval_e810 - Prep PHY port increment value change
4457 * @hw: pointer to HW struct
4458 * @incval: The new 40bit increment value to prepare
4459 *
4460 * Prepare the PHY port for a new increment value by programming the PHY
4461 * ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual change is
4462 * completed by issuing an ICE_PTP_INIT_INCVAL command.
4463 */
4464static enum ice_status
4465ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval)
4466{
4467        enum ice_status status;
4468        u32 high, low;
4469        u8 tmr_idx;
4470
4471        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4472        low = ICE_LO_DWORD(incval);
4473        high = ICE_HI_DWORD(incval);
4474
4475        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_L(tmr_idx), low);
4476        if (status) {
4477                ice_debug(hw, ICE_DBG_PTP, "Failed to write incval to PHY SHADJ_L, status %d\n",
4478                          status);
4479                return status;
4480        }
4481
4482        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHADJ_H(tmr_idx), high);
4483        if (status) {
4484                ice_debug(hw, ICE_DBG_PTP, "Failed to write incval PHY SHADJ_H, status %d\n",
4485                          status);
4486                return status;
4487        }
4488
4489        return ICE_SUCCESS;
4490}
4491
4492/**
4493 * ice_ptp_prep_phy_adj_target_e810 - Prepare PHY port with adjust target
4494 * @hw: Board private structure
4495 * @target_time: Time to trigger the clock adjustment at
4496 *
4497 * Program the PHY port ETH_GLTSYN_SHTIME registers in preparation for
4498 * a target time adjust, which will trigger an adjustment of the clock in the
4499 * future. The actual adjustment will occur the next time the PHY port timer
4500 * crosses over the provided value after the driver issues an
4501 * ICE_PTP_ADJ_TIME_AT_TIME command.
4502 *
4503 * The time value is the upper 32 bits of the PHY timer, usually in units of
4504 * nominal nanoseconds.
4505 */
4506static enum ice_status
4507ice_ptp_prep_phy_adj_target_e810(struct ice_hw *hw, u32 target_time)
4508{
4509        enum ice_status status;
4510        u8 tmr_idx;
4511
4512        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4513        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_0(tmr_idx), 0);
4514        if (status) {
4515                ice_debug(hw, ICE_DBG_PTP, "Failed to write target time to SHTIME_0, status %d\n",
4516                          status);
4517                return status;
4518        }
4519
4520        status = ice_write_phy_reg_e810(hw, ETH_GLTSYN_SHTIME_L(tmr_idx),
4521                                        target_time);
4522        if (status) {
4523                ice_debug(hw, ICE_DBG_PTP, "Failed to write target time to SHTIME_L, status %d\n",
4524                          status);
4525                return status;
4526        }
4527
4528        return ICE_SUCCESS;
4529}
4530
4531/**
4532 * ice_ptp_port_cmd_e810 - Prepare all external PHYs for a timer command
4533 * @hw: pointer to HW struct
4534 * @cmd: Command to be sent to the port
4535 * @lock_sbq: true if the sideband queue lock must be acquired
4536 *
4537 * Prepare the external PHYs connected to this device for a timer sync
4538 * command.
4539 */
4540static enum ice_status
4541ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
4542                      bool lock_sbq)
4543{
4544        enum ice_status status;
4545        u32 cmd_val, val;
4546
4547        switch (cmd) {
4548        case ICE_PTP_INIT_TIME:
4549                cmd_val = GLTSYN_CMD_INIT_TIME;
4550                break;
4551        case ICE_PTP_INIT_INCVAL:
4552                cmd_val = GLTSYN_CMD_INIT_INCVAL;
4553                break;
4554        case ICE_PTP_ADJ_TIME:
4555                cmd_val = GLTSYN_CMD_ADJ_TIME;
4556                break;
4557        case ICE_PTP_ADJ_TIME_AT_TIME:
4558                cmd_val = GLTSYN_CMD_ADJ_INIT_TIME;
4559                break;
4560        case ICE_PTP_READ_TIME:
4561                cmd_val = GLTSYN_CMD_READ_TIME;
4562                break;
4563        default:
4564                ice_warn(hw, "Unknown timer command %u\n", cmd);
4565                return ICE_ERR_PARAM;
4566        }
4567
4568        /* Read, modify, write */
4569        status = ice_read_phy_reg_e810_lp(hw, ETH_GLTSYN_CMD, &val, lock_sbq);
4570        if (status) {
4571                ice_debug(hw, ICE_DBG_PTP, "Failed to read GLTSYN_CMD, status %d\n",
4572                          status);
4573                return status;
4574        }
4575
4576        /* Modify necessary bits only and perform write */
4577        val &= ~TS_CMD_MASK_E810;
4578        val |= cmd_val;
4579
4580        status = ice_write_phy_reg_e810_lp(hw, ETH_GLTSYN_CMD, val, lock_sbq);
4581        if (status) {
4582                ice_debug(hw, ICE_DBG_PTP, "Failed to write back GLTSYN_CMD, status %d\n",
4583                          status);
4584                return status;
4585        }
4586
4587        return ICE_SUCCESS;
4588}
4589
4590/* E810T SMA functions
4591 *
4592 * The following functions operate specifically on E810T hardware and are used
4593 * to access the extended GPIOs available.
4594 */
4595
4596/**
4597 * ice_get_pca9575_handle
4598 * @hw: pointer to the hw struct
4599 * @pca9575_handle: GPIO controller's handle
4600 *
4601 * Find and return the GPIO controller's handle in the netlist.
4602 * When found - the value will be cached in the hw structure and following calls
4603 * will return cached value
4604 */
4605static enum ice_status
4606ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
4607{
4608        struct ice_aqc_get_link_topo cmd;
4609        u8 node_part_number, idx;
4610        enum ice_status status;
4611        u16 node_handle;
4612
4613        if (!hw || !pca9575_handle)
4614                return ICE_ERR_PARAM;
4615
4616        /* If handle was read previously return cached value */
4617        if (hw->io_expander_handle) {
4618                *pca9575_handle = hw->io_expander_handle;
4619                return ICE_SUCCESS;
4620        }
4621
4622        memset(&cmd, 0, sizeof(cmd));
4623
4624        /* Set node type to GPIO controller */
4625        cmd.addr.topo_params.node_type_ctx =
4626                (ICE_AQC_LINK_TOPO_NODE_TYPE_M &
4627                 ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL);
4628
4629#define SW_PCA9575_SFP_TOPO_IDX         2
4630#define SW_PCA9575_QSFP_TOPO_IDX        1
4631
4632        /* Check if the SW IO expander controlling SMA exists in the netlist. */
4633        if (hw->device_id == ICE_DEV_ID_E810C_SFP)
4634                idx = SW_PCA9575_SFP_TOPO_IDX;
4635        else if (hw->device_id == ICE_DEV_ID_E810C_QSFP)
4636                idx = SW_PCA9575_QSFP_TOPO_IDX;
4637        else
4638                return ICE_ERR_NOT_SUPPORTED;
4639
4640        cmd.addr.topo_params.index = idx;
4641
4642        status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number,
4643                                         &node_handle);
4644        if (status)
4645                return ICE_ERR_NOT_SUPPORTED;
4646
4647        /* Verify if we found the right IO expander type */
4648        if (node_part_number != ICE_ACQ_GET_LINK_TOPO_NODE_NR_PCA9575)
4649                return ICE_ERR_NOT_SUPPORTED;
4650
4651        /* If present save the handle and return it */
4652        hw->io_expander_handle = node_handle;
4653        *pca9575_handle = hw->io_expander_handle;
4654
4655        return ICE_SUCCESS;
4656}
4657
4658/**
4659 * ice_is_gps_present_e810t
4660 * @hw: pointer to the hw struct
4661 *
4662 * Check if the GPS generic device is present in the netlist
4663 */
4664bool ice_is_gps_present_e810t(struct ice_hw *hw)
4665{
4666        if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_GPS,
4667                                  ICE_ACQ_GET_LINK_TOPO_NODE_NR_GEN_GPS, NULL))
4668                return false;
4669
4670        return true;
4671}
4672
4673/**
4674 * ice_read_pca9575_reg_e810t
4675 * @hw: pointer to the hw struct
4676 * @offset: GPIO controller register offset
4677 * @data: pointer to data to be read from the GPIO controller
4678 *
4679 * Read the register from the GPIO controller
4680 */
4681enum ice_status
4682ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data)
4683{
4684        struct ice_aqc_link_topo_addr link_topo;
4685        enum ice_status status;
4686        __le16 addr;
4687        u16 handle;
4688
4689        memset(&link_topo, 0, sizeof(link_topo));
4690
4691        status = ice_get_pca9575_handle(hw, &handle);
4692        if (status)
4693                return status;
4694
4695        link_topo.handle = CPU_TO_LE16(handle);
4696        link_topo.topo_params.node_type_ctx =
4697                (ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED <<
4698                 ICE_AQC_LINK_TOPO_NODE_CTX_S);
4699
4700        addr = CPU_TO_LE16((u16)offset);
4701
4702        return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL);
4703}
4704
4705/**
4706 * ice_write_pca9575_reg_e810t
4707 * @hw: pointer to the hw struct
4708 * @offset: GPIO controller register offset
4709 * @data: data to be written to the GPIO controller
4710 *
4711 * Write the data to the GPIO controller register
4712 */
4713enum ice_status
4714ice_write_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 data)
4715{
4716        struct ice_aqc_link_topo_addr link_topo;
4717        enum ice_status status;
4718        __le16 addr;
4719        u16 handle;
4720
4721        memset(&link_topo, 0, sizeof(link_topo));
4722
4723        status = ice_get_pca9575_handle(hw, &handle);
4724        if (status)
4725                return status;
4726
4727        link_topo.handle = CPU_TO_LE16(handle);
4728        link_topo.topo_params.node_type_ctx =
4729                (ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED <<
4730                 ICE_AQC_LINK_TOPO_NODE_CTX_S);
4731
4732        addr = CPU_TO_LE16((u16)offset);
4733
4734        return ice_aq_write_i2c(hw, link_topo, 0, addr, 1, &data, NULL);
4735}
4736
4737/**
4738 * ice_read_sma_ctrl_e810t
4739 * @hw: pointer to the hw struct
4740 * @data: pointer to data to be read from the GPIO controller
4741 *
4742 * Read the SMA controller state. Only bits 3-7 in data are valid.
4743 */
4744enum ice_status ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
4745{
4746        enum ice_status status;
4747        u16 handle;
4748        u8 i;
4749
4750        status = ice_get_pca9575_handle(hw, &handle);
4751        if (status)
4752                return status;
4753
4754        *data = 0;
4755
4756        for (i = ICE_E810T_SMA_MIN_BIT; i <= ICE_E810T_SMA_MAX_BIT; i++) {
4757                bool pin;
4758
4759                status = ice_aq_get_gpio(hw, handle, i + ICE_E810T_P1_OFFSET,
4760                                         &pin, NULL);
4761                if (status)
4762                        break;
4763                *data |= (u8)(!pin) << i;
4764        }
4765
4766        return status;
4767}
4768
4769/**
4770 * ice_write_sma_ctrl_e810t
4771 * @hw: pointer to the hw struct
4772 * @data: data to be written to the GPIO controller
4773 *
4774 * Write the data to the SMA controller. Only bits 3-7 in data are valid.
4775 */
4776enum ice_status ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
4777{
4778        enum ice_status status;
4779        u16 handle;
4780        u8 i;
4781
4782        status = ice_get_pca9575_handle(hw, &handle);
4783        if (status)
4784                return status;
4785
4786        for (i = ICE_E810T_SMA_MIN_BIT; i <= ICE_E810T_SMA_MAX_BIT; i++) {
4787                bool pin;
4788
4789                pin = !(data & (1 << i));
4790                status = ice_aq_set_gpio(hw, handle, i + ICE_E810T_P1_OFFSET,
4791                                         pin, NULL);
4792                if (status)
4793                        break;
4794        }
4795
4796        return status;
4797}
4798
4799/**
4800 * ice_is_pca9575_present
4801 * @hw: pointer to the hw struct
4802 *
4803 * Check if the SW IO expander is present in the netlist
4804 */
4805bool ice_is_pca9575_present(struct ice_hw *hw)
4806{
4807        enum ice_status status;
4808        u16 handle = 0;
4809
4810        status = ice_get_pca9575_handle(hw, &handle);
4811        if (!status && handle)
4812                return true;
4813
4814        return false;
4815}
4816
4817/* Device agnostic functions
4818 *
4819 * The following functions implement shared behavior common to both E822/E823
4820 * and E810 devices, possibly calling a device specific implementation where
4821 * necessary.
4822 */
4823
4824/**
4825 * ice_ptp_lock - Acquire PTP global semaphore register lock
4826 * @hw: pointer to the HW struct
4827 *
4828 * Acquire the global PTP hardware semaphore lock. Returns true if the lock
4829 * was acquired, false otherwise.
4830 *
4831 * The PFTSYN_SEM register sets the busy bit on read, returning the previous
4832 * value. If software sees the busy bit cleared, this means that this function
4833 * acquired the lock (and the busy bit is now set). If software sees the busy
4834 * bit set, it means that another function acquired the lock.
4835 *
4836 * Software must clear the busy bit with a write to release the lock for other
4837 * functions when done.
4838 */
4839bool ice_ptp_lock(struct ice_hw *hw)
4840{
4841        u32 hw_lock;
4842        int i;
4843
4844#define MAX_TRIES 15
4845
4846        for (i = 0; i < MAX_TRIES; i++) {
4847                hw_lock = rd32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
4848                hw_lock = hw_lock & PFTSYN_SEM_BUSY_M;
4849                if (hw_lock) {
4850                        /* Somebody is holding the lock */
4851                        ice_msec_delay(5, true);
4852                        continue;
4853                }
4854
4855                break;
4856        }
4857
4858        return !hw_lock;
4859}
4860
4861/**
4862 * ice_ptp_unlock - Release PTP global semaphore register lock
4863 * @hw: pointer to the HW struct
4864 *
4865 * Release the global PTP hardware semaphore lock. This is done by writing to
4866 * the PFTSYN_SEM register.
4867 */
4868void ice_ptp_unlock(struct ice_hw *hw)
4869{
4870        wr32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), 0);
4871}
4872
4873/**
4874 * ice_ptp_tmr_cmd - Prepare and trigger a timer sync command
4875 * @hw: pointer to HW struct
4876 * @cmd: the command to issue
4877 * @lock_sbq: true if the sideband queue lock must be acquired
4878 *
4879 * Prepare the source timer and PHY timers and then trigger the requested
4880 * command. This causes the shadow registers previously written in preparation
4881 * for the command to be synchronously applied to both the source and PHY
4882 * timers.
4883 */
4884static enum ice_status
4885ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd, bool lock_sbq)
4886{
4887        enum ice_status status;
4888
4889        /* First, prepare the source timer */
4890        ice_ptp_src_cmd(hw, cmd);
4891
4892        /* Next, prepare the ports */
4893        switch (hw->phy_cfg) {
4894        case ICE_PHY_ETH56G:
4895                status = ice_ptp_port_cmd_eth56g(hw, cmd, lock_sbq);
4896                break;
4897        case ICE_PHY_E810:
4898                status = ice_ptp_port_cmd_e810(hw, cmd, lock_sbq);
4899                break;
4900        case ICE_PHY_E822:
4901                status = ice_ptp_port_cmd_e822(hw, cmd, lock_sbq);
4902                break;
4903        default:
4904                status = ICE_ERR_NOT_SUPPORTED;
4905        }
4906        if (status) {
4907                ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY ports for timer command %u, status %d\n",
4908                          cmd, status);
4909                return status;
4910        }
4911
4912        /* Write the sync command register to drive both source and PHY timer
4913         * commands synchronously
4914         */
4915        ice_ptp_exec_tmr_cmd(hw);
4916        ice_ptp_clean_cmd(hw);
4917
4918        return ICE_SUCCESS;
4919}
4920
4921/**
4922 * ice_ptp_init_time - Initialize device time to provided value
4923 * @hw: pointer to HW struct
4924 * @time: 64bits of time (GLTSYN_TIME_L and GLTSYN_TIME_H)
4925 *
4926 * Initialize the device to the specified time provided. This requires a three
4927 * step process:
4928 *
4929 * 1) write the new init time to the source timer shadow registers
4930 * 2) write the new init time to the phy timer shadow registers
4931 * 3) issue an init_time timer command to synchronously switch both the source
4932 *    and port timers to the new init time value at the next clock cycle.
4933 */
4934enum ice_status ice_ptp_init_time(struct ice_hw *hw, u64 time)
4935{
4936        enum ice_status status;
4937        u8 tmr_idx;
4938
4939        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4940
4941        /* Source timers */
4942        wr32(hw, GLTSYN_SHTIME_L(tmr_idx), ICE_LO_DWORD(time));
4943        wr32(hw, GLTSYN_SHTIME_H(tmr_idx), ICE_HI_DWORD(time));
4944        wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
4945
4946        /* PHY Clks */
4947        /* Fill Rx and Tx ports and send msg to PHY */
4948        switch (hw->phy_cfg) {
4949        case ICE_PHY_ETH56G:
4950                status = ice_ptp_prep_phy_time_eth56g(hw, time & 0xFFFFFFFF);
4951                break;
4952        case ICE_PHY_E810:
4953                status = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF);
4954                break;
4955        case ICE_PHY_E822:
4956                status = ice_ptp_prep_phy_time_e822(hw, time & 0xFFFFFFFF);
4957                break;
4958        default:
4959                status = ICE_ERR_NOT_SUPPORTED;
4960        }
4961
4962        if (status)
4963                return status;
4964
4965        return ice_ptp_tmr_cmd(hw, ICE_PTP_INIT_TIME, true);
4966}
4967
4968/**
4969 * ice_ptp_write_incval - Program PHC with new increment value
4970 * @hw: pointer to HW struct
4971 * @incval: Source timer increment value per clock cycle
4972 *
4973 * Program the PHC with a new increment value. This requires a three-step
4974 * process:
4975 *
4976 * 1) Write the increment value to the source timer shadow registers
4977 * 2) Write the increment value to the PHY timer shadow registers
4978 * 3) Issue an ICE_PTP_INIT_INCVAL timer command to synchronously switch both
4979 *    the source and port timers to the new increment value at the next clock
4980 *    cycle.
4981 */
4982enum ice_status ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
4983{
4984        enum ice_status status;
4985        u8 tmr_idx;
4986
4987        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
4988
4989        /* Shadow Adjust */
4990        wr32(hw, GLTSYN_SHADJ_L(tmr_idx), ICE_LO_DWORD(incval));
4991        wr32(hw, GLTSYN_SHADJ_H(tmr_idx), ICE_HI_DWORD(incval));
4992
4993        switch (hw->phy_cfg) {
4994        case ICE_PHY_ETH56G:
4995                status = ice_ptp_prep_phy_incval_eth56g(hw, incval);
4996                break;
4997        case ICE_PHY_E810:
4998                status = ice_ptp_prep_phy_incval_e810(hw, incval);
4999                break;
5000        case ICE_PHY_E822:
5001                status = ice_ptp_prep_phy_incval_e822(hw, incval);
5002                break;
5003        default:
5004                status = ICE_ERR_NOT_SUPPORTED;
5005        }
5006
5007        if (status)
5008                return status;
5009
5010        return ice_ptp_tmr_cmd(hw, ICE_PTP_INIT_INCVAL, true);
5011}
5012
5013/**
5014 * ice_ptp_write_incval_locked - Program new incval while holding semaphore
5015 * @hw: pointer to HW struct
5016 * @incval: Source timer increment value per clock cycle
5017 *
5018 * Program a new PHC incval while holding the PTP semaphore.
5019 */
5020enum ice_status ice_ptp_write_incval_locked(struct ice_hw *hw, u64 incval)
5021{
5022        enum ice_status status;
5023
5024        if (!ice_ptp_lock(hw))
5025                return ICE_ERR_NOT_READY;
5026
5027        status = ice_ptp_write_incval(hw, incval);
5028
5029        ice_ptp_unlock(hw);
5030
5031        return status;
5032}
5033
5034/**
5035 * ice_ptp_adj_clock - Adjust PHC clock time atomically
5036 * @hw: pointer to HW struct
5037 * @adj: Adjustment in nanoseconds
5038 * @lock_sbq: true to lock the sbq sq_lock (the usual case); false if the
5039 *            sq_lock has already been locked at a higher level
5040 *
5041 * Perform an atomic adjustment of the PHC time by the specified number of
5042 * nanoseconds. This requires a three-step process:
5043 *
5044 * 1) Write the adjustment to the source timer shadow registers
5045 * 2) Write the adjustment to the PHY timer shadow registers
5046 * 3) Issue an ICE_PTP_ADJ_TIME timer command to synchronously apply the
5047 *    adjustment to both the source and port timers at the next clock cycle.
5048 */
5049enum ice_status ice_ptp_adj_clock(struct ice_hw *hw, s32 adj, bool lock_sbq)
5050{
5051        enum ice_status status;
5052        u8 tmr_idx;
5053
5054        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
5055
5056        /* Write the desired clock adjustment into the GLTSYN_SHADJ register.
5057         * For an ICE_PTP_ADJ_TIME command, this set of registers represents
5058         * the value to add to the clock time. It supports subtraction by
5059         * interpreting the value as a 2's complement integer.
5060         */
5061        wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
5062        wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
5063
5064        switch (hw->phy_cfg) {
5065        case ICE_PHY_ETH56G:
5066                status = ice_ptp_prep_phy_adj_eth56g(hw, adj, lock_sbq);
5067                break;
5068        case ICE_PHY_E810:
5069                status = ice_ptp_prep_phy_adj_e810(hw, adj, lock_sbq);
5070                break;
5071        case ICE_PHY_E822:
5072                status = ice_ptp_prep_phy_adj_e822(hw, adj, lock_sbq);
5073                break;
5074        default:
5075                status = ICE_ERR_NOT_SUPPORTED;
5076        }
5077
5078        if (status)
5079                return status;
5080
5081        return ice_ptp_tmr_cmd(hw, ICE_PTP_ADJ_TIME, lock_sbq);
5082}
5083
5084/**
5085 * ice_ptp_adj_clock_at_time - Adjust PHC atomically at specified time
5086 * @hw: pointer to HW struct
5087 * @at_time: Time in nanoseconds at which to perform the adjustment
5088 * @adj: Adjustment in nanoseconds
5089 *
5090 * Perform an atomic adjustment to the PHC clock at the specified time. This
5091 * requires a five-step process:
5092 *
5093 * 1) Write the adjustment to the source timer shadow adjust registers
5094 * 2) Write the target time to the source timer shadow time registers
5095 * 3) Write the adjustment to the PHY timers shadow adjust registers
5096 * 4) Write the target time to the PHY timers shadow adjust registers
5097 * 5) Issue an ICE_PTP_ADJ_TIME_AT_TIME command to initiate the atomic
5098 *    adjustment.
5099 */
5100enum ice_status
5101ice_ptp_adj_clock_at_time(struct ice_hw *hw, u64 at_time, s32 adj)
5102{
5103        enum ice_status status;
5104        u32 time_lo, time_hi;
5105        u8 tmr_idx;
5106
5107        tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
5108        time_lo = ICE_LO_DWORD(at_time);
5109        time_hi = ICE_HI_DWORD(at_time);
5110
5111        /* Write the desired clock adjustment into the GLTSYN_SHADJ register.
5112         * For an ICE_PTP_ADJ_TIME_AT_TIME command, this set of registers
5113         * represents the value to add to the clock time. It supports
5114         * subtraction by interpreting the value as a 2's complement integer.
5115         */
5116        wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
5117        wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
5118
5119        /* Write the target time to trigger the adjustment for source clock */
5120        wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
5121        wr32(hw, GLTSYN_SHTIME_L(tmr_idx), time_lo);
5122        wr32(hw, GLTSYN_SHTIME_H(tmr_idx), time_hi);
5123
5124        /* Prepare PHY port adjustments */
5125        switch (hw->phy_cfg) {
5126        case ICE_PHY_ETH56G:
5127                status = ice_ptp_prep_phy_adj_eth56g(hw, adj, true);
5128                break;
5129        case ICE_PHY_E810:
5130                status = ice_ptp_prep_phy_adj_e810(hw, adj, true);
5131                break;
5132        case ICE_PHY_E822:
5133                status = ice_ptp_prep_phy_adj_e822(hw, adj, true);
5134                break;
5135        default:
5136                status = ICE_ERR_NOT_SUPPORTED;
5137        }
5138
5139        if (status)
5140                return status;
5141
5142        /* Set target time for each PHY port */
5143        switch (hw->phy_cfg) {
5144        case ICE_PHY_ETH56G:
5145                status = ice_ptp_prep_phy_adj_target_eth56g(hw, time_lo);
5146                break;
5147        case ICE_PHY_E810:
5148                status = ice_ptp_prep_phy_adj_target_e810(hw, time_lo);
5149                break;
5150        case ICE_PHY_E822:
5151                status = ice_ptp_prep_phy_adj_target_e822(hw, time_lo);
5152                break;
5153        default:
5154                status = ICE_ERR_NOT_SUPPORTED;
5155        }
5156
5157        if (status)
5158                return status;
5159
5160        return ice_ptp_tmr_cmd(hw, ICE_PTP_ADJ_TIME_AT_TIME, true);
5161}
5162
5163/**
5164 * ice_read_phy_tstamp - Read a PHY timestamp from the timestamp block
5165 * @hw: pointer to the HW struct
5166 * @block: the block/port to read from
5167 * @idx: the timestamp index to read
5168 * @tstamp: on return, the 40bit timestamp value
5169 *
5170 * Read a 40bit timestamp value out of the timestamp block. For E822 devices,
5171 * the block is the quad to read from. For E810 devices, the block is the
5172 * logical port to read from.
5173 */
5174enum ice_status
5175ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
5176{
5177        enum ice_status status;
5178
5179        switch (hw->phy_cfg) {
5180        case ICE_PHY_ETH56G:
5181                status = ice_read_phy_tstamp_eth56g(hw, block, idx, tstamp);
5182                break;
5183        case ICE_PHY_E810:
5184                status = ice_read_phy_tstamp_e810(hw, block, idx, tstamp);
5185                break;
5186        case ICE_PHY_E822:
5187                status = ice_read_phy_tstamp_e822(hw, block, idx, tstamp);
5188                break;
5189        default:
5190                status = ICE_ERR_NOT_SUPPORTED;
5191        }
5192
5193        return status;
5194}
5195
5196/**
5197 * ice_clear_phy_tstamp - Clear a timestamp from the timestamp block
5198 * @hw: pointer to the HW struct
5199 * @block: the block to read from
5200 * @idx: the timestamp index to reset
5201 *
5202 * Clear a timestamp, resetting its valid bit, from the timestamp block. For
5203 * E822 devices, the block is the quad to clear from. For E810 devices, the
5204 * block is the logical port to clear from.
5205 */
5206enum ice_status
5207ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
5208{
5209        enum ice_status status;
5210
5211        switch (hw->phy_cfg) {
5212        case ICE_PHY_ETH56G:
5213                status = ice_clear_phy_tstamp_eth56g(hw, block, idx);
5214                break;
5215        case ICE_PHY_E810:
5216                status = ice_clear_phy_tstamp_e810(hw, block, idx);
5217                break;
5218        case ICE_PHY_E822:
5219                status = ice_clear_phy_tstamp_e822(hw, block, idx);
5220                break;
5221        default:
5222                status = ICE_ERR_NOT_SUPPORTED;
5223        }
5224
5225        return status;
5226}
5227
5228/**
5229 * ice_ptp_init_phc - Initialize PTP hardware clock
5230 * @hw: pointer to the HW struct
5231 *
5232 * Perform the steps required to initialize the PTP hardware clock.
5233 */
5234enum ice_status ice_ptp_init_phc(struct ice_hw *hw)
5235{
5236        enum ice_status status;
5237        u8 src_idx = hw->func_caps.ts_func_info.tmr_index_owned;
5238
5239        /* Enable source clocks */
5240        wr32(hw, GLTSYN_ENA(src_idx), GLTSYN_ENA_TSYN_ENA_M);
5241
5242        /* Clear event status indications for auxiliary pins */
5243        (void)rd32(hw, GLTSYN_STAT(src_idx));
5244
5245        switch (hw->phy_cfg) {
5246        case ICE_PHY_ETH56G:
5247                status = ice_ptp_init_phc_eth56g(hw);
5248                break;
5249        case ICE_PHY_E810:
5250                status = ice_ptp_init_phc_e810(hw);
5251                break;
5252        case ICE_PHY_E822:
5253                status = ice_ptp_init_phc_e822(hw);
5254                break;
5255        default:
5256                status = ICE_ERR_NOT_SUPPORTED;
5257        }
5258
5259        return status;
5260}
5261