Commit 64088b2a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-dsa-mv88e6xxx-serdes-link-without-phy'

Chris Packham says:

====================
net: dsa: mv88e6xxx: serdes link without phy

This small series gets my hardware into a working state. The key points are to
make sure we don't force the link and that we ask the MAC for the link status.
I also have updated my dts to say `phy-mode = "1000base-x";` and `managed =
"in-band-status";`

I've dropped the patch for the 88E6123 as it's a distraction and I lack
hardware to do any proper testing with it. Earlier versions are on the mailing
list if anyone wants to pick it up in the future.

I notice there's a series for mv88e6393x circulating on the netdev mailing
list. As patch #1 is adding a new device specific op either this series will
need updating to cover the mv88e6393x or the mv88e6393x series will need
updating for the new op depenting on which lands first.
====================

Link: https://lore.kernel.org/r/20201124043440.28400-1-chris.packham@alliedtelesis.co.nz


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0f614511 0fd5d79e
Loading
Loading
Loading
Loading
+43 −4
Original line number Diff line number Diff line
@@ -727,8 +727,8 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,

	mv88e6xxx_reg_lock(chip);
	if ((!mv88e6xxx_port_ppu_updates(chip, port) ||
	     mode == MLO_AN_FIXED) && ops->port_set_link)
		err = ops->port_set_link(chip, port, LINK_FORCED_DOWN);
	     mode == MLO_AN_FIXED) && ops->port_sync_link)
		err = ops->port_sync_link(chip, port, mode, false);
	mv88e6xxx_reg_unlock(chip);

	if (err)
@@ -768,8 +768,8 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
				goto error;
		}

		if (ops->port_set_link)
			err = ops->port_set_link(chip, port, LINK_FORCED_UP);
		if (ops->port_sync_link)
			err = ops->port_sync_link(chip, port, mode, true);
	}
error:
	mv88e6xxx_reg_unlock(chip);
@@ -3210,6 +3210,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -3249,6 +3250,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6185_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
@@ -3261,6 +3263,9 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
	.stats_get_strings = mv88e6095_stats_get_strings,
	.stats_get_stats = mv88e6095_stats_get_stats,
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
	.serdes_power = mv88e6185_serdes_power,
	.serdes_get_lane = mv88e6185_serdes_get_lane,
	.serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
	.reset = mv88e6185_g1_reset,
@@ -3279,6 +3284,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6185_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -3299,6 +3305,12 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
	.set_egress_port = mv88e6095_g1_set_egress_port,
	.watchdog_ops = &mv88e6097_watchdog_ops,
	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
	.serdes_power = mv88e6185_serdes_power,
	.serdes_get_lane = mv88e6185_serdes_get_lane,
	.serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
	.serdes_irq_enable = mv88e6097_serdes_irq_enable,
	.serdes_irq_status = mv88e6097_serdes_irq_status,
	.pot_clear = mv88e6xxx_g2_pot_clear,
	.reset = mv88e6352_g1_reset,
	.rmu_disable = mv88e6085_g1_rmu_disable,
@@ -3317,6 +3329,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
@@ -3351,6 +3364,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -3392,6 +3406,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6341_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6341_port_max_speed_mode,
@@ -3443,6 +3458,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -3484,6 +3500,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
	.phy_read = mv88e6165_phy_read,
	.phy_write = mv88e6165_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
	.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
@@ -3518,6 +3535,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -3560,6 +3578,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -3611,6 +3630,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -3653,6 +3673,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -3706,6 +3727,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
	.phy_read = mv88e6185_phy_ppu_read,
	.phy_write = mv88e6185_phy_ppu_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6185_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
	.port_set_egress_floods = mv88e6185_port_set_egress_floods,
@@ -3723,6 +3745,9 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
	.set_egress_port = mv88e6095_g1_set_egress_port,
	.watchdog_ops = &mv88e6097_watchdog_ops,
	.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
	.serdes_power = mv88e6185_serdes_power,
	.serdes_get_lane = mv88e6185_serdes_get_lane,
	.serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state,
	.set_cascade_port = mv88e6185_g1_set_cascade_port,
	.ppu_enable = mv88e6185_g1_ppu_enable,
	.ppu_disable = mv88e6185_g1_ppu_disable,
@@ -3743,6 +3768,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
@@ -3802,6 +3828,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390x_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390x_port_max_speed_mode,
@@ -3861,6 +3888,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
@@ -3920,6 +3948,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -3978,6 +4007,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6250_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -4015,6 +4045,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
@@ -4076,6 +4107,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -4118,6 +4150,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -4158,6 +4191,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6341_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6341_port_max_speed_mode,
@@ -4211,6 +4245,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -4251,6 +4286,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -4295,6 +4331,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6352_port_set_speed_duplex,
	.port_tag_remap = mv88e6095_port_tag_remap,
