From patchwork Fri Jun 5 05:21:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenzhuo Lu X-Patchwork-Id: 5166 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id CCC055A06; Fri, 5 Jun 2015 07:22:30 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 0C10EC37E for ; Fri, 5 Jun 2015 07:22:28 +0200 (CEST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga102.fm.intel.com with ESMTP; 04 Jun 2015 22:22:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,556,1427785200"; d="scan'208";a="582505444" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga003.jf.intel.com with ESMTP; 04 Jun 2015 22:22:27 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id t555MPZU032582; Fri, 5 Jun 2015 13:22:25 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id t555MMld024358; Fri, 5 Jun 2015 13:22:25 +0800 Received: (from wenzhuol@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t555MMFv024354; Fri, 5 Jun 2015 13:22:22 +0800 From: Wenzhuo Lu To: dev@dpdk.org Date: Fri, 5 Jun 2015 13:21:42 +0800 Message-Id: <1433481718-24253-11-git-send-email-wenzhuo.lu@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1433481718-24253-1-git-send-email-wenzhuo.lu@intel.com> References: <1433481718-24253-1-git-send-email-wenzhuo.lu@intel.com> Subject: [dpdk-dev] [PATCH 10/26] ixgbe/base: add logic to reset CS4227 when needed X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" On some hardware platforms, the CS4227 does not initialize properly. Detect those cases and reset it appropriately. Signed-off-by: Wenzhuo Lu --- drivers/net/ixgbe/base/ixgbe_phy.h | 12 +++ drivers/net/ixgbe/base/ixgbe_x550.c | 184 ++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/drivers/net/ixgbe/base/ixgbe_phy.h b/drivers/net/ixgbe/base/ixgbe_phy.h index 7456bf4..ba5b308 100644 --- a/drivers/net/ixgbe/base/ixgbe_phy.h +++ b/drivers/net/ixgbe/base/ixgbe_phy.h @@ -83,9 +83,21 @@ POSSIBILITY OF SUCH DAMAGE. #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 #define IXGBE_CS4227 0xBE /* CS4227 address */ +#define IXGBE_CS4227_GLOBAL_ID_LSB 0 +#define IXGBE_CS4227_SCRATCH 2 +#define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5 +#define IXGBE_CS4227_SCRATCH_VALUE 0x5aa5 +#define IXGBE_CS4227_RETRIES 5 #define IXGBE_CS4227_SPARE24_LSB 0x12B0 /* Reg to program EDC */ #define IXGBE_CS4227_EDC_MODE_CX1 0x0002 #define IXGBE_CS4227_EDC_MODE_SR 0x0004 +#define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */ +#define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */ +#define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */ +#define IXGBE_PE 0xE0 /* Port expander address */ +#define IXGBE_PE_OUTPUT 1 /* Output register offset */ +#define IXGBE_PE_CONFIG 3 /* Config register offset */ +#define IXGBE_PE_BIT1 (1 << 1) /* Flow control defines */ #define IXGBE_TAF_SYM_PAUSE 0x400 diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c index 0ce1c85..c91e737 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.c +++ b/drivers/net/ixgbe/base/ixgbe_x550.c @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "ixgbe_common.h" #include "ixgbe_phy.h" + /** * ixgbe_init_ops_X550 - Inits func ptrs and MAC type * @hw: pointer to hardware structure @@ -82,6 +83,187 @@ s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw) } /** + * ixgbe_read_cs4227 - Read CS4227 register + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: pointer to receive value read + * + * Returns status code + **/ +STATIC s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) +{ + return ixgbe_read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value); +} + +/** + * ixgbe_write_cs4227 - Write CS4227 register + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: value to write to register + * + * Returns status code + **/ +STATIC s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) +{ + return ixgbe_write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value); +} + +/** + * ixgbe_get_cs4227_status - Return CS4227 status + * @hw: pointer to hardware structure + * + * Returns error if CS4227 not successfully initialized + **/ +STATIC s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw) +{ + s32 status; + u16 value = 0; + u8 retry; + + for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) { + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_GLOBAL_ID_LSB, + &value); + if (status != IXGBE_SUCCESS) + return status; + if (value == IXGBE_CS4227_GLOBAL_ID_VALUE) + break; + msec_delay(IXGBE_CS4227_CHECK_DELAY); + } + if (value != IXGBE_CS4227_GLOBAL_ID_VALUE) + return IXGBE_ERR_PHY; + + status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, + IXGBE_CS4227_SCRATCH_VALUE); + if (status != IXGBE_SUCCESS) + return status; + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); + if (status != IXGBE_SUCCESS) + return status; + if (value != IXGBE_CS4227_SCRATCH_VALUE) + return IXGBE_ERR_PHY; + return IXGBE_SUCCESS; +} + +/** + * ixgbe_read_pe - Read register from port expander + * @hw: pointer to hardware structure + * @reg: register number to read + * @value: pointer to receive read value + * + * Returns status code + **/ +STATIC s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) +{ + s32 status; + + status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); + if (status != IXGBE_SUCCESS) + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "port expander access failed with %d\n", status); + return status; +} + +/** + * ixgbe_write_pe - Write register to port expander + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: value to write + * + * Returns status code + **/ +STATIC s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) +{ + s32 status; + + status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); + if (status != IXGBE_SUCCESS) + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "port expander access failed with %d\n", status); + return status; +} + +/** + * ixgbe_reset_cs4227 - Reset CS4227 using port expander + * @hw: pointer to hardware structure + * + * Returns error code + **/ +STATIC s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) +{ + s32 status; + u8 reg; + + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status != IXGBE_SUCCESS) + return status; + reg |= IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status != IXGBE_SUCCESS) + return status; + + status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); + if (status != IXGBE_SUCCESS) + return status; + reg &= ~IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); + if (status != IXGBE_SUCCESS) + return status; + + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status != IXGBE_SUCCESS) + return status; + reg &= ~IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status != IXGBE_SUCCESS) + return status; + + usec_delay(IXGBE_CS4227_RESET_HOLD); + + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status != IXGBE_SUCCESS) + return status; + reg |= IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status != IXGBE_SUCCESS) + return status; + + msec_delay(IXGBE_CS4227_RESET_DELAY); + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_check_cs4227 - Check CS4227 and reset as needed + * @hw: pointer to hardware structure + **/ +STATIC void ixgbe_check_cs4227(struct ixgbe_hw *hw) +{ + u32 swfw_mask = hw->phy.phy_semaphore_mask; + s32 status; + u8 retry; + + for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status != IXGBE_SUCCESS) { + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "semaphore failed with %d\n", status); + return; + } + status = ixgbe_get_cs4227_status(hw); + if (status == IXGBE_SUCCESS) { + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msec_delay(hw->eeprom.semaphore_delay); + return; + } + ixgbe_reset_cs4227(hw); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msec_delay(hw->eeprom.semaphore_delay); + } + ERROR_REPORT2(IXGBE_ERROR_CAUTION, + "Unable to initialize CS4227, err=%d\n", status); +} + +/** * ixgbe_identify_phy_x550em - Get PHY type based on device id * @hw: pointer to hardware structure * @@ -103,6 +285,8 @@ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + ixgbe_check_cs4227(hw); + return ixgbe_identify_module_generic(hw); break; case IXGBE_DEV_ID_X550EM_X_KX4: