mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
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: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
412723d54a
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@ struct dw_xpcs;
|
|||
|
||||
struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs);
|
||||
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface);
|
||||
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns,
|
||||
int enable);
|
||||
void xpcs_config_eee_mult_fact(struct dw_xpcs *xpcs, u8 mult_fact);
|
||||
struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr);
|
||||
struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode);
|
||||
void xpcs_destroy(struct dw_xpcs *xpcs);
|
||||
|
|
|
|||
|
|
@ -477,6 +477,10 @@ struct phylink_pcs {
|
|||
* @pcs_an_restart: restart 802.3z BaseX autonegotiation.
|
||||
* @pcs_link_up: program the PCS for the resolved link configuration
|
||||
* (where necessary).
|
||||
* @pcs_disable_eee: optional notification to PCS that EEE has been disabled
|
||||
* at the MAC.
|
||||
* @pcs_enable_eee: optional notification to PCS that EEE will be enabled at
|
||||
* the MAC.
|
||||
* @pcs_pre_init: configure PCS components necessary for MAC hardware
|
||||
* initialization e.g. RX clock for stmmac.
|
||||
*/
|
||||
|
|
@ -500,6 +504,8 @@ struct phylink_pcs_ops {
|
|||
void (*pcs_an_restart)(struct phylink_pcs *pcs);
|
||||
void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
phy_interface_t interface, int speed, int duplex);
|
||||
void (*pcs_disable_eee)(struct phylink_pcs *pcs);
|
||||
void (*pcs_enable_eee)(struct phylink_pcs *pcs);
|
||||
int (*pcs_pre_init)(struct phylink_pcs *pcs);
|
||||
};
|
||||
|
||||
|
|
@ -625,6 +631,22 @@ void pcs_an_restart(struct phylink_pcs *pcs);
|
|||
void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
phy_interface_t interface, int speed, int duplex);
|
||||
|
||||
/**
|
||||
* pcs_disable_eee() - Disable EEE at the PCS
|
||||
* @pcs: a pointer to a &struct phylink_pcs
|
||||
*
|
||||
* Optional method informing the PCS that EEE has been disabled at the MAC.
|
||||
*/
|
||||
void pcs_disable_eee(struct phylink_pcs *pcs);
|
||||
|
||||
/**
|
||||
* pcs_enable_eee() - Enable EEE at the PCS
|
||||
* @pcs: a pointer to a &struct phylink_pcs
|
||||
*
|
||||
* Optional method informing the PCS that EEE is about to be enabled at the MAC.
|
||||
*/
|
||||
void pcs_enable_eee(struct phylink_pcs *pcs);
|
||||
|
||||
/**
|
||||
* pcs_pre_init() - Configure PCS components necessary for MAC initialization
|
||||
* @pcs: a pointer to a &struct phylink_pcs.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user