/** * e1000_setup_copper_link_82540 - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). **/ static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u16 data; DEBUGFUNC("e1000_setup_copper_link_82540"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = e1000_set_phy_mode_82540(hw); if (ret_val) goto out; if (hw->mac.type == e1000_82545_rev_3 || hw->mac.type == e1000_82546_rev_3) { ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data); if (ret_val) goto out; data |= 0x00000008; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data); if (ret_val) goto out; } ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw); out: return ret_val; }
/** * e1000_setup_copper_link_82543 - Configure copper link settings * @hw: pointer to the HW structure * * Configures the link for auto-neg or forced speed and duplex. Then we check * for link, once link is established calls to configure collision distance * and flow control are called. **/ static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; bool link; DEBUGFUNC("e1000_setup_copper_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU; /* * With 82543, we need to force speed and duplex on the MAC * equal to what the PHY speed and duplex configuration is. * In addition, we need to perform a hardware reset on the * PHY to take it out of reset. */ if (hw->mac.type == e1000_82543) { ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = hw->phy.ops.reset(hw); if (ret_val) goto out; hw->phy.reset_disable = FALSE; } else { ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); } /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */ ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) goto out; if (hw->mac.autoneg) { /* * Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) goto out; } else { /* * PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); ret_val = e1000_phy_force_speed_duplex_82543(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); goto out; } } /* * Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, &link); if (ret_val) goto out; if (link) { DEBUGOUT("Valid link established!!!\n"); /* Config the MAC and PHY after link is up */ if (hw->mac.type == e1000_82544) { e1000_config_collision_dist_generic(hw); } else { ret_val = e1000_config_mac_to_phy_82543(hw); if (ret_val) goto out; } ret_val = e1000_config_fc_after_link_up_generic(hw); } else { DEBUGOUT("Unable to establish link!!!\n"); } out: return ret_val; }