|
@@ -56,6 +56,283 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
|
|
IXGBE_WRITE_FLUSH(hw);
|
|
IXGBE_WRITE_FLUSH(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 hw->phy.ops.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 hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
|
|
|
|
+ value);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_check_cs4227_reg - Perform diag on a CS4227 register
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @reg: the register to check
|
|
|
|
+ *
|
|
|
|
+ * Performs a diagnostic on a register in the CS4227 chip. Returns an error
|
|
|
|
+ * if it is not operating correctly.
|
|
|
|
+ * This function assumes that the caller has acquired the proper semaphore.
|
|
|
|
+ */
|
|
|
|
+static s32 ixgbe_check_cs4227_reg(struct ixgbe_hw *hw, u16 reg)
|
|
|
|
+{
|
|
|
|
+ s32 status;
|
|
|
|
+ u32 retry;
|
|
|
|
+ u16 reg_val;
|
|
|
|
+
|
|
|
|
+ reg_val = (IXGBE_CS4227_EDC_MODE_DIAG << 1) | 1;
|
|
|
|
+ status = ixgbe_write_cs4227(hw, reg, reg_val);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
|
|
|
|
+ msleep(IXGBE_CS4227_CHECK_DELAY);
|
|
|
|
+ reg_val = 0xFFFF;
|
|
|
|
+ ixgbe_read_cs4227(hw, reg, ®_val);
|
|
|
|
+ if (!reg_val)
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (reg_val) {
|
|
|
|
+ hw_err(hw, "CS4227 reg 0x%04X failed diagnostic\n", reg);
|
|
|
|
+ return status;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_get_cs4227_status - Return CS4227 status
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ *
|
|
|
|
+ * Performs a diagnostic on the CS4227 chip. Returns an error if it is
|
|
|
|
+ * not operating correctly.
|
|
|
|
+ * This function assumes that the caller has acquired the proper semaphore.
|
|
|
|
+ */
|
|
|
|
+static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw)
|
|
|
|
+{
|
|
|
|
+ s32 status;
|
|
|
|
+ u16 value = 0;
|
|
|
|
+
|
|
|
|
+ /* Exit if the diagnostic has already been performed. */
|
|
|
|
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ if (value == IXGBE_CS4227_RESET_COMPLETE)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ /* Check port 0. */
|
|
|
|
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ /* Check port 1. */
|
|
|
|
+ status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB +
|
|
|
|
+ (1 << 12));
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ return ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB +
|
|
|
|
+ (1 << 12));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 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_generic_unlocked(hw, reg, IXGBE_PE, value);
|
|
|
|
+ if (status)
|
|
|
|
+ hw_err(hw, "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_generic_unlocked(hw, reg, IXGBE_PE,
|
|
|
|
+ value);
|
|
|
|
+ if (status)
|
|
|
|
+ hw_err(hw, "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;
|
|
|
|
+ u32 retry;
|
|
|
|
+ u16 value;
|
|
|
|
+ u8 reg;
|
|
|
|
+
|
|
|
|
+ /* Trigger hard reset. */
|
|
|
|
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ reg |= IXGBE_PE_BIT1;
|
|
|
|
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ reg &= ~IXGBE_PE_BIT1;
|
|
|
|
+ status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ reg &= ~IXGBE_PE_BIT1;
|
|
|
|
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100);
|
|
|
|
+
|
|
|
|
+ status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+ reg |= IXGBE_PE_BIT1;
|
|
|
|
+ status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ /* Wait for the reset to complete. */
|
|
|
|
+ msleep(IXGBE_CS4227_RESET_DELAY);
|
|
|
|
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
|
|
|
|
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
|
|
|
|
+ &value);
|
|
|
|
+ if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK)
|
|
|
|
+ break;
|
|
|
|
+ msleep(IXGBE_CS4227_CHECK_DELAY);
|
|
|
|
+ }
|
|
|
|
+ if (retry == IXGBE_CS4227_RETRIES) {
|
|
|
|
+ hw_err(hw, "CS4227 reset did not complete\n");
|
|
|
|
+ return IXGBE_ERR_PHY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
|
|
|
|
+ if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
|
|
|
|
+ hw_err(hw, "CS4227 EEPROM did not load successfully\n");
|
|
|
|
+ return IXGBE_ERR_PHY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 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;
|
|
|
|
+ u16 value;
|
|
|
|
+ u8 retry;
|
|
|
|
+
|
|
|
|
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
|
|
|
|
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
|
|
|
|
+ if (status) {
|
|
|
|
+ hw_err(hw, "semaphore failed with %d\n", status);
|
|
|
|
+ msleep(IXGBE_CS4227_CHECK_DELAY);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Get status of reset flow. */
|
|
|
|
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
|
|
|
|
+ if (!status && value == IXGBE_CS4227_RESET_COMPLETE)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ if (status || value != IXGBE_CS4227_RESET_PENDING)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /* Reset is pending. Wait and check again. */
|
|
|
|
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
|
|
|
+ msleep(IXGBE_CS4227_CHECK_DELAY);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Reset the CS4227. */
|
|
|
|
+ status = ixgbe_reset_cs4227(hw);
|
|
|
|
+ if (status) {
|
|
|
|
+ hw_err(hw, "CS4227 reset failed: %d", status);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Reset takes so long, temporarily release semaphore in case the
|
|
|
|
+ * other driver instance is waiting for the reset indication.
|
|
|
|
+ */
|
|
|
|
+ ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
|
|
|
|
+ IXGBE_CS4227_RESET_PENDING);
|
|
|
|
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
|
|
|
+ usleep_range(10000, 12000);
|
|
|
|
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
|
|
|
|
+ if (status) {
|
|
|
|
+ hw_err(hw, "semaphore failed with %d", status);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Is the CS4227 working correctly? */
|
|
|
|
+ status = ixgbe_get_cs4227_status(hw);
|
|
|
|
+ if (status) {
|
|
|
|
+ hw_err(hw, "CS4227 status failed: %d", status);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Record completion for next time. */
|
|
|
|
+ status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
|
|
|
|
+ IXGBE_CS4227_RESET_COMPLETE);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
|
|
|
+ msleep(hw->eeprom.semaphore_delay);
|
|
|
|
+}
|
|
|
|
+
|
|
/** ixgbe_identify_phy_x550em - Get PHY type based on device id
|
|
/** ixgbe_identify_phy_x550em - Get PHY type based on device id
|
|
* @hw: pointer to hardware structure
|
|
* @hw: pointer to hardware structure
|
|
*
|
|
*
|
|
@@ -68,7 +345,7 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
|
|
/* set up for CS4227 usage */
|
|
/* set up for CS4227 usage */
|
|
hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
|
|
hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
|
|
ixgbe_setup_mux_ctl(hw);
|
|
ixgbe_setup_mux_ctl(hw);
|
|
-
|
|
|
|
|
|
+ ixgbe_check_cs4227(hw);
|
|
return ixgbe_identify_module_generic(hw);
|
|
return ixgbe_identify_module_generic(hw);
|
|
case IXGBE_DEV_ID_X550EM_X_KX4:
|
|
case IXGBE_DEV_ID_X550EM_X_KX4:
|
|
hw->phy.type = ixgbe_phy_x550em_kx4;
|
|
hw->phy.type = ixgbe_phy_x550em_kx4;
|
|
@@ -909,6 +1186,96 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @linear: true if SFP module is linear
|
|
|
|
+ */
|
|
|
|
+static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
|
|
|
|
+{
|
|
|
|
+ switch (hw->phy.sfp_type) {
|
|
|
|
+ case ixgbe_sfp_type_not_present:
|
|
|
|
+ return IXGBE_ERR_SFP_NOT_PRESENT;
|
|
|
|
+ case ixgbe_sfp_type_da_cu_core0:
|
|
|
|
+ case ixgbe_sfp_type_da_cu_core1:
|
|
|
|
+ *linear = true;
|
|
|
|
+ break;
|
|
|
|
+ case ixgbe_sfp_type_srlr_core0:
|
|
|
|
+ case ixgbe_sfp_type_srlr_core1:
|
|
|
|
+ case ixgbe_sfp_type_da_act_lmt_core0:
|
|
|
|
+ case ixgbe_sfp_type_da_act_lmt_core1:
|
|
|
|
+ case ixgbe_sfp_type_1g_sx_core0:
|
|
|
|
+ case ixgbe_sfp_type_1g_sx_core1:
|
|
|
|
+ case ixgbe_sfp_type_1g_lx_core0:
|
|
|
|
+ case ixgbe_sfp_type_1g_lx_core1:
|
|
|
|
+ *linear = false;
|
|
|
|
+ break;
|
|
|
|
+ case ixgbe_sfp_type_unknown:
|
|
|
|
+ case ixgbe_sfp_type_1g_cu_core0:
|
|
|
|
+ case ixgbe_sfp_type_1g_cu_core1:
|
|
|
|
+ default:
|
|
|
|
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP.
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ *
|
|
|
|
+ * Configures the extern PHY and the integrated KR PHY for SFP support.
|
|
|
|
+ */
|
|
|
|
+static s32
|
|
|
|
+ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
|
|
|
|
+ ixgbe_link_speed speed,
|
|
|
|
+ __always_unused bool autoneg_wait_to_complete)
|
|
|
|
+{
|
|
|
|
+ s32 status;
|
|
|
|
+ u16 slice, value;
|
|
|
|
+ bool setup_linear = false;
|
|
|
|
+
|
|
|
|
+ /* Check if SFP module is supported and linear */
|
|
|
|
+ status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
|
|
|
|
+
|
|
|
|
+ /* If no SFP module present, then return success. Return success since
|
|
|
|
+ * there is no reason to configure CS4227 and SFP not present error is
|
|
|
|
+ * not accepted in the setup MAC link flow.
|
|
|
|
+ */
|
|
|
|
+ if (status == IXGBE_ERR_SFP_NOT_PRESENT)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ /* Configure CS4227 LINE side to 10G SR. */
|
|
|
|
+ slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
|
|
|
|
+ value = IXGBE_CS4227_SPEED_10G;
|
|
|
|
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
|
|
|
|
+ value);
|
|
|
|
+
|
|
|
|
+ /* Configure CS4227 for HOST connection rate then type. */
|
|
|
|
+ slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
|
|
|
|
+ value = speed & IXGBE_LINK_SPEED_10GB_FULL ?
|
|
|
|
+ IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
|
|
|
|
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
|
|
|
|
+ value);
|
|
|
|
+
|
|
|
|
+ slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
|
|
|
|
+ if (setup_linear)
|
|
|
|
+ value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
|
|
|
|
+ else
|
|
|
|
+ value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
|
|
|
|
+ status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice,
|
|
|
|
+ value);
|
|
|
|
+
|
|
|
|
+ /* If internal link mode is XFI, then setup XFI internal link. */
|
|
|
|
+ if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))
|
|
|
|
+ status = ixgbe_setup_ixfi_x550em(hw, &speed);
|
|
|
|
+
|
|
|
|
+ return status;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
|
|
* ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
|
|
* @hw: pointer to hardware structure
|
|
* @hw: pointer to hardware structure
|
|
@@ -1003,6 +1370,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
|
|
mac->ops.disable_tx_laser = NULL;
|
|
mac->ops.disable_tx_laser = NULL;
|
|
mac->ops.enable_tx_laser = NULL;
|
|
mac->ops.enable_tx_laser = NULL;
|
|
mac->ops.flap_tx_laser = NULL;
|
|
mac->ops.flap_tx_laser = NULL;
|
|
|
|
+ mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
|
|
|
|
+ mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em;
|
|
|
|
+ mac->ops.set_rate_select_speed =
|
|
|
|
+ ixgbe_set_soft_rate_select_speed;
|
|
break;
|
|
break;
|
|
case ixgbe_media_type_copper:
|
|
case ixgbe_media_type_copper:
|
|
mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
|
|
mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
|
|
@@ -1018,53 +1389,18 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
|
|
*/
|
|
*/
|
|
static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
|
|
static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
|
|
{
|
|
{
|
|
- bool setup_linear;
|
|
|
|
- u16 reg_slice, edc_mode;
|
|
|
|
- s32 ret_val;
|
|
|
|
|
|
+ s32 status;
|
|
|
|
+ bool linear;
|
|
|
|
|
|
- switch (hw->phy.sfp_type) {
|
|
|
|
- case ixgbe_sfp_type_unknown:
|
|
|
|
- return 0;
|
|
|
|
- case ixgbe_sfp_type_not_present:
|
|
|
|
- return IXGBE_ERR_SFP_NOT_PRESENT;
|
|
|
|
- case ixgbe_sfp_type_da_cu_core0:
|
|
|
|
- case ixgbe_sfp_type_da_cu_core1:
|
|
|
|
- setup_linear = true;
|
|
|
|
- break;
|
|
|
|
- case ixgbe_sfp_type_srlr_core0:
|
|
|
|
- case ixgbe_sfp_type_srlr_core1:
|
|
|
|
- case ixgbe_sfp_type_da_act_lmt_core0:
|
|
|
|
- case ixgbe_sfp_type_da_act_lmt_core1:
|
|
|
|
- case ixgbe_sfp_type_1g_sx_core0:
|
|
|
|
- case ixgbe_sfp_type_1g_sx_core1:
|
|
|
|
- setup_linear = false;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return IXGBE_ERR_SFP_NOT_SUPPORTED;
|
|
|
|
- }
|
|
|
|
|
|
+ /* Check if SFP module is supported */
|
|
|
|
+ status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
|
|
ixgbe_init_mac_link_ops_X550em(hw);
|
|
ixgbe_init_mac_link_ops_X550em(hw);
|
|
hw->phy.ops.reset = NULL;
|
|
hw->phy.ops.reset = NULL;
|
|
|
|
|
|
- /* The CS4227 slice address is the base address + the port-pair reg
|
|
|
|
- * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
|
|
|
|
- */
|
|
|
|
- reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
|
|
|
|
-
|
|
|
|
- if (setup_linear)
|
|
|
|
- edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
|
|
|
|
- else
|
|
|
|
- edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
|
|
|
|
-
|
|
|
|
- /* Configure CS4227 for connection type. */
|
|
|
|
- ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
|
|
|
|
- edc_mode);
|
|
|
|
-
|
|
|
|
- if (ret_val)
|
|
|
|
- ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice,
|
|
|
|
- edc_mode);
|
|
|
|
-
|
|
|
|
- return ret_val;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
|
|
/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
|
|
@@ -1927,6 +2263,62 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
|
|
IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
|
|
IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_set_mux - Set mux for port 1 access with CS4227
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @state: set mux if 1, clear if 0
|
|
|
|
+ */
|
|
|
|
+static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
|
|
|
|
+{
|
|
|
|
+ u32 esdp;
|
|
|
|
+
|
|
|
|
+ if (!hw->bus.lan_id)
|
|
|
|
+ return;
|
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
|
+ if (state)
|
|
|
|
+ esdp |= IXGBE_ESDP_SDP1;
|
|
|
|
+ else
|
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP1;
|
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @mask: Mask to specify which semaphore to acquire
|
|
|
|
+ *
|
|
|
|
+ * Acquires the SWFW semaphore and sets the I2C MUX
|
|
|
|
+ */
|
|
|
|
+static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
|
|
|
|
+{
|
|
|
|
+ s32 status;
|
|
|
|
+
|
|
|
|
+ status = ixgbe_acquire_swfw_sync_X540(hw, mask);
|
|
|
|
+ if (status)
|
|
|
|
+ return status;
|
|
|
|
+
|
|
|
|
+ if (mask & IXGBE_GSSR_I2C_MASK)
|
|
|
|
+ ixgbe_set_mux(hw, 1);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @mask: Mask to specify which semaphore to release
|
|
|
|
+ *
|
|
|
|
+ * Releases the SWFW semaphore and sets the I2C MUX
|
|
|
|
+ */
|
|
|
|
+static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
|
|
|
|
+{
|
|
|
|
+ if (mask & IXGBE_GSSR_I2C_MASK)
|
|
|
|
+ ixgbe_set_mux(hw, 0);
|
|
|
|
+
|
|
|
|
+ ixgbe_release_swfw_sync_X540(hw, mask);
|
|
|
|
+}
|
|
|
|
+
|
|
#define X550_COMMON_MAC \
|
|
#define X550_COMMON_MAC \
|
|
.init_hw = &ixgbe_init_hw_generic, \
|
|
.init_hw = &ixgbe_init_hw_generic, \
|
|
.start_hw = &ixgbe_start_hw_X540, \
|
|
.start_hw = &ixgbe_start_hw_X540, \
|
|
@@ -1964,8 +2356,6 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
|
|
&ixgbe_set_source_address_pruning_X550, \
|
|
&ixgbe_set_source_address_pruning_X550, \
|
|
.set_ethertype_anti_spoofing = \
|
|
.set_ethertype_anti_spoofing = \
|
|
&ixgbe_set_ethertype_anti_spoofing_X550, \
|
|
&ixgbe_set_ethertype_anti_spoofing_X550, \
|
|
- .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \
|
|
|
|
- .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \
|
|
|
|
.disable_rx_buff = &ixgbe_disable_rx_buff_generic, \
|
|
.disable_rx_buff = &ixgbe_disable_rx_buff_generic, \
|
|
.enable_rx_buff = &ixgbe_enable_rx_buff_generic, \
|
|
.enable_rx_buff = &ixgbe_enable_rx_buff_generic, \
|
|
.get_thermal_sensor_data = NULL, \
|
|
.get_thermal_sensor_data = NULL, \
|
|
@@ -1985,6 +2375,8 @@ static struct ixgbe_mac_operations mac_ops_X550 = {
|
|
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
|
|
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
|
|
.get_bus_info = &ixgbe_get_bus_info_generic,
|
|
.get_bus_info = &ixgbe_get_bus_info_generic,
|
|
.setup_sfp = NULL,
|
|
.setup_sfp = NULL,
|
|
|
|
+ .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540,
|
|
|
|
+ .release_swfw_sync = &ixgbe_release_swfw_sync_X540,
|
|
};
|
|
};
|
|
|
|
|
|
static struct ixgbe_mac_operations mac_ops_X550EM_x = {
|
|
static struct ixgbe_mac_operations mac_ops_X550EM_x = {
|
|
@@ -1997,7 +2389,8 @@ static struct ixgbe_mac_operations mac_ops_X550EM_x = {
|
|
.get_link_capabilities = &ixgbe_get_link_capabilities_X550em,
|
|
.get_link_capabilities = &ixgbe_get_link_capabilities_X550em,
|
|
.get_bus_info = &ixgbe_get_bus_info_X550em,
|
|
.get_bus_info = &ixgbe_get_bus_info_X550em,
|
|
.setup_sfp = ixgbe_setup_sfp_modules_X550em,
|
|
.setup_sfp = ixgbe_setup_sfp_modules_X550em,
|
|
-
|
|
|
|
|
|
+ .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em,
|
|
|
|
+ .release_swfw_sync = &ixgbe_release_swfw_sync_X550em,
|
|
};
|
|
};
|
|
|
|
|
|
#define X550_COMMON_EEP \
|
|
#define X550_COMMON_EEP \
|