Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 87824
b: refs/heads/master
c: be937f1
h: refs/heads/master
v: v3
  • Loading branch information
Alexandr Smirnov authored and Jeff Garzik committed Mar 26, 2008
1 parent f9e177d commit d70b800
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 6 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: d1847a722e79bbfc557755d78f44d3e2c8ae5ea9
refs/heads/master: be937f1f89cacd833bd242c35af911b971225cf0
129 changes: 124 additions & 5 deletions trunk/drivers/net/phy/marvell.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,25 @@
#define MII_M1111_RX_DELAY 0x80
#define MII_M1111_TX_DELAY 0x2
#define MII_M1111_PHY_EXT_SR 0x1b
#define MII_M1111_HWCFG_MODE_MASK 0xf
#define MII_M1111_HWCFG_MODE_RGMII 0xb

#define MII_M1111_HWCFG_MODE_MASK 0xf
#define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb
#define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3
#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
#define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000
#define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000

#define MII_M1111_COPPER 0
#define MII_M1111_FIBER 1

#define MII_M1011_PHY_STATUS 0x11
#define MII_M1011_PHY_STATUS_1000 0x8000
#define MII_M1011_PHY_STATUS_100 0x4000
#define MII_M1011_PHY_STATUS_SPD_MASK 0xc000
#define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
#define MII_M1011_PHY_STATUS_RESOLVED 0x0800
#define MII_M1011_PHY_STATUS_LINK 0x0400


MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
Expand Down Expand Up @@ -141,12 +157,22 @@ static int marvell_config_aneg(struct phy_device *phydev)
static int m88e1111_config_init(struct phy_device *phydev)
{
int err;
int temp;
int mode;

/* Enable Fiber/Copper auto selection */
temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);

temp = phy_read(phydev, MII_BMCR);
temp |= BMCR_RESET;
phy_write(phydev, MII_BMCR, temp);

if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
int temp;

temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
if (temp < 0)
Expand All @@ -171,7 +197,13 @@ static int m88e1111_config_init(struct phy_device *phydev)
return temp;

temp &= ~(MII_M1111_HWCFG_MODE_MASK);
temp |= MII_M1111_HWCFG_MODE_RGMII;

mode = phy_read(phydev, MII_M1111_PHY_EXT_CR);

if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES)
temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
else
temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;

err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
if (err < 0)
Expand Down Expand Up @@ -262,6 +294,93 @@ static int m88e1145_config_init(struct phy_device *phydev)
return 0;
}

/* marvell_read_status
*
* Generic status code does not detect Fiber correctly!
* Description:
* Check the link, then figure out the current state
* by comparing what we advertise with what the link partner
* advertises. Start by checking the gigabit possibilities,
* then move on to 10/100.
*/
static int marvell_read_status(struct phy_device *phydev)
{
int adv;
int err;
int lpa;
int status = 0;

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

if (AUTONEG_ENABLE == phydev->autoneg) {
status = phy_read(phydev, MII_M1011_PHY_STATUS);
if (status < 0)
return status;

lpa = phy_read(phydev, MII_LPA);
if (lpa < 0)
return lpa;

adv = phy_read(phydev, MII_ADVERTISE);
if (adv < 0)
return adv;

lpa &= adv;

if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;

status = status & MII_M1011_PHY_STATUS_SPD_MASK;
phydev->pause = phydev->asym_pause = 0;

switch (status) {
case MII_M1011_PHY_STATUS_1000:
phydev->speed = SPEED_1000;
break;

case MII_M1011_PHY_STATUS_100:
phydev->speed = SPEED_100;
break;

default:
phydev->speed = SPEED_10;
break;
}

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 struct phy_driver marvell_drivers[] = {
{
.phy_id = 0x01410c60,
Expand Down Expand Up @@ -296,7 +415,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1111_config_init,
.config_aneg = &marvell_config_aneg,
.read_status = &genphy_read_status,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
.driver = { .owner = THIS_MODULE },
Expand Down

0 comments on commit d70b800

Please sign in to comment.