Skip to content

Commit

Permalink
at803x: fix suspend/resume for SGMII link
Browse files Browse the repository at this point in the history
When operating the at803x in SGMII mode, resuming the chip
from power down brings up the copper-side link but leaves
the SGMII link in unconnected state (tested with at8031
attached to gianfar). In effect, this caused a permanent
link loss once the related interface was put down.

This patch ensures that power down handling in supspend()
and resume() is also applied to the SGMII link.

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Zefir Kurtisi authored and David S. Miller committed Mar 14, 2016
1 parent 5d60841 commit 9826731
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions drivers/net/phy/at803x.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
#define AT803X_DEBUG_REG_5 0x05
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)

#define AT803X_REG_CHIP_CONFIG 0x1f
#define AT803X_BT_BX_REG_SEL 0x8000

#define ATH8030_PHY_ID 0x004dd076
#define ATH8031_PHY_ID 0x004dd074
#define ATH8035_PHY_ID 0x004dd072
Expand Down Expand Up @@ -206,6 +209,7 @@ static int at803x_suspend(struct phy_device *phydev)
{
int value;
int wol_enabled;
int ccr;

mutex_lock(&phydev->lock);

Expand All @@ -221,6 +225,16 @@ static int at803x_suspend(struct phy_device *phydev)

phy_write(phydev, MII_BMCR, value);

if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
goto done;

/* also power-down SGMII interface */
ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);

done:
mutex_unlock(&phydev->lock);

return 0;
Expand All @@ -229,13 +243,25 @@ static int at803x_suspend(struct phy_device *phydev)
static int at803x_resume(struct phy_device *phydev)
{
int value;
int ccr;

mutex_lock(&phydev->lock);

value = phy_read(phydev, MII_BMCR);
value &= ~(BMCR_PDOWN | BMCR_ISOLATE);
phy_write(phydev, MII_BMCR, value);

if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
goto done;

/* also power-up SGMII interface */
ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
value = phy_read(phydev, MII_BMCR) & ~(BMCR_PDOWN | BMCR_ISOLATE);
phy_write(phydev, MII_BMCR, value);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);

done:
mutex_unlock(&phydev->lock);

return 0;
Expand Down

0 comments on commit 9826731

Please sign in to comment.