DPDK patches and discussions
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v3 10/56] net/txgbe: add module identify
Date: Wed, 14 Oct 2020 13:54:31 +0800
Message-ID: <20201014055517.1214386-11-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20201014055517.1214386-1-jiawenwu@trustnetic.com>

Add sfp anf qsfp module identify, i2c start and stop.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/txgbe/base/txgbe_eeprom.h |   1 +
 drivers/net/txgbe/base/txgbe_hw.c     |   4 +
 drivers/net/txgbe/base/txgbe_phy.c    | 588 +++++++++++++++++++++++++-
 drivers/net/txgbe/base/txgbe_phy.h    |  12 +
 drivers/net/txgbe/base/txgbe_type.h   |   1 +
 5 files changed, 603 insertions(+), 3 deletions(-)

diff --git a/drivers/net/txgbe/base/txgbe_eeprom.h b/drivers/net/txgbe/base/txgbe_eeprom.h
index 137fb1c30..25d03421c 100644
--- a/drivers/net/txgbe/base/txgbe_eeprom.h
+++ b/drivers/net/txgbe/base/txgbe_eeprom.h
@@ -23,6 +23,7 @@
 #define TXGBE_EEPROM_VERSION_H          0x1E
 #define TXGBE_ISCSI_BOOT_CONFIG         0x07
 
+#define TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP		0x1
 
 s32 txgbe_init_eeprom_params(struct txgbe_hw *hw);
 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw);
diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c
index a067192fa..d2d12a929 100644
--- a/drivers/net/txgbe/base/txgbe_hw.c
+++ b/drivers/net/txgbe/base/txgbe_hw.c
@@ -291,6 +291,10 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)
 	/* PHY */
 	phy->identify = txgbe_identify_phy;
 	phy->init = txgbe_init_phy_raptor;
+	phy->read_i2c_byte = txgbe_read_i2c_byte;
+	phy->write_i2c_byte = txgbe_write_i2c_byte;
+	phy->read_i2c_eeprom = txgbe_read_i2c_eeprom;
+	phy->write_i2c_eeprom = txgbe_write_i2c_eeprom;
 
 	/* MAC */
 	mac->init_hw = txgbe_init_hw;
diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c
index 2ed497c48..b36bffcac 100644
--- a/drivers/net/txgbe/base/txgbe_phy.c
+++ b/drivers/net/txgbe/base/txgbe_phy.c
@@ -7,6 +7,9 @@
 #include "txgbe_mng.h"
 #include "txgbe_phy.h"
 
