From 952d7325362ffbefa6ce5619fb4e53c2159ec7a7 Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Mon, 17 Feb 2025 17:40:21 +0800 Subject: [PATCH] net: ethernet: mediatek: add EEE support 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 --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 64 +++++++++++++++++++++ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 ++++ 2 files changed, 75 insertions(+) --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -786,6 +786,7 @@ static void mtk_mac_link_up(struct phyli mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 | + MAC_MCR_EEE100M | MAC_MCR_EEE1G | MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC | MAC_MCR_FORCE_RX_FC); @@ -811,6 +812,18 @@ static void mtk_mac_link_up(struct phyli if (rx_pause) mcr |= MAC_MCR_FORCE_RX_FC; + if (mode == MLO_AN_PHY && phy && phy_init_eee(phy, false) >= 0) { + switch (speed) { + case SPEED_2500: + case SPEED_1000: + mcr |= MAC_MCR_EEE1G; + break; + case SPEED_100: + mcr |= MAC_MCR_EEE100M; + break; + } + } + mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -3956,6 +3969,7 @@ static int mtk_hw_init(struct mtk_eth *e continue; mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); + mtk_w32(eth, FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, 1), MTK_MAC_EEECR(i)); mtk_set_mcr_max_rx(netdev_priv(dev), dev->mtu + MTK_RX_ETH_HLEN); } @@ -4476,6 +4490,55 @@ static int mtk_set_pauseparam(struct net return phylink_ethtool_set_pauseparam(mac->phylink, pause); } +static int mtk_get_eee(struct net_device *dev, struct ethtool_eee *eee) +{ + struct mtk_mac *mac = netdev_priv(dev); + u32 reg; + int ret; + + ret = phylink_ethtool_get_eee(mac->phylink, eee); + if (ret) + return ret; + + reg = mtk_r32(mac->hw, MTK_MAC_EEECR(mac->id)); + eee->tx_lpi_enabled = !(reg & MAC_EEE_LPI_MODE); + eee->tx_lpi_timer = FIELD_GET(MAC_EEE_LPI_TXIDLE_THD, reg) * 1000; + + return 0; +} + +static int mtk_set_eee(struct net_device *dev, struct ethtool_eee *eee) +{ + struct mtk_mac *mac = netdev_priv(dev); + u32 txidle_thd_ms, reg; + int ret; + + /* Tx idle timer in ms */ + txidle_thd_ms = DIV_ROUND_UP(eee->tx_lpi_timer, 1000); + if (!FIELD_FIT(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms)) + return -EINVAL; + + reg = FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms); + + /* PHY Wake-up time, this field does not have a reset value, so use the + * reset value from MT7531 (36us for 100BaseT and 17us for 1000BaseT). + */ + reg |= FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) | + FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36); + + if (!txidle_thd_ms) + /* Force LPI Mode without a delay */ + reg |= MAC_EEE_LPI_MODE; + + ret = phylink_ethtool_set_eee(mac->phylink, eee); + if (ret) + return ret; + + mtk_w32(mac->hw, reg, MTK_MAC_EEECR(mac->id)); + + return 0; +} + static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) { @@ -4508,6 +4571,8 @@ static const struct ethtool_ops mtk_etht .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 = { --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -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) @@ -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)