Skip to content

Commit

Permalink
net: mvpp2: add EEE implementation
Browse files Browse the repository at this point in the history
Add EEE support for mvpp2, using phylink's EEE implementation, which
means we just need to implement the two methods for LPI control, and
with the initial configuration. Only SGMII mode is supported, so only
100M and 1G speeds.

Disabling LPI requires clearing a single bit. Enabling LPI needs a full
configuration of several values, as the timer values are dependent on
the MAC operating speed.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/E1tYAE0-0014Pz-R9@rmk-PC.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Russell King (Oracle) authored and Jakub Kicinski committed Jan 17, 2025
1 parent ac79927 commit b53b147
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
5 changes: 5 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,11 @@
#define MVPP22_GMAC_INT_SUM_MASK 0xa4
#define MVPP22_GMAC_INT_SUM_MASK_LINK_STAT BIT(1)
#define MVPP22_GMAC_INT_SUM_MASK_PTP BIT(2)
#define MVPP2_GMAC_LPI_CTRL0 0xc0
#define MVPP2_GMAC_LPI_CTRL0_TS_MASK GENMASK(15, 8)
#define MVPP2_GMAC_LPI_CTRL1 0xc4
#define MVPP2_GMAC_LPI_CTRL1_REQ_EN BIT(0)
#define MVPP2_GMAC_LPI_CTRL1_TW_MASK GENMASK(15, 4)

/* Per-port XGMAC registers. PPv2.2 and PPv2.3, only for GOP port 0,
* relative to port->base.
Expand Down
86 changes: 86 additions & 0 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5757,6 +5757,28 @@ static int mvpp2_ethtool_set_rxfh(struct net_device *dev,
return mvpp2_modify_rxfh_context(dev, NULL, rxfh, extack);
}

static int mvpp2_ethtool_get_eee(struct net_device *dev,
struct ethtool_keee *eee)
{
struct mvpp2_port *port = netdev_priv(dev);

if (!port->phylink)
return -EOPNOTSUPP;

return phylink_ethtool_get_eee(port->phylink, eee);
}

static int mvpp2_ethtool_set_eee(struct net_device *dev,
struct ethtool_keee *eee)
{
struct mvpp2_port *port = netdev_priv(dev);

if (!port->phylink)
return -EOPNOTSUPP;

return phylink_ethtool_set_eee(port->phylink, eee);
}

/* Device ops */

static const struct net_device_ops mvpp2_netdev_ops = {
Expand Down Expand Up @@ -5802,6 +5824,8 @@ static const struct ethtool_ops mvpp2_eth_tool_ops = {
.create_rxfh_context = mvpp2_create_rxfh_context,
.modify_rxfh_context = mvpp2_modify_rxfh_context,
.remove_rxfh_context = mvpp2_remove_rxfh_context,
.get_eee = mvpp2_ethtool_get_eee,
.set_eee = mvpp2_ethtool_set_eee,
};

/* Used for PPv2.1, or PPv2.2 with the old Device Tree binding that
Expand Down Expand Up @@ -6674,13 +6698,64 @@ static void mvpp2_mac_link_down(struct phylink_config *config,
mvpp2_port_disable(port);
}

static void mvpp2_mac_disable_tx_lpi(struct phylink_config *config)
{
struct mvpp2_port *port = mvpp2_phylink_to_port(config);

mvpp2_modify(port->base + MVPP2_GMAC_LPI_CTRL1,
MVPP2_GMAC_LPI_CTRL1_REQ_EN, 0);
}

static int mvpp2_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
bool tx_clk_stop)
{
struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 ts, tw, lpi1, status;

status = readl(port->base + MVPP2_GMAC_STATUS0);
if (status & MVPP2_GMAC_STATUS0_GMII_SPEED) {
/* At 1G speeds, the timer resolution are 1us, and
* 802.3 says tw is 16.5us. Round up to 17us.
*/
tw = 17;
ts = timer;
} else {
/* At 100M speeds, the timer resolutions are 10us, and
* 802.3 says tw is 30us.
*/
tw = 3;
ts = DIV_ROUND_UP(timer, 10);
}

if (ts > 255)
ts = 255;

/* Configure ts */
mvpp2_modify(port->base + MVPP2_GMAC_LPI_CTRL0,
MVPP2_GMAC_LPI_CTRL0_TS_MASK,
FIELD_PREP(MVPP2_GMAC_LPI_CTRL0_TS_MASK, ts));

lpi1 = readl(port->base + MVPP2_GMAC_LPI_CTRL1);

/* Configure tw */
lpi1 = u32_replace_bits(lpi1, tw, MVPP2_GMAC_LPI_CTRL1_TW_MASK);

/* Enable LPI generation */
writel(lpi1 | MVPP2_GMAC_LPI_CTRL1_REQ_EN,
port->base + MVPP2_GMAC_LPI_CTRL1);

return 0;
}

static const struct phylink_mac_ops mvpp2_phylink_ops = {
.mac_select_pcs = mvpp2_select_pcs,
.mac_prepare = mvpp2_mac_prepare,
.mac_config = mvpp2_mac_config,
.mac_finish = mvpp2_mac_finish,
.mac_link_up = mvpp2_mac_link_up,
.mac_link_down = mvpp2_mac_link_down,
.mac_enable_tx_lpi = mvpp2_mac_enable_tx_lpi,
.mac_disable_tx_lpi = mvpp2_mac_disable_tx_lpi,
};

/* Work-around for ACPI */
Expand Down Expand Up @@ -6959,6 +7034,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port->phylink_config.mac_capabilities =
MAC_2500FD | MAC_1000FD | MAC_100 | MAC_10;

__set_bit(PHY_INTERFACE_MODE_SGMII,
port->phylink_config.lpi_interfaces);

port->phylink_config.lpi_capabilities = MAC_1000FD | MAC_100FD;

/* Setup EEE. Choose 250us idle. */
port->phylink_config.lpi_timer_default = 250;
port->phylink_config.eee_enabled_default = true;

if (port->priv->global_tx_fc)
port->phylink_config.mac_capabilities |=
MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
Expand Down Expand Up @@ -7033,6 +7117,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
goto err_free_port_pcpu;
}
port->phylink = phylink;

mvpp2_mac_disable_tx_lpi(&port->phylink_config);
} else {
dev_warn(&pdev->dev, "Use link irqs for port#%d. FW update required\n", port->id);
port->phylink = NULL;
Expand Down

0 comments on commit b53b147

Please sign in to comment.