E810 products can support low latency Tx timestamp register read.
Add a check for the device capability and use the new method if
supported.

Signed-off-by: Karol Kolacinski <karol.kolacin...@intel.com>
Signed-off-by: Qi Zhang <qi.z.zh...@intel.com>
---
 drivers/net/ice/base/ice_common.c |  7 ++-
 drivers/net/ice/base/ice_ptp_hw.c | 95 +++++++++++++++++++++++++++----
 drivers/net/ice/base/ice_ptp_hw.h | 12 +++-
 drivers/net/ice/base/ice_type.h   |  2 +
 4 files changed, 101 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ice/base/ice_common.c 
b/drivers/net/ice/base/ice_common.c
index c90ae20c43..2014f8361d 100644
--- a/drivers/net/ice/base/ice_common.c
+++ b/drivers/net/ice/base/ice_common.c
@@ -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);
 }
diff --git a/drivers/net/ice/base/ice_ptp_hw.c 
b/drivers/net/ice/base/ice_ptp_hw.c
index 7ed420be8e..712b7dedfb 100644
--- a/drivers/net/ice/base/ice_ptp_hw.c
+++ b/drivers/net/ice/base/ice_ptp_hw.c
@@ -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.
         */
diff --git a/drivers/net/ice/base/ice_ptp_hw.h 
b/drivers/net/ice/base/ice_ptp_hw.h
index 1e016ef177..9fa17787df 100644
--- a/drivers/net/ice/base/ice_ptp_hw.h
+++ b/drivers/net/ice/base/ice_ptp_hw.h
@@ -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 +          \
diff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h
index 5c7cc06e0c..cdfef47e94 100644
--- a/drivers/net/ice/base/ice_type.h
+++ b/drivers/net/ice/base/ice_type.h
@@ -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 */
-- 
2.31.1

Reply via email to