aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZefir Kurtisi <zefir.kurtisi@neratec.com>2016-10-24 06:40:54 -0400
committerDavid S. Miller <davem@davemloft.net>2016-10-27 16:05:17 -0400
commitf62265b53ef34a372b657c99e23d32e95b464316 (patch)
treec84f02849929f6a6ef4e9c58747fd7793226487b
parent4fc6d239ee5640909932c47f3c7b93dd8e415fea (diff)
at803x: double check SGMII side autoneg
In SGMII mode, we observed an autonegotiation issue after power-down-up cycles where the copper side reports successful link establishment but the SGMII side's link is down. This happened in a setup where the at8031 is connected over SGMII to a eTSEC (fsl gianfar), but so far could not be reproduced with other Ethernet device / driver combinations. This commit adds a wrapper function for at8031 that in case of operating in SGMII mode double checks SGMII link state when generic aneg_done() succeeds. It prints a warning on failure but intentionally does not try to recover from this state. As a result, if you ever see a warning '803x_aneg_done: SGMII link is not ok' you will end up having an Ethernet link up but won't get any data through. This should not happen, if it does, please contact the module maintainer. Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/at803x.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index cf74d108953e..a52b560e428b 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -42,10 +42,18 @@
42#define AT803X_MMD_ACCESS_CONTROL 0x0D 42#define AT803X_MMD_ACCESS_CONTROL 0x0D
43#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E 43#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
44#define AT803X_FUNC_DATA 0x4003 44#define AT803X_FUNC_DATA 0x4003
45#define AT803X_REG_CHIP_CONFIG 0x1f
46#define AT803X_BT_BX_REG_SEL 0x8000
45 47
46#define AT803X_DEBUG_ADDR 0x1D 48#define AT803X_DEBUG_ADDR 0x1D
47#define AT803X_DEBUG_DATA 0x1E 49#define AT803X_DEBUG_DATA 0x1E
48 50
51#define AT803X_MODE_CFG_MASK 0x0F
52#define AT803X_MODE_CFG_SGMII 0x01
53
54#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/
55#define AT803X_PSSR_MR_AN_COMPLETE 0x0200
56
49#define AT803X_DEBUG_REG_0 0x00 57#define AT803X_DEBUG_REG_0 0x00
50#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) 58#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15)
51 59
@@ -355,6 +363,36 @@ static void at803x_link_change_notify(struct phy_device *phydev)
355 } 363 }
356} 364}
357 365
366static int at803x_aneg_done(struct phy_device *phydev)
367{
368 int ccr;
369
370 int aneg_done = genphy_aneg_done(phydev);
371 if (aneg_done != BMSR_ANEGCOMPLETE)
372 return aneg_done;
373
374 /*
375 * in SGMII mode, if copper side autoneg is successful,
376 * also check SGMII side autoneg result
377 */
378 ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
379 if ((ccr & AT803X_MODE_CFG_MASK) != AT803X_MODE_CFG_SGMII)
380 return aneg_done;
381
382 /* switch to SGMII/fiber page */
383 phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
384
385 /* check if the SGMII link is OK. */
386 if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
387 pr_warn("803x_aneg_done: SGMII link is not ok\n");
388 aneg_done = 0;
389 }
390 /* switch back to copper page */
391 phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
392
393 return aneg_done;
394}
395
358static struct phy_driver at803x_driver[] = { 396static struct phy_driver at803x_driver[] = {
359{ 397{
360 /* ATHEROS 8035 */ 398 /* ATHEROS 8035 */
@@ -406,6 +444,7 @@ static struct phy_driver at803x_driver[] = {
406 .flags = PHY_HAS_INTERRUPT, 444 .flags = PHY_HAS_INTERRUPT,
407 .config_aneg = genphy_config_aneg, 445 .config_aneg = genphy_config_aneg,
408 .read_status = genphy_read_status, 446 .read_status = genphy_read_status,
447 .aneg_done = at803x_aneg_done,
409 .ack_interrupt = &at803x_ack_interrupt, 448 .ack_interrupt = &at803x_ack_interrupt,
410 .config_intr = &at803x_config_intr, 449 .config_intr = &at803x_config_intr,
411} }; 450} };