for (i = 0; i < iterations; i++) { /* Some PHYs require the PHY_STATUS register to be read *twiceduetothelinkbitbeingsticky.Noharmdoing *itacrosstheboard.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val && usec_interval > 0) { /* If the first read fails, another entity may have *ownershipoftheresources,waitandtryagainto *seeiftheyhaverelinquishedtheresourcesyet.
*/ if (usec_interval >= 1000)
mdelay(usec_interval / 1000); else
udelay(usec_interval);
}
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) break; if (usec_interval >= 1000)
mdelay(usec_interval / 1000); else
udelay(usec_interval);
}
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
usleep_range(1000, 2000);
}
/* SW should guarantee 100us for the completion of the PHY reset */
usleep_range(100, 150); do {
phpm = rd32(IGC_I225_PHPM);
timeout--;
udelay(1);
} while (!(phpm & IGC_PHY_RST_COMP) && timeout);
if (!timeout)
hw_dbg("Timeout is expired after a phy reset\n");
/* Read the MII Auto-Neg Advertisement Register (Address 4). */
ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) return ret_val;
if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */
ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
&mii_1000t_ctrl_reg); if (ret_val) return ret_val;
}
if (phy->autoneg_mask & ADVERTISE_2500_FULL) { /* Read the MULTI GBT AN Control Register - reg 7.32 */
ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
MMD_DEVADDR_SHIFT) |
IGC_ANEG_MULTIGBT_AN_CTRL,
&aneg_multigbt_an_ctrl);
if (ret_val) return ret_val;
}
/* Need to parse both autoneg_advertised and fc and set up *theappropriatePHYregisters.Firstwewillparsefor *autoneg_advertisedsoftwareoverride.Sincewecanadvertise *aplethoraofcombinations,weneedtocheckeachbit *individually.
*/
/* First we clear all the 10/100 mb speed bits in the Auto-Neg *AdvertisementRegister(Address4)andthe1000mbspeedbitsin *the1000Base-TControlRegister(Address9).
*/
mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
NWAY_AR_100TX_HD_CAPS |
NWAY_AR_10T_FD_CAPS |
NWAY_AR_10T_HD_CAPS);
mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
/* Do we want to advertise 10 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
hw_dbg("Advertise 10mb Half duplex\n");
mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
}
/* Do we want to advertise 10 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
hw_dbg("Advertise 10mb Full duplex\n");
mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
}
/* Do we want to advertise 100 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
hw_dbg("Advertise 100mb Half duplex\n");
mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
}
/* Do we want to advertise 100 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
hw_dbg("Advertise 100mb Full duplex\n");
mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
}
/* We do not allow the Phy to advertise 1000 Mb Half Duplex */ if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
hw_dbg("Advertise 1000mb Half duplex request denied!\n");
/* Do we want to advertise 1000 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
hw_dbg("Advertise 1000mb Full duplex\n");
mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
}
/* We do not allow the Phy to advertise 2500 Mb Half Duplex */ if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
hw_dbg("Advertise 2500mb Half duplex request denied!\n");
/* Do we want to advertise 2500 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
hw_dbg("Advertise 2500mb Full duplex\n");
aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
} else {
aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS;
}
/* Check for a software override of the flow control settings, and *setupthePHYadvertisementregistersaccordingly.If *auto-negotiationisenabled,thensoftwarewillhavetosetthe *"PAUSE"bitstothecorrectvalueintheAuto-Negotiation *AdvertisementRegister(PHY_AUTONEG_ADV)andre-startauto- *negotiation. * *Thepossiblevaluesofthe"fc"parameterare: *0:Flowcontroliscompletelydisabled *1:Rxflowcontrolisenabled(wecanreceivepauseframes *butnotsendpauseframes). *2:Txflowcontrolisenabled(wecansendpauseframes *butwedonotsupportreceivingpauseframes). *3:BothRxandTxflowcontrol(symmetric)areenabled. *other:Nosoftwareoverride.Theflowcontrolconfiguration *intheEEPROMisused.
*/ switch (hw->fc.current_mode) { case igc_fc_none: /* Flow control (Rx & Tx) is completely disabled by a *softwareover-ride.
*/
mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case igc_fc_rx_pause: /* Rx Flow control is enabled, and Tx Flow control is *disabled,byasoftwareover-ride. * *Sincetherereallyisn'tawaytoadvertisethatweare *capableofRxPauseONLY,wewilladvertisethatwe *supportbothsymmetricandasymmetricRxPAUSE.Later *(inigc_config_fc_after_link_up)wewilldisablethe *hw'sabilitytosendPAUSEframes.
*/
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case igc_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is *disabled,byasoftwareover-ride.
*/
mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; case igc_fc_full: /* Flow control (both Rx and Tx) is enabled by a software *over-ride.
*/
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; default:
hw_dbg("Flow control param set incorrectly\n"); return -IGC_ERR_CONFIG;
}
ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) return ret_val;
/* Perform some bounds checking on the autoneg advertisement *parameter.
*/
phy->autoneg_advertised &= phy->autoneg_mask;
/* If autoneg_advertised is zero, we assume it was not defaulted *bythecallingcodesowesettoadvertisefullcapability.
*/ if (phy->autoneg_advertised == 0)
phy->autoneg_advertised = phy->autoneg_mask;
hw_dbg("Reconfiguring auto-neg advertisement params\n");
ret_val = igc_phy_setup_autoneg(hw); if (ret_val) {
hw_dbg("Error Setting up Auto-Negotiation\n"); goto out;
}
hw_dbg("Restarting Auto-Neg\n");
/* Restart auto-negotiation by setting the Auto Neg Enable bit and *theAutoNegRestartbitinthePHYcontrolregister.
*/
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out;
/* Does the user want to wait for Auto-Neg to complete here, or *checkatalatertime(forexample,callbackroutine).
*/ if (phy->autoneg_wait_to_complete) {
ret_val = igc_wait_autoneg(hw); if (ret_val) {
hw_dbg("Error while waiting for autoneg to complete\n"); goto out;
}
}
/* Setup autoneg and flow control advertisement and perform *autonegotiation.
*/
ret_val = igc_copper_link_autoneg(hw); if (ret_val) goto out;
/* Check link status. Wait up to 100 microseconds for link to become *valid.
*/
ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link); if (ret_val) goto out;
if (link) {
hw_dbg("Valid link established!!!\n");
igc_config_collision_dist(hw);
ret_val = igc_config_fc_after_link_up(hw);
} else {
hw_dbg("Unable to establish link!!!\n");
}
if (offset > MAX_PHY_REG_ADDRESS) {
hw_dbg("PHY Address %d is out of range\n", offset);
ret_val = -IGC_ERR_PARAM; goto out;
}
/* Set up Op-code, Phy Address, and register offset in the MDI *Controlregister.TheMACwilltakecareofinterfacingwiththe *PHYtoretrievethedesireddata.
*/
mdic = ((offset << IGC_MDIC_REG_SHIFT) |
(phy->addr << IGC_MDIC_PHY_SHIFT) |
(IGC_MDIC_OP_READ));
wr32(IGC_MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed *Increasingthetimeoutastestingshowedfailureswith *thelowertimeout
*/ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
udelay(50);
mdic = rd32(IGC_MDIC); if (mdic & IGC_MDIC_READY) break;
} if (!(mdic & IGC_MDIC_READY)) {
hw_dbg("MDI Read did not complete\n");
ret_val = -IGC_ERR_PHY; goto out;
} if (mdic & IGC_MDIC_ERROR) {
hw_dbg("MDI Error\n");
ret_val = -IGC_ERR_PHY; goto out;
}
*data = (u16)mdic;
if (offset > MAX_PHY_REG_ADDRESS) {
hw_dbg("PHY Address %d is out of range\n", offset);
ret_val = -IGC_ERR_PARAM; goto out;
}
/* Set up Op-code, Phy Address, and register offset in the MDI *Controlregister.TheMACwilltakecareofinterfacingwiththe *PHYtowritethedesireddata.
*/
mdic = (((u32)data) |
(offset << IGC_MDIC_REG_SHIFT) |
(phy->addr << IGC_MDIC_PHY_SHIFT) |
(IGC_MDIC_OP_WRITE));
wr32(IGC_MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed *Increasingthetimeoutastestingshowedfailureswith *thelowertimeout
*/ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
udelay(50);
mdic = rd32(IGC_MDIC); if (mdic & IGC_MDIC_READY) break;
} if (!(mdic & IGC_MDIC_READY)) {
hw_dbg("MDI Write did not complete\n");
ret_val = -IGC_ERR_PHY; goto out;
} if (mdic & IGC_MDIC_ERROR) {
hw_dbg("MDI Error\n");
ret_val = -IGC_ERR_PHY; goto out;
}
/* NVM image version is reported as firmware version for i225 device */
ret_val = phy->ops.read_reg(hw, IGC_GPHY_VERSION, &gphy_version); if (ret_val)
hw_dbg("igc_phy: read wrong gphy version\n");
return gphy_version;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.25Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-04)
¤