summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-08-16 09:32:18 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2020-09-02 09:59:54 +0100
commitc616669da716516ac4556714aaee693280cfb069 (patch)
tree12dd45c8e122f9c425a189b32c35ea159a873be6
parentf993ec0c3670499f027ecf57a1561e5895648f25 (diff)
net: phy: marvell10g: select host interface configuration
Select the host interface configuration according to the capabilities of the host; this allows the kernel to support SFP modules using the 88x3310. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/phy/marvell10g.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 9c9a31a99673..46a518f2783d 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -95,6 +95,7 @@ enum {
MV_V2_PORT_CTRL = 0xf001,
MV_V2_PORT_CTRL_SWRST = BIT(15),
MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
+ MV_V2_PORT_CTRL_MACTYPE = 7 << 0,
/* Temperature control/read registers (88X3310 only) */
MV_V2_TEMP_CTRL = 0xf08a,
MV_V2_TEMP_CTRL_MASK = 0xc000,
@@ -593,17 +594,43 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
}
+static int mv3310_select_mode(struct phy_device *phydev,
+ unsigned long *host_interfaces)
+{
+ int mac_type = -1;
+
+ if (test_bit(PHY_INTERFACE_MODE_USXGMII, host_interfaces))
+ mac_type = 7;
+ else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces) &&
+ test_bit(PHY_INTERFACE_MODE_10GBASER, host_interfaces))
+ mac_type = 4;
+ else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces) &&
+ test_bit(PHY_INTERFACE_MODE_RXAUI, host_interfaces))
+ mac_type = 0;
+ else if (test_bit(PHY_INTERFACE_MODE_10GBASER, host_interfaces))
+ mac_type = 6;
+ else if (test_bit(PHY_INTERFACE_MODE_RXAUI, host_interfaces))
+ mac_type = 2;
+ else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces))
+ mac_type = 4;
+
+ return mac_type;
+}
+
static int mv3310_config_init(struct phy_device *phydev)
{
- int err;
+ int ret, err, mac_type = -1;
/* Check that the PHY interface type is compatible */
- if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
- phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
- phydev->interface != PHY_INTERFACE_MODE_XAUI &&
- phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
- phydev->interface != PHY_INTERFACE_MODE_10GBASER)
+ if (!phy_interface_empty(phydev->host_interfaces)) {
+ mac_type = mv3310_select_mode(phydev, phydev->host_interfaces);
+ } else if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
+ phydev->interface != PHY_INTERFACE_MODE_XAUI &&
+ phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
+ phydev->interface != PHY_INTERFACE_MODE_10GBASER) {
return -ENODEV;
+ }
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
@@ -612,6 +639,20 @@ static int mv3310_config_init(struct phy_device *phydev)
if (err)
return err;
+ if (mac_type != -1) {
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2,
+ MV_V2_PORT_CTRL,
+ MV_V2_PORT_CTRL_MACTYPE, mac_type);
+ if (ret > 0)
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+ MV_V2_PORT_CTRL,
+ MV_V2_PORT_CTRL_SWRST,
+ MV_V2_PORT_CTRL_SWRST);
+
+ if (ret < 0)
+ return ret;
+ }
+
/* Enable EDPD mode - saving 600mW */
err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
if (err)