Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 56549
b: refs/heads/master
c: 5bb96e9
h: refs/heads/master
i:
  56547: 4b6b0c5
v: v3
  • Loading branch information
Eugene Surovegin authored and Jeff Garzik committed May 18, 2007
1 parent a986ae4 commit 94df69b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0ec6d95053885055a50d973b3a3906905a78a8bf
refs/heads/master: 5bb96e9f2434b49a5b8f135f2a384974aa73db51
60 changes: 45 additions & 15 deletions trunk/drivers/net/ibm_emac/ibm_emac_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <asm/ocp.h>

#include "ibm_emac_core.h"
#include "ibm_emac_phy.h"

static inline int phy_read(struct mii_phy *phy, int reg)
Expand All @@ -34,28 +35,51 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
phy->mdio_write(phy->dev, phy->address, reg, val);
}

int mii_reset_phy(struct mii_phy *phy)
/*
* polls MII_BMCR until BMCR_RESET bit clears or operation times out.
*
* returns:
* >= 0 => success, value in BMCR returned to caller
* -EBUSY => failure, RESET bit never cleared
* otherwise => failure, lower level PHY read failed
*/
static int mii_spin_reset_complete(struct mii_phy *phy)
{
int val;
int limit = 10000;

while (limit--) {
val = phy_read(phy, MII_BMCR);
if (val >= 0 && !(val & BMCR_RESET))
return val; /* success */
udelay(10);
}
if (val & BMCR_RESET)
val = -EBUSY;

if (net_ratelimit())
printk(KERN_ERR "emac%d: PHY reset timeout (%d)\n",
((struct ocp_enet_private *)phy->dev->priv)->def->index,
val);
return val;
}

int mii_reset_phy(struct mii_phy *phy)
{
int val;

val = phy_read(phy, MII_BMCR);
val &= ~BMCR_ISOLATE;
val |= BMCR_RESET;
phy_write(phy, MII_BMCR, val);

udelay(300);

while (limit--) {
val = phy_read(phy, MII_BMCR);
if (val >= 0 && (val & BMCR_RESET) == 0)
break;
udelay(10);
}
if ((val & BMCR_ISOLATE) && limit > 0)
val = mii_spin_reset_complete(phy);
if (val >= 0 && (val & BMCR_ISOLATE))
phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);

return limit <= 0;
return val < 0;
}

static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
Expand Down Expand Up @@ -102,8 +126,14 @@ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
}

/* Start/Restart aneg */
ctl = phy_read(phy, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
/* on some PHYs (e.g. National DP83843) a write to MII_ADVERTISE
* causes BMCR_RESET to be set on the next read of MII_BMCR, which
* if not checked for causes the PHY to be reset below */
ctl = mii_spin_reset_complete(phy);
if (ctl < 0)
return ctl;

ctl |= BMCR_ANENABLE | BMCR_ANRESTART;
phy_write(phy, MII_BMCR, ctl);

return 0;
Expand All @@ -118,13 +148,13 @@ static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
phy->duplex = fd;
phy->pause = phy->asym_pause = 0;

/* First reset the PHY */
mii_reset_phy(phy);

ctl = phy_read(phy, MII_BMCR);
if (ctl < 0)
return ctl;
ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);

/* First reset the PHY */
phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE | BMCR_SPEED1000);

/* Select speed & duplex */
switch (speed) {
Expand Down

0 comments on commit 94df69b

Please sign in to comment.