diff options
Diffstat (limited to 'target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch')
-rw-r--r-- | target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch b/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch new file mode 100644 index 0000000000..6ca43043fa --- /dev/null +++ b/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch @@ -0,0 +1,131 @@ +From 4a4aca08b11501cb1b2c509113bbb65eb66a1f45 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: sfp: hack: allow marvell 10G phy support to use SFP + +Allow the Marvell 10G PHY to register with the SFP bus, so that SFP+ +cages can work. This bypasses phylink, meaning that socket status +is not taken into account for the link state. Also, the tx-disable +signal must be commented out in DT for this to work... + +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +--- + drivers/net/phy/marvell10g.c | 54 +++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 53 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -15,8 +15,10 @@ + * If both the fiber and copper ports are connected, the first to gain + * link takes priority and the other port is completely locked out. + */ ++#include <linux/of.h> + #include <linux/phy.h> + #include <linux/marvell_phy.h> ++#include <linux/sfp.h> + + enum { + MV_PCS_BASE_T = 0x0000, +@@ -38,6 +40,11 @@ enum { + MV_AN_RESULT_SPD_10000 = BIT(15), + }; + ++struct mv3310_priv { ++ struct device_node *sfp_node; ++ struct sfp_bus *sfp_bus; ++}; ++ + static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg, + u16 mask, u16 bits) + { +@@ -56,17 +63,52 @@ static int mv3310_modify(struct phy_devi + return ret < 0 ? ret : 1; + } + ++static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ ++ if (sfp_parse_interface(priv->sfp_bus, id) != 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 = { ++ .module_insert = mv3310_sfp_insert, ++}; ++ + static int mv3310_probe(struct phy_device *phydev) + { ++ struct mv3310_priv *priv; + u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; + + if (!phydev->is_c45 || + (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) + return -ENODEV; + ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&phydev->mdio.dev, priv); ++ ++ if (phydev->mdio.dev.of_node) ++ priv->sfp_node = of_parse_phandle(phydev->mdio.dev.of_node, ++ "sfp", 0); ++ + return 0; + } + ++static void mv3310_remove(struct phy_device *phydev) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ ++ if (priv->sfp_bus) ++ sfp_unregister_upstream(priv->sfp_bus); ++} ++ + /* + * Resetting the MV88X3310 causes it to become non-responsive. Avoid + * setting the reset bit(s). +@@ -78,6 +120,7 @@ static int mv3310_soft_reset(struct phy_ + + static int mv3310_config_init(struct phy_device *phydev) + { ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; + u32 mask; + int val; +@@ -166,6 +209,14 @@ static int mv3310_config_init(struct phy + phydev->supported &= mask; + phydev->advertising &= phydev->supported; + ++ /* Would be nice to do this in the probe function, but unfortunately, ++ * phylib doesn't have phydev->attached_dev set there. ++ */ ++ if (priv->sfp_node && !priv->sfp_bus) ++ priv->sfp_bus = sfp_register_upstream(priv->sfp_node, ++ phydev->attached_dev, ++ phydev, &mv3310_sfp_ops); ++ + return 0; + } + +@@ -349,12 +400,13 @@ static struct phy_driver mv3310_drivers[ + SUPPORTED_FIBRE | + SUPPORTED_10000baseT_Full | + SUPPORTED_Backplane, +- .probe = mv3310_probe, + .soft_reset = mv3310_soft_reset, + .config_init = mv3310_config_init, ++ .probe = mv3310_probe, + .config_aneg = mv3310_config_aneg, + .aneg_done = mv3310_aneg_done, + .read_status = mv3310_read_status, ++ .remove = mv3310_remove, + }, + }; + |