[23/30] net/ice/base: change method to get pca9575 handle

Message ID 20230427062001.478032-24-qiming.yang@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Qi Zhang
Headers
Series net/ice/base: share code update |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Qiming Yang April 27, 2023, 6:19 a.m. UTC
  More universal method for getting pca9575 handle is introduced.
The first step is to look for CLK_MUX handle. Having that it is
possible to find CLK_MUX GPIO pin. Provided data let check what is
driving the pin - the expectation is that pca9575 node part number
is returned.

Signed-off-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 drivers/net/ice/base/ice_adminq_cmd.h |  12 ++-
 drivers/net/ice/base/ice_ptp_hw.c     | 125 ++++++++++++++++++++++----
 2 files changed, 120 insertions(+), 17 deletions(-)
  

Patch

diff --git a/drivers/net/ice/base/ice_adminq_cmd.h b/drivers/net/ice/base/ice_adminq_cmd.h
index c51054ecc1..29b123d900 100644
--- a/drivers/net/ice/base/ice_adminq_cmd.h
+++ b/drivers/net/ice/base/ice_adminq_cmd.h
@@ -1723,6 +1723,8 @@  struct ice_aqc_link_topo_params {
 #define ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE	6
 #define ICE_AQC_LINK_TOPO_NODE_TYPE_MEZZ	7
 #define ICE_AQC_LINK_TOPO_NODE_TYPE_ID_EEPROM	8
+#define ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL	9
+#define ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX	10
 #define ICE_AQC_LINK_TOPO_NODE_TYPE_GPS		11
 #define ICE_AQC_LINK_TOPO_NODE_CTX_S		4
 #define ICE_AQC_LINK_TOPO_NODE_CTX_M		\
@@ -1760,8 +1762,13 @@  struct ice_aqc_link_topo_addr {
 struct ice_aqc_get_link_topo {
 	struct ice_aqc_link_topo_addr addr;
 	u8 node_part_num;
-#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_PCA9575	0x21
-#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_GEN_GPS	0x48
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_PCA9575			0x21
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_ZL30632_80032		0x24
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_SI5383_5384		0x25
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_E822_PHY			0x30
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_C827			0x31
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX		0x47
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_GEN_GPS			0x48
 	u8 rsvd[9];
 };
 
@@ -1789,6 +1796,7 @@  struct ice_aqc_get_link_topo_pin {
 #define ICE_AQC_LINK_TOPO_IO_FUNC_RED_LED	12
 #define ICE_AQC_LINK_TOPO_IO_FUNC_GREEN_LED	13
 #define ICE_AQC_LINK_TOPO_IO_FUNC_BLUE_LED	14
+#define ICE_AQC_LINK_TOPO_IO_FUNC_CLK_IN	20
 #define ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S	5
 #define ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_M	\
 			(0x7 << ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S)
diff --git a/drivers/net/ice/base/ice_ptp_hw.c b/drivers/net/ice/base/ice_ptp_hw.c
index cc6c1f3152..29840b2b91 100644
--- a/drivers/net/ice/base/ice_ptp_hw.c
+++ b/drivers/net/ice/base/ice_ptp_hw.c
@@ -1962,14 +1962,19 @@  ice_calc_fixed_tx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd)
  * adjust Tx timestamps by. This is calculated by combining some known static
  * latency along with the Vernier offset computations done by hardware.
  *
- * This function must be called only after the offset registers are valid,
- * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
- * has measured the offset.
+ * This function will not return successfully until the Tx offset calculations
+ * have been completed, which requires waiting until at least one packet has
+ * been transmitted by the device. It is safe to call this function
+ * periodically until calibration succeeds, as it will only program the offset
+ * once.
  *
  * To avoid overflow, when calculating the offset based on the known static
  * latency values, we use measurements in 1/100th of a nanosecond, and divide
  * the TUs per second up front. This avoids overflow while allowing
  * calculation of the adjustment using integer arithmetic.
+ *
+ * Returns zero on success, ICE_ERR_NOT_READY if the hardware vernier offset
+ * calibration has not completed, or another error code on failure.
  */
 enum ice_status ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
 {
@@ -1977,6 +1982,28 @@  enum ice_status ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
 	enum ice_ptp_fec_mode fec_mode;
 	enum ice_status status;
 	u64 total_offset, val;
+	u32 reg;
+
+	/* Nothing to do if we've already programmed the offset */
+	status = ice_read_phy_reg_e822(hw, port, P_REG_TX_OR, &reg);
+	if (status) {
+		ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OR for port %u, status %d\n",
+			  port, status);
+		return status;
+	}
+
+	if (reg)
+		return ICE_SUCCESS;
+
+	status = ice_read_phy_reg_e822(hw, port, P_REG_TX_OV_STATUS, &reg);
+	if (status) {
+		ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_OV_STATUS for port %u, status %d\n",
+			  port, status);
+		return status;
+	}
+
+	if (!(reg & P_REG_TX_OV_STATUS_OV_M))
+		return ICE_ERR_NOT_READY;
 
 	status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
 	if (status)
@@ -2030,6 +2057,7 @@  enum ice_status ice_phy_cfg_tx_offset_e822(struct ice_hw *hw, u8 port)
 	if (status)
 		return status;
 
+	ice_info(hw, "Port=%d Tx vernier offset calibration complete\n", port);
 
 	return ICE_SUCCESS;
 }