@@ -4355,6 +4392,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390_port_max_speed_mode,
@@ -4418,6 +4456,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
	.phy_read = mv88e6xxx_g2_smi_phy_read,
	.phy_write = mv88e6xxx_g2_smi_phy_write,
	.port_set_link = mv88e6xxx_port_set_link,
	.port_sync_link = mv88e6xxx_port_sync_link,
	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
	.port_set_speed_duplex = mv88e6390x_port_set_speed_duplex,
	.port_max_speed_mode = mv88e6390x_port_max_speed_mode,
+4 −0
Original line number Diff line number Diff line
@@ -417,6 +417,10 @@ struct mv88e6xxx_ops {
	 */
	int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);

	/* Synchronise the port link state with that of the SERDES
	 */
	int (*port_sync_link)(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);

#define PAUSE_ON		1
#define PAUSE_OFF		0

+36 −0
Original line number Diff line number Diff line
@@ -162,6 +162,42 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
	return 0;
}

int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
{
	const struct mv88e6xxx_ops *ops = chip->info->ops;
	int err = 0;
	int link;

	if (isup)
		link = LINK_FORCED_UP;
	else
		link = LINK_FORCED_DOWN;

	if (ops->port_set_link)
		err = ops->port_set_link(chip, port, link);

	return err;
}

int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
{
	const struct mv88e6xxx_ops *ops = chip->info->ops;
	int err = 0;
	int link;

	if (mode == MLO_AN_INBAND)
		link = LINK_UNFORCED;
	else if (isup)
		link = LINK_FORCED_UP;
	else
		link = LINK_FORCED_DOWN;

	if (ops->port_set_link)
		err = ops->port_set_link(chip, port, link);

	return err;
}

static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip,
					   int port, int speed, bool alt_bit,
					   bool force_bit, int duplex)
+3 −0
Original line number Diff line number Diff line
@@ -298,6 +298,9 @@ int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,

int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);

int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);

int mv88e6065_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
				    int speed, int duplex);
int mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
+118 −5
Original line number Diff line number Diff line
@@ -400,13 +400,15 @@ void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
{
	u16 *p = _p;
	u16 reg;
	int err;
	int i;

	if (!mv88e6352_port_has_serdes(chip, port))
		return;

	for (i = 0 ; i < 32; i++) {
		mv88e6352_serdes_read(chip, i, &reg);
		err = mv88e6352_serdes_read(chip, i, &reg);
		if (!err)
			p[i] = reg;
	}
}
@@ -428,6 +430,115 @@ u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
	return lane;
}

int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
			   bool up)
{
	/* The serdes power can't be controlled on this switch chip but we need
	 * to supply this function to avoid returning -EOPNOTSUPP in
	 * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down
	 */
	return 0;
}

u8 mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
{
	/* There are no configurable serdes lanes on this switch chip but we
	 * need to return non-zero so that callers of
	 * mv88e6xxx_serdes_get_lane() know this is a serdes port.
	 */
	switch (chip->ports[port].cmode) {
	case MV88E6185_PORT_STS_CMODE_SERDES:
	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
		return 0xff;
	default:
		return 0;
	}
}

int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
				   u8 lane, struct phylink_link_state *state)
{
	int err;
	u16 status;

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

	state->link = !!(status & MV88E6XXX_PORT_STS_LINK);

	if (state->link) {
		state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF;

		switch (status &  MV88E6XXX_PORT_STS_SPEED_MASK) {
		case MV88E6XXX_PORT_STS_SPEED_1000:
			state->speed = SPEED_1000;
			break;
		case MV88E6XXX_PORT_STS_SPEED_100:
			state->speed = SPEED_100;
			break;
		case MV88E6XXX_PORT_STS_SPEED_10:
			state->speed = SPEED_10;
			break;
		default:
			dev_err(chip->dev, "invalid PHY speed\n");
			return -EINVAL;
		}
	} else {
		state->duplex = DUPLEX_UNKNOWN;
		state->speed = SPEED_UNKNOWN;
	}

	return 0;
}

int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
				bool enable)
{
	u8 cmode = chip->ports[port].cmode;

	/* The serdes interrupts are enabled in the G2_INT_MASK register. We
	 * need to return 0 to avoid returning -EOPNOTSUPP in
	 * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable
	 */
	switch (cmode) {
	case MV88E6185_PORT_STS_CMODE_SERDES:
	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
		return 0;
	}

	return -EOPNOTSUPP;
}

static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
{
	u16 status;
	int err;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
	if (err) {
		dev_err(chip->dev, "can't read port status: %d\n", err);
		return;
	}

	dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK));
}

irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
					u8 lane)
{
	u8 cmode = chip->ports[port].cmode;

	switch (cmode) {
	case MV88E6185_PORT_STS_CMODE_SERDES:
	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
		mv88e6097_serdes_irq_link(chip, port);
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
{
	u8 cmode = chip->ports[port].cmode;
@@ -987,6 +1098,7 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
	u16 *p = _p;
	int lane;
	u16 reg;
	int err;
	int i;

	lane = mv88e6xxx_serdes_get_lane(chip, port);
@@ -994,8 +1106,9 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
		return;

	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
					    mv88e6390_serdes_regs[i], &reg);
		if (!err)
			p[i] = reg;
	}
}
Loading