Commit a29de52b authored by Dan Murphy's avatar Dan Murphy Committed by David S. Miller

net: dp83869: Add ability to advertise Fiber connection

Add the ability to advertise the Fiber connection if the strap or the
op-mode is configured for 100Base-FX.

Auto negotiation is not supported on this PHY when in fiber mode.
Signed-off-by: default avatarDan Murphy <dmurphy@ti.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 55f13311
......@@ -52,6 +52,10 @@
BMCR_FULLDPLX | \
BMCR_SPEED1000)
#define MII_DP83869_FIBER_ADVERTISE (ADVERTISED_FIBRE | \
ADVERTISED_Pause | \
ADVERTISED_Asym_Pause)
/* This is the same bit mask as the BMCR so re-use the BMCR default */
#define DP83869_FX_CTRL_DEFAULT MII_DP83869_BMCR_DEFAULT
......@@ -118,6 +122,28 @@ struct dp83869_private {
int mode;
};
static int dp83869_read_status(struct phy_device *phydev)
{
struct dp83869_private *dp83869 = phydev->priv;
int ret;
ret = genphy_read_status(phydev);
if (ret)
return ret;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
if (phydev->link) {
if (dp83869->mode == DP83869_RGMII_100_BASE)
phydev->speed = SPEED_100;
} else {
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
}
}
return 0;
}
static int dp83869_ack_interrupt(struct phy_device *phydev)
{
int err = phy_read(phydev, MII_DP83869_ISR);
......@@ -295,6 +321,51 @@ static int dp83869_configure_rgmii(struct phy_device *phydev,
return ret;
}
static int dp83869_configure_fiber(struct phy_device *phydev,
struct dp83869_private *dp83869)
{
int bmcr;
int ret;
/* Only allow advertising what this PHY supports */
linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
linkmode_set_bit(ADVERTISED_FIBRE, phydev->advertising);
if (dp83869->mode == DP83869_RGMII_1000_BASE) {
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->supported);
} else {
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
phydev->supported);
/* Auto neg is not supported in 100base FX mode */
bmcr = phy_read(phydev, MII_BMCR);
if (bmcr < 0)
return bmcr;
phydev->autoneg = AUTONEG_DISABLE;
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);
if (bmcr & BMCR_ANENABLE) {
ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
if (ret < 0)
return ret;
}
}
/* Update advertising from supported */
linkmode_or(phydev->advertising, phydev->advertising,
phydev->supported);
return 0;
}
static int dp83869_configure_mode(struct phy_device *phydev,
struct dp83869_private *dp83869)
{
......@@ -384,6 +455,7 @@ static int dp83869_configure_mode(struct phy_device *phydev,
break;
case DP83869_RGMII_1000_BASE:
case DP83869_RGMII_100_BASE:
ret = dp83869_configure_fiber(phydev, dp83869);
break;
default:
return -EINVAL;
......@@ -494,6 +566,7 @@ static struct phy_driver dp83869_driver[] = {
/* IRQ related */
.ack_interrupt = dp83869_ack_interrupt,
.config_intr = dp83869_config_intr,
.read_status = dp83869_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment