diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index bc71947..303c5ae 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -32,10 +32,56 @@
#define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
#define AT803X_DEBUG_RGMII_TX_CLK_DLY BIT(8)
+#define AT803X_BMCR_SOFTRESET BIT(15)
+
MODULE_DESCRIPTION("Atheros 803x PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
+struct at803x_priv {
+ bool phy_reset;
+};
+
+static void at803x_adjust_state(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+
+ if (phydev->state == PHY_NOLINK) {
+ unsigned long timeout;
+ unsigned int val;
+
+ if (priv->phy_reset)
+ return;
+
+ val = phy_read(phydev, MII_BMCR);
+ val |= AT803X_BMCR_SOFTRESET;
+ phy_write(phydev, MII_BMCR, val);
+
+ timeout = jiffies + HZ/10;
+ do {
+ cpu_relax();
+ } while ((phy_read(phydev, MII_BMCR) & AT803X_BMCR_SOFTRESET) &&
+ time_after(timeout, jiffies));
+
+ WARN(phy_read(phydev, MII_BMCR) & AT803X_BMCR_SOFTRESET,
+ "failed to soft-reset phy\n");
+
+ priv->phy_reset = true;
+ } else {
+ priv->phy_reset = false;
+ }
+}
+
+static int at803x_probe(struct phy_device *phydev)
+{
+ phydev->priv = devm_kzalloc(&phydev->dev, sizeof(struct at803x_priv),
+ GFP_KERNEL);
+ if (!phydev->priv)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int at803x_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{@@ -197,6 +243,7 @@ static struct phy_driver at803x_driver[] = {
.phy_id = 0x004dd072,
.name = "Atheros 8035 ethernet",
.phy_id_mask = 0xffffffef,
+ .probe = at803x_probe,
.config_init = at803x_config_init,
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,@@ -206,6 +253,7 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .adjust_state = at803x_adjust_state,
.driver = {
.owner = THIS_MODULE,
},@@ -214,6 +262,7 @@ static struct phy_driver at803x_driver[] = {
.phy_id = 0x004dd076,
.name = "Atheros 8030 ethernet",
.phy_id_mask = 0xffffffef,
+ .probe = at803x_probe,
.config_init = at803x_config_init,
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,@@ -223,6 +272,7 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .adjust_state = at803x_adjust_state,
.driver = {
.owner = THIS_MODULE,
},@@ -231,6 +281,7 @@ static struct phy_driver at803x_driver[] = {
.phy_id = 0x004dd074,
.name = "Atheros 8031 ethernet",
.phy_id_mask = 0xffffffef,
+ .probe = at803x_probe,
.config_init = at803x_config_init,
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,@@ -240,6 +291,7 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .adjust_state = at803x_adjust_state,
.driver = {
.owner = THIS_MODULE,
},--
1.8.4.2