@@ -2757,7 +2757,8 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0);
info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
- info->ena_ports = logical_id;
+ info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0);
+
info->tmr_own_map = phys_id;
ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n",
@@ -2774,8 +2775,8 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
info->tmr1_owned);
ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n",
info->tmr1_ena);
- ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
- info->ena_ports);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n",
+ info->ts_ll_read);
ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",
info->tmr_own_map);
}
@@ -4142,38 +4142,111 @@ ice_write_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 val)
}
/**
- * ice_read_phy_tstamp_e810 - Read a PHY timestamp out of the external PHY
+ * ice_read_phy_tstamp_ll_e810 - Read a PHY timestamp registers through the FW
+ * @hw: pointer to the HW struct
+ * @idx: the timestamp index to read
+ * @hi: 8 bit timestamp high value
+ * @lo: 32 bit timestamp low value
+ *
+ * Read a 8bit timestamp high value and 32 bit timestamp low value out of the
+ * timestamp block of the external PHY on the E810 device using the low latency
+ * timestamp read.
+ */
+static enum ice_status
+ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
+{
+ u8 i;
+
+ /* Write TS index to read to the PF register so the FW can read it */
+ wr32(hw, PF_SB_ATQBAL, TS_LL_READ_TS_IDX(idx));
+
+ /* Read the register repeatedly until the FW provides us the TS */
+ for (i = TS_LL_READ_RETRIES; i > 0; i--) {
+ u32 val = rd32(hw, PF_SB_ATQBAL);
+
+ /* When the bit is cleared, the TS is ready in the register */
+ if (!(val & TS_LL_READ_TS)) {
+ /* High 8 bit value of the TS is on the bits 16:23 */
+ *hi = (u8)(val >> TS_LL_READ_TS_HIGH_S);
+
+ /* Read the low 32 bit value and set the TS valid bit */
+ *lo = rd32(hw, PF_SB_ATQBAH) | TS_VALID;
+ return ICE_SUCCESS;
+ }
+
+ ice_usec_delay(10, false);
+ }
+
+ /* FW failed to provide the TS in time */
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read PTP timestamp using low latency read\n");
+ return ICE_ERR_NOT_READY;
+}
+
+/**
+ * ice_read_phy_tstamp_sbq_e810 - Read a PHY timestamp registers through the sbq
* @hw: pointer to the HW struct
* @lport: the lport to read from
* @idx: the timestamp index to read
- * @tstamp: on return, the 40bit timestamp value
+ * @hi: 8 bit timestamp high value
+ * @lo: 32 bit timestamp low value
*
- * Read a 40bit timestamp value out of the timestamp block of the external PHY
- * on the E810 device.
+ * Read a 8bit timestamp high value and 32 bit timestamp low value out of the
+ * timestamp block of the external PHY on the E810 device using sideband queue.
*/
static enum ice_status
-ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
+ice_read_phy_tstamp_sbq_e810(struct ice_hw *hw, u8 lport, u8 idx, u8 *hi,
+ u32 *lo)
{
+ u32 hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx);
+ u32 lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx);
enum ice_status status;
- u32 lo_addr, hi_addr, lo, hi;
-
- lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx);
- hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx);
+ u32 lo_val, hi_val;
- status = ice_read_phy_reg_e810(hw, lo_addr, &lo);
+ status = ice_read_phy_reg_e810(hw, lo_addr, &lo_val);
if (status) {
ice_debug(hw, ICE_DBG_PTP, "Failed to read low PTP timestamp register, status %d\n",
status);
return status;
}
- status = ice_read_phy_reg_e810(hw, hi_addr, &hi);
+ status = ice_read_phy_reg_e810(hw, hi_addr, &hi_val);
if (status) {
ice_debug(hw, ICE_DBG_PTP, "Failed to read high PTP timestamp register, status %d\n",
status);
return status;
}
+ *lo = lo_val;
+ *hi = (u8)hi_val;
+
+ return ICE_SUCCESS;
+}
+
+/**
+ * ice_read_phy_tstamp_e810 - Read a PHY timestamp out of the external PHY
+ * @hw: pointer to the HW struct
+ * @lport: the lport to read from
+ * @idx: the timestamp index to read
+ * @tstamp: on return, the 40bit timestamp value
+ *
+ * Read a 40bit timestamp value out of the timestamp block of the external PHY
+ * on the E810 device.
+ */
+static enum ice_status
+ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
+{
+ enum ice_status status;
+ u32 lo = 0;
+ u8 hi = 0;
+
+ if (hw->dev_caps.ts_dev_info.ts_ll_read)
+ status = ice_read_phy_tstamp_ll_e810(hw, idx, &hi, &lo);
+ else
+ status = ice_read_phy_tstamp_sbq_e810(hw, lport, idx, &hi, &lo);
+
+ if (status)
+ return status;
+
/* For E810 devices, the timestamp is reported with the lower 32 bits
* in the low register, and the upper 8 bits in the high register.
*/
@@ -476,8 +476,8 @@ enum ice_status ice_ptp_init_phy_cfg(struct ice_hw *hw);
#define INCVAL_HIGH_M 0xFF
/* Timestamp block macros */
+#define TS_VALID BIT(0)
#define TS_LOW_M 0xFFFFFFFF
-#define TS_HIGH_M 0xFF
#define TS_HIGH_S 32
#define TS_PHY_LOW_M 0xFF
@@ -487,6 +487,16 @@ enum ice_status ice_ptp_init_phy_cfg(struct ice_hw *hw);
#define BYTES_PER_IDX_ADDR_L_U 8
#define BYTES_PER_IDX_ADDR_L 4
+/* Tx timestamp low latency read definitions */
+#define TS_LL_READ_RETRIES 200
+#define TS_LL_READ_TS BIT(31)
+#define TS_LL_READ_TS_IDX_S 24
+#define TS_LL_READ_TS_IDX_M MAKEMASK(0x3F, 0)
+#define TS_LL_READ_TS_IDX(__idx) (TS_LL_READ_TS | \
+ (((__idx) & TS_LL_READ_TS_IDX_M) << \
+ TS_LL_READ_TS_IDX_S))
+#define TS_LL_READ_TS_HIGH_S 16
+
/* Internal PHY timestamp address */
#define TS_L(a, idx) ((a) + ((idx) * BYTES_PER_IDX_ADDR_L_U))
#define TS_H(a, idx) ((a) + ((idx) * BYTES_PER_IDX_ADDR_L_U + \
@@ -651,6 +651,7 @@ struct ice_ts_func_info {
#define ICE_TS_DEV_ENA_M BIT(24)
#define ICE_TS_TMR0_ENA_M BIT(25)
#define ICE_TS_TMR1_ENA_M BIT(26)
+#define ICE_TS_LL_TX_TS_READ_M BIT(28)
struct ice_ts_dev_info {
/* Device specific info */
@@ -663,6 +664,7 @@ struct ice_ts_dev_info {
u8 ena;
u8 tmr0_ena;
u8 tmr1_ena;
+ u8 ts_ll_read;
};
/* Function specific capabilities */