summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2019-08-13 08:09:32 +0200
committerDavid S. Miller <davem@davemloft.net>2019-08-14 13:26:08 -0400
commit5181b473d64ee278f24035ce335b89ddc4520fc0 (patch)
tree4d2018cc8c1b9df312299d7fc5a1e7082ffecc83
parent4773f9bdb476501df565b610adc0edf1932f2c6e (diff)
net: phy: realtek: add NBase-T PHY auto-detection
Realtek provided information on how the new NIC-integrated PHY's expose whether they support 2.5G/5G/10G. This allows to automatically differentiate 1Gbps and 2.5Gbps PHY's, and therefore allows to remove the fake PHY ID mechanism for RTL8125. So far RTL8125 supports 2.5Gbps only, but register layout for faster modes has been defined already, so let's use this information to be future-proof. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/realtek.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 5b466e80d956..c948af16fb13 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -39,11 +39,16 @@
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
+#define RTL_SUPPORTS_5000FULL BIT(14)
+#define RTL_SUPPORTS_2500FULL BIT(13)
+#define RTL_SUPPORTS_10000FULL BIT(0)
#define RTL_ADV_2500FULL BIT(7)
#define RTL_LPADV_10000FULL BIT(11)
#define RTL_LPADV_5000FULL BIT(6)
#define RTL_LPADV_2500FULL BIT(5)
+#define RTL_GENERIC_PHYID 0x001cc800
+
MODULE_DESCRIPTION("Realtek PHY driver");
MODULE_AUTHOR("Johnson Leung");
MODULE_LICENSE("GPL");
@@ -263,8 +268,18 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
static int rtl8125_get_features(struct phy_device *phydev)
{
- linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
- phydev->supported);
+ int val;
+
+ val = phy_read_paged(phydev, 0xa61, 0x13);
+ if (val < 0)
+ return val;
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+ phydev->supported, val & RTL_SUPPORTS_2500FULL);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+ phydev->supported, val & RTL_SUPPORTS_5000FULL);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ phydev->supported, val & RTL_SUPPORTS_10000FULL);
return genphy_read_abilities(phydev);
}
@@ -308,6 +323,29 @@ static int rtl8125_read_status(struct phy_device *phydev)
return genphy_read_status(phydev);
}
+static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
+{
+ int val;
+
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61);
+ val = phy_read(phydev, 0x13);
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0);
+
+ return val >= 0 && val & RTL_SUPPORTS_2500FULL;
+}
+
+static int rtlgen_match_phy_device(struct phy_device *phydev)
+{
+ return phydev->phy_id == RTL_GENERIC_PHYID &&
+ !rtlgen_supports_2_5gbps(phydev);
+}
+
+static int rtl8125_match_phy_device(struct phy_device *phydev)
+{
+ return phydev->phy_id == RTL_GENERIC_PHYID &&
+ rtlgen_supports_2_5gbps(phydev);
+}
+
static struct phy_driver realtek_drvs[] = {
{
PHY_ID_MATCH_EXACT(0x00008201),
@@ -378,15 +416,15 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- PHY_ID_MATCH_EXACT(0x001cc800),
- .name = "Generic Realtek PHY",
+ .name = "Generic FE-GE Realtek PHY",
+ .match_phy_device = rtlgen_match_phy_device,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- PHY_ID_MATCH_EXACT(0x001cca50),
.name = "RTL8125 2.5Gbps internal",
+ .match_phy_device = rtl8125_match_phy_device,
.get_features = rtl8125_get_features,
.config_aneg = rtl8125_config_aneg,
.read_status = rtl8125_read_status,