net: phy: allow PHY drivers to implement their own software reset
authorFlorian Fainelli <f.fainelli@gmail.com>
Mon, 17 Feb 2014 21:34:03 +0000 (13:34 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Feb 2014 21:40:09 +0000 (16:40 -0500)
As pointed out by Shaohui, most 10G PHYs out there have a non-standard
compliant software reset sequence, eventually something much more
complex than just toggling the BMCR_RESET bit. Allow PHY driver to
implement their own soft_reset() callback to deal with that. If no
callback is provided, call into genphy_soft_reset() which makes sure the
existing behavior is kept intact.

Reported-by: Shaohui Xie <Shaohui.Xie@freescale.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phy_device.c
include/linux/phy.h

index 7c21b8214bb982d115a18011f180748e18ee6657..a70b604ac6446bc2347e48f821002517f62afca1 100644 (file)
@@ -535,12 +535,16 @@ static int phy_poll_reset(struct phy_device *phydev)
 
 int phy_init_hw(struct phy_device *phydev)
 {
-       int ret;
+       int ret = 0;
 
        if (!phydev->drv || !phydev->drv->config_init)
                return 0;
 
-       ret = genphy_soft_reset(phydev);
+       if (phydev->drv->soft_reset)
+               ret = phydev->drv->soft_reset(phydev);
+       else
+               ret = genphy_soft_reset(phydev);
+
        if (ret < 0)
                return ret;
 
@@ -1108,6 +1112,12 @@ static int genphy_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int gen10g_soft_reset(struct phy_device *phydev)
+{
+       /* Do nothing for now */
+       return 0;
+}
+
 static int gen10g_config_init(struct phy_device *phydev)
 {
        /* Temporarily just say we support everything */
@@ -1282,6 +1292,7 @@ static struct phy_driver genphy_driver[] = {
        .phy_id         = 0xffffffff,
        .phy_id_mask    = 0xffffffff,
        .name           = "Generic PHY",
+       .soft_reset     = genphy_soft_reset,
        .config_init    = genphy_config_init,
        .features       = 0,
        .config_aneg    = genphy_config_aneg,
@@ -1294,6 +1305,7 @@ static struct phy_driver genphy_driver[] = {
        .phy_id         = 0xffffffff,
        .phy_id_mask    = 0xffffffff,
        .name           = "Generic 10G PHY",
+       .soft_reset     = gen10g_soft_reset,
        .config_init    = gen10g_config_init,
        .features       = 0,
        .config_aneg    = gen10g_config_aneg,
index bffe0ec1604f635ba6b0a1949a887c4b3c1e2eae..24126c4b27b58e443fe3569fa7143e256466ce84 100644 (file)
@@ -439,6 +439,11 @@ struct phy_driver {
        u32 features;
        u32 flags;
 
+       /*
+        * Called to issue a PHY software reset
+        */
+       int (*soft_reset)(struct phy_device *phydev);
+
        /*
         * Called to initialize the PHY,
         * including after a reset