Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214751
b: refs/heads/master
c: 308fb39
h: refs/heads/master
i:
  214749: 24d458b
  214747: 08daaa1
  214743: afc69ce
  214735: 253edfd
  214719: d701dc2
v: v3
  • Loading branch information
Joseph Gasparakis authored and David S. Miller committed Sep 23, 2010
1 parent 48029d3 commit 5297b90
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d85b9004bc2047d79248b167cc151ff9a4b509c3
refs/heads/master: 308fb39a860c816be8741fe783ae7c64e9c1af5d
18 changes: 16 additions & 2 deletions trunk/drivers/net/igb/e1000_82575.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_82580_SERDES:
case E1000_DEV_ID_82580_SGMII:
case E1000_DEV_ID_82580_COPPER_DUAL:
case E1000_DEV_ID_DH89XXCC_SGMII:
case E1000_DEV_ID_DH89XXCC_SERDES:
mac->type = e1000_82580;
break;
case E1000_DEV_ID_I350_COPPER:
Expand Down Expand Up @@ -282,10 +284,18 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)

/* Verify phy id and set remaining function pointers */
switch (phy->id) {
case I347AT4_E_PHY_ID:
case M88E1112_E_PHY_ID:
case M88E1111_I_PHY_ID:
phy->type = e1000_phy_m88;
phy->ops.get_phy_info = igb_get_phy_info_m88;
phy->ops.get_cable_length = igb_get_cable_length_m88;

if (phy->id == I347AT4_E_PHY_ID ||
phy->id == M88E1112_E_PHY_ID)
phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
else
phy->ops.get_cable_length = igb_get_cable_length_m88;

phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
Expand Down Expand Up @@ -1058,7 +1068,11 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
}
switch (hw->phy.type) {
case e1000_phy_m88:
ret_val = igb_copper_link_setup_m88(hw);
if (hw->phy.id == I347AT4_E_PHY_ID ||
hw->phy.id == M88E1112_E_PHY_ID)
ret_val = igb_copper_link_setup_m88_gen2(hw);
else
ret_val = igb_copper_link_setup_m88(hw);
break;
case e1000_phy_igp_3:
ret_val = igb_copper_link_setup_igp(hw);
Expand Down
31 changes: 31 additions & 0 deletions trunk/drivers/net/igb/e1000_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,8 @@
* E = External
*/
#define M88E1111_I_PHY_ID 0x01410CC0
#define M88E1112_E_PHY_ID 0x01410C90
#define I347AT4_E_PHY_ID 0x01410DC0
#define IGP03E1000_E_PHY_ID 0x02A80390
#define I82580_I_PHY_ID 0x015403A0
#define I350_I_PHY_ID 0x015403B0
Expand Down Expand Up @@ -702,6 +704,35 @@
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */

/* Intel i347-AT4 Registers */

#define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */
#define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */
#define I347AT4_PAGE_SELECT 0x16

/* i347-AT4 Extended PHY Specific Control Register */

/*
* Number of times we will attempt to autonegotiate before downshifting if we
* are the master
*/
#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
#define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000
#define I347AT4_PSCR_DOWNSHIFT_1X 0x0000
#define I347AT4_PSCR_DOWNSHIFT_2X 0x1000
#define I347AT4_PSCR_DOWNSHIFT_3X 0x2000
#define I347AT4_PSCR_DOWNSHIFT_4X 0x3000
#define I347AT4_PSCR_DOWNSHIFT_5X 0x4000
#define I347AT4_PSCR_DOWNSHIFT_6X 0x5000
#define I347AT4_PSCR_DOWNSHIFT_7X 0x6000
#define I347AT4_PSCR_DOWNSHIFT_8X 0x7000

/* i347-AT4 PHY Cable Diagnostics Control */
#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */

/* Marvell 1112 only registers */
#define M88E1112_VCT_DSP_DISTANCE 0x001A

/* M88EC018 Rev 2 specific DownShift settings */
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/igb/e1000_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct e1000_hw;
#define E1000_DEV_ID_82580_SERDES 0x1510
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436
#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438
#define E1000_DEV_ID_I350_COPPER 0x1521
#define E1000_DEV_ID_I350_FIBER 0x1522
#define E1000_DEV_ID_I350_SERDES 0x1523
Expand Down
206 changes: 194 additions & 12 deletions trunk/drivers/net/igb/e1000_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,89 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw)
return ret_val;
}

