summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/cadence
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/cadence')
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c112
1 files changed, 73 insertions, 39 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index ffce528aa00e..57c5f48d19a4 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -513,29 +513,47 @@ static void macb_validate(struct phylink_config *config,
struct net_device *ndev = to_net_dev(config->dev);
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
struct macb *bp = netdev_priv(ndev);
+ bool have_1g, have_sgmii, have_10g;
+
+ /* Determine what modes are supported */
+ if (macb_is_gem(bp) &&
+ (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
+ have_1g = true;
+ if (bp->caps & MACB_CAPS_PCS)
+ have_sgmii = true;
+ if (bp->caps & MACB_CAPS_HIGH_SPEED)
+ have_10g = true;
+ }
+
+ /* Eliminate unsupported modes */
+ switch (state->interface) {
+ case PHY_INTERFACE_MODE_NA:
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_RMII:
+ break;
- /* We only support MII, RMII, GMII, RGMII & SGMII. */
- if (state->interface != PHY_INTERFACE_MODE_NA &&
- state->interface != PHY_INTERFACE_MODE_MII &&
- state->interface != PHY_INTERFACE_MODE_RMII &&
- state->interface != PHY_INTERFACE_MODE_GMII &&
- state->interface != PHY_INTERFACE_MODE_SGMII &&
- state->interface != PHY_INTERFACE_MODE_10GBASER &&
- !phy_interface_mode_is_rgmii(state->interface)) {
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ if (have_1g)
+ break;
linkmode_zero(supported);
return;
- }
- if (!macb_is_gem(bp) &&
- (state->interface == PHY_INTERFACE_MODE_GMII ||
- phy_interface_mode_is_rgmii(state->interface))) {
+ case PHY_INTERFACE_MODE_SGMII:
+ if (have_sgmii)
+ break;
linkmode_zero(supported);
return;
- }
- if (state->interface == PHY_INTERFACE_MODE_10GBASER &&
- !(bp->caps & MACB_CAPS_HIGH_SPEED &&
- bp->caps & MACB_CAPS_PCS)) {
+ case PHY_INTERFACE_MODE_10GBASER:
+ if (have_10g)
+ break;
+ fallthrough;
+
+ default:
linkmode_zero(supported);
return;
}
@@ -544,32 +562,48 @@ static void macb_validate(struct phylink_config *config,
phylink_set(mask, Autoneg);
phylink_set(mask, Asym_Pause);
- if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE &&
- (state->interface == PHY_INTERFACE_MODE_NA ||
- state->interface == PHY_INTERFACE_MODE_10GBASER)) {
- phylink_set_10g_modes(mask);
- phylink_set(mask, 10000baseKR_Full);
+ /* And set the appropriate mask */
+ switch (state->interface) {
+ case PHY_INTERFACE_MODE_NA:
+ case PHY_INTERFACE_MODE_10GBASER:
+ if (have_10g) {
+ phylink_set_10g_modes(mask);
+ phylink_set(mask, 10000baseKR_Full);
+ }
if (state->interface != PHY_INTERFACE_MODE_NA)
- goto out;
- }
+ break;
+ fallthrough;
+
+ /* FIXME: Do we actually support 10/100 for SGMII? Half duplex? */
+ case PHY_INTERFACE_MODE_SGMII:
+ if (!have_sgmii && state->interface != PHY_INTERFACE_MODE_NA)
+ break;
+ fallthrough;
+
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ if (have_1g) {
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+
+ if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
+ phylink_set(mask, 1000baseT_Half);
+ } else if (state->interface != PHY_INTERFACE_MODE_NA) {
+ break;
+ }
+ fallthrough;
- phylink_set(mask, 10baseT_Half);
- phylink_set(mask, 10baseT_Full);
- phylink_set(mask, 100baseT_Half);
- phylink_set(mask, 100baseT_Full);
-
- if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE &&
- (state->interface == PHY_INTERFACE_MODE_NA ||
- state->interface == PHY_INTERFACE_MODE_GMII ||
- state->interface == PHY_INTERFACE_MODE_SGMII ||
- phy_interface_mode_is_rgmii(state->interface))) {
- phylink_set(mask, 1000baseT_Full);
- phylink_set(mask, 1000baseX_Full);
-
- if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
- phylink_set(mask, 1000baseT_Half);
+ default:
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ break;
}
-out:
+
linkmode_and(supported, supported, mask);
linkmode_and(state->advertising, state->advertising, mask);
}