mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-29 23:26:44 +07:00
Merge branch 'realtek-phy-next'
Heiner Kallweit says: ==================== net: phy: realtek: add support for integrated 2.5Gbps PHY in RTL8125 This series adds support for the integrated 2.5Gbps PHY in RTL8125. First three patches add necessary functionality to phylib. Changes in v2: - added patch 1 - changed patch 4 to use a fake PHY ID that is injected by the network driver. This allows to use a dedicated PHY driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d35bbe84c1
@ -782,6 +782,29 @@ int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
|
||||
}
|
||||
EXPORT_SYMBOL(phy_write_paged);
|
||||
|
||||
/**
|
||||
* phy_modify_paged_changed() - Function for modifying a paged register
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @page: the page for the phy
|
||||
* @regnum: register number
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*
|
||||
* Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
*/
|
||||
int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
int ret = 0, oldpage;
|
||||
|
||||
oldpage = phy_select_page(phydev, page);
|
||||
if (oldpage >= 0)
|
||||
ret = __phy_modify_changed(phydev, regnum, mask, set);
|
||||
|
||||
return phy_restore_page(phydev, oldpage, ret);
|
||||
}
|
||||
EXPORT_SYMBOL(phy_modify_paged_changed);
|
||||
|
||||
/**
|
||||
* phy_modify_paged() - Convenience function for modifying a paged register
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
@ -795,12 +818,8 @@ EXPORT_SYMBOL(phy_write_paged);
|
||||
int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
int ret = 0, oldpage;
|
||||
int ret = phy_modify_paged_changed(phydev, page, regnum, mask, set);
|
||||
|
||||
oldpage = phy_select_page(phydev, page);
|
||||
if (oldpage >= 0)
|
||||
ret = __phy_modify(phydev, regnum, mask, set);
|
||||
|
||||
return phy_restore_page(phydev, oldpage, ret);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(phy_modify_paged);
|
||||
|
@ -1564,24 +1564,20 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable);
|
||||
*/
|
||||
static int genphy_config_advert(struct phy_device *phydev)
|
||||
{
|
||||
u32 advertise;
|
||||
int bmsr, adv;
|
||||
int err, changed = 0;
|
||||
int err, bmsr, changed = 0;
|
||||
u32 adv;
|
||||
|
||||
/* Only allow advertising what this PHY supports */
|
||||
linkmode_and(phydev->advertising, phydev->advertising,
|
||||
phydev->supported);
|
||||
if (!ethtool_convert_link_mode_to_legacy_u32(&advertise,
|
||||
phydev->advertising))
|
||||
phydev_warn(phydev, "PHY advertising (%*pb) more modes than genphy supports, some modes not advertised.\n",
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS,
|
||||
phydev->advertising);
|
||||
|
||||
adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
|
||||
|
||||
/* Setup standard advertisement */
|
||||
err = phy_modify_changed(phydev, MII_ADVERTISE,
|
||||
ADVERTISE_ALL | ADVERTISE_100BASE4 |
|
||||
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
|
||||
ethtool_adv_to_mii_adv_t(advertise));
|
||||
adv);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
@ -1598,13 +1594,7 @@ static int genphy_config_advert(struct phy_device *phydev)
|
||||
if (!(bmsr & BMSR_ESTATEN))
|
||||
return changed;
|
||||
|
||||
/* Configure gigabit if it's supported */
|
||||
adv = 0;
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
phydev->supported) ||
|
||||
linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
phydev->supported))
|
||||
adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
|
||||
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
|
||||
|
||||
err = phy_modify_changed(phydev, MII_CTRL1000,
|
||||
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
|
||||
@ -1681,18 +1671,20 @@ int genphy_restart_aneg(struct phy_device *phydev)
|
||||
EXPORT_SYMBOL(genphy_restart_aneg);
|
||||
|
||||
/**
|
||||
* genphy_config_aneg - restart auto-negotiation or write BMCR
|
||||
* __genphy_config_aneg - restart auto-negotiation or write BMCR
|
||||
* @phydev: target phy_device struct
|
||||
* @changed: whether autoneg is requested
|
||||
*
|
||||
* Description: If auto-negotiation is enabled, we configure the
|
||||
* advertising, and then restart auto-negotiation. If it is not
|
||||
* enabled, then we write the BMCR.
|
||||
*/
|
||||
int genphy_config_aneg(struct phy_device *phydev)
|
||||
int __genphy_config_aneg(struct phy_device *phydev, bool changed)
|
||||
{
|
||||
int err, changed;
|
||||
int err;
|
||||
|
||||
changed = genphy_config_eee_advert(phydev);
|
||||
if (genphy_config_eee_advert(phydev))
|
||||
changed = true;
|
||||
|
||||
if (AUTONEG_ENABLE != phydev->autoneg)
|
||||
return genphy_setup_forced(phydev);
|
||||
@ -1700,10 +1692,10 @@ int genphy_config_aneg(struct phy_device *phydev)
|
||||
err = genphy_config_advert(phydev);
|
||||
if (err < 0) /* error */
|
||||
return err;
|
||||
else if (err)
|
||||
changed = true;
|
||||
|
||||
changed |= err;
|
||||
|
||||
if (changed == 0) {
|
||||
if (!changed) {
|
||||
/* Advertisement hasn't changed, but maybe aneg was never on to
|
||||
* begin with? Or maybe phy was isolated?
|
||||
*/
|
||||
@ -1713,18 +1705,15 @@ int genphy_config_aneg(struct phy_device *phydev)
|
||||
return ctl;
|
||||
|
||||
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
|
||||
changed = 1; /* do restart aneg */
|
||||
changed = true; /* do restart aneg */
|
||||
}
|
||||
|
||||
/* Only restart aneg if we are advertising something different
|
||||
* than we were before.
|
||||
*/
|
||||
if (changed > 0)
|
||||
return genphy_restart_aneg(phydev);
|
||||
|
||||
return 0;
|
||||
return changed ? genphy_restart_aneg(phydev) : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(genphy_config_aneg);
|
||||
EXPORT_SYMBOL(__genphy_config_aneg);
|
||||
|
||||
/**
|
||||
* genphy_aneg_done - return auto-negotiation status
|
||||
@ -1811,8 +1800,6 @@ int genphy_read_status(struct phy_device *phydev)
|
||||
phydev->pause = 0;
|
||||
phydev->asym_pause = 0;
|
||||
|
||||
linkmode_zero(phydev->lp_advertising);
|
||||
|
||||
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
|
||||
if (phydev->is_gigabit_capable) {
|
||||
lpagb = phy_read(phydev, MII_STAT1000);
|
||||
|
@ -39,6 +39,11 @@
|
||||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
|
||||
#define RTL_ADV_2500FULL BIT(7)
|
||||
#define RTL_LPADV_10000FULL BIT(11)
|
||||
#define RTL_LPADV_5000FULL BIT(6)
|
||||
#define RTL_LPADV_2500FULL BIT(5)
|
||||
|
||||
MODULE_DESCRIPTION("Realtek PHY driver");
|
||||
MODULE_AUTHOR("Johnson Leung");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -256,6 +261,53 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl8125_get_features(struct phy_device *phydev)
|
||||
{
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
|
||||
return genphy_read_abilities(phydev);
|
||||
}
|
||||
|
||||
static int rtl8125_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||
u16 adv2500 = 0;
|
||||
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->advertising))
|
||||
adv2500 = RTL_ADV_2500FULL;
|
||||
|
||||
ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12,
|
||||
RTL_ADV_2500FULL, adv2500);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return __genphy_config_aneg(phydev, ret);
|
||||
}
|
||||
|
||||
static int rtl8125_read_status(struct phy_device *phydev)
|
||||
{
|
||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||
int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
|
||||
|
||||
if (lpadv < 0)
|
||||
return lpadv;
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
|
||||
phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL);
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||
phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL);
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
|
||||
}
|
||||
|
||||
return genphy_read_status(phydev);
|
||||
}
|
||||
|
||||
static struct phy_driver realtek_drvs[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(0x00008201),
|
||||
@ -332,6 +384,16 @@ static struct phy_driver realtek_drvs[] = {
|
||||
.resume = genphy_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cca50),
|
||||
.name = "RTL8125 2.5Gbps internal",
|
||||
.get_features = rtl8125_get_features,
|
||||
.config_aneg = rtl8125_config_aneg,
|
||||
.read_status = rtl8125_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc961),
|
||||
.name = "RTL8366RB Gigabit Ethernet",
|
||||
|
@ -984,6 +984,8 @@ int phy_select_page(struct phy_device *phydev, int page);
|
||||
int phy_restore_page(struct phy_device *phydev, int oldpage, int ret);
|
||||
int phy_read_paged(struct phy_device *phydev, int page, u32 regnum);
|
||||
int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val);
|
||||
int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
|
||||
u16 mask, u16 set);
|
||||
int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
|
||||
u16 mask, u16 set);
|
||||
|
||||
@ -1069,7 +1071,7 @@ int genphy_read_abilities(struct phy_device *phydev);
|
||||
int genphy_setup_forced(struct phy_device *phydev);
|
||||
int genphy_restart_aneg(struct phy_device *phydev);
|
||||
int genphy_config_eee_advert(struct phy_device *phydev);
|
||||
int genphy_config_aneg(struct phy_device *phydev);
|
||||
int __genphy_config_aneg(struct phy_device *phydev, bool changed);
|
||||
int genphy_aneg_done(struct phy_device *phydev);
|
||||
int genphy_update_link(struct phy_device *phydev);
|
||||
int genphy_read_status(struct phy_device *phydev);
|
||||
@ -1077,6 +1079,12 @@ int genphy_suspend(struct phy_device *phydev);
|
||||
int genphy_resume(struct phy_device *phydev);
|
||||
int genphy_loopback(struct phy_device *phydev, bool enable);
|
||||
int genphy_soft_reset(struct phy_device *phydev);
|
||||
|
||||
static inline int genphy_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
return __genphy_config_aneg(phydev, false);
|
||||
}
|
||||
|
||||
static inline int genphy_no_soft_reset(struct phy_device *phydev)
|
||||
{
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user