diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2014-02-17 16:34:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-17 16:40:09 -0500 |
commit | 9df81dd7583d14862d0cfb673a941b261f3b2112 (patch) | |
tree | a790b50329b80f6a6b29f745fd2baad8b4d1944f /drivers/net/phy/phy_device.c | |
parent | 797ac07137d9ae8572008e21e6123a9ae17dae50 (diff) |
net: phy: allow PHY drivers to implement their own software reset
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>
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7c21b8214bb9..a70b604ac644 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -535,12 +535,16 @@ static int phy_poll_reset(struct phy_device *phydev) | |||
535 | 535 | ||
536 | int phy_init_hw(struct phy_device *phydev) | 536 | int phy_init_hw(struct phy_device *phydev) |
537 | { | 537 | { |
538 | int ret; | 538 | int ret = 0; |
539 | 539 | ||
540 | if (!phydev->drv || !phydev->drv->config_init) | 540 | if (!phydev->drv || !phydev->drv->config_init) |
541 | return 0; | 541 | return 0; |
542 | 542 | ||
543 | ret = genphy_soft_reset(phydev); | 543 | if (phydev->drv->soft_reset) |
544 | ret = phydev->drv->soft_reset(phydev); | ||
545 | else | ||
546 | ret = genphy_soft_reset(phydev); | ||
547 | |||
544 | if (ret < 0) | 548 | if (ret < 0) |
545 | return ret; | 549 | return ret; |
546 | 550 | ||
@@ -1108,6 +1112,12 @@ static int genphy_config_init(struct phy_device *phydev) | |||
1108 | return 0; | 1112 | return 0; |
1109 | } | 1113 | } |
1110 | 1114 | ||
1115 | static int gen10g_soft_reset(struct phy_device *phydev) | ||
1116 | { | ||
1117 | /* Do nothing for now */ | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1111 | static int gen10g_config_init(struct phy_device *phydev) | 1121 | static int gen10g_config_init(struct phy_device *phydev) |
1112 | { | 1122 | { |
1113 | /* Temporarily just say we support everything */ | 1123 | /* Temporarily just say we support everything */ |
@@ -1282,6 +1292,7 @@ static struct phy_driver genphy_driver[] = { | |||
1282 | .phy_id = 0xffffffff, | 1292 | .phy_id = 0xffffffff, |
1283 | .phy_id_mask = 0xffffffff, | 1293 | .phy_id_mask = 0xffffffff, |
1284 | .name = "Generic PHY", | 1294 | .name = "Generic PHY", |
1295 | .soft_reset = genphy_soft_reset, | ||
1285 | .config_init = genphy_config_init, | 1296 | .config_init = genphy_config_init, |
1286 | .features = 0, | 1297 | .features = 0, |
1287 | .config_aneg = genphy_config_aneg, | 1298 | .config_aneg = genphy_config_aneg, |
@@ -1294,6 +1305,7 @@ static struct phy_driver genphy_driver[] = { | |||
1294 | .phy_id = 0xffffffff, | 1305 | .phy_id = 0xffffffff, |
1295 | .phy_id_mask = 0xffffffff, | 1306 | .phy_id_mask = 0xffffffff, |
1296 | .name = "Generic 10G PHY", | 1307 | .name = "Generic 10G PHY", |
1308 | .soft_reset = gen10g_soft_reset, | ||
1297 | .config_init = gen10g_config_init, | 1309 | .config_init = gen10g_config_init, |
1298 | .features = 0, | 1310 | .features = 0, |
1299 | .config_aneg = gen10g_config_aneg, | 1311 | .config_aneg = gen10g_config_aneg, |