Commit 412723d5 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-phylink-xpcs-stmmac-support-pcs-eee-configuration'

Russell King says:

====================
net: phylink,xpcs,stmmac: support PCS EEE configuration

This series adds support for phylink managed EEE at the PCS level,
allowing xpcs_config_eee() to be removed. Sadly, we still end up with
a XPCS specific function to configure the clock multiplier.
====================

Link: https://patch.msgid.link/Z6naiPpxfxGr1Ic6@shell.armlinux.org.uk


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 6aa3960d 1d4c99a1
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -1046,10 +1046,6 @@ static void stmmac_mac_disable_tx_lpi(struct phylink_config *config)
	priv->tx_path_in_lpi_mode = false;

	stmmac_set_eee_timer(priv, priv->hw, 0, STMMAC_DEFAULT_TWT_LS);
	if (priv->hw->xpcs)
		xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
				false);

	mutex_unlock(&priv->lock);
}

@@ -1068,9 +1064,6 @@ static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,

	stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
			     STMMAC_DEFAULT_TWT_LS);
	if (priv->hw->xpcs)
		xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
				true);

	/* Try to cnfigure the hardware timer. */
	ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
+2 −0
Original line number Diff line number Diff line
@@ -524,6 +524,8 @@ int stmmac_pcs_setup(struct net_device *ndev)
	if (ret)
		return dev_err_probe(priv->device, ret, "No xPCS found\n");

	xpcs_config_eee_mult_fact(xpcs, priv->plat->mult_fact_100ns);

	priv->hw->xpcs = xpcs;

	return 0;
+59 −30
Original line number Diff line number Diff line
@@ -602,36 +602,6 @@ static void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
		__set_bit(compat->interface, interfaces);
}

int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
{
	u16 mask, val;
	int ret;

	mask = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
	       DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
	       DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
	       DW_VR_MII_EEE_MULT_FACT_100NS;

	if (enable)
		val = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
		      DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
		      DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
		      FIELD_PREP(DW_VR_MII_EEE_MULT_FACT_100NS,
				 mult_fact_100ns);
	else
		val = 0;

	ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
			  val);
	if (ret < 0)
		return ret;

	return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
			   DW_VR_MII_EEE_TRN_LPI,
			   enable ? DW_VR_MII_EEE_TRN_LPI : 0);
}
EXPORT_SYMBOL_GPL(xpcs_config_eee);

static void xpcs_pre_config(struct phylink_pcs *pcs, phy_interface_t interface)
{
	struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
@@ -1193,6 +1163,63 @@ static void xpcs_an_restart(struct phylink_pcs *pcs)
		    BMCR_ANRESTART);
}

static int xpcs_config_eee(struct dw_xpcs *xpcs, bool enable)
{
	u16 mask, val;
	int ret;

	mask = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
	       DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
	       DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
	       DW_VR_MII_EEE_MULT_FACT_100NS;

	if (enable)
		val = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
		      DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
		      DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
		      FIELD_PREP(DW_VR_MII_EEE_MULT_FACT_100NS,
				 xpcs->eee_mult_fact);
	else
		val = 0;

	ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
			  val);
	if (ret < 0)
		return ret;

	return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
			   DW_VR_MII_EEE_TRN_LPI,
			   enable ? DW_VR_MII_EEE_TRN_LPI : 0);
}

static void xpcs_disable_eee(struct phylink_pcs *pcs)
{
	struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);

	xpcs_config_eee(xpcs, false);
}

static void xpcs_enable_eee(struct phylink_pcs *pcs)
{
	struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);

	xpcs_config_eee(xpcs, true);
}

/**
 * xpcs_config_eee_mult_fact() - set the EEE clock multiplying factor
 * @xpcs: pointer to a &struct dw_xpcs instance
 * @mult_fact: the multiplying factor
 *
 * Configure the EEE clock multiplying factor. This value should be such that
 * clk_eee_time_period * (mult_fact + 1) is within the range 80 to 120ns.
 */
void xpcs_config_eee_mult_fact(struct dw_xpcs *xpcs, u8 mult_fact)
{
	xpcs->eee_mult_fact = mult_fact;
}
EXPORT_SYMBOL_GPL(xpcs_config_eee_mult_fact);

static int xpcs_read_ids(struct dw_xpcs *xpcs)
{
	int ret;
@@ -1341,6 +1368,8 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
	.pcs_get_state = xpcs_get_state,
	.pcs_an_restart = xpcs_an_restart,
	.pcs_link_up = xpcs_link_up,
	.pcs_disable_eee = xpcs_disable_eee,
	.pcs_enable_eee = xpcs_enable_eee,
};

static int xpcs_identify(struct dw_xpcs *xpcs)
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ struct dw_xpcs {
	struct phylink_pcs pcs;
	phy_interface_t interface;
	bool need_reset;
	u8 eee_mult_fact;
};

int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg);
+22 −3
Original line number Diff line number Diff line
@@ -1073,6 +1073,18 @@ static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
		pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
}

static void phylink_pcs_disable_eee(struct phylink_pcs *pcs)
{
	if (pcs && pcs->ops->pcs_disable_eee)
		pcs->ops->pcs_disable_eee(pcs);
}

static void phylink_pcs_enable_eee(struct phylink_pcs *pcs)
{
	if (pcs && pcs->ops->pcs_enable_eee)
		pcs->ops->pcs_enable_eee(pcs);
}

/* Query inband for a specific interface mode, asking the MAC for the
 * PCS which will be used to handle the interface mode.
 */
@@ -1601,6 +1613,8 @@ static void phylink_deactivate_lpi(struct phylink *pl)
		phylink_dbg(pl, "disabling LPI\n");

		pl->mac_ops->mac_disable_tx_lpi(pl->config);

		phylink_pcs_disable_eee(pl->pcs);
	}
}

@@ -1617,13 +1631,18 @@ static void phylink_activate_lpi(struct phylink *pl)
	phylink_dbg(pl, "LPI timer %uus, tx clock stop %u\n",
		    pl->mac_tx_lpi_timer, pl->mac_tx_clk_stop);

	phylink_pcs_enable_eee(pl->pcs);

	err = pl->mac_ops->mac_enable_tx_lpi(pl->config, pl->mac_tx_lpi_timer,
					     pl->mac_tx_clk_stop);
	if (!err)
		pl->mac_enable_tx_lpi = true;
	else
	if (err) {
		phylink_pcs_disable_eee(pl->pcs);
		phylink_err(pl, "%ps() failed: %pe\n",
			    pl->mac_ops->mac_enable_tx_lpi, ERR_PTR(err));
		return;
	}

	pl->mac_enable_tx_lpi = true;
}

static void phylink_link_up(struct phylink *pl,
Loading