|
|
@@ -1124,6 +1124,52 @@ static int rtl8214fc_get_port(struct phy_device *phydev)
|
|
|
return PORT_MII;
|
|
|
}
|
|
|
|
|
|
+static int rtl8214fc_get_features(struct phy_device *phydev)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ ret = genphy_read_abilities(phydev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ /*
|
|
|
+ * The RTL8214FC only advertises TP capabilities in the standard registers. This is
|
|
|
+ * independent from what fibre/copper combination is currently activated. For now just
|
|
|
+ * announce the superset of all possible features.
|
|
|
+ */
|
|
|
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, phydev->supported);
|
|
|
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtl8214fc_read_status(struct phy_device *phydev)
|
|
|
+{
|
|
|
+ bool changed;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (rtl8214fc_media_is_fibre(phydev)) {
|
|
|
+ phydev->port = PORT_FIBRE;
|
|
|
+ ret = genphy_c37_read_status(phydev, &changed);
|
|
|
+ } else {
|
|
|
+ phydev->port = PORT_MII; /* for now aligend with rest of code */
|
|
|
+ ret = genphy_read_status(phydev);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtl8214fc_config_aneg(struct phy_device *phydev)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (rtl8214fc_media_is_fibre(phydev))
|
|
|
+ ret = genphy_c37_config_aneg(phydev);
|
|
|
+ else
|
|
|
+ ret = genphy_config_aneg(phydev);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* Enable EEE on the RTL8218B PHYs
|
|
|
* The method used is not the preferred way (which would be based on the MAC-EEE state,
|
|
|
* but the only way that works since the kernel first enables EEE in the MAC
|
|
|
@@ -3713,7 +3759,15 @@ int rtl931x_link_sts_get(u32 sds)
|
|
|
|
|
|
static int rtl8214fc_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
|
|
{
|
|
|
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
|
|
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
|
|
|
struct phy_device *phydev = upstream;
|
|
|
+ phy_interface_t iface;
|
|
|
+
|
|
|
+ sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
|
|
|
+ iface = sfp_select_interface(phydev->sfp_bus, support);
|
|
|
+
|
|
|
+ dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface));
|
|
|
|
|
|
rtl8214fc_media_set(phydev, true);
|
|
|
|
|
|
@@ -3914,17 +3968,18 @@ static struct phy_driver rtl83xx_phy_driver[] = {
|
|
|
{
|
|
|
.match_phy_device = rtl8214fc_match_phy_device,
|
|
|
.name = "Realtek RTL8214FC",
|
|
|
- .features = PHY_GBIT_FIBRE_FEATURES,
|
|
|
+ .config_aneg = rtl8214fc_config_aneg,
|
|
|
+ .get_eee = rtl8214fc_get_eee,
|
|
|
+ .get_features = rtl8214fc_get_features,
|
|
|
+ .get_port = rtl8214fc_get_port,
|
|
|
.probe = rtl8214fc_phy_probe,
|
|
|
.read_page = rtl821x_read_page,
|
|
|
- .write_page = rtl821x_write_page,
|
|
|
- .suspend = rtl8214fc_suspend,
|
|
|
+ .read_status = rtl8214fc_read_status,
|
|
|
.resume = rtl8214fc_resume,
|
|
|
- .set_loopback = genphy_loopback,
|
|
|
- .set_port = rtl8214fc_set_port,
|
|
|
- .get_port = rtl8214fc_get_port,
|
|
|
.set_eee = rtl8214fc_set_eee,
|
|
|
- .get_eee = rtl8214fc_get_eee,
|
|
|
+ .set_port = rtl8214fc_set_port,
|
|
|
+ .suspend = rtl8214fc_suspend,
|
|
|
+ .write_page = rtl821x_write_page,
|
|
|
},
|
|
|
{
|
|
|
.match_phy_device = rtl8218b_ext_match_phy_device,
|