Implement the missing callbacks for Generic 10G PHY. Tested using XGMAC with a C45 PHY working at 10G Link.
Signed-off-by: Jose Abreu <joab...@synopsys.com> Cc: Andrew Lunn <and...@lunn.ch> Cc: Florian Fainelli <f.faine...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Joao Pinto <joao.pi...@synopsys.com> --- drivers/net/phy/phy-c45.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c0135217b81f..7e62bd7795a3 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -1,6 +1,7 @@ /* * Clause 45 PHY support */ +#include <linux/delay.h> #include <linux/ethtool.h> #include <linux/export.h> #include <linux/mdio.h> @@ -294,6 +295,35 @@ int gen10g_read_status(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(gen10g_read_status); +static int gen10g_poll_reset(struct phy_device *phydev) +{ + /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ + unsigned int retries = 12; + int ret; + + do { + msleep(50); + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); + if (ret < 0) + return ret; + } while (ret & MDIO_CTRL1_RESET && --retries); + if (ret & MDIO_CTRL1_RESET) + return -ETIMEDOUT; + + return 0; +} + +static int gen10g_soft_reset(struct phy_device *phydev) +{ + int val; + + val = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, MDIO_CTRL1_RESET); + if (val < 0) + return val; + + return gen10g_poll_reset(phydev); +} + int gen10g_no_soft_reset(struct phy_device *phydev) { /* Do nothing for now */ @@ -313,12 +343,36 @@ EXPORT_SYMBOL_GPL(gen10g_config_init); int gen10g_suspend(struct phy_device *phydev) { + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); + if (val < 0) + return val; + + val |= MDIO_CTRL1_LPOWER; + + val = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, val); + if (val < 0) + return val; + return 0; } EXPORT_SYMBOL_GPL(gen10g_suspend); int gen10g_resume(struct phy_device *phydev) { + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); + if (val < 0) + return val; + + val &= ~MDIO_CTRL1_LPOWER; + + val = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, val); + if (val < 0) + return val; + return 0; } EXPORT_SYMBOL_GPL(gen10g_resume); @@ -327,7 +381,7 @@ struct phy_driver genphy_10g_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic 10G PHY", - .soft_reset = gen10g_no_soft_reset, + .soft_reset = gen10g_soft_reset, .config_init = gen10g_config_init, .features = 0, .aneg_done = genphy_c45_aneg_done, -- 2.7.4