summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-05-17 15:53:59 -0700
committerDavid S. Miller <davem@davemloft.net>2021-05-17 15:53:59 -0700
commit8ed2e60b7788825d71e70ed26160d327a588dee5 (patch)
tree3c680fdc647e8191167059fa1f6cb724333c0f12
parent9d8a29aed03539a9012bff1232bacf062b5459cf (diff)
parente80fe71b3ffe1ec31c4a9be60170f897bbdf1b92 (diff)
Merge branch 'stmmac-xpcs-eee'
Michael Sit Wei Hong says: ==================== Introducing support for DWC xpcs Energy Efficient Ethernet The goal of this patch set is to enable EEE in the xpcs so that when EEE is enabled, the MAC-->xpcs-->PHY have all the EEE related configurations enabled. Patch 1 adds the functions to enable EEE in the xpcs and sets it to transparent mode. Patch 2 adds the callbacks to configure the xpcs EEE mode. The results are tested by checking the lpi counters of the tx and rx path of the interface. When EEE is enabled, the lpi counters should increament as it enters and exits lpi states. host@EHL$ ethtool --show-eee enp0s30f4 EEE Settings for enp0s30f4: EEE status: disabled Tx LPI: disabled Supported EEE link modes: 100baseT/Full 1000baseT/Full Advertised EEE link modes: Not reported Link partner advertised EEE link modes: 100baseT/Full 1000baseT/Full host@EHL$ ethtool -S enp0s30f4 | grep lpi irq_tx_path_in_lpi_mode_n: 0 irq_tx_path_exit_lpi_mode_n: 0 irq_rx_path_in_lpi_mode_n: 0 irq_rx_path_exit_lpi_mode_n: 0 host@EHL$ ethtool --set-eee enp0s30f4 eee on host@EHL$ [ 110.265154] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Down [ 112.315155] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Up - 1Gbps/Full - flow control off [ 112.324612] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s30f4: link becomes ready host@EHL$ ethtool --show-eee enp0s30f4 EEE Settings for enp0s30f4: EEE status: enabled - active Tx LPI: 1000000 (us) Supported EEE link modes: 100baseT/Full 1000baseT/Full Advertised EEE link modes: 100baseT/Full 1000baseT/Full Link partner advertised EEE link modes: 100baseT/Full 1000baseT/Full host@EHL$ ethtool -S enp0s30f4 | grep lpi irq_tx_path_in_lpi_mode_n: 6 irq_tx_path_exit_lpi_mode_n: 5 irq_rx_path_in_lpi_mode_n: 7 irq_rx_path_exit_lpi_mode_n: 6 host@EHL$ ping 192.168.1.1 PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. 64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.02 ms 64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.510 ms 64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.489 ms 64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.484 ms 64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.504 ms 64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=0.466 ms 64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=0.529 ms 64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=0.519 ms 64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=0.518 ms 64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=0.501 ms --- 192.168.1.1 ping statistics --- 10 packets transmitted, 10 received, 0% packet loss, time 9216ms rtt min/avg/max/mdev = 0.466/0.553/1.018/0.155 ms host@EHL$ ethtool -S enp0s30f4 | grep lpi irq_tx_path_in_lpi_mode_n: 22 irq_tx_path_exit_lpi_mode_n: 21 irq_rx_path_in_lpi_mode_n: 21 irq_rx_path_exit_lpi_mode_n: 20 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c6
-rw-r--r--drivers/net/pcs/pcs-xpcs.c51
-rw-r--r--include/linux/pcs/pcs-xpcs.h2
-rw-r--r--include/linux/stmmac.h1
6 files changed, 73 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 80728a4c0e3f..e36a8cc59ad0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -429,6 +429,17 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
plat->force_sf_dma_mode = 0;
plat->tso_en = 1;
+ /* Multiplying factor to the clk_eee_i clock time
+ * period to make it closer to 100 ns. This value
+ * should be programmed such that the clk_eee_time_period *
+ * (MULT_FACT_100NS + 1) should be within 80 ns to 120 ns
+ * clk_eee frequency is 19.2Mhz
+ * clk_eee_time_period is 52ns
+ * 52ns * (1 + 1) = 104ns
+ * MULT_FACT_100NS = 1
+ */
+ plat->mult_fact_100ns = 1;
+
plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
for (i = 0; i < plat->rx_queues_to_use; i++) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 6d5e0f2b03ce..75a8b90c202a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -623,6 +623,8 @@ struct stmmac_mmc_ops {
stmmac_do_callback(__priv, xpcs, link_up, __args)
#define stmmac_xpcs_probe(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, probe, __args)
+#define stmmac_xpcs_config_eee(__priv, __args...) \
+ stmmac_do_callback(__priv, xpcs, config_eee, __args)
struct stmmac_regs_off {
u32 ptp_off;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 61b11639ee0c..1f6d749fd9a3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -720,6 +720,12 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
netdev_warn(priv->dev,
"Setting EEE tx-lpi is not supported\n");
+ ret = stmmac_xpcs_config_eee(priv, &priv->hw->xpcs_args,
+ priv->plat->mult_fact_100ns,
+ edata->eee_enabled);
+ if (ret)
+ return ret;
+
if (!edata->eee_enabled)
stmmac_disable_eee_mode(priv);
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 944ba105cac1..aa985a5aae8d 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -63,6 +63,9 @@
#define DW_VR_MII_DIG_CTRL1 0x8000
#define DW_VR_MII_AN_CTRL 0x8001
#define DW_VR_MII_AN_INTR_STS 0x8002
+/* EEE Mode Control Register */
+#define DW_VR_MII_EEE_MCTRL0 0x8006
+#define DW_VR_MII_EEE_MCTRL1 0x800b
/* VR_MII_DIG_CTRL1 */
#define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)
@@ -86,6 +89,20 @@
#define DW_VR_MII_C37_ANSGM_SP_1000 0x2
#define DW_VR_MII_C37_ANSGM_SP_LNKSTS BIT(4)
+/* VR MII EEE Control 0 defines */
+#define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */
+#define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */
+#define DW_VR_MII_EEE_TX_QUIET_EN BIT(2) /* Tx Quiet Enable */
+#define DW_VR_MII_EEE_RX_QUIET_EN BIT(3) /* Rx Quiet Enable */
+#define DW_VR_MII_EEE_TX_EN_CTRL BIT(4) /* Tx Control Enable */
+#define DW_VR_MII_EEE_RX_EN_CTRL BIT(7) /* Rx Control Enable */
+
+#define DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT 8
+#define DW_VR_MII_EEE_MULT_FACT_100NS GENMASK(11, 8)
+
+/* VR MII EEE Control 1 defines */
+#define DW_VR_MII_EEE_TRN_LPI BIT(0) /* Transparent Mode Enable */
+
static const int xpcs_usxgmii_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@@ -650,6 +667,39 @@ static int xpcs_validate(struct mdio_xpcs_args *xpcs,
return 0;
}
+static int xpcs_config_eee(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
+ int enable)
+{
+ int ret;
+
+ if (enable) {
+ /* Enable EEE */
+ ret = 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 |
+ mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT;
+ } else {
+ ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0);
+ if (ret < 0)
+ return ret;
+ ret &= ~(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);
+ }
+
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret);
+ if (ret < 0)
+ return ret;
+
+ ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1);
+ if (ret < 0)
+ return ret;
+
+ ret |= DW_VR_MII_EEE_TRN_LPI;
+ return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret);
+}
+
static int xpcs_config_aneg_c37_sgmii(struct mdio_xpcs_args *xpcs)
{
int ret;
@@ -908,6 +958,7 @@ static struct mdio_xpcs_ops xpcs_ops = {
.get_state = xpcs_get_state,
.link_up = xpcs_link_up,
.probe = xpcs_probe,
+ .config_eee = xpcs_config_eee,
};
struct mdio_xpcs_ops *mdio_xpcs_get_ops(void)
diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h
index 2cb5188a7ef1..5938ced805f4 100644
--- a/include/linux/pcs/pcs-xpcs.h
+++ b/include/linux/pcs/pcs-xpcs.h
@@ -32,6 +32,8 @@ struct mdio_xpcs_ops {
int (*link_up)(struct mdio_xpcs_args *xpcs, int speed,
phy_interface_t interface);
int (*probe)(struct mdio_xpcs_args *xpcs, phy_interface_t interface);
+ int (*config_eee)(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
+ int enable);
};
#if IS_ENABLED(CONFIG_PCS_XPCS)
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 0db36360ef21..e14a12df381b 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -223,6 +223,7 @@ struct plat_stmmacenet_data {
struct clk *clk_ptp_ref;
unsigned int clk_ptp_rate;
unsigned int clk_ref_rate;
+ unsigned int mult_fact_100ns;
s32 ptp_max_adj;
struct reset_control *stmmac_rst;
struct stmmac_axi *axi;