Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 328107
b: refs/heads/master
c: 871d1d6
h: refs/heads/master
i:
  328105: f8ac67b
  328103: 56eb417
v: v3
  • Loading branch information
LEROY Christophe authored and David S. Miller committed Sep 27, 2012
1 parent b436962 commit f55216c
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 26f7cbc0a5a42d8cc0c7725d10317089a8215f97
refs/heads/master: 871d1d6b59802adfd42fd22c82ec419bc8fd2f10
127 changes: 127 additions & 0 deletions trunk/drivers/net/phy/lxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,123 @@ static int lxt971_config_intr(struct phy_device *phydev)
return err;
}

/*
* A2 version of LXT973 chip has an ERRATA: it randomly return the contents
* of the previous even register when you read a odd register regularly
*/

static int lxt973a2_update_link(struct phy_device *phydev)
{
int status;
int control;
int retry = 8; /* we try 8 times */

/* Do a fake read */
status = phy_read(phydev, MII_BMSR);

if (status < 0)
return status;

control = phy_read(phydev, MII_BMCR);
if (control < 0)
return control;

do {
/* Read link and autonegotiation status */
status = phy_read(phydev, MII_BMSR);
} while (status >= 0 && retry-- && status == control);

if (status < 0)
return status;

if ((status & BMSR_LSTATUS) == 0)
phydev->link = 0;
else
phydev->link = 1;

return 0;
}

int lxt973a2_read_status(struct phy_device *phydev)
{
int adv;
int err;
int lpa;
int lpagb = 0;

/* Update the link, but return if there was an error */
err = lxt973a2_update_link(phydev);
if (err)
return err;

if (AUTONEG_ENABLE == phydev->autoneg) {
int retry = 1;

adv = phy_read(phydev, MII_ADVERTISE);

if (adv < 0)
return adv;

do {
lpa = phy_read(phydev, MII_LPA);

if (lpa < 0)
return lpa;

/* If both registers are equal, it is suspect but not
* impossible, hence a new try
*/
} while (lpa == adv && retry--);

lpa &= adv;

phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF;
phydev->pause = phydev->asym_pause = 0;

if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
phydev->speed = SPEED_1000;

if (lpagb & LPA_1000FULL)
phydev->duplex = DUPLEX_FULL;
} else if (lpa & (LPA_100FULL | LPA_100HALF)) {
phydev->speed = SPEED_100;

if (lpa & LPA_100FULL)
phydev->duplex = DUPLEX_FULL;
} else {
if (lpa & LPA_10FULL)
phydev->duplex = DUPLEX_FULL;
}

if (phydev->duplex == DUPLEX_FULL) {
phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
}
} else {
int bmcr = phy_read(phydev, MII_BMCR);

if (bmcr < 0)
return bmcr;

if (bmcr & BMCR_FULLDPLX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;

if (bmcr & BMCR_SPEED1000)
phydev->speed = SPEED_1000;
else if (bmcr & BMCR_SPEED100)
phydev->speed = SPEED_100;
else
phydev->speed = SPEED_10;

phydev->pause = phydev->asym_pause = 0;
}

return 0;
}

static int lxt973_probe(struct phy_device *phydev)
{
int val = phy_read(phydev, MII_LXT973_PCR);
Expand Down Expand Up @@ -173,6 +290,16 @@ static struct phy_driver lxt97x_driver[] = {
.ack_interrupt = lxt971_ack_interrupt,
.config_intr = lxt971_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = 0x00137a10,
.name = "LXT973-A2",
.phy_id_mask = 0xffffffff,
.features = PHY_BASIC_FEATURES,
.flags = 0,
.probe = lxt973_probe,
.config_aneg = lxt973_config_aneg,
.read_status = lxt973a2_read_status,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = 0x00137a10,
.name = "LXT973",
Expand Down

0 comments on commit f55216c

Please sign in to comment.