Skip to content

Commit

Permalink
net: ethernet: mediatek: add EEE support
Browse files Browse the repository at this point in the history
Add EEE support to MediaTek SoC Ethernet. The register fields are
similar to the ones in MT7531, except that the LPI threshold is in
milliseconds.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://patch.msgid.link/20250217094022.1065436-1-dqfext@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Qingfang Deng authored and Jakub Kicinski committed Feb 19, 2025
1 parent 9faaaef commit 952d732
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
67 changes: 67 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,12 +815,60 @@ static void mtk_mac_link_up(struct phylink_config *config,
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
}

static void mtk_mac_disable_tx_lpi(struct phylink_config *config)
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
struct mtk_eth *eth = mac->hw;

mtk_m32(eth, MAC_MCR_EEE100M | MAC_MCR_EEE1G, 0, MTK_MAC_MCR(mac->id));
}

static int mtk_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
bool tx_clk_stop)
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
struct mtk_eth *eth = mac->hw;
u32 val;

/* Tx idle timer in ms */
timer = DIV_ROUND_UP(timer, 1000);

/* If the timer is zero, then set LPI_MODE, which allows the
* system to enter LPI mode immediately rather than waiting for
* the LPI threshold.
*/
if (!timer)
val = MAC_EEE_LPI_MODE;
else if (FIELD_FIT(MAC_EEE_LPI_TXIDLE_THD, timer))
val = FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, timer);
else
val = MAC_EEE_LPI_TXIDLE_THD;

if (tx_clk_stop)
val |= MAC_EEE_CKG_TXIDLE;

/* PHY Wake-up time, this field does not have a reset value, so use the
* reset value from MT7531 (36us for 100M and 17us for 1000M).
*/
val |= FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) |
FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36);

mtk_w32(eth, val, MTK_MAC_EEECR(mac->id));
mtk_m32(eth, 0, MAC_MCR_EEE100M | MAC_MCR_EEE1G, MTK_MAC_MCR(mac->id));

return 0;
}

static const struct phylink_mac_ops mtk_phylink_ops = {
.mac_select_pcs = mtk_mac_select_pcs,
.mac_config = mtk_mac_config,
.mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
.mac_link_up = mtk_mac_link_up,
.mac_disable_tx_lpi = mtk_mac_disable_tx_lpi,
.mac_enable_tx_lpi = mtk_mac_enable_tx_lpi,
};

static int mtk_mdio_init(struct mtk_eth *eth)
Expand Down Expand Up @@ -4469,6 +4517,20 @@ static int mtk_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
return phylink_ethtool_set_pauseparam(mac->phylink, pause);
}

static int mtk_get_eee(struct net_device *dev, struct ethtool_keee *eee)
{
struct mtk_mac *mac = netdev_priv(dev);

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

static int mtk_set_eee(struct net_device *dev, struct ethtool_keee *eee)
{
struct mtk_mac *mac = netdev_priv(dev);

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

static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev)
{
Expand Down Expand Up @@ -4501,6 +4563,8 @@ static const struct ethtool_ops mtk_ethtool_ops = {
.set_pauseparam = mtk_set_pauseparam,
.get_rxnfc = mtk_get_rxnfc,
.set_rxnfc = mtk_set_rxnfc,
.get_eee = mtk_get_eee,
.set_eee = mtk_set_eee,
};

static const struct net_device_ops mtk_netdev_ops = {
Expand Down Expand Up @@ -4610,6 +4674,9 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->phylink_config.type = PHYLINK_NETDEV;
mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD |
MAC_2500FD;
mac->phylink_config.lpi_timer_default = 1000;

/* MT7623 gmac0 is now missing its speed-specific PLL configuration
* in its .mac_config method (since state->speed is not valid there.
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@
#define MAC_MCR_RX_FIFO_CLR_DIS BIT(12)
#define MAC_MCR_BACKOFF_EN BIT(9)
#define MAC_MCR_BACKPR_EN BIT(8)
#define MAC_MCR_EEE1G BIT(7)
#define MAC_MCR_EEE100M BIT(6)
#define MAC_MCR_FORCE_RX_FC BIT(5)
#define MAC_MCR_FORCE_TX_FC BIT(4)
#define MAC_MCR_SPEED_1000 BIT(3)
Expand All @@ -461,6 +463,15 @@
#define MAC_MCR_FORCE_LINK BIT(0)
#define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)

/* Mac EEE control registers */
#define MTK_MAC_EEECR(x) (0x10104 + (x * 0x100))
#define MAC_EEE_WAKEUP_TIME_1000 GENMASK(31, 24)
#define MAC_EEE_WAKEUP_TIME_100 GENMASK(23, 16)
#define MAC_EEE_LPI_TXIDLE_THD GENMASK(15, 8)
#define MAC_EEE_CKG_TXIDLE BIT(3)
#define MAC_EEE_CKG_RXLPI BIT(2)
#define MAC_EEE_LPI_MODE BIT(0)

/* Mac status registers */
#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
#define MAC_MSR_EEE1G BIT(7)
Expand Down

0 comments on commit 952d732

Please sign in to comment.