diff options
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2f6989b1e0dc..0ce606624296 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -139,6 +139,7 @@ static int phy_scan_fixups(struct phy_device *phydev) | |||
139 | mutex_unlock(&phy_fixup_lock); | 139 | mutex_unlock(&phy_fixup_lock); |
140 | return err; | 140 | return err; |
141 | } | 141 | } |
142 | phydev->has_fixups = true; | ||
142 | } | 143 | } |
143 | } | 144 | } |
144 | mutex_unlock(&phy_fixup_lock); | 145 | mutex_unlock(&phy_fixup_lock); |
@@ -534,16 +535,16 @@ static int phy_poll_reset(struct phy_device *phydev) | |||
534 | 535 | ||
535 | int phy_init_hw(struct phy_device *phydev) | 536 | int phy_init_hw(struct phy_device *phydev) |
536 | { | 537 | { |
537 | int ret; | 538 | int ret = 0; |
538 | 539 | ||
539 | if (!phydev->drv || !phydev->drv->config_init) | 540 | if (!phydev->drv || !phydev->drv->config_init) |
540 | return 0; | 541 | return 0; |
541 | 542 | ||
542 | ret = phy_write(phydev, MII_BMCR, BMCR_RESET); | 543 | if (phydev->drv->soft_reset) |
543 | if (ret < 0) | 544 | ret = phydev->drv->soft_reset(phydev); |
544 | return ret; | 545 | else |
546 | ret = genphy_soft_reset(phydev); | ||
545 | 547 | ||
546 | ret = phy_poll_reset(phydev); | ||
547 | if (ret < 0) | 548 | if (ret < 0) |
548 | return ret; | 549 | return ret; |
549 | 550 | ||
@@ -864,6 +865,22 @@ int genphy_config_aneg(struct phy_device *phydev) | |||
864 | } | 865 | } |
865 | EXPORT_SYMBOL(genphy_config_aneg); | 866 | EXPORT_SYMBOL(genphy_config_aneg); |
866 | 867 | ||
868 | /** | ||
869 | * genphy_aneg_done - return auto-negotiation status | ||
870 | * @phydev: target phy_device struct | ||
871 | * | ||
872 | * Description: Reads the status register and returns 0 either if | ||
873 | * auto-negotiation is incomplete, or if there was an error. | ||
874 | * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done. | ||
875 | */ | ||
876 | int genphy_aneg_done(struct phy_device *phydev) | ||
877 | { | ||
878 | int retval = phy_read(phydev, MII_BMSR); | ||
879 | |||
880 | return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE); | ||
881 | } | ||
882 | EXPORT_SYMBOL(genphy_aneg_done); | ||
883 | |||
867 | static int gen10g_config_aneg(struct phy_device *phydev) | 884 | static int gen10g_config_aneg(struct phy_device *phydev) |
868 | { | 885 | { |
869 | return 0; | 886 | return 0; |
@@ -1029,6 +1046,27 @@ static int gen10g_read_status(struct phy_device *phydev) | |||
1029 | return 0; | 1046 | return 0; |
1030 | } | 1047 | } |
1031 | 1048 | ||
1049 | /** | ||
1050 | * genphy_soft_reset - software reset the PHY via BMCR_RESET bit | ||
1051 | * @phydev: target phy_device struct | ||
1052 | * | ||
1053 | * Description: Perform a software PHY reset using the standard | ||
1054 | * BMCR_RESET bit and poll for the reset bit to be cleared. | ||
1055 | * | ||
1056 | * Returns: 0 on success, < 0 on failure | ||
1057 | */ | ||
1058 | int genphy_soft_reset(struct phy_device *phydev) | ||
1059 | { | ||
1060 | int ret; | ||
1061 | |||
1062 | ret = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
1063 | if (ret < 0) | ||
1064 | return ret; | ||
1065 | |||
1066 | return phy_poll_reset(phydev); | ||
1067 | } | ||
1068 | EXPORT_SYMBOL(genphy_soft_reset); | ||
1069 | |||
1032 | static int genphy_config_init(struct phy_device *phydev) | 1070 | static int genphy_config_init(struct phy_device *phydev) |
1033 | { | 1071 | { |
1034 | int val; | 1072 | int val; |
@@ -1075,6 +1113,12 @@ static int genphy_config_init(struct phy_device *phydev) | |||
1075 | return 0; | 1113 | return 0; |
1076 | } | 1114 | } |
1077 | 1115 | ||
1116 | static int gen10g_soft_reset(struct phy_device *phydev) | ||
1117 | { | ||
1118 | /* Do nothing for now */ | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1078 | static int gen10g_config_init(struct phy_device *phydev) | 1122 | static int gen10g_config_init(struct phy_device *phydev) |
1079 | { | 1123 | { |
1080 | /* Temporarily just say we support everything */ | 1124 | /* Temporarily just say we support everything */ |
@@ -1249,9 +1293,11 @@ static struct phy_driver genphy_driver[] = { | |||
1249 | .phy_id = 0xffffffff, | 1293 | .phy_id = 0xffffffff, |
1250 | .phy_id_mask = 0xffffffff, | 1294 | .phy_id_mask = 0xffffffff, |
1251 | .name = "Generic PHY", | 1295 | .name = "Generic PHY", |
1296 | .soft_reset = genphy_soft_reset, | ||
1252 | .config_init = genphy_config_init, | 1297 | .config_init = genphy_config_init, |
1253 | .features = 0, | 1298 | .features = 0, |
1254 | .config_aneg = genphy_config_aneg, | 1299 | .config_aneg = genphy_config_aneg, |
1300 | .aneg_done = genphy_aneg_done, | ||
1255 | .read_status = genphy_read_status, | 1301 | .read_status = genphy_read_status, |
1256 | .suspend = genphy_suspend, | 1302 | .suspend = genphy_suspend, |
1257 | .resume = genphy_resume, | 1303 | .resume = genphy_resume, |
@@ -1260,6 +1306,7 @@ static struct phy_driver genphy_driver[] = { | |||
1260 | .phy_id = 0xffffffff, | 1306 | .phy_id = 0xffffffff, |
1261 | .phy_id_mask = 0xffffffff, | 1307 | .phy_id_mask = 0xffffffff, |
1262 | .name = "Generic 10G PHY", | 1308 | .name = "Generic 10G PHY", |
1309 | .soft_reset = gen10g_soft_reset, | ||
1263 | .config_init = gen10g_config_init, | 1310 | .config_init = gen10g_config_init, |
1264 | .features = 0, | 1311 | .features = 0, |
1265 | .config_aneg = gen10g_config_aneg, | 1312 | .config_aneg = gen10g_config_aneg, |