[][kernel][common][eth][Add EEE support for GDM]
[Description]
Add EEE support for GDM.
- ethtool --set-eee eth1 tx-lpi on tx-timer 1
- ethtool --show-eee eth1
If without this patch, user can't use ethtool to enable
MAC/PHY EEE capability.
[Release-log]
N/A
Change-Id: I624fbefba33fa2d75bc10efec0531b96f7d8034a
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6829459
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index af4893c..6f3b918 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -292,6 +292,44 @@
mtk_w32(eth, val, MTK_GSW_CFG);
}
+static void mtk_setup_eee(struct mtk_mac *mac, bool enable)
+{
+ struct mtk_eth *eth = mac->hw;
+ u32 mcr, mcr_cur;
+ u32 val;
+
+ mcr = mcr_cur = mtk_r32(eth, MTK_MAC_MCR(mac->id));
+ mcr &= ~(MAC_MCR_FORCE_EEE100 | MAC_MCR_FORCE_EEE1000);
+
+ if (enable) {
+ mac->tx_lpi_enabled = 1;
+
+ val = FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 19) |
+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 33) |
+ FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD,
+ mac->tx_lpi_timer) |
+ FIELD_PREP(MAC_EEE_RESV0, 14);
+ mtk_w32(eth, val, MTK_MAC_EEE(mac->id));
+
+ switch (mac->speed) {
+ case SPEED_1000:
+ mcr |= MAC_MCR_FORCE_EEE1000;
+ break;
+ case SPEED_100:
+ mcr |= MAC_MCR_FORCE_EEE100;
+ break;
+ };
+ } else {
+ mac->tx_lpi_enabled = 0;
+
+ mtk_w32(eth, 0x00000002, MTK_MAC_EEE(mac->id));
+ }
+
+ /* Only update control register when needed! */
+ if (mcr != mcr_cur)
+ mtk_w32(eth, mcr, MTK_MAC_MCR(mac->id));
+}
+
static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -629,6 +667,8 @@
phylink_config);
u32 mcr, mcr_cur;
+ mac->speed = speed;
+
if (mac->type == MTK_GDM_TYPE) {
mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
mcr = mcr_cur;
@@ -666,6 +706,9 @@
/* Only update control register when needed! */
if (mcr != mcr_cur)
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+
+ if (mode == MLO_AN_PHY && phy)
+ mtk_setup_eee(mac, phy_init_eee(phy, false) >= 0);
} else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
@@ -3936,6 +3979,39 @@
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);
+ struct mtk_eth *eth = mac->hw;
+ u32 val;
+
+ if (mac->type == MTK_GDM_TYPE) {
+ val = mtk_r32(eth, MTK_MAC_EEE(mac->id));
+
+ eee->tx_lpi_enabled = mac->tx_lpi_enabled;
+ eee->tx_lpi_timer = FIELD_GET(MAC_EEE_LPI_TXIDLE_THD, val);
+ }
+
+ return phylink_ethtool_get_eee(mac->phylink, eee);
+}
+
+static int mtk_set_eee(struct net_device *dev, struct ethtool_eee *eee)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
+ if (mac->type == MTK_GDM_TYPE) {
+ if (eee->tx_lpi_enabled && eee->tx_lpi_timer > 255)
+ return -EINVAL;
+
+ mac->tx_lpi_timer = eee->tx_lpi_timer;
+
+ mtk_setup_eee(mac, eee->eee_enabled && eee->tx_lpi_timer);
+ }
+
+ return phylink_ethtool_set_eee(mac->phylink, eee);
+}
+
static const struct ethtool_ops mtk_ethtool_ops = {
.get_link_ksettings = mtk_get_link_ksettings,
.set_link_ksettings = mtk_set_link_ksettings,
@@ -3951,6 +4027,8 @@
.set_rxnfc = mtk_set_rxnfc,
.get_pauseparam = mtk_get_pauseparam,
.set_pauseparam = mtk_set_pauseparam,
+ .get_eee = mtk_get_eee,
+ .set_eee = mtk_set_eee,
};
static const struct net_device_ops mtk_netdev_ops = {
@@ -4037,6 +4115,8 @@
mac->mode = MLO_AN_PHY;
mac->speed = SPEED_UNKNOWN;
+ mac->tx_lpi_timer = 1;
+
mac->phylink_config.dev = ð->netdev[id]->dev;
mac->phylink_config.type = PHYLINK_NETDEV;
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index a594d0b..f0b3a24 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -662,6 +662,8 @@
#define MAC_MCR_RX_EN BIT(13)
#define MAC_MCR_BACKOFF_EN BIT(9)
#define MAC_MCR_BACKPR_EN BIT(8)
+#define MAC_MCR_FORCE_EEE1000 BIT(7)
+#define MAC_MCR_FORCE_EEE100 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)
@@ -676,6 +678,17 @@
#define XMAC_MCR_FORCE_TX_FC BIT(5)
#define XMAC_MCR_FORCE_RX_FC BIT(4)
+/* Mac EEE control registers */
+#define MTK_MAC_EEE(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_RESV0 GENMASK(7, 4)
+#define MAC_EEE_CKG_TXILDE BIT(3)
+#define MAC_EEE_CKG_RXLPI BIT(2)
+#define MAC_EEE_TX_DOWN_REQ BIT(1)
+#define MAC_EEE_LPI_MODE BIT(0)
+
/* Mac status registers */
#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
#define MAC_MSR_EEE1G BIT(7)
@@ -1659,6 +1672,8 @@
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
+ bool tx_lpi_enabled;
+ u32 tx_lpi_timer;
};
/* the struct describing the SoC. these are declared in the soc_xyz.c files */