static u32 mii_get_an(struct mii_if_info *mii, u16 addr) { int advert; advert = mii->mdio_read(mii->dev, mii->phy_id, addr); return mii_lpa_to_ethtool_lpa_t(advert); }
/** * genphy_c45_read_lpa - read the link partner advertisment and pause * @phydev: target phy_device struct * * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers, * filling in the link partner advertisment, pause and asym_pause members * in @phydev. This assumes that the auto-negotiation MMD is present, and * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected * to fill in the remainder of the link partner advert from vendor registers. */ int genphy_c45_read_lpa(struct phy_device *phydev) { int val; /* Read the link partner's base page advertisment */ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA); if (val < 0) return val; phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val); phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0; /* Read the link partner's 10G advertisment */ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); if (val < 0) return val; if (val & MDIO_AN_10GBT_STAT_LP10G) phydev->lp_advertising |= ADVERTISED_10000baseT_Full; return 0; }
/* marvell_read_status * * Generic status code does not detect Fiber correctly! * Description: * Check the link, then figure out the current state * by comparing what we advertise with what the link partner * advertises. Start by checking the gigabit possibilities, * then move on to 10/100. */ static int marvell_read_status(struct phy_device *phydev) { int adv; int err; int lpa; int lpagb; int status = 0; /* Update the link, but return if there * was an error */ err = genphy_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { status = phy_read(phydev, MII_M1011_PHY_STATUS); if (status < 0) return status; lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa; lpagb = phy_read(phydev, MII_STAT1000); if (lpagb < 0) return lpagb; adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) return adv; phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) | mii_lpa_to_ethtool_lpa_t(lpa); lpa &= adv; if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; status = status & MII_M1011_PHY_STATUS_SPD_MASK; phydev->pause = phydev->asym_pause = 0; switch (status) { case MII_M1011_PHY_STATUS_1000: phydev->speed = SPEED_1000; break; case MII_M1011_PHY_STATUS_100: phydev->speed = SPEED_100; break; default: phydev->speed = SPEED_10; break; } if (phydev->duplex == DUPLEX_FULL) { phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; phydev->lp_advertising = 0; } return 0; }