@@ -2236,6 +2264,11 @@  ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd)
  * measurements taken in hardware with some data about known fixed delay as
  * well as adjusting for multi-lane alignment delay.
  *
+ * This function will not return successfully until the Rx offset calculations
+ * have been completed, which requires waiting until at least one packet has
+ * been received by the device. It is safe to call this function periodically
+ * until calibration succeeds, as it will only program the offset once.
+ *
  * This function must be called only after the offset registers are valid,
  * i.e. after the Vernier calibration wait has passed, to ensure that the PHY
  * has measured the offset.
@@ -2244,6 +2277,9 @@  ice_calc_fixed_rx_offset_e822(struct ice_hw *hw, enum ice_ptp_link_spd link_spd)
  * latency values, we use measurements in 1/100th of a nanosecond, and divide
  * the TUs per second up front. This avoids overflow while allowing
  * calculation of the adjustment using integer arithmetic.
+ *
+ * Returns zero on success, ICE_ERR_NOT_READY if the hardware vernier offset
+ * calibration has not completed, or another error code on failure.
  */
 enum ice_status ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
 {
@@ -2251,6 +2287,28 @@  enum ice_status ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
 	enum ice_ptp_fec_mode fec_mode;
 	u64 total_offset, pmd, val;
 	enum ice_status status;
+	u32 reg;
+
+	/* Nothing to do if we've already programmed the offset */
+	status = ice_read_phy_reg_e822(hw, port, P_REG_RX_OR, &reg);
+	if (status) {
+		ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OR for port %u, status %d\n",
+			  port, status);
+		return status;
+	}
+
+	if (reg)
+		return ICE_SUCCESS;
+
+	status = ice_read_phy_reg_e822(hw, port, P_REG_RX_OV_STATUS, &reg);
+	if (status) {
+		ice_debug(hw, ICE_DBG_PTP, "Failed to read RX_OV_STATUS for port %u, status %d\n",
+			  port, status);
+		return status;
+	}
+
+	if (!(reg & P_REG_RX_OV_STATUS_OV_M))
+		return ICE_ERR_NOT_READY;
 
 	status = ice_phy_get_speed_and_fec_e822(hw, port, &link_spd, &fec_mode);
 	if (status)
@@ -2311,10 +2369,11 @@  enum ice_status ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
 	if (status)
 		return status;
 
+	ice_info(hw, "Port=%d Rx vernier offset calibration complete\n", port);
+
 	return ICE_SUCCESS;
 }
 
