@@ -4856,33 +4856,46 @@ static int ice_write_phy_reg_e810(struct ice_hw *hw, u32 addr, u32 val)
48564856static int
48574857ice_read_phy_tstamp_ll_e810 (struct ice_hw * hw , u8 idx , u8 * hi , u32 * lo )
48584858{
4859+ struct ice_e810_params * params = & hw -> ptp .phy .e810 ;
4860+ unsigned long flags ;
48594861 u32 val ;
4860- u8 i ;
4862+ int err ;
4863+
4864+ spin_lock_irqsave (& params -> atqbal_wq .lock , flags );
4865+
4866+ /* Wait for any pending in-progress low latency interrupt */
4867+ err = wait_event_interruptible_locked_irq (params -> atqbal_wq ,
4868+ !(params -> atqbal_flags &
4869+ ATQBAL_FLAGS_INTR_IN_PROGRESS ));
4870+ if (err ) {
4871+ spin_unlock_irqrestore (& params -> atqbal_wq .lock , flags );
4872+ return err ;
4873+ }
48614874
48624875 /* Write TS index to read to the PF register so the FW can read it */
4863- val = FIELD_PREP (TS_LL_READ_TS_IDX , idx ) | TS_LL_READ_TS ;
4864- wr32 (hw , PF_SB_ATQBAL , val );
4876+ val = FIELD_PREP (REG_LL_PROXY_H_TS_IDX , idx ) | REG_LL_PROXY_H_EXEC ;
4877+ wr32 (hw , REG_LL_PROXY_H , val );
48654878
48664879 /* Read the register repeatedly until the FW provides us the TS */
4867- for (i = TS_LL_READ_RETRIES ; i > 0 ; i -- ) {
4868- val = rd32 (hw , PF_SB_ATQBAL );
4880+ err = read_poll_timeout_atomic (rd32 , val ,
4881+ !FIELD_GET (REG_LL_PROXY_H_EXEC , val ), 10 ,
4882+ REG_LL_PROXY_H_TIMEOUT_US , false, hw ,
4883+ REG_LL_PROXY_H );
4884+ if (err ) {
4885+ ice_debug (hw , ICE_DBG_PTP , "Failed to read PTP timestamp using low latency read\n" );
4886+ spin_unlock_irqrestore (& params -> atqbal_wq .lock , flags );
4887+ return err ;
4888+ }
48694889
4870- /* When the bit is cleared, the TS is ready in the register */
4871- if (!(FIELD_GET (TS_LL_READ_TS , val ))) {
4872- /* High 8 bit value of the TS is on the bits 16:23 */
4873- * hi = FIELD_GET (TS_LL_READ_TS_HIGH , val );
4890+ /* High 8 bit value of the TS is on the bits 16:23 */
4891+ * hi = FIELD_GET (REG_LL_PROXY_H_TS_HIGH , val );
48744892
4875- /* Read the low 32 bit value and set the TS valid bit */
4876- * lo = rd32 (hw , PF_SB_ATQBAH ) | TS_VALID ;
4877- return 0 ;
4878- }
4893+ /* Read the low 32 bit value and set the TS valid bit */
4894+ * lo = rd32 (hw , REG_LL_PROXY_L ) | TS_VALID ;
48794895
4880- udelay (10 );
4881- }
4896+ spin_unlock_irqrestore (& params -> atqbal_wq .lock , flags );
48824897
4883- /* FW failed to provide the TS in time */
4884- ice_debug (hw , ICE_DBG_PTP , "Failed to read PTP timestamp using low latency read\n" );
4885- return - EINVAL ;
4898+ return 0 ;
48864899}
48874900
48884901/**
@@ -5064,6 +5077,55 @@ static int ice_ptp_prep_phy_time_e810(struct ice_hw *hw, u32 time)
50645077 return 0 ;
50655078}
50665079
5080+ /**
5081+ * ice_ptp_prep_phy_adj_ll_e810 - Prep PHY ports for a time adjustment
5082+ * @hw: pointer to HW struct
5083+ * @adj: adjustment value to program
5084+ *
5085+ * Use the low latency firmware interface to program PHY time adjustment to
5086+ * all PHY ports.
5087+ *
5088+ * Return: 0 on success, -EBUSY on timeout
5089+ */
5090+ static int ice_ptp_prep_phy_adj_ll_e810 (struct ice_hw * hw , s32 adj )
5091+ {
5092+ const u8 tmr_idx = hw -> func_caps .ts_func_info .tmr_index_owned ;
5093+ struct ice_e810_params * params = & hw -> ptp .phy .e810 ;
5094+ u32 val ;
5095+ int err ;
5096+
5097+ spin_lock_irq (& params -> atqbal_wq .lock );
5098+
5099+ /* Wait for any pending in-progress low latency interrupt */
5100+ err = wait_event_interruptible_locked_irq (params -> atqbal_wq ,
5101+ !(params -> atqbal_flags &
5102+ ATQBAL_FLAGS_INTR_IN_PROGRESS ));
5103+ if (err ) {
5104+ spin_unlock_irq (& params -> atqbal_wq .lock );
5105+ return err ;
5106+ }
5107+
5108+ wr32 (hw , REG_LL_PROXY_L , adj );
5109+ val = FIELD_PREP (REG_LL_PROXY_H_PHY_TMR_CMD_M , REG_LL_PROXY_H_PHY_TMR_CMD_ADJ ) |
5110+ FIELD_PREP (REG_LL_PROXY_H_PHY_TMR_IDX_M , tmr_idx ) | REG_LL_PROXY_H_EXEC ;
5111+ wr32 (hw , REG_LL_PROXY_H , val );
5112+
5113+ /* Read the register repeatedly until the FW indicates completion */
5114+ err = read_poll_timeout_atomic (rd32 , val ,
5115+ !FIELD_GET (REG_LL_PROXY_H_EXEC , val ),
5116+ 10 , REG_LL_PROXY_H_TIMEOUT_US , false, hw ,
5117+ REG_LL_PROXY_H );
5118+ if (err ) {
5119+ ice_debug (hw , ICE_DBG_PTP , "Failed to prepare PHY timer adjustment using low latency interface\n" );
5120+ spin_unlock_irq (& params -> atqbal_wq .lock );
5121+ return err ;
5122+ }
5123+
5124+ spin_unlock_irq (& params -> atqbal_wq .lock );
5125+
5126+ return 0 ;
5127+ }
5128+
50675129/**
50685130 * ice_ptp_prep_phy_adj_e810 - Prep PHY port for a time adjustment
50695131 * @hw: pointer to HW struct
@@ -5082,6 +5144,9 @@ static int ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj)
50825144 u8 tmr_idx ;
50835145 int err ;
50845146
5147+ if (hw -> dev_caps .ts_dev_info .ll_phy_tmr_update )
5148+ return ice_ptp_prep_phy_adj_ll_e810 (hw , adj );
5149+
50855150 tmr_idx = hw -> func_caps .ts_func_info .tmr_index_owned ;
50865151
50875152 /* Adjustments are represented as signed 2's complement values in
@@ -5104,6 +5169,56 @@ static int ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj)
51045169 return 0 ;
51055170}
51065171
5172+ /**
5173+ * ice_ptp_prep_phy_incval_ll_e810 - Prep PHY ports increment value change
5174+ * @hw: pointer to HW struct
5175+ * @incval: The new 40bit increment value to prepare
5176+ *
5177+ * Use the low latency firmware interface to program PHY time increment value
5178+ * for all PHY ports.
5179+ *
5180+ * Return: 0 on success, -EBUSY on timeout
5181+ */
5182+ static int ice_ptp_prep_phy_incval_ll_e810 (struct ice_hw * hw , u64 incval )
5183+ {
5184+ const u8 tmr_idx = hw -> func_caps .ts_func_info .tmr_index_owned ;
5185+ struct ice_e810_params * params = & hw -> ptp .phy .e810 ;
5186+ u32 val ;
5187+ int err ;
5188+
5189+ spin_lock_irq (& params -> atqbal_wq .lock );
5190+
5191+ /* Wait for any pending in-progress low latency interrupt */
5192+ err = wait_event_interruptible_locked_irq (params -> atqbal_wq ,
5193+ !(params -> atqbal_flags &
5194+ ATQBAL_FLAGS_INTR_IN_PROGRESS ));
5195+ if (err ) {
5196+ spin_unlock_irq (& params -> atqbal_wq .lock );
5197+ return err ;
5198+ }
5199+
5200+ wr32 (hw , REG_LL_PROXY_L , lower_32_bits (incval ));
5201+ val = FIELD_PREP (REG_LL_PROXY_H_PHY_TMR_CMD_M , REG_LL_PROXY_H_PHY_TMR_CMD_FREQ ) |
5202+ FIELD_PREP (REG_LL_PROXY_H_TS_HIGH , (u8 )upper_32_bits (incval )) |
5203+ FIELD_PREP (REG_LL_PROXY_H_PHY_TMR_IDX_M , tmr_idx ) | REG_LL_PROXY_H_EXEC ;
5204+ wr32 (hw , REG_LL_PROXY_H , val );
5205+
5206+ /* Read the register repeatedly until the FW indicates completion */
5207+ err = read_poll_timeout_atomic (rd32 , val ,
5208+ !FIELD_GET (REG_LL_PROXY_H_EXEC , val ),
5209+ 10 , REG_LL_PROXY_H_TIMEOUT_US , false, hw ,
5210+ REG_LL_PROXY_H );
5211+ if (err ) {
5212+ ice_debug (hw , ICE_DBG_PTP , "Failed to prepare PHY timer increment using low latency interface\n" );
5213+ spin_unlock_irq (& params -> atqbal_wq .lock );
5214+ return err ;
5215+ }
5216+
5217+ spin_unlock_irq (& params -> atqbal_wq .lock );
5218+
5219+ return 0 ;
5220+ }
5221+
51075222/**
51085223 * ice_ptp_prep_phy_incval_e810 - Prep PHY port increment value change
51095224 * @hw: pointer to HW struct
@@ -5119,6 +5234,9 @@ static int ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval)
51195234 u8 tmr_idx ;
51205235 int err ;
51215236
5237+ if (hw -> dev_caps .ts_dev_info .ll_phy_tmr_update )
5238+ return ice_ptp_prep_phy_incval_ll_e810 (hw , incval );
5239+
51225240 tmr_idx = hw -> func_caps .ts_func_info .tmr_index_owned ;
51235241 low = lower_32_bits (incval );
51245242 high = upper_32_bits (incval );
@@ -5403,6 +5521,8 @@ static void ice_ptp_init_phy_e810(struct ice_ptp_hw *ptp)
54035521 ptp -> phy_model = ICE_PHY_E810 ;
54045522 ptp -> num_lports = 8 ;
54055523 ptp -> ports_per_phy = 4 ;
5524+
5525+ init_waitqueue_head (& ptp -> phy .e810 .atqbal_wq );
54065526}
54075527
54085528/* Device agnostic functions
0 commit comments