diff options
Diffstat (limited to 'drivers/net/ethernet/intel/e1000/e1000_hw.c')
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_hw.c | 406 |
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); |