summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/e1000/e1000_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/e1000/e1000_hw.c')
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c406
1 files changed, 329 insertions, 77 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index 36ee76bf4cb..99dfec3b412 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -30,6 +30,8 @@
* Shared functions for accessing and configuring the MAC
*/
+#include "e1000_oem_phy.h"
+#include "e1000_hw.h"
#include "e1000.h"
static s32 e1000_check_downshift(struct e1000_hw *hw);
@@ -37,21 +39,16 @@ static s32 e1000_check_polarity(struct e1000_hw *hw,
e1000_rev_polarity *polarity);
static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
static void e1000_clear_vfta(struct e1000_hw *hw);
-static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
- bool link_up);
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
-static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
u16 *max_length);
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
static s32 e1000_id_led_init(struct e1000_hw *hw);
static void e1000_init_rx_addrs(struct e1000_hw *hw);
static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info);
static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info);
-static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
static s32 e1000_set_phy_type(struct e1000_hw *hw);
@@ -59,7 +56,7 @@ static void e1000_phy_init_script(struct e1000_hw *hw);
static s32 e1000_setup_copper_link(struct e1000_hw *hw);
static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
+s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
@@ -324,6 +321,20 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_ICP_5040:
+ case E1000_DEV_ID_ICP_5041:
+ case E1000_DEV_ID_ICP_5042:
+ case E1000_DEV_ID_ICP_5043:
+ case E1000_DEV_ID_ICP_5044:
+ case E1000_DEV_ID_ICP_5045:
+ case E1000_DEV_ID_ICP_5046:
+ case E1000_DEV_ID_ICP_5047:
+ case E1000_DEV_ID_ICP_5048:
+ case E1000_DEV_ID_ICP_5049:
+ case E1000_DEV_ID_ICP_504A:
+ case E1000_DEV_ID_ICP_504B:
+ hw->mac_type = e1000_icp_xxxx;
+ break;
case E1000_DEV_ID_INTEL_CE4100_GBE:
hw->mac_type = e1000_ce4100;
break;
@@ -365,16 +376,29 @@ void e1000_set_media_type(struct e1000_hw *hw)
e_dbg("e1000_set_media_type");
- if (hw->mac_type != e1000_82543) {
+ if (hw->mac_type != e1000_82543)
/* tbi_compatibility is only valid on 82543 */
hw->tbi_compatibility_en = false;
- }
switch (hw->device_id) {
case E1000_DEV_ID_82545GM_SERDES:
case E1000_DEV_ID_82546GB_SERDES:
hw->media_type = e1000_media_type_internal_serdes;
break;
+ case E1000_DEV_ID_ICP_5040:
+ case E1000_DEV_ID_ICP_5041:
+ case E1000_DEV_ID_ICP_5042:
+ case E1000_DEV_ID_ICP_5043:
+ case E1000_DEV_ID_ICP_5044:
+ case E1000_DEV_ID_ICP_5045:
+ case E1000_DEV_ID_ICP_5046:
+ case E1000_DEV_ID_ICP_5047:
+ case E1000_DEV_ID_ICP_5048:
+ case E1000_DEV_ID_ICP_5049:
+ case E1000_DEV_ID_ICP_504A:
+ case E1000_DEV_ID_ICP_504B:
+ hw->media_type = e1000_media_type_oem;
+ break;
default:
switch (hw->mac_type) {
case e1000_82542_rev2_0:
@@ -450,6 +474,13 @@ s32 e1000_reset_hw(struct e1000_hw *hw)
msleep(5);
}
+ if (hw->phy_type == e1000_phy_oem
+ && e1000_oem_phy_needs_reset_with_mac(hw)) {
+ ret_val = e1000_oem_phy_hw_reset(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
@@ -513,7 +544,7 @@ s32 e1000_reset_hw(struct e1000_hw *hw)
}
/* Disable HW ARPs on ASF enabled adapters */
- if (hw->mac_type >= e1000_82540) {
+ if (hw->mac_type >= e1000_82540 && hw->mac_type != e1000_icp_xxxx) {
manc = er32(MANC);
manc &= ~(E1000_MANC_ARP_EN);
ew32(MANC, manc);
@@ -529,6 +560,12 @@ s32 e1000_reset_hw(struct e1000_hw *hw)
ew32(LEDCTL, led_ctrl);
}
+ /* default configure the oem phy */
+ if (hw->phy_type == e1000_phy_oem
+ && e1000_oem_phy_needs_reset_with_mac(hw)) {
+ e1000_oem_phy_init_script(hw);
+ }
+
/* Clear interrupt mask to stop board from generating interrupts */
e_dbg("Masking off all interrupts\n");
ew32(IMC, 0xffffffff);
@@ -722,9 +759,18 @@ s32 e1000_setup_link(struct e1000_hw *hw)
u32 ctrl_ext;
s32 ret_val;
u16 eeprom_data;
+ u16 eeprom_control2_reg_offset = 0;
e_dbg("e1000_setup_link");
+ /* for icp_xxxx style controllers, the init control 2 and 3 are packed
+ * into a single word, with the top byte being occupied by control 2
+ */
+ eeprom_control2_reg_offset =
+ hw->mac_type != e1000_icp_xxxx
+ ? EEPROM_INIT_CONTROL2_REG
+ : EEPROM_INIT_CONTROL3_ICP_xxxx(e1000_oem_get_phy_dev_number(hw));
+
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -734,7 +780,7 @@ s32 e1000_setup_link(struct e1000_hw *hw)
* be initialized based on a value in the EEPROM.
*/
if (hw->fc == E1000_FC_DEFAULT) {
- ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+ ret_val = e1000_read_eeprom(hw, eeprom_control2_reg_offset,
1, &eeprom_data);
if (ret_val) {
e_dbg("EEPROM Read Error\n");
@@ -783,8 +829,19 @@ s32 e1000_setup_link(struct e1000_hw *hw)
}
/* Call the necessary subroutine to configure the link. */
- ret_val = (hw->media_type == e1000_media_type_copper) ?
- e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
+ switch (hw->media_type) {
+ case e1000_media_type_copper:
+ ret_val = e1000_setup_copper_link(hw);
+ break;
+
+ case e1000_media_type_oem:
+ ret_val = e1000_oem_setup_link(hw);
+ break;
+
+ default:
+ ret_val = e1000_setup_fiber_serdes_link(hw);
+ break;
+ }
/* Initialize the flow control address, type, and PAUSE timer
* registers to their default values. This is done even if flow
@@ -874,12 +931,12 @@ static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* configure the two flow control enable bits in the CTRL register.
*
* The possible values of the "fc" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames, but
- * not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but we do
- * not support receiving pause frames).
- * 3: Both Rx and TX flow control (symmetric) are enabled.
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames, but
+ * not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but we
+ * do not support receiving pause frames).
+ * 3: Both Rx and TX flow control (symmetric) are enabled.
*/
switch (hw->fc) {
case E1000_FC_NONE:
@@ -937,9 +994,16 @@ static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
e_dbg("Looking for Link\n");
for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
msleep(10);
- status = er32(STATUS);
- if (status & E1000_STATUS_LU)
- break;
+ if (hw->mac_type != e1000_icp_xxxx) {
+ status = er32(STATUS);
+ if (status & E1000_STATUS_LU)
+ break;
+ } else {
+ int isUp = 0;
+ if (e1000_oem_phy_is_link_up(hw, &isUp) ==
+ E1000_SUCCESS && isUp)
+ break;
+ }
}
if (i == (LINK_UP_TIMEOUT / 10)) {
e_dbg("Never got a valid link from auto-neg!!!\n");
@@ -1343,7 +1407,7 @@ static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
* Setup auto-negotiation and flow control advertisements,
* and then perform auto-negotiation.
*/
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1408,19 +1472,20 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
*
* Config the MAC and the PHY after link is up.
* 1) Set up the MAC to the current PHY speed/duplex
- * if we are on 82543. If we
- * are on newer silicon, we only need to configure
- * collision distance in the Transmit Control Register.
+ * if we are on 82543. If we
+ * are on newer silicon, we only need to configure
+ * collision distance in the Transmit Control Register.
* 2) Set up flow control on the MAC to that established with
- * the link partner.
+ * the link partner.
* 3) Config DSP to improve Gigabit link quality for some PHY revisions.
*/
-static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
+s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
{
s32 ret_val;
e_dbg("e1000_copper_link_postconfig");
- if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
+ if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100) &&
+ (hw->mac_type != e1000_icp_xxxx)) {
e1000_config_collision_dist(hw);
} else {
ret_val = e1000_config_mac_to_phy(hw);
@@ -1442,6 +1507,12 @@ static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
e_dbg("Error Configuring DSP after link up\n");
return ret_val;
}
+ } else if (hw->phy_type == e1000_phy_oem) {
+ ret_val = e1000_oem_config_dsp_after_link_change(hw, true);
+ if (ret_val) {
+ e_dbg("Error Configuring OEM PHY DSP after link up\n");
+ return ret_val;
+ }
}
return E1000_SUCCESS;
@@ -1593,10 +1664,9 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
}
/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
- if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
+ if (hw->autoneg_advertised & ADVERTISE_1000_HALF)
e_dbg
("Advertise 1000mb Half duplex requested, request denied!\n");
- }
/* Do we want to advertise 1000 Mb Full Duplex? */
if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
@@ -1681,7 +1751,7 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
*
* Force PHY speed and duplex settings to hw->forced_speed_duplex
*/
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -1689,6 +1759,7 @@ static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
u16 mii_status_reg;
u16 phy_data;
u16 i;
+ bool resetPhy = false;
e_dbg("e1000_phy_force_speed_duplex");
@@ -1776,8 +1847,17 @@ static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
mii_ctrl_reg |= MII_CR_RESET;
/* Disable MDI-X support for 10/100 */
+ } else if (hw->phy_type == e1000_phy_oem) {
+ ret_val = e1000_oem_force_mdi(hw, (int *)&resetPhy);
+ if (ret_val)
+ return ret_val;
+ if (resetPhy) {
+ ret_val = e1000_oem_phy_hw_reset(hw);
+ if (ret_val)
+ return ret_val;
+ }
} else {
- /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
+ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed or duplex are forced.
*/
ret_val =
@@ -1833,7 +1913,8 @@ static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
msleep(100);
}
if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
- /* We didn't get link. Reset the DSP and wait again for link. */
+ /* We didn't get link. Reset the DSP and wait again
+ * for link. */
ret_val = e1000_phy_reset_dsp(hw);
if (ret_val) {
e_dbg("Error Resetting PHY DSP\n");
@@ -1878,8 +1959,9 @@ static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /* In addition, because of the s/w reset above, we need to enable CRS on
- * TX. This must be set for both full and half duplex operation.
+ /* In addition, because of the s/w reset above, we need to
+ * enable CRS on TX. This must be set for both full and half
+ * duplex operation.
*/
ret_val =
e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1901,6 +1983,13 @@ static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
return ret_val;
}
}
+
+ if (hw->phy_type == e1000_phy_oem && resetPhy) {
+ ret_val = e1000_oem_cleanup_after_phy_reset(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
return E1000_SUCCESS;
}
@@ -1946,12 +2035,19 @@ static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
u32 ctrl;
s32 ret_val;
u16 phy_data;
+ int is_FullDuplex = false;
+ int is_1000MBS = false;
+ int is_100MBS = false;
e_dbg("e1000_config_mac_to_phy");
/* 82544 or newer MAC, Auto Speed Detection takes care of
* MAC speed/duplex configuration.*/
- if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
+
+ if ((hw->mac_type >= e1000_82544)
+ && (hw->mac_type != e1000_ce4100)
+ && (hw->mac_type != e1000_icp_xxxx))
+
return E1000_SUCCESS;
/* Read the Device Control Register and set the bits to Force Speed
@@ -1979,6 +2075,41 @@ static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
e1000_config_collision_dist(hw);
break;
+ case e1000_phy_oem:
+ ret_val = e1000_oem_set_trans_gasket(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val =
+ e1000_oem_phy_is_full_duplex(hw, (int *)&is_FullDuplex);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_oem_phy_is_speed_1000(hw, (int *)&is_1000MBS);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_oem_phy_is_speed_100(hw, (int *)&is_100MBS);
+ if (ret_val)
+ return ret_val;
+
+ // nru: FIXME duplication
+ /* Set up duplex in the Device Control and Transmit Control
+ * registers depending on negotiated values.
+ */
+ if (is_FullDuplex)
+ ctrl |= E1000_CTRL_FD;
+ else
+ ctrl &= ~E1000_CTRL_FD;
+
+ e1000_config_collision_dist(hw);
+
+ /* Set up speed in the Device Control register depending on
+ * negotiated values.
+ */
+ if (is_1000MBS)
+ ctrl |= E1000_CTRL_SPD_1000;
+ else if (is_100MBS)
+ ctrl |= E1000_CTRL_SPD_100;
+
+ break;
default:
/* Set up duplex in the Device Control and Transmit Control
* registers depending on negotiated values.
@@ -2105,8 +2236,15 @@ static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed))
|| ((hw->media_type == e1000_media_type_internal_serdes)
&& (hw->autoneg_failed))
+ || ((hw->media_type == e1000_media_type_oem)
+ && !e1000_oem_phy_is_copper(hw)
+ && (hw->autoneg_failed))
|| ((hw->media_type == e1000_media_type_copper)
+ && (!hw->autoneg))
+ || ((hw->media_type == e1000_media_type_oem)
+ && e1000_oem_phy_is_copper(hw)
&& (!hw->autoneg))) {
+
ret_val = e1000_force_mac_fc(hw);
if (ret_val) {
e_dbg("Error forcing flow control settings\n");
@@ -2119,7 +2257,10 @@ static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
* has completed, and if so, how the PHY and link partner has
* flow control configured.
*/
- if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
+ if ((hw->media_type == e1000_media_type_copper
+ || (hw->media_type == e1000_media_type_oem
+ && e1000_oem_phy_is_copper(hw)))
+ && hw->autoneg) {
/* Read the MII Status Register and check to see if AutoNeg
* has completed. We read this twice because this reg has
* some "sticky" (latched) bits.
@@ -2308,6 +2449,7 @@ static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
u32 ctrl;
u32 status;
s32 ret_val = E1000_SUCCESS;
+ int isUp;
e_dbg("e1000_check_for_serdes_link_generic");
@@ -2315,6 +2457,18 @@ static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
status = er32(STATUS);
rxcw = er32(RXCW);
+ isUp = 0;
+
+ // SDG - this is potential issue. Should not cause problems on E1000
+ // though but may cause a problem for ETH1
+ if (hw->mac_type == e1000_icp_xxxx) {
+ ret_val = e1000_oem_phy_is_link_up(hw, &isUp);
+ if (ret_val)
+ return ret_val;
+ } else {
+ isUp = status & E1000_STATUS_LU;
+ }
+
/*
* If we don't have link (auto-negotiation failed or link partner
* cannot auto-negotiate), and our link partner is not trying to
@@ -2323,7 +2477,7 @@ static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
* time to complete.
*/
/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
- if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
+ if ((!(isUp)) && (!(rxcw & E1000_RXCW_C))) {
if (hw->autoneg_failed == 0) {
hw->autoneg_failed = 1;
goto out;
@@ -2377,8 +2531,7 @@ static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
}
if (E1000_TXCW_ANE & er32(TXCW)) {
- status = er32(STATUS);
- if (status & E1000_STATUS_LU) {
+ if (isUp) { // SDG scary change here as well
/* SYNCH bit and IV bit are sticky, so reread rxcw. */
udelay(10);
rxcw = er32(RXCW);
@@ -2433,26 +2586,33 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
* set when the optics detect a signal. On older adapters, it will be
* cleared when there is a signal. This applies to fiber media only.
*/
- if ((hw->media_type == e1000_media_type_fiber) ||
- (hw->media_type == e1000_media_type_internal_serdes)) {
+ if ((hw->media_type == e1000_media_type_fiber)
+ || (hw->media_type == e1000_media_type_internal_serdes)
+ || (hw->media_type == e1000_media_type_oem
+ && !e1000_oem_phy_is_copper(hw))) {
rxcw = er32(RXCW);
if (hw->media_type == e1000_media_type_fiber) {
signal =
(hw->mac_type >
e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
- if (status & E1000_STATUS_LU)
- hw->get_link_status = false;
+ if (hw->mac_type != e1000_icp_xxxx) {
+ if (status & E1000_STATUS_LU)
+ hw->get_link_status = false;
+ }
}
}
/* If we have a copper PHY then we only want to go out to the PHY
* registers to see if Auto-Neg has completed and/or if our link
- * status has changed. The get_link_status flag will be set if we
+ * status has changed. The get_link_status flag will be set if we
* receive a Link Status Change interrupt or we have Rx Sequence
* Errors.
*/
- if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
+ if ((hw->media_type == e1000_media_type_copper
+ || (hw->media_type == e1000_media_type_oem
+ && e1000_oem_phy_is_copper(hw)))
+ && hw->get_link_status) {
/* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
@@ -2464,6 +2624,7 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
if (ret_val)
return ret_val;
+ hw->icp_xxxx_is_link_up = (phy_data & MII_SR_LINK_STATUS) != 0;
if (phy_data & MII_SR_LINK_STATUS) {
hw->get_link_status = false;
@@ -2494,6 +2655,11 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
} else {
/* No link detected */
e1000_config_dsp_after_link_change(hw, false);
+
+ if (hw->phy_type == e1000_phy_oem)
+ e1000_oem_config_dsp_after_link_change(hw,
+ false);
+
return 0;
}
@@ -2506,6 +2672,9 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
/* optimize the dsp settings for the igp phy */
e1000_config_dsp_after_link_change(hw, true);
+ if (hw->phy_type == e1000_phy_oem)
+ e1000_oem_config_dsp_after_link_change(hw, true);
+
/* We have a M88E1000 PHY and Auto-Neg is enabled. If we
* have Si on board that is 82544 or newer, Auto
* Speed Detection takes care of MAC speed/duplex
@@ -2514,8 +2683,14 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
* speed/duplex on the MAC to the current PHY speed/duplex
* settings.
*/
+
+
+
+
if ((hw->mac_type >= e1000_82544) &&
- (hw->mac_type != e1000_ce4100))
+ (hw->mac_type != e1000_ce4100) &&
+ (hw->mac_type != e1000_icp_xxxx))
+
e1000_config_collision_dist(hw);
else {
ret_val = e1000_config_mac_to_phy(hw);
@@ -2580,7 +2755,9 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
}
if ((hw->media_type == e1000_media_type_fiber) ||
- (hw->media_type == e1000_media_type_internal_serdes))
+ (hw->media_type == e1000_media_type_internal_serdes) ||
+ (hw->media_type == e1000_media_type_oem
+ && !e1000_oem_phy_is_copper(hw))) // SDG - this was a dodgy port from iegbe
e1000_check_for_serdes_link_generic(hw);
return E1000_SUCCESS;
@@ -2861,7 +3038,8 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
return -E1000_ERR_PARAM;
}
- if (hw->mac_type > e1000_82543) {
+ if (hw->mac_type > e1000_82543
+ && hw->mac_type != e1000_icp_xxxx) {
/* Set up Op-code, Phy Address, and register address in the MDI
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
@@ -2921,7 +3099,8 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
}
*phy_data = (u16) mdic;
}
- } else {
+ } else if (hw->mac_type != e1000_icp_xxxx) {
+
/* We must first send a preamble through the MDIO pin to signal the
* beginning of an MII instruction. This is done by sending 32
* consecutive "1" bits.
@@ -2949,7 +3128,13 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
* register address.
*/
*phy_data = e1000_shift_in_mdi_bits(hw);
+ } else {
+ int32_t ret_val =
+ e1000_oem_read_phy_reg_ex(hw, reg_addr, phy_data);
+ if (ret_val)
+ return ret_val;
}
+
return E1000_SUCCESS;
}
@@ -2996,7 +3181,8 @@ static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
return -E1000_ERR_PARAM;
}
- if (hw->mac_type > e1000_82543) {
+ if (hw->mac_type > e1000_82543 &&
+ hw->mac_type != e1000_icp_xxxx) {
/* Set up Op-code, Phy Address, register address, and data
* intended for the PHY register in the MDI Control register.
* The MAC will take care of interfacing with the PHY to send
@@ -3046,7 +3232,7 @@ static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
return -E1000_ERR_PHY;
}
}
- } else {
+ } else if (hw->mac_type != e1000_icp_xxxx) {
/* We'll need to use the SW defined pins to shift the write command
* out to the PHY. We first send a preamble to the PHY to signal the
* beginning of the MII instruction. This is done by sending 32
@@ -3066,6 +3252,11 @@ static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
mdic |= (u32) phy_data;
e1000_shift_out_mdi_bits(hw, mdic, 32);
+ } else {
+ int32_t ret_val =
+ e1000_oem_write_phy_reg_ex(hw, reg_addr, phy_data);
+ if (ret_val)
+ return ret_val;
}
return E1000_SUCCESS;
@@ -3081,11 +3272,21 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
u32 ctrl, ctrl_ext;
u32 led_ctrl;
+ s32 ret_val;
e_dbg("e1000_phy_hw_reset");
e_dbg("Resetting Phy...\n");
+ if (hw->mac_type == e1000_icp_xxxx) {
+ ret_val = e1000_oem_phy_hw_reset(hw);
+ if (ret_val)
+ return ret_val;
+
+ e1000_oem_phy_init_script(hw);
+ return ret_val;
+ }
+
if (hw->mac_type > e1000_82543) {
/* Read the device control register and assert the E1000_CTRL_PHY_RST
* bit. Then, take it out of reset.
@@ -3125,6 +3326,9 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
ew32(LEDCTL, led_ctrl);
}
+ if (hw->phy_type == e1000_phy_oem)
+ e1000_oem_phy_init_script(hw);
+
/* Wait for FW to finish PHY configuration. */
return e1000_get_phy_cfg_done(hw);
}
@@ -3145,6 +3349,7 @@ s32 e1000_phy_reset(struct e1000_hw *hw)
switch (hw->phy_type) {
case e1000_phy_igp:
+ case e1000_icp_xxxx:
ret_val = e1000_phy_hw_reset(hw);
if (ret_val)
return ret_val;
@@ -3446,7 +3651,9 @@ s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
phy_info->local_rx = e1000_1000t_rx_status_undefined;
phy_info->remote_rx = e1000_1000t_rx_status_undefined;
- if (hw->media_type != e1000_media_type_copper) {
+ if (hw->media_type != e1000_media_type_copper
+ && (hw->media_type == e1000_media_type_oem
+ && !e1000_oem_phy_is_copper(hw))) {
e_dbg("PHY info is only valid for copper media\n");
return -E1000_ERR_CONFIG;
}
@@ -3466,6 +3673,8 @@ s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
if (hw->phy_type == e1000_phy_igp)
return e1000_phy_igp_get_info(hw, phy_info);
+ else if (hw->phy_type == e1000_phy_oem)
+ return e1000_oem_phy_get_info(hw, phy_info);
else if ((hw->phy_type == e1000_phy_8211) ||
(hw->phy_type == e1000_phy_8201))
return E1000_SUCCESS;
@@ -3517,6 +3726,7 @@ s32 e1000_init_eeprom_params(struct e1000_hw *hw)
case e1000_82545_rev_3:
case e1000_82546:
case e1000_82546_rev_3:
+ case e1000_icp_xxxx:
eeprom->type = e1000_eeprom_microwire;
eeprom->opcode_bits = 3;
eeprom->delay_usec = 50;
@@ -3932,8 +4142,8 @@ static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
if (eeprom->word_size == 0)
e1000_init_eeprom_params(hw);
- /* A check for invalid values: offset too large, too many words, and not
- * enough words.
+ /* A check for invalid values: offset too large, too many words, and
+ * not enough words.
*/
if ((offset >= eeprom->word_size)
|| (words > eeprom->word_size - offset) || (words == 0)) {
@@ -4106,8 +4316,8 @@ static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
if (eeprom->word_size == 0)
e1000_init_eeprom_params(hw);
- /* A check for invalid values: offset too large, too many words, and not
- * enough words.
+ /* A check for invalid values: offset too large, too many words, and
+ * not enough words.
*/
if ((offset >= eeprom->word_size)
|| (words > eeprom->word_size - offset) || (words == 0)) {
@@ -4236,14 +4446,15 @@ static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
/* Send the data */
e1000_shift_out_ee_bits(hw, data[words_written], 16);
- /* Toggle the CS line. This in effect tells the EEPROM to execute
- * the previous command.
+ /* Toggle the CS line. This in effect tells the EEPROM to
+ * execute the previous command.
*/
e1000_standby_eeprom(hw);
- /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will
- * signal that the command has been completed by raising the DO signal.
- * If DO does not go high in 10 milliseconds, then error out.
+ /* Read DO repeatedly until it is high (equal to '1'). The
+ * EEPROM will signal that the command has been completed by
+ * raising the DO signal. If DO does not go high in 10
+ * milliseconds, then error out.
*/
for (i = 0; i < 200; i++) {
eecd = er32(EECD);
@@ -4287,12 +4498,24 @@ s32 e1000_read_mac_addr(struct e1000_hw *hw)
{
u16 offset;
u16 eeprom_data, i;
+ uint16_t ia_base_addr = 0;
e_dbg("e1000_read_mac_addr");
+ if (hw->mac_type == e1000_icp_xxxx) {
+ struct e1000_adapter *adapter;
+ uint32_t device_number;
+
+ adapter = (struct e1000_adapter *)hw->back;
+ device_number = PCI_SLOT(adapter->pdev->devfn);
+ ia_base_addr =
+ (uint16_t) EEPROM_IA_START_ICP_xxxx(device_number);
+ }
+
for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
offset = i >> 1;
- if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+ if (e1000_read_eeprom(hw, ia_base_addr + offset, 1,
+ &eeprom_data) < 0) {
e_dbg("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
@@ -4488,7 +4711,8 @@ static s32 e1000_id_led_init(struct e1000_hw *hw)
e_dbg("e1000_id_led_init");
- if (hw->mac_type < e1000_82540) {
+ if (hw->mac_type < e1000_82540
+ || hw->mac_type == e1000_icp_xxxx) {
/* Nothing to do */
return E1000_SUCCESS;
}
@@ -4566,6 +4790,7 @@ s32 e1000_setup_led(struct e1000_hw *hw)
case e1000_82542_rev2_1:
case e1000_82543:
case e1000_82544:
+ case e1000_icp_xxxx:
/* No setup necessary */
break;
case e1000_82541:
@@ -4618,6 +4843,7 @@ s32 e1000_cleanup_led(struct e1000_hw *hw)
case e1000_82542_rev2_1:
case e1000_82543:
case e1000_82544:
+ case e1000_icp_xxxx:
/* No cleanup necessary */
break;
case e1000_82541:
@@ -4650,6 +4876,9 @@ s32 e1000_led_on(struct e1000_hw *hw)
e_dbg("e1000_led_on");
switch (hw->mac_type) {
+ case e1000_icp_xxxx:
+ /* No LED control on ICP family of gigE controllers */
+ return E1000_SUCCESS;
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -4696,6 +4925,9 @@ s32 e1000_led_off(struct e1000_hw *hw)
e_dbg("e1000_led_off");
switch (hw->mac_type) {
+ case e1000_icp_xxxx:
+ /* No LED control on ICP family of gigE controllers */
+ return E1000_SUCCESS;
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -4803,7 +5035,7 @@ static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = er32(TSCTC);
temp = er32(TSCTFC);
- if (hw->mac_type <= e1000_82544)
+ if (hw->mac_type <= e1000_82544 || hw->mac_type == e1000_icp_xxxx)
return;
temp = er32(MGTPRC);
@@ -4974,6 +5206,11 @@ void e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
+ case e1000_icp_xxxx:
+ hw->bus_type = e1000_bus_type_cpp;
+ hw->bus_speed = e1000_bus_speed_unknown;
+ hw->bus_width = e1000_bus_width_unknown;
+ break;
default:
status = er32(STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
@@ -5138,6 +5375,11 @@ static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
+ } else if (hw->phy_type == e1000_phy_oem) {
+ ret_val = e1000_oem_get_cable_length(hw,
+ min_length, max_length);
+ if (ret_val)
+ return ret_val;
}
return E1000_SUCCESS;
@@ -5207,7 +5449,10 @@ static s32 e1000_check_polarity(struct e1000_hw *hw,
e1000_rev_polarity_reversed :
e1000_rev_polarity_normal;
}
+ } else if (hw->phy_type == e1000_phy_oem) {
+ return e1000_oem_check_polarity(hw, (uint16_t *) polarity);
}
+
return E1000_SUCCESS;
}
@@ -5248,8 +5493,15 @@ static s32 e1000_check_downshift(struct e1000_hw *hw)
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
+ } else if (hw->phy_type == e1000_phy_oem) {
+ ret_val = e1000_oem_phy_speed_downgraded(hw, &phy_data);
+
+ if (ret_val)
+ return ret_val;
+ hw->speed_downgraded = phy_data > 0;
}
+
return E1000_SUCCESS;
}
@@ -5259,13 +5511,13 @@ static s32 e1000_check_downshift(struct e1000_hw *hw)
* @link_up: was link up at the time this was called
*
* returns: - E1000_ERR_PHY if fail to read/write the PHY
- * E1000_SUCCESS at any other case.
+ * E1000_SUCCESS at any other case.
*
* 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
* gigabit link is achieved to improve link quality.
*/
-static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
+s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
{
s32 ret_val;
u16 phy_data, phy_saved_data, speed, duplex, i;
@@ -5527,9 +5779,9 @@ static s32 e1000_set_phy_mode(struct e1000_hw *hw)
* meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
*
* returns: - E1000_ERR_PHY if fail to read/write the PHY
- * E1000_SUCCESS at any other case.
+ * E1000_SUCCESS at any other case.
*/
-static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
+s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
{
s32 ret_val;
u16 phy_data;
@@ -5560,10 +5812,10 @@ static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
return ret_val;
}
- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
- * Dx states where the power conservation is most important. During
- * driver activity we should enable SmartSpeed, so performance is
- * maintained. */
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained. */
if (hw->smart_speed == e1000_smart_speed_on) {
ret_val =
e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
@@ -5805,9 +6057,9 @@ static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
*
* Check for EEPROM Auto Read bit done.
* returns: - E1000_ERR_RESET if fail to reset MAC
- * E1000_SUCCESS at any other case.
+ * E1000_SUCCESS at any other case.
*/
-static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
+s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
{
e_dbg("e1000_get_auto_rd_done");
msleep(5);
@@ -5820,9 +6072,9 @@ static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
*
* Checks if the PHY configuration is done
* returns: - E1000_ERR_RESET if fail to reset MAC
- * E1000_SUCCESS at any other case.
+ * E1000_SUCCESS at any other case.
*/
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
+s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
e_dbg("e1000_get_phy_cfg_done");
msleep(10);