{
s32 status;
u16 value = 0;
+ u16 reg_slice, reg_val;
u8 retry;
for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) {
if (value != IXGBE_CS4227_GLOBAL_ID_VALUE)
return IXGBE_ERR_PHY;
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ /* If this is the first time after power-on, check the ucode.
+ * Otherwise, this will disrupt link on all ports. Because we
+ * can only do this the first time, we must check all ports,
+ * not just our own.
+ */
+ if (value != IXGBE_CS4227_SCRATCH_VALUE) {
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
+ reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+ status = ixgbe_write_cs4227(hw, reg_slice, reg_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ status = ixgbe_write_cs4227(hw, reg_slice, reg_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
+ reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+ status = ixgbe_write_cs4227(hw, reg_slice, reg_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ status = ixgbe_write_cs4227(hw, reg_slice, reg_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ msec_delay(10);
+ }
+
+ /* Verify that the ucode is operational on all ports. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
+ reg_val = 0xFFFF;
+ status = ixgbe_read_cs4227(hw, reg_slice, ®_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ if (reg_val != 0)
+ return IXGBE_ERR_PHY;
+
+ reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
+ reg_val = 0xFFFF;
+ status = ixgbe_read_cs4227(hw, reg_slice, ®_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ if (reg_val != 0)
+ return IXGBE_ERR_PHY;
+
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
+ reg_val = 0xFFFF;
+ status = ixgbe_read_cs4227(hw, reg_slice, ®_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ if (reg_val != 0)
+ return IXGBE_ERR_PHY;
+
+ reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
+ reg_val = 0xFFFF;
+ status = ixgbe_read_cs4227(hw, reg_slice, ®_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ if (reg_val != 0)
+ return IXGBE_ERR_PHY;
+
+ /* Set scratch indicating that the diagnostic was successful. */
status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
IXGBE_CS4227_SCRATCH_VALUE);
if (status != IXGBE_SUCCESS)
return status;
if (value != IXGBE_CS4227_SCRATCH_VALUE)
return IXGBE_ERR_PHY;
+
return IXGBE_SUCCESS;
}
link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX;
+ /* Must disable FEC when EEE is enabled. */
+ link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
+ IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
+
status = ixgbe_write_iosf_sb_reg_x550(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX);
+ /* Enable FEC when EEE is disabled. */
+ link_reg |= (IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
+ IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
+
status = ixgbe_write_iosf_sb_reg_x550(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
}
+/**
+ * ixgbe_iosf_wait - Wait for IOSF command completion
+ * @hw: pointer to hardware structure
+ * @ctrl: pointer to location to receive final IOSF control value
+ *
+ * Returns failing status on timeout
+ *
+ * Note: ctrl can be NULL if the IOSF control register value is not needed
+ **/
+STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
+{
+ u32 i, command = 0;
+
+ /* Check every 10 usec to see if the address cycle completed.
+ * The SB IOSF BUSY bit will clear when the operation is
+ * complete
+ */
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+ command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
+ if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
+ break;
+ usec_delay(10);
+ }
+ if (ctrl)
+ *ctrl = command;
+ if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
+ ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n");
+ return IXGBE_ERR_PHY;
+ }
+
+ return IXGBE_SUCCESS;
+}
+
/**
* ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the IOSF
* device
s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 data)
{
- u32 i, command, error;
+ u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
+ u32 command, error;
+ s32 ret;
+
+ ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
+ if (ret != IXGBE_SUCCESS)
+ return ret;
+
+ ret = ixgbe_iosf_wait(hw, NULL);
+ if (ret != IXGBE_SUCCESS)
+ goto out;
command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
(device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
/* Write IOSF data register */
IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
- /*
- * Check every 10 usec to see if the address cycle completed.
- * The SB IOSF BUSY bit will clear when the operation is
- * complete
- */
- for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
- usec_delay(10);
- command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
- if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
- break;
- }
+ ret = ixgbe_iosf_wait(hw, &command);
if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
ERROR_REPORT2(IXGBE_ERROR_POLLING,
"Failed to write, error %x\n", error);
- return IXGBE_ERR_PHY;
+ ret = IXGBE_ERR_PHY;
}
- if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
- ERROR_REPORT1(IXGBE_ERROR_POLLING, "Write timed out\n");
- return IXGBE_ERR_PHY;
- }
-
- return IXGBE_SUCCESS;
+out:
+ ixgbe_release_swfw_semaphore(hw, gssr);
+ return ret;
}
/**
s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 *data)
{
- u32 i, command, error;
+ u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
+ u32 command, error;
+ s32 ret;
+
+ ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
+ if (ret != IXGBE_SUCCESS)
+ return ret;
+
+ ret = ixgbe_iosf_wait(hw, NULL);
+ if (ret != IXGBE_SUCCESS)
+ goto out;
command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
(device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
/* Write IOSF control register */
IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
- /*
- * Check every 10 usec to see if the address cycle completed.
- * The SB IOSF BUSY bit will clear when the operation is
- * complete
- */
- for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
- usec_delay(10);
-
- command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
- if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
- break;
- }
+ ret = ixgbe_iosf_wait(hw, &command);
if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
ERROR_REPORT2(IXGBE_ERROR_POLLING,
"Failed to read, error %x\n", error);
- return IXGBE_ERR_PHY;
+ ret = IXGBE_ERR_PHY;
}
- if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
- ERROR_REPORT1(IXGBE_ERROR_POLLING, "Read timed out\n");
- return IXGBE_ERR_PHY;
- }
+ if (ret == IXGBE_SUCCESS)
+ *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
- *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
-
- return IXGBE_SUCCESS;
+out:
+ ixgbe_release_swfw_semaphore(hw, gssr);
+ return ret;
}
/**
return status;
reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
- reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
- IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
if (ret_val != IXGBE_SUCCESS)
return ret_val;
- /* Configure CS4227 for connection rate. */
+ /* Configure CS4227 for LINE connection rate then type. */
reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
reg_val);
- /* Configure CS4227 for connection type. */
reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
if (setup_linear)
reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
reg_val);
+ /* Configure CS4227 for HOST connection rate then type. */
reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
reg_val);
- /* Configure CS4227 for connection type. */
reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
if (setup_linear)
reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;