+static void txgbe_i2c_start(struct txgbe_hw *hw);
+static void txgbe_i2c_stop(struct txgbe_hw *hw);
+
 /**
  * txgbe_identify_extphy - Identify a single address for a PHY
  * @hw: pointer to hardware structure
@@ -234,8 +237,204 @@ s32 txgbe_identify_module(struct txgbe_hw *hw)
  **/
 s32 txgbe_identify_sfp_module(struct txgbe_hw *hw)
 {
-	RTE_SET_USED(hw);
-	return 0;
+	s32 err = TXGBE_ERR_PHY_ADDR_INVALID;
+	u32 vendor_oui = 0;
+	enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
+	u8 identifier = 0;
+	u8 comp_codes_1g = 0;
+	u8 comp_codes_10g = 0;
+	u8 oui_bytes[3] = {0, 0, 0};
+	u8 cable_tech = 0;
+	u8 cable_spec = 0;
+	u16 enforce_sfp = 0;
+
+	DEBUGFUNC("txgbe_identify_sfp_module");
+
+	if (hw->phy.media_type != txgbe_media_type_fiber) {
+		hw->phy.sfp_type = txgbe_sfp_type_not_present;
+		return TXGBE_ERR_SFP_NOT_PRESENT;
+	}
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER,
+					     &identifier);
+	if (err != 0) {
+ERR_I2C:
+		hw->phy.sfp_type = txgbe_sfp_type_not_present;
+		if (hw->phy.type != txgbe_phy_nl) {
+			hw->phy.id = 0;
+			hw->phy.type = txgbe_phy_unknown;
+		}
+		return TXGBE_ERR_SFP_NOT_PRESENT;
+	}
+
+	if (identifier != TXGBE_SFF_IDENTIFIER_SFP) {
+		hw->phy.type = txgbe_phy_sfp_unsupported;
+		return TXGBE_ERR_SFP_NOT_SUPPORTED;
+	}
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_1GBE_COMP_CODES,
+					     &comp_codes_1g);
+	if (err != 0)
+		goto ERR_I2C;
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_10GBE_COMP_CODES,
+					     &comp_codes_10g);
+	if (err != 0)
+		goto ERR_I2C;
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_TECHNOLOGY,
+					     &cable_tech);
+	if (err != 0)
+		goto ERR_I2C;
+
+	 /* ID Module
+	  * =========
+	  * 0   SFP_DA_CU
+	  * 1   SFP_SR
+	  * 2   SFP_LR
+	  * 3   SFP_DA_CORE0 - chip-specific
+	  * 4   SFP_DA_CORE1 - chip-specific
+	  * 5   SFP_SR/LR_CORE0 - chip-specific
+	  * 6   SFP_SR/LR_CORE1 - chip-specific
+	  * 7   SFP_act_lmt_DA_CORE0 - chip-specific
+	  * 8   SFP_act_lmt_DA_CORE1 - chip-specific
+	  * 9   SFP_1g_cu_CORE0 - chip-specific
+	  * 10  SFP_1g_cu_CORE1 - chip-specific
+	  * 11  SFP_1g_sx_CORE0 - chip-specific
+	  * 12  SFP_1g_sx_CORE1 - chip-specific
+	  */
+	if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) {
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0;
+		else
+			hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1;
+	} else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) {
+		err = hw->phy.read_i2c_eeprom(hw,
+			TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec);
+		if (err != 0)
+			goto ERR_I2C;
+		if (cable_spec & TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
+			hw->phy.sfp_type = (hw->bus.lan_id == 0
+				? txgbe_sfp_type_da_act_lmt_core0
+				: txgbe_sfp_type_da_act_lmt_core1);
+		} else {
+			hw->phy.sfp_type = txgbe_sfp_type_unknown;
+		}
+	} else if (comp_codes_10g &
+		   (TXGBE_SFF_10GBASESR_CAPABLE |
+		    TXGBE_SFF_10GBASELR_CAPABLE)) {
+		hw->phy.sfp_type = (hw->bus.lan_id == 0
+				? txgbe_sfp_type_srlr_core0
+				: txgbe_sfp_type_srlr_core1);
+	} else if (comp_codes_1g & TXGBE_SFF_1GBASET_CAPABLE) {
+		hw->phy.sfp_type = (hw->bus.lan_id == 0
+				? txgbe_sfp_type_1g_cu_core0
+				: txgbe_sfp_type_1g_cu_core1);
+	} else if (comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) {
+		hw->phy.sfp_type = (hw->bus.lan_id == 0
+				? txgbe_sfp_type_1g_sx_core0
+				: txgbe_sfp_type_1g_sx_core1);
+	} else if (comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) {
+		hw->phy.sfp_type = (hw->bus.lan_id == 0
+				? txgbe_sfp_type_1g_lx_core0
+				: txgbe_sfp_type_1g_lx_core1);
+	} else {
+		hw->phy.sfp_type = txgbe_sfp_type_unknown;
+	}
+
+	if (hw->phy.sfp_type != stored_sfp_type)
+		hw->phy.sfp_setup_needed = true;
+
+	/* Determine if the SFP+ PHY is dual speed or not. */
+	hw->phy.multispeed_fiber = false;
+	if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) &&
+	     (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) ||
+	    ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) &&
+	     (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE)))
+		hw->phy.multispeed_fiber = true;
+
+	/* Determine PHY vendor */
+	if (hw->phy.type != txgbe_phy_nl) {
+		hw->phy.id = identifier;
+		err = hw->phy.read_i2c_eeprom(hw,
+			TXGBE_SFF_VENDOR_OUI_BYTE0, &oui_bytes[0]);
+		if (err != 0)
+			goto ERR_I2C;
+
+		err = hw->phy.read_i2c_eeprom(hw,
+			TXGBE_SFF_VENDOR_OUI_BYTE1, &oui_bytes[1]);
+		if (err != 0)
+			goto ERR_I2C;
+
+		err = hw->phy.read_i2c_eeprom(hw,
+			TXGBE_SFF_VENDOR_OUI_BYTE2, &oui_bytes[2]);
+		if (err != 0)
+			goto ERR_I2C;
+
+		vendor_oui = ((u32)oui_bytes[0] << 24) |
+			     ((u32)oui_bytes[1] << 16) |
+			     ((u32)oui_bytes[2] << 8);
+		switch (vendor_oui) {
+		case TXGBE_SFF_VENDOR_OUI_TYCO:
+			if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE)
+				hw->phy.type = txgbe_phy_sfp_tyco_passive;
+			break;
+		case TXGBE_SFF_VENDOR_OUI_FTL:
+			if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE)
+				hw->phy.type = txgbe_phy_sfp_ftl_active;
+			else
+				hw->phy.type = txgbe_phy_sfp_ftl;
+			break;
+		case TXGBE_SFF_VENDOR_OUI_AVAGO:
+			hw->phy.type = txgbe_phy_sfp_avago;
+			break;
+		case TXGBE_SFF_VENDOR_OUI_INTEL:
+			hw->phy.type = txgbe_phy_sfp_intel;
+			break;
+		default:
+			if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE)
+				hw->phy.type = txgbe_phy_sfp_unknown_passive;
+			else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE)
+				hw->phy.type = txgbe_phy_sfp_unknown_active;
+			else
+				hw->phy.type = txgbe_phy_sfp_unknown;
+			break;
+		}
+	}
+
+	/* Allow any DA cable vendor */
+	if (cable_tech & (TXGBE_SFF_CABLE_DA_PASSIVE |
+			  TXGBE_SFF_CABLE_DA_ACTIVE)) {
+		return 0;
+	}
+
+	/* Verify supported 1G SFP modules */
+	if (comp_codes_10g == 0 &&
+	    !(hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core1 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core1 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) {
+		hw->phy.type = txgbe_phy_sfp_unsupported;
+		return TXGBE_ERR_SFP_NOT_SUPPORTED;
+	}
+
+	hw->mac.get_device_caps(hw, &enforce_sfp);
+	if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
+	    !hw->allow_unsupported_sfp &&
+	    !(hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core1 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core1 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 ||
+	      hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) {
+		DEBUGOUT("SFP+ module not supported\n");
+		hw->phy.type = txgbe_phy_sfp_unsupported;
+		return TXGBE_ERR_SFP_NOT_SUPPORTED;
+	}
+
+	return err;
 }
 
 /**
@@ -246,7 +445,390 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw)
  **/
 s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw)
 {
-	RTE_SET_USED(hw);
+	s32 err = TXGBE_ERR_PHY_ADDR_INVALID;
+	u32 vendor_oui = 0;
+	enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
+	u8 identifier = 0;
+	u8 comp_codes_1g = 0;
+	u8 comp_codes_10g = 0;
+	u8 oui_bytes[3] = {0, 0, 0};
+	u16 enforce_sfp = 0;
+	u8 connector = 0;
+	u8 cable_length = 0;
+	u8 device_tech = 0;
+	bool active_cable = false;
+
+	DEBUGFUNC("txgbe_identify_qsfp_module");
+
+	if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) {
+		hw->phy.sfp_type = txgbe_sfp_type_not_present;
+		err = TXGBE_ERR_SFP_NOT_PRESENT;
+		goto out;
+	}
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER,
+					     &identifier);
+ERR_I2C:
+	if (err != 0) {
+		hw->phy.sfp_type = txgbe_sfp_type_not_present;
+		hw->phy.id = 0;
+		hw->phy.type = txgbe_phy_unknown;
+		return TXGBE_ERR_SFP_NOT_PRESENT;
+	}
+	if (identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
+		hw->phy.type = txgbe_phy_sfp_unsupported;
+		err = TXGBE_ERR_SFP_NOT_SUPPORTED;
+		goto out;
+	}
+
+	hw->phy.id = identifier;
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_10GBE_COMP,
+					     &comp_codes_10g);
+
+	if (err != 0)
+		goto ERR_I2C;
+
+	err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_1GBE_COMP,
+					     &comp_codes_1g);
+
+	if (err != 0)
+		goto ERR_I2C;
+
+	if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) {
+		hw->phy.type = txgbe_phy_qsfp_unknown_passive;
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0;
+		else
+			hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1;
+	} else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE |
+				     TXGBE_SFF_10GBASELR_CAPABLE)) {
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = txgbe_sfp_type_srlr_core0;
+		else
+			hw->phy.sfp_type = txgbe_sfp_type_srlr_core1;
+	} else {
+		if (comp_codes_10g & TXGBE_SFF_QSFP_DA_ACTIVE_CABLE)
+			active_cable = true;
+
+		if (!active_cable) {
+			hw->phy.read_i2c_eeprom(hw,
+					TXGBE_SFF_QSFP_CONNECTOR,
+					&connector);
+
+			hw->phy.read_i2c_eeprom(hw,
+					TXGBE_SFF_QSFP_CABLE_LENGTH,
+					&cable_length);
+
+			hw->phy.read_i2c_eeprom(hw,
+					TXGBE_SFF_QSFP_DEVICE_TECH,
+					&device_tech);
+
+			if (connector ==
+				     TXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE &&
+			    cable_length > 0 &&
+			    ((device_tech >> 4) ==
+				     TXGBE_SFF_QSFP_TRANSMITTER_850NM_VCSEL))
+				active_cable = true;
+		}
+
+		if (active_cable) {
+			hw->phy.type = txgbe_phy_qsfp_unknown_active;
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					txgbe_sfp_type_da_act_lmt_core0;
+			else
+				hw->phy.sfp_type =
+					txgbe_sfp_type_da_act_lmt_core1;
+		} else {
+			/* unsupported module type */
+			hw->phy.type = txgbe_phy_sfp_unsupported;
+			err = TXGBE_ERR_SFP_NOT_SUPPORTED;
+			goto out;
+		}
+	}
+
+	if (hw->phy.sfp_type != stored_sfp_type)
+		hw->phy.sfp_setup_needed = true;
+
+	/* Determine if the QSFP+ PHY is dual speed or not. */
+	hw->phy.multispeed_fiber = false;
+	if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) &&
+	   (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) ||
+	   ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) &&
+	   (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE)))
+		hw->phy.multispeed_fiber = true;
+
+	/* Determine PHY vendor for optical modules */
+	if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE |
+			      TXGBE_SFF_10GBASELR_CAPABLE))  {
+		err = hw->phy.read_i2c_eeprom(hw,
+					    TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0,
+					    &oui_bytes[0]);
+
+		if (err != 0)
+			goto ERR_I2C;
+
+		err = hw->phy.read_i2c_eeprom(hw,
+					    TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1,
+					    &oui_bytes[1]);
+
+		if (err != 0)
+			goto ERR_I2C;
+
+		err = hw->phy.read_i2c_eeprom(hw,
+					    TXGBE_SFF_QSFP_VENDOR_OUI_BYTE2,
+					    &oui_bytes[2]);
+
+		if (err != 0)
+			goto ERR_I2C;
+
+		vendor_oui =
+		  ((oui_bytes[0] << 24) |
+		   (oui_bytes[1] << 16) |
+		   (oui_bytes[2] << 8));
+
+		if (vendor_oui == TXGBE_SFF_VENDOR_OUI_INTEL)
+			hw->phy.type = txgbe_phy_qsfp_intel;
+		else
+			hw->phy.type = txgbe_phy_qsfp_unknown;
+
+		hw->mac.get_device_caps(hw, &enforce_sfp);
+		if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
+			/* Make sure we're a supported PHY type */
+			if (hw->phy.type == txgbe_phy_qsfp_intel) {
+				err = 0;
+			} else {
+				if (hw->allow_unsupported_sfp) {
+					DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. "
+						"Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. "
+						"Wangxun Corporation is not responsible for any harm caused by using untested modules.\n");
+					err = 0;
+				} else {
+					DEBUGOUT("QSFP module not supported\n");
+					hw->phy.type =
+						txgbe_phy_sfp_unsupported;
+					err = TXGBE_ERR_SFP_NOT_SUPPORTED;
+				}
+			}
+		} else {
+			err = 0;
+		}
+	}
+
+out:
+	return err;
+}
+
+/**
+ *  txgbe_read_i2c_eeprom - Reads 8 bit EEPROM word over I2C interface
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: EEPROM byte offset to read
+ *  @eeprom_data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
+				  u8 *eeprom_data)
+{
+	DEBUGFUNC("txgbe_read_i2c_eeprom");
+
+	return hw->phy.read_i2c_byte(hw, byte_offset,
+					 TXGBE_I2C_EEPROM_DEV_ADDR,
+					 eeprom_data);
+}
+
+/**
+ *  txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: EEPROM byte offset to write
+ *  @eeprom_data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
+				   u8 eeprom_data)
+{
+	DEBUGFUNC("txgbe_write_i2c_eeprom");
+
+	return hw->phy.write_i2c_byte(hw, byte_offset,
+					  TXGBE_I2C_EEPROM_DEV_ADDR,
+					  eeprom_data);
+}
+
+/**
+ *  txgbe_read_i2c_byte_unlocked - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: address to read from
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
+					   u8 dev_addr, u8 *data)
+{
+	UNREFERENCED_PARAMETER(dev_addr);
+
+	DEBUGFUNC("txgbe_read_i2c_byte");
+
+	txgbe_i2c_start(hw);
+
+	/* wait tx empty */
+	if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY,
+		TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) {
+		return -TERR_TIMEOUT;
+	}
+
+	/* read data */
+	wr32(hw, TXGBE_I2CDATA,
+			byte_offset | TXGBE_I2CDATA_STOP);
+	wr32(hw, TXGBE_I2CDATA, TXGBE_I2CDATA_READ);
+
+	/* wait for read complete */
+	if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL,
+		TXGBE_I2CICR_RXFULL, NULL, 100, 100)) {
+		return -TERR_TIMEOUT;
+	}
+
+	txgbe_i2c_stop(hw);
+
+	*data = 0xFF & rd32(hw, TXGBE_I2CDATA);
+
+	return 0;
+}
+
+/**
+ *  txgbe_read_i2c_byte - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: address to read from
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data)
+{
+	u32 swfw_mask = hw->phy.phy_semaphore_mask;
+	int err = 0;
+
+	if (hw->mac.acquire_swfw_sync(hw, swfw_mask))
+		return TXGBE_ERR_SWFW_SYNC;
+	err = txgbe_read_i2c_byte_unlocked(hw, byte_offset, dev_addr, data);
+	hw->mac.release_swfw_sync(hw, swfw_mask);
+	return err;
+}
+
+/**
+ *  txgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: address to write to
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
+					    u8 dev_addr, u8 data)
+{
+	UNREFERENCED_PARAMETER(dev_addr);
+
+	DEBUGFUNC("txgbe_write_i2c_byte");
+
+	txgbe_i2c_start(hw);
+
+	/* wait tx empty */
+	if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY,
+		TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) {
+		return -TERR_TIMEOUT;
+	}
+
+	wr32(hw, TXGBE_I2CDATA, byte_offset | TXGBE_I2CDATA_STOP);
+	wr32(hw, TXGBE_I2CDATA, data | TXGBE_I2CDATA_WRITE);
+
+	/* wait for write complete */
+	if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL,
+		TXGBE_I2CICR_RXFULL, NULL, 100, 100)) {
+		return -TERR_TIMEOUT;
+	}
+	txgbe_i2c_stop(hw);
+
 	return 0;
 }
 
+/**
+ *  txgbe_write_i2c_byte - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: address to write to
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data)
+{
+	u32 swfw_mask = hw->phy.phy_semaphore_mask;
+	int err = 0;
+
+	if (hw->mac.acquire_swfw_sync(hw, swfw_mask))
+		return TXGBE_ERR_SWFW_SYNC;
+	err = txgbe_write_i2c_byte_unlocked(hw, byte_offset, dev_addr, data);
+	hw->mac.release_swfw_sync(hw, swfw_mask);
+
+	return err;
+}
+
+/**
+ *  txgbe_i2c_start - Sets I2C start condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+static void txgbe_i2c_start(struct txgbe_hw *hw)
+{
+	DEBUGFUNC("txgbe_i2c_start");
+
+	wr32(hw, TXGBE_I2CENA, 0);
+
+	wr32(hw, TXGBE_I2CCON,
+		(TXGBE_I2CCON_MENA |
+		TXGBE_I2CCON_SPEED(1) |
+		TXGBE_I2CCON_RESTART |
+		TXGBE_I2CCON_SDIA));
+	wr32(hw, TXGBE_I2CTAR, TXGBE_I2C_SLAVEADDR);
+	wr32(hw, TXGBE_I2CSSSCLHCNT, 600);
+	wr32(hw, TXGBE_I2CSSSCLLCNT, 600);
+	wr32(hw, TXGBE_I2CRXTL, 0); /* 1byte for rx full signal */
+	wr32(hw, TXGBE_I2CTXTL, 4);
+	wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF);
+	wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF);
+
+	wr32(hw, TXGBE_I2CICM, 0);
+	wr32(hw, TXGBE_I2CENA, 1);
+}
+
+/**
+ *  txgbe_i2c_stop - Sets I2C stop condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+static void txgbe_i2c_stop(struct txgbe_hw *hw)
+{
+	DEBUGFUNC("txgbe_i2c_stop");
+
+	/* wait for completion */
+	if (!po32m(hw, TXGBE_I2CSTAT, TXGBE_I2CSTAT_MST,
+		0, NULL, 100, 100)) {
+		DEBUGFUNC("i2c stop timeout.");
+	}
+
+	wr32(hw, TXGBE_I2CENA, 0);
+}
+
diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h
index 544ab064e..3c3f2914a 100644
--- a/drivers/net/txgbe/base/txgbe_phy.h
+++ b/drivers/net/txgbe/base/txgbe_phy.h
@@ -332,5 +332,17 @@ s32 txgbe_identify_phy(struct txgbe_hw *hw);
 s32 txgbe_identify_module(struct txgbe_hw *hw);
 s32 txgbe_identify_sfp_module(struct txgbe_hw *hw);
 s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw);
