Commit 6c422e34 authored by Russell King's avatar Russell King Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: add phylink support



Add rudimentary phylink support to mv88e6xxx.

TODO:
- needs to call phylink_mac_change() when the port link comes up/goes down.

Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 624c0f02
Loading
Loading
Loading
Loading
+138 −1
Original line number Diff line number Diff line
@@ -598,10 +598,92 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
		dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
}

static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	if (!phy_interface_mode_is_8023z(state->interface)) {
		/* 10M and 100M are only supported in non-802.3z mode */
		phylink_set(mask, 10baseT_Half);
		phylink_set(mask, 10baseT_Full);
		phylink_set(mask, 100baseT_Half);
		phylink_set(mask, 100baseT_Full);
	}
}

static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	/* FIXME: if the port is in 1000Base-X mode, then it only supports
	 * 1000M FD speeds.  In this case, CMODE will indicate 5.
	 */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	/* No ethtool bits for 200Mbps */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port,
				       unsigned long *mask,
				       struct phylink_link_state *state)
{
	if (port >= 9)
		phylink_set(mask, 2500baseX_Full);

	/* No ethtool bits for 200Mbps */
	phylink_set(mask, 1000baseT_Full);
	phylink_set(mask, 1000baseX_Full);

	mv88e6065_phylink_validate(chip, port, mask, state);
}

static void mv88e6390x_phylink_validate(struct mv88e6xxx_chip *chip, int port,
					unsigned long *mask,
					struct phylink_link_state *state)
{
	if (port >= 9) {
		phylink_set(mask, 10000baseT_Full);
		phylink_set(mask, 10000baseKR_Full);
	}

	mv88e6390_phylink_validate(chip, port, mask, state);
}

static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
			       unsigned long *supported,
			       struct phylink_link_state *state)
{
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
	struct mv88e6xxx_chip *chip = ds->priv;

	/* Allow all the expected bits */
	phylink_set(mask, Autoneg);
	phylink_set(mask, Pause);
	phylink_set_port_modes(mask);

	if (chip->info->ops->phylink_validate)
		chip->info->ops->phylink_validate(chip, port, mask, state);

	bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
	bitmap_and(state->advertising, state->advertising, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);

	/* We can only operate at 2500BaseX or 1000BaseX.  If requested
	 * to advertise both, only report advertising at 2500BaseX.
	 */
	phylink_helper_basex_speed(state);
}

