Commit 5d8a1c0f authored by Scott Feldman's avatar Scott Feldman Committed by Linus Torvalds

[e1000] h/w workaround for mis-fused parts

* h/w workaround: several 10's of thousands of 82547 controllers where
  mis-fused during manufacturing, resulting in PHY Tx amplitude to be
  too high and out of spec.  This workaround detects those parts, and
  compensates the Tx amplitude by subtracting ~80mV.
parent 32e9b144
...@@ -135,6 +135,41 @@ e1000_phy_init_script(struct e1000_hw *hw) ...@@ -135,6 +135,41 @@ e1000_phy_init_script(struct e1000_hw *hw)
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000);
e1000_write_phy_reg(hw,0x0000,0x3300); e1000_write_phy_reg(hw,0x0000,0x3300);
if(hw->mac_type == e1000_82547) {
uint16_t fused, fine, coarse;
/* Move to analog registers page */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_ANALOG_REGS_PAGE);
e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
} else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
(fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
(coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS,
IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
}
/* Return to first page of registers */
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_IEEE_REGS_PAGE);
}
} }
} }
......
...@@ -1668,6 +1668,7 @@ struct e1000_hw { ...@@ -1668,6 +1668,7 @@ struct e1000_hw {
#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
#define IGP01E1000_IEEE_REGS_PAGE 0x0000
/* IGP01E1000 Specific Registers */ /* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
...@@ -1690,6 +1691,7 @@ struct e1000_hw { ...@@ -1690,6 +1691,7 @@ struct e1000_hw {
* speed = 1000 Mbps. */ * speed = 1000 Mbps. */
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
...@@ -1980,6 +1982,22 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = ...@@ -1980,6 +1982,22 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed #define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed
* on Link-Up */ * on Link-Up */
#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ #define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */
/* IGP01E1000 Analog Register */
#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x0011
#define IGP01E1000_ANALOG_FUSE_STATUS 0x0010
#define IGP01E1000_ANALOG_FUSE_CONTROL 0x001C
#define IGP01E1000_ANALOG_FUSE_BYPASS 0x001E
#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000
#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80
#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070
#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100
#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002
#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040
#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010
#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
/* Bit definitions for valid PHY IDs. */ /* Bit definitions for valid PHY IDs. */
#define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_E_PHY_ID 0x01410C50
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment