net: phy: realtek: read actual speed to detect downshift
At least some integrated PHY's in RTL8168/RTL8125 chip versions support downshift, and the actual link speed can be read from a vendor-specific register. Info about this register was provided by Realtek. More details about downshift configuration (e.g. number of attempts) aren't available, therefore the downshift tunable is not implemented. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2c4b58dc75
commit
d445dff2df
@ -49,6 +49,8 @@
|
|||||||
#define RTL_LPADV_5000FULL BIT(6)
|
#define RTL_LPADV_5000FULL BIT(6)
|
||||||
#define RTL_LPADV_2500FULL BIT(5)
|
#define RTL_LPADV_2500FULL BIT(5)
|
||||||
|
|
||||||
|
#define RTLGEN_SPEED_MASK 0x0630
|
||||||
|
|
||||||
#define RTL_GENERIC_PHYID 0x001cc800
|
#define RTL_GENERIC_PHYID 0x001cc800
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Realtek PHY driver");
|
MODULE_DESCRIPTION("Realtek PHY driver");
|
||||||
@ -309,6 +311,55 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get actual speed to cover the downshift case */
|
||||||
|
static int rtlgen_get_speed(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (!phydev->link)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
val = phy_read_paged(phydev, 0xa43, 0x12);
|
||||||
|
if (val < 0)
|
||||||
|
return val;
|
||||||
|
|
||||||
|
switch (val & RTLGEN_SPEED_MASK) {
|
||||||
|
case 0x0000:
|
||||||
|
phydev->speed = SPEED_10;
|
||||||
|
break;
|
||||||
|
case 0x0010:
|
||||||
|
phydev->speed = SPEED_100;
|
||||||
|
break;
|
||||||
|
case 0x0020:
|
||||||
|
phydev->speed = SPEED_1000;
|
||||||
|
break;
|
||||||
|
case 0x0200:
|
||||||
|
phydev->speed = SPEED_10000;
|
||||||
|
break;
|
||||||
|
case 0x0210:
|
||||||
|
phydev->speed = SPEED_2500;
|
||||||
|
break;
|
||||||
|
case 0x0220:
|
||||||
|
phydev->speed = SPEED_5000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtlgen_read_status(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = genphy_read_status(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return rtlgen_get_speed(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
|
static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -429,6 +480,8 @@ static int rtl8125_config_aneg(struct phy_device *phydev)
|
|||||||
|
|
||||||
static int rtl8125_read_status(struct phy_device *phydev)
|
static int rtl8125_read_status(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||||
int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
|
int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
|
||||||
|
|
||||||
@ -443,7 +496,11 @@ static int rtl8125_read_status(struct phy_device *phydev)
|
|||||||
phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
|
phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return genphy_read_status(phydev);
|
ret = genphy_read_status(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return rtlgen_get_speed(phydev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
|
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
|
||||||
@ -550,6 +607,7 @@ static struct phy_driver realtek_drvs[] = {
|
|||||||
}, {
|
}, {
|
||||||
.name = "Generic FE-GE Realtek PHY",
|
.name = "Generic FE-GE Realtek PHY",
|
||||||
.match_phy_device = rtlgen_match_phy_device,
|
.match_phy_device = rtlgen_match_phy_device,
|
||||||
|
.read_status = rtlgen_read_status,
|
||||||
.suspend = genphy_suspend,
|
.suspend = genphy_suspend,
|
||||||
.resume = genphy_resume,
|
.resume = genphy_resume,
|
||||||
.read_page = rtl821x_read_page,
|
.read_page = rtl821x_read_page,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user