static int mv88e6xxx_link_state(struct dsa_switch *ds, int port,
@@ -611,7 +693,10 @@ static int mv88e6xxx_link_state(struct dsa_switch *ds, int port,
	int err;

	mutex_lock(&chip->reg_lock);
	err = mv88e6xxx_port_link_state(chip, port, state);
	if (chip->info->ops->port_link_state)
		err = chip->info->ops->port_link_state(chip, port, state);
	else
		err = -EOPNOTSUPP;
	mutex_unlock(&chip->reg_lock);

	return err;
@@ -2611,6 +2696,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2627,6 +2713,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
	.rmu_disable = mv88e6085_g1_rmu_disable,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6095_ops = {
@@ -2642,6 +2729,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
	.port_link_state = mv88e6185_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2653,6 +2741,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
	.reset = mv88e6185_g1_reset,
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6097_ops = {
@@ -2675,6 +2764,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2689,6 +2779,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
	.rmu_disable = mv88e6085_g1_rmu_disable,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6123_ops = {
@@ -2706,6 +2797,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2719,6 +2811,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
	.reset = mv88e6352_g1_reset,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6131_ops = {
@@ -2740,6 +2833,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_set_pause = mv88e6185_port_set_pause,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2755,6 +2849,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
	.reset = mv88e6185_g1_reset,
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6141_ops = {
@@ -2780,6 +2875,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -2795,6 +2891,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.serdes_power = mv88e6341_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6161_ops = {
@@ -2817,6 +2914,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2832,6 +2930,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.avb_ops = &mv88e6165_avb_ops,
	.ptp_ops = &mv88e6165_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6165_ops = {
@@ -2847,6 +2946,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
	.port_set_speed = mv88e6185_port_set_speed,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2862,6 +2962,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.avb_ops = &mv88e6165_avb_ops,
	.ptp_ops = &mv88e6165_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6171_ops = {
@@ -2885,6 +2986,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2898,6 +3000,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
	.reset = mv88e6352_g1_reset,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6172_ops = {
@@ -2923,6 +3026,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2939,6 +3043,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.serdes_power = mv88e6352_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6352_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6175_ops = {
@@ -2962,6 +3067,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2975,6 +3081,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
	.reset = mv88e6352_g1_reset,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6176_ops = {
@@ -3000,6 +3107,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3016,6 +3124,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.serdes_power = mv88e6352_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6352_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6185_ops = {
@@ -3033,6 +3142,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
	.port_set_upstream_port = mv88e6095_port_set_upstream_port,
	.port_set_pause = mv88e6185_port_set_pause,
	.port_link_state = mv88e6185_port_link_state,
	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3048,6 +3158,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
	.reset = mv88e6185_g1_reset,
	.vtu_getnext = mv88e6185_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6190_ops = {
@@ -3069,6 +3180,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
	.port_pause_limit = mv88e6390_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3085,6 +3197,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
	.serdes_power = mv88e6390_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6190x_ops = {
@@ -3106,6 +3219,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
	.port_pause_limit = mv88e6390_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3122,6 +3236,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
	.serdes_power = mv88e6390_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6390x_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6191_ops = {
@@ -3143,6 +3258,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
	.port_pause_limit = mv88e6390_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3160,6 +3276,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
	.serdes_power = mv88e6390_serdes_power,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6240_ops = {
@@ -3185,6 +3302,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3203,6 +3321,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6352_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -3225,6 +3344,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.port_set_cmode = mv88e6390x_port_set_cmode,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3243,6 +3363,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6320_ops = {
@@ -3267,6 +3388,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3282,6 +3404,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6321_ops = {
@@ -3306,6 +3429,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3319,6 +3443,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6341_ops = {
@@ -3344,6 +3469,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3361,6 +3487,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6350_ops = {
@@ -3384,6 +3511,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3397,6 +3525,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
	.reset = mv88e6352_g1_reset,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6351_ops = {
@@ -3420,6 +3549,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3435,6 +3565,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6352_ops = {
@@ -3460,6 +3591,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6320_g1_stats_snapshot,
	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3481,6 +3613,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
	.phylink_validate = mv88e6352_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6390_ops = {
@@ -3505,6 +3638,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.port_set_cmode = mv88e6390x_port_set_cmode,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3523,6 +3657,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6390_phylink_validate,
};

static const struct mv88e6xxx_ops mv88e6390x_ops = {
@@ -3547,6 +3682,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
	.port_set_cmode = mv88e6390x_port_set_cmode,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
	.port_link_state = mv88e6352_port_link_state,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3565,6 +3701,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_validate = mv88e6390x_phylink_validate,
};

static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+8 −0
Original line number Diff line number Diff line
@@ -396,6 +396,9 @@ struct mv88e6xxx_ops {
	 */
	int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port,
				      int upstream_port);
	/* Return the port link state, as required by phylink */
	int (*port_link_state)(struct mv88e6xxx_chip *chip, int port,
			       struct phylink_link_state *state);

	/* Snapshot the statistics for a port. The statistics can then
	 * be read back a leisure but still with a consistent view.
@@ -451,6 +454,11 @@ struct mv88e6xxx_ops {

	/* Precision Time Protocol operations */
	const struct mv88e6xxx_ptp_ops *ptp_ops;

	/* Phylink */
	void (*phylink_validate)(struct mv88e6xxx_chip *chip, int port,
				 unsigned long *mask,
				 struct phylink_link_state *state);
};

struct mv88e6xxx_irq_ops {
+54 −2
Original line number Diff line number Diff line
@@ -388,6 +388,19 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
	return 0;
}

/* mv88e6185 only has 3 bits for CMODE */
static int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port)
{
	int err;
	u16 reg;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
	if (err)
		return err;

	return reg & MV88E6185_PORT_STS_CMODE_MASK;
}

int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
{
	int err;
@@ -402,7 +415,7 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
	return 0;
}

int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state)
{
	int err;
@@ -440,6 +453,45 @@ int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
	return 0;
}

int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state)
{
	if (state->interface == PHY_INTERFACE_MODE_1000BASEX) {
		int cmode = mv88e6185_port_get_cmode(chip, port);

		if (cmode < 0)
			return cmode;

		/* When a port is in "Cross-chip serdes" mode, it uses
		 * 1000Base-X full duplex mode, but there is no automatic
		 * link detection. Use the sync OK status for link (as it
		 * would do for 1000Base-X mode.)
		 */
		if (cmode == MV88E6185_PORT_STS_CMODE_SERDES) {
			u16 mac;
			int err;

			err = mv88e6xxx_port_read(chip, port,
						  MV88E6XXX_PORT_MAC_CTL, &mac);
			if (err)
				return err;

			state->link = !!(mac & MV88E6185_PORT_MAC_CTL_SYNC_OK);
			state->an_enabled = 1;
			state->an_complete =
				!!(mac & MV88E6185_PORT_MAC_CTL_AN_DONE);
			state->duplex =
				state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
			state->speed =
				state->link ? SPEED_1000 : SPEED_UNKNOWN;

			return 0;
		}
	}

	return mv88e6352_port_link_state(chip, port, state);
}

/* Offset 0x02: Jamming Control
 *
 * Do not limit the period of time that this port can be paused for by
+17 −1
Original line number Diff line number Diff line
@@ -42,14 +42,28 @@
#define MV88E6XXX_PORT_STS_CMODE_2500BASEX	0x000b
#define MV88E6XXX_PORT_STS_CMODE_XAUI		0x000c
#define MV88E6XXX_PORT_STS_CMODE_RXAUI		0x000d
#define MV88E6185_PORT_STS_CDUPLEX		0x0008
#define MV88E6185_PORT_STS_CMODE_MASK		0x0007
#define MV88E6185_PORT_STS_CMODE_GMII_FD	0x0000
#define MV88E6185_PORT_STS_CMODE_MII_100_FD_PS	0x0001
#define MV88E6185_PORT_STS_CMODE_MII_100	0x0002
#define MV88E6185_PORT_STS_CMODE_MII_10		0x0003
#define MV88E6185_PORT_STS_CMODE_SERDES		0x0004
#define MV88E6185_PORT_STS_CMODE_1000BASE_X	0x0005
#define MV88E6185_PORT_STS_CMODE_PHY		0x0006
#define MV88E6185_PORT_STS_CMODE_DISABLED	0x0007

/* Offset 0x01: MAC (or PCS or Physical) Control Register */
#define MV88E6XXX_PORT_MAC_CTL				0x01
#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK	0x8000
#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK	0x4000
#define MV88E6185_PORT_MAC_CTL_SYNC_OK			0x4000
#define MV88E6390_PORT_MAC_CTL_FORCE_SPEED		0x2000
#define MV88E6390_PORT_MAC_CTL_ALTSPEED			0x1000
#define MV88E6352_PORT_MAC_CTL_200BASE			0x1000
#define MV88E6185_PORT_MAC_CTL_AN_EN			0x0400
#define MV88E6185_PORT_MAC_CTL_AN_RESTART		0x0200
#define MV88E6185_PORT_MAC_CTL_AN_DONE			0x0100
#define MV88E6XXX_PORT_MAC_CTL_FC			0x0080
#define MV88E6XXX_PORT_MAC_CTL_FORCE_FC			0x0040
#define MV88E6XXX_PORT_MAC_CTL_LINK_UP			0x0020
@@ -298,7 +312,9 @@ int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
			      phy_interface_t mode);
int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state);
int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state);
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,