aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/marvell.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2018-09-25 14:28:46 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-25 23:26:45 -0400
commitd6ab93364734bd88a1011432faa9253680f7e9da (patch)
treed4212b6bc158f001a595aecc3f3018ccb62829cb /drivers/net/phy/marvell.c
parent6e2d85ec05591b739059f65fe8438c9c5999f7d8 (diff)
net: phy: marvell: Avoid unnecessary soft reset
The BMCR.RESET bit on the Marvell PHYs has a special meaning in that it commits the register writes into the HW for it to latch and be configured appropriately. Doing software resets causes link drops, and this is unnecessary disruption if nothing changed. Determine from marvell_set_polarity()'s return code whether the register value was changed and if it was, propagate that to the logic that hits the software reset bit. This avoids doing unnecessary soft reset if the PHY is configured in the same state it was previously, this also eliminates the need for a m88e1111_config_aneg() function since it now is the same as marvell_config_aneg(). Tested-by: Wang, Dongsheng <dongsheng.wang@hxt-semitech.com> Tested-by: Chris Healy <cphealy@gmail.com> Tested-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Clemens Gruber <clemens.gruber@pqgruber.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/marvell.c')
-rw-r--r--drivers/net/phy/marvell.c63
1 files changed, 21 insertions, 42 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index f7c69ca34056..b55a7376bfdc 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -265,7 +265,7 @@ static int marvell_set_polarity(struct phy_device *phydev, int polarity)
265 return err; 265 return err;
266 } 266 }
267 267
268 return 0; 268 return val != reg;
269} 269}
270 270
271static int marvell_set_downshift(struct phy_device *phydev, bool enable, 271static int marvell_set_downshift(struct phy_device *phydev, bool enable,
@@ -287,12 +287,15 @@ static int marvell_set_downshift(struct phy_device *phydev, bool enable,
287 287
288static int marvell_config_aneg(struct phy_device *phydev) 288static int marvell_config_aneg(struct phy_device *phydev)
289{ 289{
290 int changed = 0;
290 int err; 291 int err;
291 292
292 err = marvell_set_polarity(phydev, phydev->mdix_ctrl); 293 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
293 if (err < 0) 294 if (err < 0)
294 return err; 295 return err;
295 296
297 changed = err;
298
296 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 299 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
297 MII_M1111_PHY_LED_DIRECT); 300 MII_M1111_PHY_LED_DIRECT);
298 if (err < 0) 301 if (err < 0)
@@ -302,7 +305,7 @@ static int marvell_config_aneg(struct phy_device *phydev)
302 if (err < 0) 305 if (err < 0)
303 return err; 306 return err;
304 307
305 if (phydev->autoneg != AUTONEG_ENABLE) { 308 if (phydev->autoneg != AUTONEG_ENABLE || changed) {
306 /* A write to speed/duplex bits (that is performed by 309 /* A write to speed/duplex bits (that is performed by
307 * genphy_config_aneg() call above) must be followed by 310 * genphy_config_aneg() call above) must be followed by
308 * a software reset. Otherwise, the write has no effect. 311 * a software reset. Otherwise, the write has no effect.
@@ -350,42 +353,6 @@ static int m88e1101_config_aneg(struct phy_device *phydev)
350 return marvell_config_aneg(phydev); 353 return marvell_config_aneg(phydev);
351} 354}
352 355
353static int m88e1111_config_aneg(struct phy_device *phydev)
354{
355 int err;
356
357 /* The Marvell PHY has an errata which requires
358 * that certain registers get written in order
359 * to restart autonegotiation
360 */
361 err = genphy_soft_reset(phydev);
362
363 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
364 if (err < 0)
365 return err;
366
367 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
368 MII_M1111_PHY_LED_DIRECT);
369 if (err < 0)
370 return err;
371
372 err = genphy_config_aneg(phydev);
373 if (err < 0)
374 return err;
375
376 if (phydev->autoneg != AUTONEG_ENABLE) {
377 /* A write to speed/duplex bits (that is performed by
378 * genphy_config_aneg() call above) must be followed by
379 * a software reset. Otherwise, the write has no effect.
380 */
381 err = genphy_soft_reset(phydev);
382 if (err < 0)
383 return err;
384 }
385
386 return 0;
387}
388
389#ifdef CONFIG_OF_MDIO 356#ifdef CONFIG_OF_MDIO
390/* Set and/or override some configuration registers based on the 357/* Set and/or override some configuration registers based on the
391 * marvell,reg-init property stored in the of_node for the phydev. 358 * marvell,reg-init property stored in the of_node for the phydev.
@@ -479,6 +446,7 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
479 446
480static int m88e1121_config_aneg(struct phy_device *phydev) 447static int m88e1121_config_aneg(struct phy_device *phydev)
481{ 448{
449 int changed = 0;
482 int err = 0; 450 int err = 0;
483 451
484 if (phy_interface_is_rgmii(phydev)) { 452 if (phy_interface_is_rgmii(phydev)) {
@@ -487,15 +455,26 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
487 return err; 455 return err;
488 } 456 }
489 457
490 err = genphy_soft_reset(phydev); 458 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
491 if (err < 0) 459 if (err < 0)
492 return err; 460 return err;
493 461
494 err = marvell_set_polarity(phydev, phydev->mdix_ctrl); 462 changed = err;
463
464 err = genphy_config_aneg(phydev);
495 if (err < 0) 465 if (err < 0)
496 return err; 466 return err;
497 467
498 return genphy_config_aneg(phydev); 468 if (phydev->autoneg != autoneg || changed) {
469 /* A software reset is used to ensure a "commit" of the
470 * changes is done.
471 */
472 err = genphy_soft_reset(phydev);
473 if (err < 0)
474 return err;
475 }
476
477 return 0;
499} 478}
500 479
501static int m88e1318_config_aneg(struct phy_device *phydev) 480static int m88e1318_config_aneg(struct phy_device *phydev)
@@ -2067,7 +2046,7 @@ static struct phy_driver marvell_drivers[] = {
2067 .flags = PHY_HAS_INTERRUPT, 2046 .flags = PHY_HAS_INTERRUPT,
2068 .probe = marvell_probe, 2047 .probe = marvell_probe,
2069 .config_init = &m88e1111_config_init, 2048 .config_init = &m88e1111_config_init,
2070 .config_aneg = &m88e1111_config_aneg, 2049 .config_aneg = &marvell_config_aneg,
2071 .read_status = &marvell_read_status, 2050 .read_status = &marvell_read_status,
2072 .ack_interrupt = &marvell_ack_interrupt, 2051 .ack_interrupt = &marvell_ack_interrupt,
2073 .config_intr = &marvell_config_intr, 2052 .config_intr = &marvell_config_intr,