[dpdk-dev] [PATCH 09/29] ixgbe/base: add link mac setup for x550a SFP+

Beilei Xing beilei.xing at intel.com
Fri May 6 08:07:21 CEST 2016


This patch updates ixgbe_setup_mac_link_sfp_x550a for x550 SFP+.
ixgbe_set_lan_id_multi_port_pcie has been updated to set the MAC
instance(0/1) which is needed when configuring the external PHY,
since x550a has two instances of MGPK. The MAC instance is read
from the EEPROM.

Signed-off-by: Beilei Xing <beilei.xing at intel.com>
---
 drivers/net/ixgbe/base/ixgbe_common.c | 13 +++++-
 drivers/net/ixgbe/base/ixgbe_phy.h    |  3 ++
 drivers/net/ixgbe/base/ixgbe_type.h   |  8 ++++
 drivers/net/ixgbe/base/ixgbe_x550.c   | 85 ++++++++++++++++++++++++++---------
 4 files changed, 86 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c
index ec61408..82a8416 100644
--- a/drivers/net/ixgbe/base/ixgbe_common.c
+++ b/drivers/net/ixgbe/base/ixgbe_common.c
@@ -1020,13 +1020,15 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
  *  @hw: pointer to the HW structure
  *
- *  Determines the LAN function id by reading memory-mapped registers
- *  and swaps the port value if requested.
+ *  Determines the LAN function id by reading memory-mapped registers and swaps
+ *  the port value if requested, and set MAC instance for devices that share
+ *  CS4227.
  **/
 void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
 {
 	struct ixgbe_bus_info *bus = &hw->bus;
 	u32 reg;
+	u16 ee_ctrl_4;
 
 	DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
 
@@ -1038,6 +1040,13 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
 	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
 	if (reg & IXGBE_FACTPS_LFS)
 		bus->func ^= 0x1;
+
+	/* Get MAC instance from EEPROM for configuring CS4227 */
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
+		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
+		bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
+			IXGBE_EE_CTRL_4_INST_ID_SHIFT;
+	}
 }
 
 /**
diff --git a/drivers/net/ixgbe/base/ixgbe_phy.h b/drivers/net/ixgbe/base/ixgbe_phy.h
index 1a5affe..281f9fa 100644
--- a/drivers/net/ixgbe/base/ixgbe_phy.h
+++ b/drivers/net/ixgbe/base/ixgbe_phy.h
@@ -89,8 +89,11 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #define IXGBE_CS4227			0xBE	/* CS4227 address */
 #define IXGBE_CS4227_GLOBAL_ID_LSB	0
+#define IXGBE_CS4227_GLOBAL_ID_MSB	1
 #define IXGBE_CS4227_SCRATCH		2
 #define IXGBE_CS4227_GLOBAL_ID_VALUE	0x03E5
+#define IXGBE_CS4223_PHY_ID		0x7003/* Quad port */
+#define IXGBE_CS4227_PHY_ID		0x3003/* Dual port */
 #define IXGBE_CS4227_RESET_PENDING	0x1357
 #define IXGBE_CS4227_RESET_COMPLETE	0x5AA5
 #define IXGBE_CS4227_RETRIES		15
diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index 7bd6f2c..0a35891 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -1472,6 +1472,7 @@ struct ixgbe_dmac_config {
 #define IXGBE_CORECTL_WRITE_CMD		0x00010000
 
 /* Device Type definitions for new protocol MDIO commands */
+#define IXGBE_MDIO_ZERO_DEV_TYPE		0x0
 #define IXGBE_MDIO_PMA_PMD_DEV_TYPE		0x1
 #define IXGBE_MDIO_PCS_DEV_TYPE			0x3
 #define IXGBE_MDIO_PHY_XS_DEV_TYPE		0x4
@@ -2247,6 +2248,9 @@ enum {
 #define IXGBE_PBANUM_PTR_GUARD		0xFAFA
 #define IXGBE_EEPROM_CHECKSUM		0x3F
 #define IXGBE_EEPROM_SUM		0xBABA
+#define IXGBE_EEPROM_CTRL_4		0x45
+#define IXGBE_EE_CTRL_4_INST_ID		0x10
+#define IXGBE_EE_CTRL_4_INST_ID_SHIFT	4
 #define IXGBE_PCIE_ANALOG_PTR		0x03
 #define IXGBE_ATLAS0_CONFIG_PTR		0x04
 #define IXGBE_PHY_PTR			0x04
@@ -3630,6 +3634,7 @@ struct ixgbe_bus_info {
 
 	u16 func;
 	u16 lan_id;
+	u16 instance_id;
 };
 
 /* Flow control parameters */
@@ -4130,5 +4135,8 @@ struct ixgbe_hw {
 
 #define IXGBE_NW_MNG_IF_SEL		0x00011178
 #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT 3
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD	\
+		(0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
 
 #endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index 1ae79f5..0bb3436 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -1550,7 +1550,8 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
 		mac->ops.set_rate_select_speed =
 					ixgbe_set_soft_rate_select_speed;
-		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N)
+		if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
+		    (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
 			mac->ops.setup_mac_link =
 				ixgbe_setup_mac_link_sfp_x550a;
 		else
@@ -2206,8 +2207,9 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
 				   bool autoneg_wait_to_complete)
 {
 	s32 ret_val;
-	u32 reg_val;
+	u16 reg_phy_ext;
 	bool setup_linear = false;
+	u32 reg_slice, reg_phy_int, slice_offset;
 
 	UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
 
@@ -2223,32 +2225,73 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
 	if (ret_val != IXGBE_SUCCESS)
 		return ret_val;
 
-	/* Configure internal PHY for native SFI */
-	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
-		       IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-		       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
+		/* Configure internal PHY for native SFI */
+		ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+			       IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
+			       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
 
-	if (ret_val != IXGBE_SUCCESS)
-		return ret_val;
+		if (ret_val != IXGBE_SUCCESS)
+			return ret_val;
+
+		if (setup_linear) {
+			reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
+			reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR;
+		} else {
+			reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING;
+			reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
+		}
+
+		ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+				IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
 
-	if (setup_linear) {
-		reg_val &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
-		reg_val |= IXGBE_KRM_AN_CNTL_8_LINEAR;
+		if (ret_val != IXGBE_SUCCESS)
+			return ret_val;
+
+		/* Setup XFI/SFI internal link. */
+		ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
 	} else {
-		reg_val |= IXGBE_KRM_AN_CNTL_8_LIMITING;
-		reg_val &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
-	}
+		/* Configure internal PHY for KR/KX. */
+		ixgbe_setup_kr_speed_x550em(hw, speed);
 
-	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
-			IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+		/* Get CS4227 MDIO address */
+		hw->phy.addr =
+			(hw->phy.nw_mng_if_sel &
+			 IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD)
+			>> IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
 
-	if (ret_val != IXGBE_SUCCESS)
-		return ret_val;
+		if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
+			/* Find Address */
+			DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
+			return IXGBE_ERR_PHY_ADDR_INVALID;
+		}
+
+		/* Get external PHY device id */
+		ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
+				       IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
 
-	/* Setup XFI/SFI internal link. */
-	ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
+		if (ret_val != IXGBE_SUCCESS)
+			return ret_val;
 
+		/* When configuring quad port CS4223, the MAC instance is part
+		 * of the slice offset.
+		 */
+		if (reg_phy_ext == IXGBE_CS4223_PHY_ID)
+			slice_offset = (hw->bus.lan_id +
+					(hw->bus.instance_id << 1)) << 12;
+		else
+			slice_offset = hw->bus.lan_id << 12;
+
+		/* Configure CS4227/CS4223 LINE side to proper mode. */
+		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
+		if (setup_linear)
+			reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+		else
+			reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+		ret_val = hw->phy.ops.write_reg(hw, reg_slice,
+					IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
+	}
 	return ret_val;
 }
 
-- 
2.5.0



More information about the dev mailing list