|
@@ -709,18 +709,13 @@ static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg)
|
|
|
|
|
|
static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
|
|
|
|
if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed)
|
|
if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed)
|
|
return;
|
|
return;
|
|
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_TP;
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_FIBRE;
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_100baseT_Full;
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_1000baseT_Full;
|
|
|
|
- pdata->phy.supported &= ~SUPPORTED_10000baseT_Full;
|
|
|
|
|
|
+ XGBE_ZERO_SUP(lks);
|
|
|
|
|
|
if (phy_data->sfp_mod_absent) {
|
|
if (phy_data->sfp_mod_absent) {
|
|
pdata->phy.speed = SPEED_UNKNOWN;
|
|
pdata->phy.speed = SPEED_UNKNOWN;
|
|
@@ -728,18 +723,13 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
pdata->phy.autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_ENABLE;
|
|
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_FIBRE;
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
|
|
+ XGBE_SET_SUP(lks, FIBRE);
|
|
|
|
|
|
- pdata->phy.advertising = pdata->phy.supported;
|
|
|
|
|
|
+ XGBE_LM_COPY(lks, advertising, lks, supported);
|
|
|
|
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -753,8 +743,18 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
pdata->phy.duplex = DUPLEX_UNKNOWN;
|
|
pdata->phy.duplex = DUPLEX_UNKNOWN;
|
|
pdata->phy.autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_ENABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_ENABLE;
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T) {
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
|
|
|
|
+ XGBE_SET_SUP(lks, 100baseT_Full);
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseT_Full);
|
|
|
|
+ } else {
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseX_Full);
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
case XGBE_SFP_BASE_10000_SR:
|
|
case XGBE_SFP_BASE_10000_SR:
|
|
case XGBE_SFP_BASE_10000_LR:
|
|
case XGBE_SFP_BASE_10000_LR:
|
|
@@ -765,6 +765,27 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
pdata->phy.duplex = DUPLEX_FULL;
|
|
pdata->phy.duplex = DUPLEX_FULL;
|
|
pdata->phy.autoneg = AUTONEG_DISABLE;
|
|
pdata->phy.autoneg = AUTONEG_DISABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_DISABLE;
|
|
pdata->phy.pause_autoneg = AUTONEG_DISABLE;
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
|
|
+ switch (phy_data->sfp_base) {
|
|
|
|
+ case XGBE_SFP_BASE_10000_SR:
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseSR_Full);
|
|
|
|
+ break;
|
|
|
|
+ case XGBE_SFP_BASE_10000_LR:
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseLR_Full);
|
|
|
|
+ break;
|
|
|
|
+ case XGBE_SFP_BASE_10000_LRM:
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseLRM_Full);
|
|
|
|
+ break;
|
|
|
|
+ case XGBE_SFP_BASE_10000_ER:
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseER_Full);
|
|
|
|
+ break;
|
|
|
|
+ case XGBE_SFP_BASE_10000_CR:
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseCR_Full);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
pdata->phy.speed = SPEED_UNKNOWN;
|
|
pdata->phy.speed = SPEED_UNKNOWN;
|
|
@@ -778,38 +799,14 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
|
|
case XGBE_SFP_BASE_1000_T:
|
|
case XGBE_SFP_BASE_1000_T:
|
|
case XGBE_SFP_BASE_1000_CX:
|
|
case XGBE_SFP_BASE_1000_CX:
|
|
case XGBE_SFP_BASE_10000_CR:
|
|
case XGBE_SFP_BASE_10000_CR:
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- pdata->phy.supported |= SUPPORTED_FIBRE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch (phy_data->sfp_speed) {
|
|
|
|
- case XGBE_SFP_SPEED_100_1000:
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
- break;
|
|
|
|
- case XGBE_SFP_SPEED_1000:
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, FIBRE);
|
|
break;
|
|
break;
|
|
- case XGBE_SFP_SPEED_10000:
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- /* Choose the fastest supported speed */
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
- else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
- else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
|
|
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- pdata->phy.advertising = pdata->phy.supported;
|
|
|
|
|
|
+ XGBE_LM_COPY(lks, advertising, lks, supported);
|
|
}
|
|
}
|
|
|
|
|
|
static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
|
|
static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
|
|
@@ -886,8 +883,10 @@ static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
|
|
static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct phy_device *phydev;
|
|
struct phy_device *phydev;
|
|
|
|
+ u32 advertising;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* If we already have a PHY, just return */
|
|
/* If we already have a PHY, just return */
|
|
@@ -943,7 +942,10 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
|
|
phy_data->phydev = phydev;
|
|
phy_data->phydev = phydev;
|
|
|
|
|
|
xgbe_phy_external_phy_quirks(pdata);
|
|
xgbe_phy_external_phy_quirks(pdata);
|
|
- phydev->advertising &= pdata->phy.advertising;
|
|
|
|
|
|
+
|
|
|
|
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
|
|
|
|
+ lks->link_modes.advertising);
|
|
|
|
+ phydev->advertising &= advertising;
|
|
|
|
|
|
phy_start_aneg(phy_data->phydev);
|
|
phy_start_aneg(phy_data->phydev);
|
|
|
|
|
|
@@ -1277,6 +1279,7 @@ put:
|
|
|
|
|
|
static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
|
|
static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
u16 lcl_adv = 0, rmt_adv = 0;
|
|
u16 lcl_adv = 0, rmt_adv = 0;
|
|
u8 fc;
|
|
u8 fc;
|
|
@@ -1293,11 +1296,11 @@ static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
|
|
lcl_adv |= ADVERTISE_PAUSE_ASYM;
|
|
lcl_adv |= ADVERTISE_PAUSE_ASYM;
|
|
|
|
|
|
if (phy_data->phydev->pause) {
|
|
if (phy_data->phydev->pause) {
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Pause);
|
|
rmt_adv |= LPA_PAUSE_CAP;
|
|
rmt_adv |= LPA_PAUSE_CAP;
|
|
}
|
|
}
|
|
if (phy_data->phydev->asym_pause) {
|
|
if (phy_data->phydev->asym_pause) {
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Asym_Pause);
|
|
rmt_adv |= LPA_PAUSE_ASYM;
|
|
rmt_adv |= LPA_PAUSE_ASYM;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1310,10 +1313,11 @@ static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
|
|
static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
enum xgbe_mode mode;
|
|
enum xgbe_mode mode;
|
|
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_TP;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Autoneg);
|
|
|
|
+ XGBE_SET_LP_ADV(lks, TP);
|
|
|
|
|
|
/* Use external PHY to determine flow control */
|
|
/* Use external PHY to determine flow control */
|
|
if (pdata->phy.pause_autoneg)
|
|
if (pdata->phy.pause_autoneg)
|
|
@@ -1322,21 +1326,21 @@ static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
|
|
switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) {
|
|
switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) {
|
|
case XGBE_SGMII_AN_LINK_SPEED_100:
|
|
case XGBE_SGMII_AN_LINK_SPEED_100:
|
|
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
|
|
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
|
|
- pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 100baseT_Full);
|
|
mode = XGBE_MODE_SGMII_100;
|
|
mode = XGBE_MODE_SGMII_100;
|
|
} else {
|
|
} else {
|
|
/* Half-duplex not supported */
|
|
/* Half-duplex not supported */
|
|
- pdata->phy.lp_advertising |= ADVERTISED_100baseT_Half;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 100baseT_Half);
|
|
mode = XGBE_MODE_UNKNOWN;
|
|
mode = XGBE_MODE_UNKNOWN;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case XGBE_SGMII_AN_LINK_SPEED_1000:
|
|
case XGBE_SGMII_AN_LINK_SPEED_1000:
|
|
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
|
|
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 1000baseT_Full);
|
|
mode = XGBE_MODE_SGMII_1000;
|
|
mode = XGBE_MODE_SGMII_1000;
|
|
} else {
|
|
} else {
|
|
/* Half-duplex not supported */
|
|
/* Half-duplex not supported */
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 1000baseT_Half);
|
|
mode = XGBE_MODE_UNKNOWN;
|
|
mode = XGBE_MODE_UNKNOWN;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -1349,19 +1353,20 @@ static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
|
|
static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
enum xgbe_mode mode;
|
|
enum xgbe_mode mode;
|
|
unsigned int ad_reg, lp_reg;
|
|
unsigned int ad_reg, lp_reg;
|
|
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_FIBRE;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Autoneg);
|
|
|
|
+ XGBE_SET_LP_ADV(lks, FIBRE);
|
|
|
|
|
|
/* Compare Advertisement and Link Partner register */
|
|
/* Compare Advertisement and Link Partner register */
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_LP_ABILITY);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_LP_ABILITY);
|
|
if (lp_reg & 0x100)
|
|
if (lp_reg & 0x100)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Pause);
|
|
if (lp_reg & 0x80)
|
|
if (lp_reg & 0x80)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Asym_Pause);
|
|
|
|
|
|
if (pdata->phy.pause_autoneg) {
|
|
if (pdata->phy.pause_autoneg) {
|
|
/* Set flow control based on auto-negotiation result */
|
|
/* Set flow control based on auto-negotiation result */
|
|
@@ -1379,10 +1384,8 @@ static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (lp_reg & 0x40)
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
|
|
|
|
if (lp_reg & 0x20)
|
|
if (lp_reg & 0x20)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 1000baseX_Full);
|
|
|
|
|
|
/* Half duplex is not supported */
|
|
/* Half duplex is not supported */
|
|
ad_reg &= lp_reg;
|
|
ad_reg &= lp_reg;
|
|
@@ -1393,12 +1396,13 @@ static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
|
|
static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
enum xgbe_mode mode;
|
|
enum xgbe_mode mode;
|
|
unsigned int ad_reg, lp_reg;
|
|
unsigned int ad_reg, lp_reg;
|
|
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Backplane;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Autoneg);
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Backplane);
|
|
|
|
|
|
/* Use external PHY to determine flow control */
|
|
/* Use external PHY to determine flow control */
|
|
if (pdata->phy.pause_autoneg)
|
|
if (pdata->phy.pause_autoneg)
|
|
@@ -1408,9 +1412,9 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
|
|
if (lp_reg & 0x80)
|
|
if (lp_reg & 0x80)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 10000baseKR_Full);
|
|
if (lp_reg & 0x20)
|
|
if (lp_reg & 0x20)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 1000baseKX_Full);
|
|
|
|
|
|
ad_reg &= lp_reg;
|
|
ad_reg &= lp_reg;
|
|
if (ad_reg & 0x80) {
|
|
if (ad_reg & 0x80) {
|
|
@@ -1463,26 +1467,27 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
|
|
if (lp_reg & 0xc000)
|
|
if (lp_reg & 0xc000)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 10000baseR_FEC);
|
|
|
|
|
|
return mode;
|
|
return mode;
|
|
}
|
|
}
|
|
|
|
|
|
static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
|
|
static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
enum xgbe_mode mode;
|
|
enum xgbe_mode mode;
|
|
unsigned int ad_reg, lp_reg;
|
|
unsigned int ad_reg, lp_reg;
|
|
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
|
|
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Backplane;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Autoneg);
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Backplane);
|
|
|
|
|
|
/* Compare Advertisement and Link Partner register 1 */
|
|
/* Compare Advertisement and Link Partner register 1 */
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
|
|
if (lp_reg & 0x400)
|
|
if (lp_reg & 0x400)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Pause);
|
|
if (lp_reg & 0x800)
|
|
if (lp_reg & 0x800)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, Asym_Pause);
|
|
|
|
|
|
if (pdata->phy.pause_autoneg) {
|
|
if (pdata->phy.pause_autoneg) {
|
|
/* Set flow control based on auto-negotiation result */
|
|
/* Set flow control based on auto-negotiation result */
|
|
@@ -1504,9 +1509,9 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
|
|
if (lp_reg & 0x80)
|
|
if (lp_reg & 0x80)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 10000baseKR_Full);
|
|
if (lp_reg & 0x20)
|
|
if (lp_reg & 0x20)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 1000baseKX_Full);
|
|
|
|
|
|
ad_reg &= lp_reg;
|
|
ad_reg &= lp_reg;
|
|
if (ad_reg & 0x80)
|
|
if (ad_reg & 0x80)
|
|
@@ -1520,7 +1525,7 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
|
|
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
|
|
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
|
|
if (lp_reg & 0xc000)
|
|
if (lp_reg & 0xc000)
|
|
- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
|
|
|
|
|
|
+ XGBE_SET_LP_ADV(lks, 10000baseR_FEC);
|
|
|
|
|
|
return mode;
|
|
return mode;
|
|
}
|
|
}
|
|
@@ -1541,41 +1546,43 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
+static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata,
|
|
|
|
+ struct ethtool_link_ksettings *dlks)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *slks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
- unsigned int advertising;
|
|
|
|
|
|
+
|
|
|
|
+ XGBE_LM_COPY(dlks, advertising, slks, advertising);
|
|
|
|
|
|
/* Without a re-driver, just return current advertising */
|
|
/* Without a re-driver, just return current advertising */
|
|
if (!phy_data->redrv)
|
|
if (!phy_data->redrv)
|
|
- return pdata->phy.advertising;
|
|
|
|
|
|
+ return;
|
|
|
|
|
|
/* With the KR re-driver we need to advertise a single speed */
|
|
/* With the KR re-driver we need to advertise a single speed */
|
|
- advertising = pdata->phy.advertising;
|
|
|
|
- advertising &= ~ADVERTISED_1000baseKX_Full;
|
|
|
|
- advertising &= ~ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_CLR_ADV(dlks, 1000baseKX_Full);
|
|
|
|
+ XGBE_CLR_ADV(dlks, 10000baseKR_Full);
|
|
|
|
|
|
switch (phy_data->port_mode) {
|
|
switch (phy_data->port_mode) {
|
|
case XGBE_PORT_MODE_BACKPLANE:
|
|
case XGBE_PORT_MODE_BACKPLANE:
|
|
- advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 10000baseKR_Full);
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_BACKPLANE_2500:
|
|
case XGBE_PORT_MODE_BACKPLANE_2500:
|
|
- advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 1000baseKX_Full);
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_1000BASE_T:
|
|
case XGBE_PORT_MODE_1000BASE_T:
|
|
case XGBE_PORT_MODE_1000BASE_X:
|
|
case XGBE_PORT_MODE_1000BASE_X:
|
|
case XGBE_PORT_MODE_NBASE_T:
|
|
case XGBE_PORT_MODE_NBASE_T:
|
|
- advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 1000baseKX_Full);
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_10GBASE_T:
|
|
case XGBE_PORT_MODE_10GBASE_T:
|
|
if (phy_data->phydev &&
|
|
if (phy_data->phydev &&
|
|
(phy_data->phydev->speed == SPEED_10000))
|
|
(phy_data->phydev->speed == SPEED_10000))
|
|
- advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 10000baseKR_Full);
|
|
else
|
|
else
|
|
- advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 1000baseKX_Full);
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_10GBASE_R:
|
|
case XGBE_PORT_MODE_10GBASE_R:
|
|
- advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 10000baseKR_Full);
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_SFP:
|
|
case XGBE_PORT_MODE_SFP:
|
|
switch (phy_data->sfp_base) {
|
|
switch (phy_data->sfp_base) {
|
|
@@ -1583,24 +1590,24 @@ static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
|
|
case XGBE_SFP_BASE_1000_SX:
|
|
case XGBE_SFP_BASE_1000_SX:
|
|
case XGBE_SFP_BASE_1000_LX:
|
|
case XGBE_SFP_BASE_1000_LX:
|
|
case XGBE_SFP_BASE_1000_CX:
|
|
case XGBE_SFP_BASE_1000_CX:
|
|
- advertising |= ADVERTISED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 1000baseKX_Full);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 10000baseKR_Full);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- advertising |= ADVERTISED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_ADV(dlks, 10000baseKR_Full);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return advertising;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
|
|
static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
|
|
+ u32 advertising;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
ret = xgbe_phy_find_phy_device(pdata);
|
|
ret = xgbe_phy_find_phy_device(pdata);
|
|
@@ -1610,9 +1617,12 @@ static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
|
|
if (!phy_data->phydev)
|
|
if (!phy_data->phydev)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
|
|
|
|
+ lks->link_modes.advertising);
|
|
|
|
+
|
|
phy_data->phydev->autoneg = pdata->phy.autoneg;
|
|
phy_data->phydev->autoneg = pdata->phy.autoneg;
|
|
phy_data->phydev->advertising = phy_data->phydev->supported &
|
|
phy_data->phydev->advertising = phy_data->phydev->supported &
|
|
- pdata->phy.advertising;
|
|
|
|
|
|
+ advertising;
|
|
|
|
|
|
if (pdata->phy.autoneg != AUTONEG_ENABLE) {
|
|
if (pdata->phy.autoneg != AUTONEG_ENABLE) {
|
|
phy_data->phydev->speed = pdata->phy.speed;
|
|
phy_data->phydev->speed = pdata->phy.speed;
|
|
@@ -2073,11 +2083,10 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
|
|
}
|
|
}
|
|
|
|
|
|
static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
|
|
- enum xgbe_mode mode, u32 advert)
|
|
|
|
|
|
+ enum xgbe_mode mode, bool advert)
|
|
{
|
|
{
|
|
if (pdata->phy.autoneg == AUTONEG_ENABLE) {
|
|
if (pdata->phy.autoneg == AUTONEG_ENABLE) {
|
|
- if (pdata->phy.advertising & advert)
|
|
|
|
- return true;
|
|
|
|
|
|
+ return advert;
|
|
} else {
|
|
} else {
|
|
enum xgbe_mode cur_mode;
|
|
enum xgbe_mode cur_mode;
|
|
|
|
|
|
@@ -2092,13 +2101,15 @@ static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata,
|
|
enum xgbe_mode mode)
|
|
enum xgbe_mode mode)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
|
|
+
|
|
switch (mode) {
|
|
switch (mode) {
|
|
case XGBE_MODE_X:
|
|
case XGBE_MODE_X:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_1000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 1000baseX_Full));
|
|
case XGBE_MODE_KR:
|
|
case XGBE_MODE_KR:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_10000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 10000baseKR_Full));
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2107,19 +2118,21 @@ static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
|
|
enum xgbe_mode mode)
|
|
enum xgbe_mode mode)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
|
|
+
|
|
switch (mode) {
|
|
switch (mode) {
|
|
case XGBE_MODE_SGMII_100:
|
|
case XGBE_MODE_SGMII_100:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_100baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 100baseT_Full));
|
|
case XGBE_MODE_SGMII_1000:
|
|
case XGBE_MODE_SGMII_1000:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_1000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 1000baseT_Full));
|
|
case XGBE_MODE_KX_2500:
|
|
case XGBE_MODE_KX_2500:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_2500baseX_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 2500baseT_Full));
|
|
case XGBE_MODE_KR:
|
|
case XGBE_MODE_KR:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_10000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 10000baseT_Full));
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2128,6 +2141,7 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
|
|
enum xgbe_mode mode)
|
|
enum xgbe_mode mode)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
|
|
|
|
|
switch (mode) {
|
|
switch (mode) {
|
|
@@ -2135,22 +2149,26 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
|
|
if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
|
|
if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
|
|
return false;
|
|
return false;
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_1000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 1000baseX_Full));
|
|
case XGBE_MODE_SGMII_100:
|
|
case XGBE_MODE_SGMII_100:
|
|
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
|
|
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
|
|
return false;
|
|
return false;
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_100baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 100baseT_Full));
|
|
case XGBE_MODE_SGMII_1000:
|
|
case XGBE_MODE_SGMII_1000:
|
|
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
|
|
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
|
|
return false;
|
|
return false;
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_1000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 1000baseT_Full));
|
|
case XGBE_MODE_SFI:
|
|
case XGBE_MODE_SFI:
|
|
if (phy_data->sfp_mod_absent)
|
|
if (phy_data->sfp_mod_absent)
|
|
return true;
|
|
return true;
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_10000baseT_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 10000baseSR_Full) ||
|
|
|
|
+ XGBE_ADV(lks, 10000baseLR_Full) ||
|
|
|
|
+ XGBE_ADV(lks, 10000baseLRM_Full) ||
|
|
|
|
+ XGBE_ADV(lks, 10000baseER_Full) ||
|
|
|
|
+ XGBE_ADV(lks, 10000baseCR_Full));
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2159,10 +2177,12 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata,
|
|
enum xgbe_mode mode)
|
|
enum xgbe_mode mode)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
|
|
+
|
|
switch (mode) {
|
|
switch (mode) {
|
|
case XGBE_MODE_KX_2500:
|
|
case XGBE_MODE_KX_2500:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_2500baseX_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 2500baseX_Full));
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2171,13 +2191,15 @@ static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_bp_mode(struct xgbe_prv_data *pdata,
|
|
static bool xgbe_phy_use_bp_mode(struct xgbe_prv_data *pdata,
|
|
enum xgbe_mode mode)
|
|
enum xgbe_mode mode)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
|
|
+
|
|
switch (mode) {
|
|
switch (mode) {
|
|
case XGBE_MODE_KX_1000:
|
|
case XGBE_MODE_KX_1000:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_1000baseKX_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 1000baseKX_Full));
|
|
case XGBE_MODE_KR:
|
|
case XGBE_MODE_KR:
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
return xgbe_phy_check_mode(pdata, mode,
|
|
- ADVERTISED_10000baseKR_Full);
|
|
|
|
|
|
+ XGBE_ADV(lks, 10000baseKR_Full));
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2744,6 +2766,7 @@ static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
{
|
|
{
|
|
|
|
+ struct ethtool_link_ksettings *lks = &pdata->phy.lks;
|
|
struct xgbe_phy_data *phy_data;
|
|
struct xgbe_phy_data *phy_data;
|
|
struct mii_bus *mii;
|
|
struct mii_bus *mii;
|
|
unsigned int reg;
|
|
unsigned int reg;
|
|
@@ -2823,32 +2846,33 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
phy_data->cur_mode = XGBE_MODE_UNKNOWN;
|
|
phy_data->cur_mode = XGBE_MODE_UNKNOWN;
|
|
|
|
|
|
/* Initialize supported features */
|
|
/* Initialize supported features */
|
|
- pdata->phy.supported = 0;
|
|
|
|
|
|
+ XGBE_ZERO_SUP(lks);
|
|
|
|
|
|
switch (phy_data->port_mode) {
|
|
switch (phy_data->port_mode) {
|
|
/* Backplane support */
|
|
/* Backplane support */
|
|
case XGBE_PORT_MODE_BACKPLANE:
|
|
case XGBE_PORT_MODE_BACKPLANE:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Backplane;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Backplane);
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
- pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseKX_Full);
|
|
phy_data->start_mode = XGBE_MODE_KX_1000;
|
|
phy_data->start_mode = XGBE_MODE_KX_1000;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
- pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseKR_Full);
|
|
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
|
|
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
|
|
- pdata->phy.supported |=
|
|
|
|
- SUPPORTED_10000baseR_FEC;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseR_FEC);
|
|
phy_data->start_mode = XGBE_MODE_KR;
|
|
phy_data->start_mode = XGBE_MODE_KR;
|
|
}
|
|
}
|
|
|
|
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
break;
|
|
break;
|
|
case XGBE_PORT_MODE_BACKPLANE_2500:
|
|
case XGBE_PORT_MODE_BACKPLANE_2500:
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Backplane;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_2500baseX_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Backplane);
|
|
|
|
+ XGBE_SET_SUP(lks, 2500baseX_Full);
|
|
phy_data->start_mode = XGBE_MODE_KX_2500;
|
|
phy_data->start_mode = XGBE_MODE_KX_2500;
|
|
|
|
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
@@ -2856,15 +2880,16 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
/* MDIO 1GBase-T support */
|
|
/* MDIO 1GBase-T support */
|
|
case XGBE_PORT_MODE_1000BASE_T:
|
|
case XGBE_PORT_MODE_1000BASE_T:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 100baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2873,10 +2898,11 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
/* MDIO Base-X support */
|
|
/* MDIO Base-X support */
|
|
case XGBE_PORT_MODE_1000BASE_X:
|
|
case XGBE_PORT_MODE_1000BASE_X:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_FIBRE;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, FIBRE);
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseX_Full);
|
|
phy_data->start_mode = XGBE_MODE_X;
|
|
phy_data->start_mode = XGBE_MODE_X;
|
|
|
|
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
|
|
@@ -2884,19 +2910,20 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
/* MDIO NBase-T support */
|
|
/* MDIO NBase-T support */
|
|
case XGBE_PORT_MODE_NBASE_T:
|
|
case XGBE_PORT_MODE_NBASE_T:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 100baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500) {
|
|
- pdata->phy.supported |= SUPPORTED_2500baseX_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 2500baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_KX_2500;
|
|
phy_data->start_mode = XGBE_MODE_KX_2500;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2905,33 +2932,38 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
/* 10GBase-T support */
|
|
/* 10GBase-T support */
|
|
case XGBE_PORT_MODE_10GBASE_T:
|
|
case XGBE_PORT_MODE_10GBASE_T:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 100baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 1000baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
}
|
|
}
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseT_Full);
|
|
phy_data->start_mode = XGBE_MODE_KR;
|
|
phy_data->start_mode = XGBE_MODE_KR;
|
|
}
|
|
}
|
|
|
|
|
|
- phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
|
|
|
|
+ phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
|
|
break;
|
|
break;
|
|
|
|
|
|
/* 10GBase-R support */
|
|
/* 10GBase-R support */
|
|
case XGBE_PORT_MODE_10GBASE_R:
|
|
case XGBE_PORT_MODE_10GBASE_R:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, FIBRE);
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseSR_Full);
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseLR_Full);
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseLRM_Full);
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseER_Full);
|
|
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
|
|
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
|
|
- pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, 10000baseR_FEC);
|
|
phy_data->start_mode = XGBE_MODE_SFI;
|
|
phy_data->start_mode = XGBE_MODE_SFI;
|
|
|
|
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
|
|
@@ -2939,22 +2971,17 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
|
|
|
|
/* SFP support */
|
|
/* SFP support */
|
|
case XGBE_PORT_MODE_SFP:
|
|
case XGBE_PORT_MODE_SFP:
|
|
- pdata->phy.supported |= SUPPORTED_Autoneg;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_TP;
|
|
|
|
- pdata->phy.supported |= SUPPORTED_FIBRE;
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
|
|
|
|
- pdata->phy.supported |= SUPPORTED_100baseT_Full;
|
|
|
|
|
|
+ XGBE_SET_SUP(lks, Autoneg);
|
|
|
|
+ XGBE_SET_SUP(lks, Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, Asym_Pause);
|
|
|
|
+ XGBE_SET_SUP(lks, TP);
|
|
|
|
+ XGBE_SET_SUP(lks, FIBRE);
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_100;
|
|
- }
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
|
|
|
|
- pdata->phy.supported |= SUPPORTED_1000baseT_Full;
|
|
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
phy_data->start_mode = XGBE_MODE_SGMII_1000;
|
|
- }
|
|
|
|
- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
|
|
|
|
- pdata->phy.supported |= SUPPORTED_10000baseT_Full;
|
|
|
|
|
|
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
|
|
phy_data->start_mode = XGBE_MODE_SFI;
|
|
phy_data->start_mode = XGBE_MODE_SFI;
|
|
- }
|
|
|
|
|
|
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
|
|
phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
|
|
|
|
|
|
@@ -2965,8 +2992,9 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
|
}
|
|
}
|
|
|
|
|
|
if (netif_msg_probe(pdata))
|
|
if (netif_msg_probe(pdata))
|
|
- dev_dbg(pdata->dev, "phy supported=%#x\n",
|
|
|
|
- pdata->phy.supported);
|
|
|
|
|
|
+ dev_dbg(pdata->dev, "phy supported=0x%*pb\n",
|
|
|
|
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
|
|
|
|
+ lks->link_modes.supported);
|
|
|
|
|
|
if ((phy_data->conn_type & XGBE_CONN_TYPE_MDIO) &&
|
|
if ((phy_data->conn_type & XGBE_CONN_TYPE_MDIO) &&
|
|
(phy_data->phydev_mode != XGBE_MDIO_MODE_NONE)) {
|
|
(phy_data->phydev_mode != XGBE_MDIO_MODE_NONE)) {
|