diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index 50b991870edb..38afcd081a2a 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -968,22 +968,22 @@ static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane, return err; } +static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + return lynx_phy_mode_to_lane_mode(phy, mode, submode, NULL); +} + static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) { - struct lynx_28g_lane *lane = phy_get_drvdata(phy); + struct lynx_lane *lane = phy_get_drvdata(phy); int powered_up = lane->powered_up; enum lynx_lane_mode lane_mode; - int err = 0; + int err; - if (mode != PHY_MODE_ETHERNET) - return -EOPNOTSUPP; - - if (lane->mode == LANE_MODE_UNKNOWN) - return -EOPNOTSUPP; - - lane_mode = phy_interface_to_lane_mode(submode); - if (!lynx_lane_supports_mode(lane, lane_mode)) - return -EOPNOTSUPP; + err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode); + if (err) + return err; if (lane_mode == lane->mode) return 0; @@ -1014,22 +1014,6 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) return err; } -static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode, - union phy_configure_opts *opts __always_unused) -{ - struct lynx_28g_lane *lane = phy_get_drvdata(phy); - enum lynx_lane_mode lane_mode; - - if (mode != PHY_MODE_ETHERNET) - return -EOPNOTSUPP; - - lane_mode = phy_interface_to_lane_mode(submode); - if (!lynx_lane_supports_mode(lane, lane_mode)) - return -EOPNOTSUPP; - - return 0; -} - static int lynx_28g_init(struct phy *phy) { struct lynx_28g_lane *lane = phy_get_drvdata(phy); diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c index 226b2af2b599..1e411bfab404 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-core.c +++ b/drivers/phy/freescale/phy-fsl-lynx-core.c @@ -89,6 +89,36 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode) } EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX"); +/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a + * lane_mode and return 0 if it is supported and we can transition to it from + * the current lane mode, or return negative error otherwise. + */ +int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode, + int submode, enum lynx_lane_mode *lane_mode) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + enum lynx_lane_mode tmp_lane_mode; + + /* The protocol configuration tables are incomplete for full lane + * reconfiguration from an arbitrary protocol. + */ + if (lane->mode == LANE_MODE_UNKNOWN) + return -EINVAL; + + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + tmp_lane_mode = phy_interface_to_lane_mode(submode); + if (!lynx_lane_supports_mode(lane, tmp_lane_mode)) + return -EINVAL; + + if (lane_mode) + *lane_mode = tmp_lane_mode; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_phy_mode_to_lane_mode, "PHY_FSL_LYNX"); + struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode) { struct lynx_pll *pll; diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h index 3d9508dfb2c1..37fa4b544faa 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-core.h +++ b/drivers/phy/freescale/phy-fsl-lynx-core.h @@ -113,6 +113,8 @@ void lynx_remove(struct platform_device *pdev); const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode); enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf); bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode); +int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode, + int submode, enum lynx_lane_mode *lane_mode); struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode);