| From 0836d9fb41ed90090ef4af0d7abe784ee7706f80 Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Fri, 14 Apr 2017 14:21:25 +0100 |
| Subject: [PATCH 636/660] net: phy: marvell10g: add SFP+ support |
| |
| Add support for SFP+ cages to the Marvell 10G PHY driver. This is |
| slightly complicated by the way phylib works in that we need to use |
| a multi-step process to attach the SFP bus, and we also need to track |
| the phylink state machine to know when the module's transmit disable |
| signal should change state. |
| |
| With appropriate DT changes, this allows the SFP+ canges on the |
| Macchiatobin platform to be functional. |
| |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| --- |
| drivers/net/phy/marvell10g.c | 25 ++++++++++++++++++++++++- |
| 1 file changed, 24 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/net/phy/marvell10g.c |
| +++ b/drivers/net/phy/marvell10g.c |
| @@ -26,6 +26,7 @@ |
| #include <linux/hwmon.h> |
| #include <linux/marvell_phy.h> |
| #include <linux/phy.h> |
| +#include <linux/sfp.h> |
| |
| #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe |
| #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa) |
| @@ -206,6 +207,28 @@ static int mv3310_hwmon_probe(struct phy |
| } |
| #endif |
| |
| +static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) |
| +{ |
| + struct phy_device *phydev = upstream; |
| + __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; |
| + phy_interface_t iface; |
| + |
| + sfp_parse_support(phydev->sfp_bus, id, support); |
| + iface = sfp_select_interface(phydev->sfp_bus, id, support); |
| + |
| + if (iface != PHY_INTERFACE_MODE_10GKR) { |
| + dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); |
| + return -EINVAL; |
| + } |
| + return 0; |
| +} |
| + |
| +static const struct sfp_upstream_ops mv3310_sfp_ops = { |
| + .attach = phy_sfp_attach, |
| + .detach = phy_sfp_detach, |
| + .module_insert = mv3310_sfp_insert, |
| +}; |
| + |
| static int mv3310_probe(struct phy_device *phydev) |
| { |
| struct mv3310_priv *priv; |
| @@ -236,7 +259,7 @@ static int mv3310_probe(struct phy_devic |
| if (ret) |
| return ret; |
| |
| - return 0; |
| + return phy_sfp_probe(phydev, &mv3310_sfp_ops); |
| } |
| |
| static int mv3310_suspend(struct phy_device *phydev) |