-
 /**
  * ice_ptp_clear_phy_offset_ready_e822 - Clear PHY TX_/RX_OFFSET_READY registers
  * @hw: pointer to the HW struct
@@ -2424,7 +2483,8 @@  static enum ice_status ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
 		return ICE_ERR_NOT_READY;
 	}
 
-	status = ice_read_phy_and_phc_time_e822(hw, port, &phy_time, &phc_time);
+	status = ice_read_phy_and_phc_time_e822(hw, port, &phy_time,
+						&phc_time);
 	if (status)
 		goto err_unlock;
 
@@ -3175,17 +3235,18 @@  ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
  * @hw: pointer to the hw struct
  * @pca9575_handle: GPIO controller's handle
  *
- * Find and return the GPIO controller's handle in the netlist.
- * When found - the value will be cached in the hw structure and following calls
- * will return cached value
+ * Find and return the GPIO controller's handle by checking what drives clock
+ * mux pin. When found - the value will be cached in the hw structure and
+ * following calls will return cached value.
  */
 static enum ice_status
 ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
 {
+	u8 node_part_number, idx, node_type_ctx_clk_mux, node_part_num_clk_mux;
+	struct ice_aqc_get_link_topo_pin cmd_pin;
+	u16 node_handle, clock_mux_handle;
 	struct ice_aqc_get_link_topo cmd;
-	u8 node_part_number, idx;
 	enum ice_status status;
-	u16 node_handle;
 
 	if (!hw || !pca9575_handle)
 		return ICE_ERR_PARAM;
@@ -3197,11 +3258,46 @@  ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
 	}
 
 	memset(&cmd, 0, sizeof(cmd));
+	memset(&cmd_pin, 0, sizeof(cmd_pin));
+
+	node_type_ctx_clk_mux = (ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX <<
+				 ICE_AQC_LINK_TOPO_NODE_TYPE_S);
+	node_type_ctx_clk_mux |= (ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL <<
+				  ICE_AQC_LINK_TOPO_NODE_CTX_S);
+	node_part_num_clk_mux = ICE_ACQ_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX;
 
-	/* Set node type to GPIO controller */
+	/* Look for CLOCK MUX handle in the netlist */
+	status = ice_find_netlist_node(hw, node_type_ctx_clk_mux,
+				       node_part_num_clk_mux,
+				       &clock_mux_handle);
+	if (status)
+		return ICE_ERR_NOT_SUPPORTED;
+
+	/* Take CLOCK MUX GPIO pin */
+	cmd_pin.input_io_params = (ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_GPIO <<
+				   ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S);
+	cmd_pin.input_io_params |= (ICE_AQC_LINK_TOPO_IO_FUNC_CLK_IN <<
+				    ICE_AQC_LINK_TOPO_INPUT_IO_FUNC_S);
+	cmd_pin.addr.handle = CPU_TO_LE16(clock_mux_handle);
+	cmd_pin.addr.topo_params.node_type_ctx =
+		(ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX <<
+		 ICE_AQC_LINK_TOPO_NODE_TYPE_S);
+	cmd_pin.addr.topo_params.node_type_ctx |=
+		(ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED <<
+		 ICE_AQC_LINK_TOPO_NODE_CTX_S);
+
+	status = ice_aq_get_netlist_node_pin(hw, &cmd_pin, &node_handle);
+	if (status)
+		return ICE_ERR_NOT_SUPPORTED;
+
+	/* Check what is driving the pin */
 	cmd.addr.topo_params.node_type_ctx =
-		(ICE_AQC_LINK_TOPO_NODE_TYPE_M &
-		 ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL);
+		(ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL <<
+		 ICE_AQC_LINK_TOPO_NODE_TYPE_S);
+	cmd.addr.topo_params.node_type_ctx |=
+		(ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL <<
+		 ICE_AQC_LINK_TOPO_NODE_CTX_S);
+	cmd.addr.handle = CPU_TO_LE16(node_handle);
 
 #define SW_PCA9575_SFP_TOPO_IDX		2
 #define SW_PCA9575_QSFP_TOPO_IDX	1
@@ -3215,13 +3311,12 @@  ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
 		return ICE_ERR_NOT_SUPPORTED;
 
 	cmd.addr.topo_params.index = idx;
-
 	status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number,
 					 &node_handle);
 	if (status)
 		return ICE_ERR_NOT_SUPPORTED;
 
-	/* Verify if we found the right IO expander type */
+	/* Verify if PCA9575 drives the pin */
 	if (node_part_number != ICE_ACQ_GET_LINK_TOPO_NODE_NR_PCA9575)
 		return ICE_ERR_NOT_SUPPORTED;