@@ -2040,6 +2040,41 @@ int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port)
return ice_write_phy_reg_eth56g(hw, port, PHY_REG_RX_OFFSET_READY, 1);
}
+/**
+ * ice_phy_cfg_intr_eth56g - Configure TX timestamp interrupt
+ * @hw: pointer to the HW struct
+ * @port: the timestamp port
+ * @ena: enable or disable interrupt
+ * @threshold: interrupt threshold
+ *
+ * Configure TX timestamp interrupt for the specified port
+ */
+
+int
+ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold)
+{
+ int err;
+ u32 val;
+
+ err = ice_read_phy_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG,
+ &val);
+ if (err)
+ return err;
+
+ if (ena) {
+ val |= PHY_TS_INT_CONFIG_ENA_M;
+ val &= ~PHY_TS_INT_CONFIG_THRESHOLD_M;
+ val |= ((threshold << PHY_TS_INT_CONFIG_THRESHOLD_S) &
+ PHY_TS_INT_CONFIG_THRESHOLD_M);
+ } else {
+ val &= ~PHY_TS_INT_CONFIG_ENA_M;
+ }
+
+ err = ice_write_phy_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG,
+ val);
+ return err;
+}
+
/**
* ice_ptp_clear_phy_offset_ready_eth56g - Clear PHY OFFSET_READY registers
* @hw: pointer to the HW struct
@@ -2228,7 +2263,6 @@ ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset)
* ice_start_phy_timer_eth56g - Start the PHY clock timer
* @hw: pointer to the HW struct
* @port: the PHY port to start
- * @bypass: unused, for compatibility
*
* Start the clock of a PHY port. This must be done as part of the flow to
* re-calibrate Tx and Rx timestamping offsets whenever the clock time is
@@ -2236,7 +2270,7 @@ ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset)
*
*/
int
-ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool bypass)
+ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
{
int err;
u32 lo, hi;
@@ -3837,6 +3871,28 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
enum ice_ptp_fec_mode fec_mode;
u64 total_offset, val;
int err;
+ u32 reg;
+
+ /* Nothing to do if we've already programmed the offset */
+ err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OR, ®);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OR for port %u, err %d\n",
+ port, err);
+ return err;
+ }
+
+ if (reg)
+ return 0;
+
+ err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, ®);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n",
+ port, err);
+ return err;
+ }
+
+ if (!(reg & P_REG_TX_OV_STATUS_OV_M))
+ return ICE_ERR_NOT_READY;
err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
if (err)
@@ -3894,47 +3950,6 @@ int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
return 0;
}
-/**
- * ice_phy_cfg_fixed_tx_offset_e822 - Configure Tx offset for bypass mode
- * @hw: pointer to the HW struct
- * @port: the PHY port to configure
- *
- * Calculate and program the fixed Tx offset, and indicate that the offset is
- * ready. This can be used when operating in bypass mode.
- */
-static int
-ice_phy_cfg_fixed_tx_offset_e822(struct ice_hw *hw, u8 port)
-{
- enum ice_ptp_link_spd link_spd;
- enum ice_ptp_fec_mode fec_mode;
- int err;
- u64 total_offset;
-
- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
- if (err)
- return err;
-
- total_offset = ice_calc_fixed_tx_offset_e822(hw, link_spd);
-
- /* Program the fixed Tx offset into the P_REG_TOTAL_TX_OFFSET_L
- * register, then indicate that the Tx offset is ready. After this,
- * timestamps will be enabled.
- *
- * Note that this skips including the more precise offsets generated
- * by the Vernier calibration.
- */
- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_TX_OFFSET_L,
- total_offset);
- if (err)
- return err;
-
- err = ice_write_phy_reg_e822(hw, port, P_REG_TX_OR, 1);
- if (err)
- return err;
-
- return 0;
-}
-
/**
* ice_phy_calc_pmd_adj_e822 - Calculate PMD adjustment for Rx
* @hw: pointer to the HW struct
@@ -4157,6 +4172,28 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
enum ice_ptp_fec_mode fec_mode;
u64 total_offset, pmd, val;
int err;
+ u32 reg;
+
+ /* Nothing to do if we've already programmed the offset */
+ err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OR, ®);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OR for port %u, err %d\n",
+ port, err);
+ return err;
+ }
+
+ if (reg)
+ return 0;
+
+ err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, ®);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n",
+ port, err);
+ return err;
+ }
+
+ if (!(reg & P_REG_RX_OV_STATUS_OV_M))
+ return ICE_ERR_NOT_READY;
err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
if (err)
@@ -4253,47 +4290,6 @@ static int ice_ptp_clear_phy_offset_ready_e822(struct ice_hw *hw)
return 0;
}
-/**
- * ice_phy_cfg_fixed_rx_offset_e822 - Configure fixed Rx offset for bypass mode
- * @hw: pointer to the HW struct
- * @port: the PHY port to configure
- *
- * Calculate and program the fixed Rx offset, and indicate that the offset is
- * ready. This can be used when operating in bypass mode.
- */
-static int
-ice_phy_cfg_fixed_rx_offset_e822(struct ice_hw *hw, u8 port)
-{
- enum ice_ptp_link_spd link_spd;
- enum ice_ptp_fec_mode fec_mode;
- int err;
- u64 total_offset;
-
- err = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
- if (err)
- return err;
-
- total_offset = ice_calc_fixed_rx_offset_e822(hw, link_spd);
-
- /* Program the fixed Rx offset into the P_REG_TOTAL_RX_OFFSET_L
- * register, then indicate that the Rx offset is ready. After this,
- * timestamps will be enabled.
- *
- * Note that this skips including the more precise offsets generated
- * by Vernier calibration.
- */
- err = ice_write_64b_phy_reg_e822(hw, port, P_REG_TOTAL_RX_OFFSET_L,
- total_offset);
- if (err)
- return err;
-
- err = ice_write_phy_reg_e822(hw, port, P_REG_RX_OR, 1);
- if (err)
- return err;
-
- return 0;
-}
-
/**
* ice_read_phy_and_phc_time_e822 - Simultaneously capture PHC and PHY time
* @hw: pointer to the HW struct
@@ -4474,19 +4470,14 @@ ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset)
* ice_start_phy_timer_e822 - Start the PHY clock timer
* @hw: pointer to the HW struct
* @port: the PHY port to start
- * @bypass: if true, start the PHY in bypass mode
*
* Start the clock of a PHY port. This must be done as part of the flow to
* re-calibrate Tx and Rx timestamping offsets whenever the clock time is
* initialized or when link speed changes.
*
- * Bypass mode enables timestamps immediately without waiting for Vernier
- * calibration to complete. Hardware will still continue taking Vernier
- * measurements on Tx or Rx of packets, but they will not be applied to
- * timestamps. Use ice_phy_exit_bypass_e822 to exit bypass mode once hardware
- * has completed offset calculation.
+ * Hardware will take Vernier measurements on Tx or Rx of packets.
*/
-int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass)
+int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port)
{
u32 lo, hi, val;
u64 incval;
@@ -4567,23 +4558,6 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass)
if (err)
return err;
- if (bypass) {
- val |= P_REG_PS_BYPASS_MODE_M;
- /* Enter BYPASS mode, enabling timestamps immediately. */
- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
- if (err)
- return err;
-
- /* Program the fixed Tx offset */
- err = ice_phy_cfg_fixed_tx_offset_e822(hw, port);
- if (err)
- return err;
-
- /* Program the fixed Rx offset */
- err = ice_phy_cfg_fixed_rx_offset_e822(hw, port);
- if (err)
- return err;
- }
ice_debug(hw, ICE_DBG_PTP, "Enabled clock on PHY port %u\n", port);
@@ -4626,87 +4600,41 @@ ice_get_phy_tx_tstamp_ready_e822(struct ice_hw *hw, u8 quad, u64 *tstamp_ready)
}
/**
- * ice_phy_exit_bypass_e822 - Exit bypass mode, after vernier calculations
+ * ice_phy_cfg_intr_e822 - Configure TX timestamp interrupt
* @hw: pointer to the HW struct
- * @port: the PHY port to configure
+ * @quad: the timestamp quad
+ * @ena: enable or disable interrupt
+ * @threshold: interrupt threshold
*
- * After hardware finishes vernier calculations for the Tx and Rx offset, this
- * function can be used to exit bypass mode by updating the total Tx and Rx
- * offsets, and then disabling bypass. This will enable hardware to include
- * the more precise offset calibrations, increasing precision of the generated
- * timestamps.
- *
- * This cannot be done until hardware has measured the offsets, which requires
- * waiting until at least one packet has been sent and received by the device.
+ * Configure TX timestamp interrupt for the specified quad
*/
-int ice_phy_exit_bypass_e822(struct ice_hw *hw, u8 port)
+
+int
+ice_phy_cfg_intr_e822(struct ice_hw *hw, u8 quad, bool ena, u8 threshold)
{
int err;
u32 val;
- err = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, &val);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, err %d\n",
- port, err);
+ err = ice_read_quad_reg_e822(hw, quad,
+ Q_REG_TX_MEM_GBL_CFG,
+ &val);
+ if (err)
return err;
- }
-
- if (!(val & P_REG_TX_OV_STATUS_OV_M)) {
- ice_debug(hw, ICE_DBG_PTP, "Tx offset is not yet valid for port %u\n",
- port);
- return ICE_ERR_NOT_READY;
- }
-
- err = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, &val);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, err %d\n",
- port, err);
- return err;
- }
-
- if (!(val & P_REG_TX_OV_STATUS_OV_M)) {
- ice_debug(hw, ICE_DBG_PTP, "Rx offset is not yet valid for port %u\n",
- port);
- return ICE_ERR_NOT_READY;
- }
- err = ice_phy_cfg_tx_offset_e822(hw, port);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to program total Tx offset for port %u, err %d\n",
- port, err);
- return err;
- }
-
- err = ice_phy_cfg_rx_offset_e822(hw, port);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to program total Rx offset for port %u, err %d\n",
- port, err);
- return err;
- }
-
- /* Exit bypass mode now that the offset has been updated */
- err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to read P_REG_PS for port %u, err %d\n",
- port, err);
- return err;
- }
-
- if (!(val & P_REG_PS_BYPASS_MODE_M))
- ice_debug(hw, ICE_DBG_PTP, "Port %u not in bypass mode\n",
- port);
-
- val &= ~P_REG_PS_BYPASS_MODE_M;
- err = ice_write_phy_reg_e822(hw, port, P_REG_PS, val);
- if (err) {
- ice_debug(hw, ICE_DBG_PTP, "Failed to disable bypass for port %u, err %d\n",
- port, err);
- return err;
+ if (ena) {
+ val |= Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M;
+ val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_THR_M;
+ val |= ((threshold << Q_REG_TX_MEM_GBL_CFG_INTR_THR_S) &
+ Q_REG_TX_MEM_GBL_CFG_INTR_THR_M);
+ } else {
+ val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M;
}
- ice_info(hw, "Exiting bypass mode on PHY port %u\n", port);
+ err = ice_write_quad_reg_e822(hw, quad,
+ Q_REG_TX_MEM_GBL_CFG,
+ val);
- return 0;
+ return err;
}
/* E810 functions
@@ -256,11 +256,11 @@ ice_phy_get_speed_and_fec_e822(struct ice_hw *hw, u8 port,
void ice_phy_cfg_lane_e822(struct ice_hw *hw, u8 port);
int
ice_stop_phy_timer_e822(struct ice_hw *hw, u8 port, bool soft_reset);
-int
-ice_start_phy_timer_e822(struct ice_hw *hw, u8 port, bool bypass);
+int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port);
int ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port);
int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port);
-int ice_phy_exit_bypass_e822(struct ice_hw *hw, u8 port);
+int
+ice_phy_cfg_intr_e822(struct ice_hw *hw, u8 quad, bool ena, u8 threshold);
/* E810 family functions */
int ice_ptp_init_phy_e810(struct ice_hw *hw);
@@ -301,9 +301,11 @@ ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status);
int
ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset);
int
-ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool bypass);
+ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_tx_offset_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port);
+int
+ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold);
#define ICE_ETH56G_PLL_FREQ 800000000
#define ICE_ETH56G_NOMINAL_INCVAL 0x140000000ULL
@@ -2504,7 +2504,7 @@ ice_dev_init(struct rte_eth_dev *dev)
hw->phy_model = ICE_PHY_E822;
if (hw->phy_model == ICE_PHY_E822) {
- ret = ice_start_phy_timer_e822(hw, hw->pf_id, true);
+ ret = ice_start_phy_timer_e822(hw, hw->pf_id);
if (ret)
PMD_INIT_LOG(ERR, "Failed to start phy timer\n");
}