summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000/e1000_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/e1000/e1000_phy.c')
-rw-r--r--sys/dev/e1000/e1000_phy.c1015
1 files changed, 557 insertions, 458 deletions
diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c
index ead72690..fd253ba 100644
--- a/sys/dev/e1000/e1000_phy.c
+++ b/sys/dev/e1000/e1000_phy.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2012, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -95,8 +95,8 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
phy->ops.write_reg_page = e1000_null_write_reg;
phy->ops.power_up = e1000_null_phy_generic;
phy->ops.power_down = e1000_null_phy_generic;
- phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
- phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
+ phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
+ phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
phy->ops.cfg_on_link_up = e1000_null_ops_generic;
}
@@ -151,6 +151,36 @@ s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_read_i2c_byte_null - No-op function, return 0
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @dev_addr: device address
+ * @data: data value read
+ *
+ **/
+s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ DEBUGFUNC("e1000_read_i2c_byte_null");
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_i2c_byte_null - No-op function, return 0
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @dev_addr: device address
+ * @data: data value to write
+ *
+ **/
+s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data)
+{
+ DEBUGFUNC("e1000_write_i2c_byte_null");
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_check_reset_block_generic - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -186,30 +216,30 @@ s32 e1000_get_phy_id(struct e1000_hw *hw)
DEBUGFUNC("e1000_get_phy_id");
- if (!(phy->ops.read_reg))
- goto out;
+ if (!phy->ops.read_reg)
+ return E1000_SUCCESS;
while (retry_count < 2) {
ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id = (u32)(phy_id << 16);
usec_delay(20);
ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
- goto out;
+ return E1000_SUCCESS;
retry_count++;
}
-out:
- return ret_val;
+
+ return E1000_SUCCESS;
}
/**
@@ -220,21 +250,18 @@ out:
**/
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_phy_reset_dsp_generic");
- if (!(hw->phy.ops.write_reg))
- goto out;
+ if (!hw->phy.ops.write_reg)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
+ return ret_val;
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
}
/**
@@ -250,7 +277,6 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
{
struct e1000_phy_info *phy = &hw->phy;
u32 i, mdic = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_phy_reg_mdic");
@@ -283,13 +309,11 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
}
if (!(mdic & E1000_MDIC_READY)) {
DEBUGOUT("MDI Read did not complete\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
if (mdic & E1000_MDIC_ERROR) {
DEBUGOUT("MDI Error\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
*data = (u16) mdic;
@@ -300,8 +324,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -316,7 +339,6 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
{
struct e1000_phy_info *phy = &hw->phy;
u32 i, mdic = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_phy_reg_mdic");
@@ -350,13 +372,11 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
}
if (!(mdic & E1000_MDIC_READY)) {
DEBUGOUT("MDI Write did not complete\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
if (mdic & E1000_MDIC_ERROR) {
DEBUGOUT("MDI Error\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
/*
@@ -366,8 +386,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -621,23 +640,22 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
**/
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_read_phy_reg_m88");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -652,23 +670,22 @@ out:
**/
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_write_phy_reg_m88");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -711,29 +728,25 @@ static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
DEBUGFUNC("__e1000_read_phy_reg_igp");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ if (!ret_val)
+ ret_val = e1000_read_phy_reg_mdic(hw,
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -784,30 +797,25 @@ static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
DEBUGFUNC("e1000_write_phy_reg_igp");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ if (!ret_val)
+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
+ offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -854,17 +862,18 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_read_kmrn_reg");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = E1000_SUCCESS;
+
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
@@ -880,8 +889,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -929,17 +937,18 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_kmrn_reg_generic");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = E1000_SUCCESS;
+
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
@@ -952,8 +961,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -985,6 +993,46 @@ s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_set_master_slave_mode - Setup PHY for Master/slave mode
+ * @hw: pointer to the HW structure
+ *
+ * Sets up Master/slave mode
+ **/
+static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Resolve Master/Slave mode */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* load defaults for future use */
+ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) : e1000_ms_auto;
+
+ switch (hw->phy.ms_type) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ /* fall-through */
+ default:
+ break;
+ }
+
+ return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+}
+
+/**
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @hw: pointer to the HW structure
*
@@ -1001,14 +1049,14 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
DEBUGOUT("Error resetting the PHY.\n");
- goto out;
+ return ret_val;
}
}
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
@@ -1017,39 +1065,35 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- /* Resolve Master/Slave mode */
- ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+ /* Set MDI/MDIX mode */
+ ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
if (ret_val)
- goto out;
-
- /* load defaults for future use */
- hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
- ((phy_data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) : e1000_ms_auto;
-
- switch (hw->phy.ms_type) {
- case e1000_ms_force_master:
- phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ return ret_val;
+ phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
+ /*
+ * Options:
+ * 0 - Auto (default)
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ */
+ switch (hw->phy.mdix) {
+ case 1:
break;
- case e1000_ms_force_slave:
- phy_data |= CR_1000T_MS_ENABLE;
- phy_data &= ~(CR_1000T_MS_VALUE);
+ case 2:
+ phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
break;
- case e1000_ms_auto:
- phy_data &= ~CR_1000T_MS_ENABLE;
+ case 0:
default:
+ phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
break;
}
-
- ret_val = hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+ ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
-out:
- return ret_val;
+ return e1000_set_master_slave_mode(hw);
}
/**
@@ -1071,7 +1115,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* For BM PHY this bit is downshift enable */
if (phy->type != e1000_phy_bm)
@@ -1111,16 +1155,32 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
* 1 - Enabled
*/
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if (phy->disable_polarity_correction == 1)
+ if (phy->disable_polarity_correction)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
/* Enable downshift on BM (disabled by default) */
- if (phy->type == e1000_phy_bm)
+ if (phy->type == e1000_phy_bm) {
+ /* For 82574/82583, first disable then enable downshift */
+ if (phy->id == BME1000_E_PHY_ID_R2) {
+ phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ /* Commit the changes. */
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ return ret_val;
+ }
+ }
+
phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+ }
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
if ((phy->type == e1000_phy_m88) &&
(phy->revision < E1000_REVISION_4) &&
@@ -1132,7 +1192,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
&phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= M88E1000_EPSCR_TX_CLK_25;
@@ -1151,33 +1211,33 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
phy_data);
if (ret_val)
- goto out;
+ return ret_val;
}
if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
/* Set PHY page 0, register 29 to 0x0003 */
ret_val = phy->ops.write_reg(hw, 29, 0x0003);
if (ret_val)
- goto out;
+ return ret_val;
/* Set PHY page 0, register 30 to 0x0000 */
ret_val = phy->ops.write_reg(hw, 30, 0x0000);
if (ret_val)
- goto out;
+ return ret_val;
}
/* Commit the changes. */
ret_val = phy->ops.commit(hw);
if (ret_val) {
DEBUGOUT("Error committing the PHY changes\n");
- goto out;
+ return ret_val;
}
if (phy->type == e1000_phy_82578) {
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
&phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* 82578 PHY - set the downshift count to 1x. */
phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
@@ -1185,11 +1245,16 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
phy_data);
if (ret_val)
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ if (phy->type == e1000_phy_i210) {
+ ret_val = e1000_set_master_slave_mode(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
+ return E1000_SUCCESS;
}
/**
@@ -1211,7 +1276,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* Options:
@@ -1250,7 +1315,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
* 1 - Enabled
*/
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if (phy->disable_polarity_correction == 1)
+ if (phy->disable_polarity_correction)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
/* Enable downshift and setting it to X6 */
@@ -1260,17 +1325,16 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* Commit the changes. */
ret_val = phy->ops.commit(hw);
if (ret_val) {
DEBUGOUT("Error committing the PHY changes\n");
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1292,7 +1356,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
DEBUGOUT("Error resetting the PHY.\n");
- goto out;
+ return ret_val;
}
/*
@@ -1310,7 +1374,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
if (ret_val) {
DEBUGOUT("Error Disabling LPLU D3\n");
- goto out;
+ return ret_val;
}
}
@@ -1319,13 +1383,13 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
if (ret_val) {
DEBUGOUT("Error Disabling LPLU D0\n");
- goto out;
+ return ret_val;
}
}
/* Configure mdi-mdix settings */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCR_AUTO_MDIX;
@@ -1343,7 +1407,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
}
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
if (ret_val)
- goto out;
+ return ret_val;
/* set auto-master slave resolution settings */
if (hw->mac.autoneg) {
@@ -1358,125 +1422,29 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
IGP01E1000_PHY_PORT_CONFIG,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
IGP01E1000_PHY_PORT_CONFIG,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* Set auto Master/Slave resolution process */
ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~CR_1000T_MS_ENABLE;
ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
if (ret_val)
- goto out;
+ return ret_val;
}
- ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
- if (ret_val)
- goto out;
-
- /* load defaults for future use */
- phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?
- ((data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy->ms_type) {
- case e1000_ms_force_master:
- data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- data |= CR_1000T_MS_ENABLE;
- data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
- if (ret_val)
- goto out;
+ ret_val = e1000_set_master_slave_mode(hw);
}
-out:
- return ret_val;
-}
-
-/**
- * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
- * @hw: pointer to the HW structure
- *
- * Performs initial bounds checking on autoneg advertisement parameter, then
- * configure to advertise the full capability. Setup the PHY to autoneg
- * and restart the negotiation process between the link partner. If
- * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
- **/
-s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
- struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val;
- u16 phy_ctrl;
-
- DEBUGFUNC("e1000_copper_link_autoneg");
-
- /*
- * Perform some bounds checking on the autoneg advertisement
- * parameter.
- */
- phy->autoneg_advertised &= phy->autoneg_mask;
-
- /*
- * If autoneg_advertised is zero, we assume it was not defaulted
- * by the calling code so we set to advertise full capability.
- */
- if (phy->autoneg_advertised == 0)
- phy->autoneg_advertised = phy->autoneg_mask;
-
- DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
- ret_val = e1000_phy_setup_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- goto out;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
-
- /*
- * Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
- if (ret_val)
- goto out;
-
- phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
- if (ret_val)
- goto out;
-
- /*
- * Does the user want to wait for Auto-Neg to complete here, or
- * check at a later time (for example, callback routine).
- */
- if (phy->autoneg_wait_to_complete) {
- ret_val = hw->mac.ops.wait_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error while waiting for autoneg to complete\n");
- goto out;
- }
- }
-
- hw->mac.get_link_status = TRUE;
-
-out:
return ret_val;
}
@@ -1503,14 +1471,14 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
/* Read the MII Auto-Neg Advertisement Register (Address 4). */
ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
/* Read the MII 1000Base-T Control Register (Address 9). */
ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
&mii_1000t_ctrl_reg);
if (ret_val)
- goto out;
+ return ret_val;
}
/*
@@ -1624,24 +1592,87 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
+ if (phy->autoneg_mask & ADVERTISE_1000_FULL)
ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
mii_1000t_ctrl_reg);
- if (ret_val)
- goto out;
+
+ return ret_val;
+}
+
+/**
+ * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
+ * @hw: pointer to the HW structure
+ *
+ * Performs initial bounds checking on autoneg advertisement parameter, then
+ * configure to advertise the full capability. Setup the PHY to autoneg
+ * and restart the negotiation process between the link partner. If
+ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+ **/
+s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_ctrl;
+
+ DEBUGFUNC("e1000_copper_link_autoneg");
+
+ /*
+ * Perform some bounds checking on the autoneg advertisement
+ * parameter.
+ */
+ phy->autoneg_advertised &= phy->autoneg_mask;
+
+ /*
+ * If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if (!phy->autoneg_advertised)
+ phy->autoneg_advertised = phy->autoneg_mask;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = e1000_phy_setup_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Setting up Auto-Negotiation\n");
+ return ret_val;
}
+ DEBUGOUT("Restarting Auto-Neg\n");
+
+ /*
+ * Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
+ if (ret_val)
+ return ret_val;
+
+ phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
+ if (ret_val)
+ return ret_val;
+
+ /*
+ * Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+ if (phy->autoneg_wait_to_complete) {
+ ret_val = hw->mac.ops.wait_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT("Error while waiting for autoneg to complete\n");
+ return ret_val;
+ }
+ }
+
+ hw->mac.get_link_status = TRUE;
-out:
return ret_val;
}
@@ -1668,7 +1699,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
*/
ret_val = e1000_copper_link_autoneg(hw);
if (ret_val)
- goto out;
+ return ret_val;
} else {
/*
* PHY will be set to 10H, 10F, 100H or 100F
@@ -1678,7 +1709,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
ret_val = hw->phy.ops.force_speed_duplex(hw);
if (ret_val) {
DEBUGOUT("Error Forcing Speed and Duplex\n");
- goto out;
+ return ret_val;
}
}
@@ -1689,17 +1720,16 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
&link);
if (ret_val)
- goto out;
+ return ret_val;
if (link) {
DEBUGOUT("Valid link established!!!\n");
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
ret_val = e1000_config_fc_after_link_up_generic(hw);
} else {
DEBUGOUT("Unable to establish link!!!\n");
}
-out:
return ret_val;
}
@@ -1722,13 +1752,13 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* Clear Auto-Crossover to force MDI manually. IGP requires MDI
@@ -1736,14 +1766,14 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
*/
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("IGP PSCR: %X\n", phy_data);
@@ -1755,7 +1785,7 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
@@ -1763,11 +1793,8 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
/* Try once more */
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
- if (ret_val)
- goto out;
}
-out:
return ret_val;
}
@@ -1796,29 +1823,29 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
*/
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* Reset the phy to commit changes. */
ret_val = hw->phy.ops.commit(hw);
if (ret_val)
- goto out;
+ return ret_val;
if (phy->autoneg_wait_to_complete) {
DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
@@ -1826,13 +1853,25 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
- if (hw->phy.type != e1000_phy_m88 ||
- hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1340M_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID) {
+ bool reset_dsp = TRUE;
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1340M_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case I210_I_PHY_ID:
+ reset_dsp = FALSE;
+ break;
+ default:
+ if (hw->phy.type != e1000_phy_m88)
+ reset_dsp = FALSE;
+ break;
+ }
+
+ if (!reset_dsp) {
DEBUGOUT("Link taking longer than expected.\n");
} else {
/*
@@ -1843,10 +1882,10 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
M88E1000_PHY_PAGE_SELECT,
0x001d);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_phy_reset_dsp_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
}
@@ -1854,18 +1893,21 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (hw->phy.type != e1000_phy_m88 ||
- hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1340M_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID)
- goto out;
+ if (hw->phy.type != e1000_phy_m88)
+ return E1000_SUCCESS;
+ if (hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1340M_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
+ return E1000_SUCCESS;
+ if (hw->phy.id == I210_I_PHY_ID)
+ return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* Resetting the phy means we need to re-force TX_CLK in the
@@ -1875,7 +1917,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
phy_data |= M88E1000_EPSCR_TX_CLK_25;
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* In addition, we must re-enable CRS on Tx for both half and full
@@ -1883,12 +1925,11 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
*/
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-out:
return ret_val;
}
@@ -1911,25 +1952,25 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
/* Disable MDI-X support for 10/100 */
ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IFE_PMC_AUTO_MDIX;
data &= ~IFE_PMC_FORCE_MDIX;
ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("IFE PMC: %X\n", data);
@@ -1941,7 +1982,7 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
@@ -1950,11 +1991,10 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2014,7 +2054,7 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
DEBUGOUT("Forcing 10mb\n");
}
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
}
@@ -2036,24 +2076,24 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_set_d3_lplu_state_generic");
- if (!(hw->phy.ops.read_reg))
- goto out;
+ if (!hw->phy.ops.read_reg)
+ return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
if (ret_val)
- goto out;
+ return ret_val;
if (!active) {
data &= ~IGP02E1000_PM_D3_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
@@ -2065,27 +2105,27 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
IGP01E1000_PHY_PORT_CONFIG,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
IGP01E1000_PHY_PORT_CONFIG,
data);
if (ret_val)
- goto out;
+ return ret_val;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
IGP01E1000_PHY_PORT_CONFIG,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
IGP01E1000_PHY_PORT_CONFIG,
data);
if (ret_val)
- goto out;
+ return ret_val;
}
} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
(phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
@@ -2094,20 +2134,19 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
data);
}
-out:
return ret_val;
}
@@ -2128,6 +2167,7 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_downshift_generic");
switch (phy->type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
case e1000_phy_gg82563:
case e1000_phy_bm:
@@ -2144,16 +2184,14 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
default:
/* speed downshift not supported */
phy->speed_downgraded = FALSE;
- ret_val = E1000_SUCCESS;
- goto out;
+ return E1000_SUCCESS;
}
ret_val = phy->ops.read_reg(hw, offset, &phy_data);
if (!ret_val)
- phy->speed_downgraded = (phy_data & mask) ? TRUE : FALSE;
+ phy->speed_downgraded = !!(phy_data & mask);
-out:
return ret_val;
}
@@ -2206,7 +2244,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
*/
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
@@ -2228,7 +2266,6 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
-out:
return ret_val;
}
@@ -2281,7 +2318,7 @@ s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_wait_autoneg_generic");
- if (!(hw->phy.ops.read_reg))
+ if (!hw->phy.ops.read_reg)
return E1000_SUCCESS;
/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
@@ -2321,7 +2358,7 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
DEBUGFUNC("e1000_phy_has_link_generic");
- if (!(hw->phy.ops.read_reg))
+ if (!hw->phy.ops.read_reg)
return E1000_SUCCESS;
for (i = 0; i < iterations; i++) {
@@ -2349,7 +2386,7 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
usec_delay(usec_interval);
}
- *success = (i < iterations) ? TRUE : FALSE;
+ *success = (i < iterations);
return ret_val;
}
@@ -2379,22 +2416,20 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+ return -E1000_ERR_PHY;
phy->min_cable_length = e1000_m88_cable_length_table[index];
phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
@@ -2406,28 +2441,49 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
DEBUGFUNC("e1000_get_cable_length_m88_gen2");
switch (hw->phy.id) {
+ case I210_I_PHY_ID:
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ return ret_val;
+
+ is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+ break;
case M88E1340M_E_PHY_ID:
case I347AT4_E_PHY_ID:
/* Remember the original page select and set it to 7 */
ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
&default_page);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
if (ret_val)
- goto out;
+ return ret_val;
/* Get cable length from PHY Cable Diagnostics Control Reg */
ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
&phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* Check if the unit of cable length is meters or cm */
ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
if (ret_val)
- goto out;
+ return ret_val;
is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
@@ -2440,30 +2496,30 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
default_page);
if (ret_val)
- goto out;
+ return ret_val;
break;
+
case M88E1112_E_PHY_ID:
/* Remember the original page select and set it to 5 */
ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
&default_page);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
&phy_data);
if (ret_val)
- goto out;
+ return ret_val;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+ return -E1000_ERR_PHY;
phy->min_cable_length = e1000_m88_cable_length_table[index];
phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
@@ -2475,15 +2531,13 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
default_page);
if (ret_val)
- goto out;
+ return ret_val;
break;
default:
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
-out:
return ret_val;
}
@@ -2501,7 +2555,7 @@ out:
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 phy_data, i, agc_value = 0;
u16 cur_agc_index, max_agc_index = 0;
u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
@@ -2518,7 +2572,7 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/*
* Getting bits 15:9, which represent the combination of
@@ -2531,10 +2585,8 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
/* Array index bound check. */
if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
- (cur_agc_index == 0)) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+ (cur_agc_index == 0))
+ return -E1000_ERR_PHY;
/* Remove min & max AGC values from calculation. */
if (e1000_igp_2_cable_length_table[min_agc_index] >
@@ -2558,8 +2610,7 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2583,45 +2634,43 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
if (phy->media_type != e1000_media_type_copper) {
DEBUGOUT("Phy info is only valid for copper media\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL)
- ? TRUE : FALSE;
+ phy->polarity_correction = !!(phy_data &
+ M88E1000_PSCR_POLARITY_REVERSAL);
ret_val = e1000_check_polarity_m88(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
? e1000_1000t_rx_status_ok
@@ -2637,7 +2686,6 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
return ret_val;
}
@@ -2661,35 +2709,34 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
phy->polarity_correction = TRUE;
ret_val = e1000_check_polarity_igp(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
ret_val = phy->ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
? e1000_1000t_rx_status_ok
@@ -2704,7 +2751,6 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
return ret_val;
}
@@ -2725,24 +2771,22 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
if (ret_val)
- goto out;
- phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
- ? FALSE : TRUE;
+ return ret_val;
+ phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
if (phy->polarity_correction) {
ret_val = e1000_check_polarity_ife(hw);
if (ret_val)
- goto out;
+ return ret_val;
} else {
/* Polarity is forced */
phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
@@ -2752,17 +2796,16 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
/* The following parameters are undefined for 10/100 operation. */
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
phy->local_rx = e1000_1000t_rx_status_undefined;
phy->remote_rx = e1000_1000t_rx_status_undefined;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2774,26 +2817,25 @@ out:
**/
s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 phy_ctrl;
DEBUGFUNC("e1000_phy_sw_reset_generic");
- if (!(hw->phy.ops.read_reg))
- goto out;
+ if (!hw->phy.ops.read_reg)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
if (ret_val)
- goto out;
+ return ret_val;
phy_ctrl |= MII_CR_RESET;
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
if (ret_val)
- goto out;
+ return ret_val;
usec_delay(1);
-out:
return ret_val;
}
@@ -2809,20 +2851,20 @@ out:
s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u32 ctrl;
DEBUGFUNC("e1000_phy_hw_reset_generic");
- ret_val = phy->ops.check_reset_block(hw);
- if (ret_val) {
- ret_val = E1000_SUCCESS;
- goto out;
+ if (phy->ops.check_reset_block) {
+ ret_val = phy->ops.check_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
}
ret_val = phy->ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ctrl = E1000_READ_REG(hw, E1000_CTRL);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
@@ -2837,10 +2879,7 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
phy->ops.release(hw);
- ret_val = phy->ops.get_cfg_done(hw);
-
-out:
- return ret_val;
+ return phy->ops.get_cfg_done(hw);
}
/**
@@ -2994,6 +3033,9 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
case I82580_I_PHY_ID:
phy_type = e1000_phy_82580;
break;
+ case I210_I_PHY_ID:
+ phy_type = e1000_phy_i210;
+ break;
default:
phy_type = e1000_phy_unknown;
break;
@@ -3011,7 +3053,6 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
**/
s32 e1000_determine_phy_address(struct e1000_hw *hw)
{
- s32 ret_val = -E1000_ERR_PHY_TYPE;
u32 phy_addr = 0;
u32 i;
enum e1000_phy_type phy_type = e1000_phy_unknown;
@@ -3030,17 +3071,15 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
* If phy_type is valid, break - we found our
* PHY address
*/
- if (phy_type != e1000_phy_unknown) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (phy_type != e1000_phy_unknown)
+ return E1000_SUCCESS;
+
msec_delay(1);
i++;
} while (i < 10);
}
-out:
- return ret_val;
+ return -E1000_ERR_PHY_TYPE;
}
/**
@@ -3083,7 +3122,7 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
FALSE, FALSE);
- goto out;
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -3108,13 +3147,13 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -3144,7 +3183,7 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
TRUE, FALSE);
- goto out;
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -3169,12 +3208,12 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -3204,7 +3243,7 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
TRUE, FALSE);
- goto out;
+ goto release;
}
hw->phy.addr = 1;
@@ -3216,12 +3255,12 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -3250,7 +3289,7 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
FALSE, FALSE);
- goto out;
+ goto release;
}
hw->phy.addr = 1;
@@ -3261,13 +3300,13 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -3287,10 +3326,8 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
- if (!phy_reg) {
- ret_val = -E1000_ERR_PARAM;
- goto out;
- }
+ if (!phy_reg)
+ return -E1000_ERR_PARAM;
/* All page select, port ctrl and wakeup registers use phy address 1 */
hw->phy.addr = 1;
@@ -3299,14 +3336,14 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
if (ret_val) {
DEBUGOUT("Could not set Port Control page\n");
- goto out;
+ return ret_val;
}
ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
if (ret_val) {
DEBUGOUT2("Could not read PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
- goto out;
+ return ret_val;
}
/*
@@ -3321,15 +3358,14 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
if (ret_val) {
DEBUGOUT2("Could not write PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
- goto out;
+ return ret_val;
}
- /* Select Host Wakeup Registers page */
- ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
-
- /* caller now able to write registers on the Wakeup registers page */
-out:
- return ret_val;
+ /*
+ * Select Host Wakeup Registers page - caller now able to write
+ * registers on the Wakeup registers page
+ */
+ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
}
/**
@@ -3356,7 +3392,7 @@ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
if (ret_val) {
DEBUGOUT("Could not set Port Control page\n");
- goto out;
+ return ret_val;
}
/* Restore 769.17 to its original value */
@@ -3364,7 +3400,7 @@ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
if (ret_val)
DEBUGOUT2("Could not restore PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
-out:
+
return ret_val;
}
@@ -3413,7 +3449,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
if (ret_val) {
DEBUGOUT("Could not enable PHY wakeup reg access\n");
- goto out;
+ return ret_val;
}
}
@@ -3423,7 +3459,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
if (ret_val) {
DEBUGOUT1("Could not write address opcode to page %d\n", page);
- goto out;
+ return ret_val;
}
if (read) {
@@ -3438,13 +3474,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
if (ret_val) {
DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
- goto out;
+ return ret_val;
}
if (!page_set)
ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-out:
return ret_val;
}
@@ -3459,10 +3494,16 @@ out:
void e1000_power_up_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg &= ~GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}
@@ -3477,10 +3518,17 @@ void e1000_power_up_phy_copper(struct e1000_hw *hw)
void e1000_power_down_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
+ /* i210 Phy requires an additional bit for power up/down */
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg |= GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
msec_delay(1);
}
@@ -3646,7 +3694,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
if ((hw->phy.type == e1000_phy_82578) &&
(hw->phy.revision >= 1) &&
(hw->phy.addr == 2) &&
- ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
+ !(MAX_PHY_REG_ADDRESS & reg) &&
(data & (1 << 11))) {
u16 data2 = 0x7EFF;
ret_val = e1000_access_phy_debug_regs_hv(hw,
@@ -3770,7 +3818,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
if (ret_val) {
DEBUGOUT("Could not write the Address Offset port register\n");
- goto out;
+ return ret_val;
}
/* Read or write the data value next */
@@ -3779,12 +3827,9 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
else
ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
- if (ret_val) {
+ if (ret_val)
DEBUGOUT("Could not access the Data port register\n");
- goto out;
- }
-out:
return ret_val;
}
@@ -3807,24 +3852,24 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
DEBUGFUNC("e1000_link_stall_workaround_hv");
if (hw->phy.type != e1000_phy_82578)
- goto out;
+ return E1000_SUCCESS;
/* Do not apply workaround if in PHY loopback bit 14 set */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
if (data & PHY_CONTROL_LB)
- goto out;
+ return E1000_SUCCESS;
/* check if link is up and at 1Gbps */
ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK;
if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_1000))
- goto out;
+ return E1000_SUCCESS;
msec_delay(200);
@@ -3833,13 +3878,10 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
HV_MUX_DATA_CTRL_GEN_TO_MAC |
HV_MUX_DATA_CTRL_FORCE_SPEED);
if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
- HV_MUX_DATA_CTRL_GEN_TO_MAC);
+ return ret_val;
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
+ HV_MUX_DATA_CTRL_GEN_TO_MAC);
}
/**
@@ -3885,13 +3927,13 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
usec_delay(1);
@@ -3901,7 +3943,7 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
@@ -3909,11 +3951,8 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
/* Try once more */
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
- if (ret_val)
- goto out;
}
-out:
return ret_val;
}
@@ -3937,35 +3976,34 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
phy->polarity_correction = TRUE;
ret_val = e1000_check_polarity_82577(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
I82577_PHY_STATUS2_SPEED_1000MBPS) {
ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
? e1000_1000t_rx_status_ok
@@ -3980,8 +4018,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -4001,7 +4038,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
I82577_DSTATUS_CABLE_LENGTH_SHIFT;
@@ -4011,6 +4048,68 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
phy->cable_length = length;
-out:
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_phy_reg_gs40g - Write GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ DEBUGFUNC("e1000_write_phy_reg_gs40g");
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
+/**
+ * e1000_read_phy_reg_gs40g - Read GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to read to
+ * upper half is page to use.
+ * @data: data to read at register offset
+ *
+ * Acquires semaphore, if necessary, then reads the data in the PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ DEBUGFUNC("e1000_read_phy_reg_gs40g");
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
return ret_val;
}
OpenPOWER on IntegriCloud