Commit 2031c09e authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller
Browse files

net: pcs: xpcs: add support for sgmii with no inband AN



In fixed-link use cases, the XPCS can disable the clause 37 in-band
autoneg process, disable the "Automatic Speed Mode Change after CL37 AN"
setting, and force operation in a speed dictated by management.

Add support for this operating mode.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d4433d5b
Loading
Loading
Loading
Loading
+38 −3
Original line number Diff line number Diff line
@@ -690,7 +690,7 @@ int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
}
EXPORT_SYMBOL_GPL(xpcs_config_eee);

static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs)
static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
{
	int ret;

@@ -726,7 +726,10 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs)
	if (ret < 0)
		return ret;

	if (phylink_autoneg_inband(mode))
		ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
	else
		ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;

	return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
}
@@ -772,7 +775,7 @@ static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
		}
		break;
	case DW_AN_C37_SGMII:
		ret = xpcs_config_aneg_c37_sgmii(xpcs);
		ret = xpcs_config_aneg_c37_sgmii(xpcs, mode);
		if (ret)
			return ret;
		break;
@@ -905,6 +908,36 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
	}
}

static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
			       int speed, int duplex)
{
	int val, ret;

	if (phylink_autoneg_inband(mode))
		return;

	switch (speed) {
	case SPEED_1000:
		val = BMCR_SPEED1000;
		break;
	case SPEED_100:
		val = BMCR_SPEED100;
		break;
	case SPEED_10:
		val = BMCR_SPEED10;
		break;
	default:
		return;
	}

	if (duplex == DUPLEX_FULL)
		val |= BMCR_FULLDPLX;

	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
	if (ret)
		pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
}

static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
			 phy_interface_t interface, int speed, int duplex)
{
@@ -912,6 +945,8 @@ static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,

	if (interface == PHY_INTERFACE_MODE_USXGMII)
		return xpcs_config_usxgmii(xpcs, speed);
	if (interface == PHY_INTERFACE_MODE_SGMII)
		return xpcs_link_up_sgmii(xpcs, mode, speed, duplex);
}

static u32 xpcs_get_id(struct dw_xpcs *xpcs)