Skip to content

Commit a29de52

Browse files
Dan Murphydavem330
Dan Murphy
authored andcommitted
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: Dan Murphy <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 55f1331 commit a29de52

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

drivers/net/phy/dp83869.c

+73
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
BMCR_FULLDPLX | \
5353
BMCR_SPEED1000)
5454

55+
#define MII_DP83869_FIBER_ADVERTISE (ADVERTISED_FIBRE | \
56+
ADVERTISED_Pause | \
57+
ADVERTISED_Asym_Pause)
58+
5559
/* This is the same bit mask as the BMCR so re-use the BMCR default */
5660
#define DP83869_FX_CTRL_DEFAULT MII_DP83869_BMCR_DEFAULT
5761

@@ -118,6 +122,28 @@ struct dp83869_private {
118122
int mode;
119123
};
120124

125+
static int dp83869_read_status(struct phy_device *phydev)
126+
{
127+
struct dp83869_private *dp83869 = phydev->priv;
128+
int ret;
129+
130+
ret = genphy_read_status(phydev);
131+
if (ret)
132+
return ret;
133+
134+
if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
135+
if (phydev->link) {
136+
if (dp83869->mode == DP83869_RGMII_100_BASE)
137+
phydev->speed = SPEED_100;
138+
} else {
139+
phydev->speed = SPEED_UNKNOWN;
140+
phydev->duplex = DUPLEX_UNKNOWN;
141+
}
142+
}
143+
144+
return 0;
145+
}
146+
121147
static int dp83869_ack_interrupt(struct phy_device *phydev)
122148
{
123149
int err = phy_read(phydev, MII_DP83869_ISR);
@@ -295,6 +321,51 @@ static int dp83869_configure_rgmii(struct phy_device *phydev,
295321
return ret;
296322
}
297323

324+
static int dp83869_configure_fiber(struct phy_device *phydev,
325+
struct dp83869_private *dp83869)
326+
{
327+
int bmcr;
328+
int ret;
329+
330+
/* Only allow advertising what this PHY supports */
331+
linkmode_and(phydev->advertising, phydev->advertising,
332+
phydev->supported);
333+
334+
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
335+
linkmode_set_bit(ADVERTISED_FIBRE, phydev->advertising);
336+
337+
if (dp83869->mode == DP83869_RGMII_1000_BASE) {
338+
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
339+
phydev->supported);
340+
} else {
341+
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
342+
phydev->supported);
343+
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
344+
phydev->supported);
345+
346+
/* Auto neg is not supported in 100base FX mode */
347+
bmcr = phy_read(phydev, MII_BMCR);
348+
if (bmcr < 0)
349+
return bmcr;
350+
351+
phydev->autoneg = AUTONEG_DISABLE;
352+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
353+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);
354+
355+
if (bmcr & BMCR_ANENABLE) {
356+
ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
357+
if (ret < 0)
358+
return ret;
359+
}
360+
}
361+
362+
/* Update advertising from supported */
363+
linkmode_or(phydev->advertising, phydev->advertising,
364+
phydev->supported);
365+
366+
return 0;
367+
}
368+
298369
static int dp83869_configure_mode(struct phy_device *phydev,
299370
struct dp83869_private *dp83869)
300371
{
@@ -384,6 +455,7 @@ static int dp83869_configure_mode(struct phy_device *phydev,
384455
break;
385456
case DP83869_RGMII_1000_BASE:
386457
case DP83869_RGMII_100_BASE:
458+
ret = dp83869_configure_fiber(phydev, dp83869);
387459
break;
388460
default:
389461
return -EINVAL;
@@ -494,6 +566,7 @@ static struct phy_driver dp83869_driver[] = {
494566
/* IRQ related */
495567
.ack_interrupt = dp83869_ack_interrupt,
496568
.config_intr = dp83869_config_intr,
569+
.read_status = dp83869_read_status,
497570

498571
.suspend = genphy_suspend,
499572
.resume = genphy_resume,

0 commit comments

Comments
 (0)