+s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data);
+s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
+					 u8 dev_addr, u8 *data);
+s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data);
+s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset,
+					  u8 dev_addr, u8 data);
+s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
+				  u8 *eeprom_data);
+s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset,
+				   u8 eeprom_data);
 
 #endif /* _TXGBE_PHY_H_ */
diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h
index b8e85063a..438734f8c 100644
--- a/drivers/net/txgbe/base/txgbe_type.h
+++ b/drivers/net/txgbe/base/txgbe_type.h
@@ -358,6 +358,7 @@ struct txgbe_phy_info {
 	u32 media_type;
 	u32 phy_semaphore_mask;
 	bool reset_disable;
+	bool multispeed_fiber;
 	bool qsfp_shared_i2c_bus;
 	u32 nw_mng_if_sel;
 };
-- 
2.18.4




  parent reply	other threads:[~2020-10-14  5:58 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-14  5:54 [dpdk-dev] [PATCH v3 00/56] net: txgbe PMD Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 01/56] net/txgbe: add build and doc infrastructure Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 02/56] net/txgbe: add ethdev probe and remove Jiawen Wu
2020-10-15  0:56   ` Ferruh Yigit
2020-10-16  9:52     ` Jiawen Wu
2020-10-16 10:33       ` Ferruh Yigit
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 03/56] net/txgbe: add device init and uninit Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 04/56] net/txgbe: add error types and registers Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 05/56] net/txgbe: add MAC type and bus lan id Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 06/56] net/txgbe: add HW infrastructure and dummy function Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 07/56] net/txgbe: add EEPROM functions Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 08/56] net/txgbe: add HW init and reset operation Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 09/56] net/txgbe: add PHY init Jiawen Wu
2020-10-14  5:54 ` Jiawen Wu [this message]
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 11/56] net/txgbe: add PHY reset Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 12/56] net/txgbe: add info get operation Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 13/56] net/txgbe: add interrupt operation Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 14/56] net/txgbe: add device configure operation Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 15/56] net/txgbe: add link status change Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 16/56] net/txgbe: add multi-speed link setup Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 17/56] net/txgbe: add autoc read and write Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 18/56] net/txgbe: add MAC address operations Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 19/56] net/txgbe: add unicast hash bitmap Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 20/56] net/txgbe: add Rx and Tx init Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 21/56] net/txgbe: add Rx and Tx queues setup and release Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 22/56] net/txgbe: add Rx and Tx start and stop Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 23/56] net/txgbe: add packet type Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 24/56] net/txgbe: fill simple transmit function Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 25/56] net/txgbe: fill transmit function with hardware offload Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 26/56] net/txgbe: fill Tx prepare function Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 27/56] net/txgbe: fill receive functions Jiawen Wu
2020-10-15  0:55   ` Ferruh Yigit
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 28/56] net/txgbe: add device start operation Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 29/56] net/txgbe: add Rx and Tx data path start and stop Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 30/56] net/txgbe: add device stop and close operations Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 31/56] net/txgbe: support Rx interrupt Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 32/56] net/txgbe: add Rx and Tx queue info get Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 33/56] net/txgbe: add device stats get Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 34/56] net/txgbe: add device xstats get Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 35/56] net/txgbe: add queue stats mapping Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 36/56] net/txgbe: add VLAN handle support Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 37/56] net/txgbe: add SWFW semaphore and lock Jiawen Wu
2020-10-14  5:54 ` [dpdk-dev] [PATCH v3 38/56] net/txgbe: add PF module init and uninit for SRIOV Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 39/56] net/txgbe: add process mailbox operation Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 40/56] net/txgbe: add PF module configure for SRIOV Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 41/56] net/txgbe: add VMDq configure Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 42/56] net/txgbe: add RSS support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 43/56] net/txgbe: add DCB support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 44/56] net/txgbe: add flow control support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 45/56] net/txgbe: add FC auto negotiation support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 46/56] net/txgbe: add priority flow control support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 47/56] net/txgbe: add device promiscuous and allmulticast mode Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 48/56] net/txgbe: add MTU set operation Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 49/56] net/txgbe: add FW version get operation Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 50/56] net/txgbe: add EEPROM info " Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 51/56] net/txgbe: add register dump support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 52/56] net/txgbe: support device LED on and off Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 53/56] net/txgbe: add mirror rule operations Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 54/56] net/txgbe: add PTP support Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 55/56] net/txgbe: add DCB info get operation Jiawen Wu
2020-10-14  5:55 ` [dpdk-dev] [PATCH v3 56/56] net/txgbe: add Rx and Tx descriptor status Jiawen Wu
2020-10-15  0:55   ` Ferruh Yigit
2020-10-15  0:56 ` [dpdk-dev] [PATCH v3 00/56] net: txgbe PMD Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201014055517.1214386-11-jiawenwu@trustnetic.com \
    --to=jiawenwu@trustnetic.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git