/**
* igb_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
* @hw: pointer to the HW structure
*
* Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
* Also enables and sets the downshift parameters.
**/
s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u16 phy_data;

if (phy->reset_disable) {
ret_val = 0;
goto out;
}

/* 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;

/*
* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
* 1 - MDI mode
* 2 - MDI-X mode
* 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
*/
phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;

switch (phy->mdix) {
case 1:
phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
break;
case 2:
phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
break;
case 3:
/* M88E1112 does not support this mode) */
if (phy->id != M88E1112_E_PHY_ID) {
phy_data |= M88E1000_PSCR_AUTO_X_1000T;
break;
}
case 0:
default:
phy_data |= M88E1000_PSCR_AUTO_X_MODE;
break;
}

/*
* Options:
* disable_polarity_correction = 0 (default)
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
* 1 - Enabled
*/
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
if (phy->disable_polarity_correction == 1)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;

/* Enable downshift and setting it to X6 */
phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;

ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
goto out;

/* Commit the changes. */
ret_val = igb_phy_sw_reset(hw);
if (ret_val) {
hw_dbg("Error committing the PHY changes\n");
goto out;
}

out:
return ret_val;
}

/**
* igb_copper_link_setup_igp - Setup igp PHY's for copper link
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -1124,18 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;

if (!link) {
/*
* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = phy->ops.write_reg(hw,
M88E1000_PHY_PAGE_SELECT,
0x001d);
if (ret_val)
goto out;
ret_val = igb_phy_reset_dsp(hw);
if (ret_val)
goto out;
if (hw->phy.type != e1000_phy_m88 ||
hw->phy.id == I347AT4_E_PHY_ID ||
hw->phy.id == M88E1112_E_PHY_ID) {
hw_dbg("Link taking longer than expected.\n");
} else {

/*
* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = phy->ops.write_reg(hw,
M88E1000_PHY_PAGE_SELECT,
0x001d);
if (ret_val)
goto out;
ret_val = igb_phy_reset_dsp(hw);
if (ret_val)
goto out;
}
}

/* Try once more */
Expand All @@ -1145,6 +1235,11 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
}

if (hw->phy.type != e1000_phy_m88 ||
hw->phy.id == I347AT4_E_PHY_ID ||
hw->phy.id == M88E1112_E_PHY_ID)
goto out;

ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
goto out;
Expand Down Expand Up @@ -1557,6 +1652,93 @@ s32 igb_get_cable_length_m88(struct e1000_hw *hw)
return ret_val;
}

s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u16 phy_data, phy_data2, index, default_page, is_cm;

switch (hw->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;

ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
if (ret_val)
goto out;

/* 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;

/* 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;

is_cm = !(phy_data & 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);

/* Reset the page selec to its original value */
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
default_page);
if (ret_val)
goto out;
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;

ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
if (ret_val)
goto out;

ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
&phy_data);
if (ret_val)
goto out;

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;
}

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;

/* Reset the page select to its original value */
ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
default_page);
if (ret_val)
goto out;

break;
default:
ret_val = -E1000_ERR_PHY;
goto out;
}

out:
return ret_val;
}

/**
* igb_get_cable_length_igp_2 - Determine cable length for igp2 PHY
* @hw: pointer to the HW structure
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/igb/e1000_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ s32 igb_check_downshift(struct e1000_hw *hw);
s32 igb_check_reset_block(struct e1000_hw *hw);
s32 igb_copper_link_setup_igp(struct e1000_hw *hw);
s32 igb_copper_link_setup_m88(struct e1000_hw *hw);
s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
s32 igb_get_cable_length_m88(struct e1000_hw *hw);
s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
s32 igb_get_cable_length_igp_2(struct e1000_hw *hw);
s32 igb_get_phy_id(struct e1000_hw *hw);
s32 igb_get_phy_info_igp(struct e1000_hw *hw);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/igb/igb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 },
Expand Down

0 comments on commit 5297b90

Please sign in to comment.