2021-03-25 08:44:59

by Sit, Michael Wei Hong

[permalink] [raw]
Subject: [PATCH net-next v3 0/2] Enable 2.5Gbps speed for stmmac and xPCS

This patchset enables 2.5Gbps speed mode for stmmac and xPCS.
For 2.5G, we do not use SGMII in-band AN, we check the link speed mode
in the serdes and disable the in-band AN accordingly.

iperf3 and ping for 2.5Gbps and regression test on 10M/100M/1000Mbps
is done to prevent regresson issues.

10Mbps
host@EHL$ ethtool -s enp0s30f4 speed 10 duplex full autoneg on
[ 76.022186] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Down
[ 79.420699] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Up - 10Mbps/Full - flow control off
[ 79.430270] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s30f4: link becomes ready
host@EHL$ iperf3 -c 192.168.1.1 Connecting to host 192.168.1.1, port 5201 [ 5] local 192.168.1.2 port 33462 connected to 192.168.1.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 1.26 MBytes 10.6 Mbits/sec 0 29.7 KBytes
[ 5] 1.00-2.00 sec 1.09 MBytes 9.18 Mbits/sec 0 29.7 KBytes
[ 5] 2.00-3.00 sec 1.09 MBytes 9.17 Mbits/sec 0 29.7 KBytes
[ 5] 3.00-4.00 sec 1.15 MBytes 9.68 Mbits/sec 0 29.7 KBytes
[ 5] 4.00-5.00 sec 1.09 MBytes 9.17 Mbits/sec 0 29.7 KBytes
[ 5] 5.00-6.00 sec 1.09 MBytes 9.17 Mbits/sec 0 29.7 KBytes
[ 5] 6.00-7.00 sec 1.15 MBytes 9.68 Mbits/sec 0 29.7 KBytes
[ 5] 7.00-8.00 sec 1.09 MBytes 9.17 Mbits/sec 0 29.7 KBytes
[ 5] 8.00-9.00 sec 1.09 MBytes 9.17 Mbits/sec 0 29.7 KBytes
[ 5] 9.00-10.00 sec 1.15 MBytes 9.68 Mbits/sec 0 29.7 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 11.3 MBytes 9.47 Mbits/sec 0 sender
[ 5] 0.00-10.01 sec 11.1 MBytes 9.33 Mbits/sec receiver

iperf Done.
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=0.634 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.599 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.594 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.650 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.591 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=0.586 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=0.582 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=0.610 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=0.585 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=0.577 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=0.612 ms
--- 192.168.1.1 ping statistics ---
11 packets transmitted, 11 received, 0% packet loss, time 10224ms rtt min/avg/max/mdev = 0.577/0.601/0.650/0.021 ms

100Mbps
host@EHL$ ethtool -s enp0s30f4 speed 100 duplex full autoneg on
[ 269.425955] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Down
[ 271.932821] intel-eth-pci 0000:00:1e.4 enp0s30f4: Link is Up - 100Mbps/Full - flow control off [ 271.942493] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s30f4: link becomes ready
host@EHL$ iperf3 -c 192.168.1.1 Connecting to host 192.168.1.1, port 5201 [ 5] local 192.168.1.2 port 33466 connected to 192.168.1.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 11.6 MBytes 97.5 Mbits/sec 0 100 KBytes
[ 5] 1.00-2.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 2.00-3.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 3.00-4.00 sec 11.3 MBytes 94.5 Mbits/sec 0 100 KBytes
[ 5] 4.00-5.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 5.00-6.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 6.00-7.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 7.00-8.00 sec 11.3 MBytes 94.5 Mbits/sec 0 100 KBytes
[ 5] 8.00-9.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
[ 5] 9.00-10.00 sec 11.0 MBytes 92.6 Mbits/sec 0 100 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 111 MBytes 93.4 Mbits/sec 0 sender
[ 5] 0.00-10.01 sec 111 MBytes 93.0 Mbits/sec receiver

iperf Done.
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=0.393 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.354 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.414 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.377 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.426 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=0.379 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=0.348 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=0.354 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=0.351 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=0.351 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=0.429 ms
--- 192.168.1.1 ping statistics ---
11 packets transmitted, 11 received, 0% packet loss, time 10254ms rtt min/avg/max/mdev = 0.348/0.379/0.429/0.030 ms

1G speed
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.15 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.601 ms
--- 192.168.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.601/0.874/1.147/0.273 ms host@EHL$ ^C host@EHL$ ping 192.168.1.1^C host@EHL$ ^C host@EHL$ iperf3 -c 192.168.1.1 Connecting to host 192.168.1.1, port 5201 [ 5] local 192.168.1.2 port 47884 connected to 192.168.1.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 114 MBytes 957 Mbits/sec 2 571 KBytes
[ 5] 1.00-2.00 sec 111 MBytes 933 Mbits/sec 1 525 KBytes
[ 5] 2.00-3.00 sec 111 MBytes 933 Mbits/sec 0 624 KBytes
[ 5] 3.00-4.00 sec 111 MBytes 933 Mbits/sec 0 718 KBytes
[ 5] 4.00-5.00 sec 111 MBytes 933 Mbits/sec 0 799 KBytes
[ 5] 5.00-6.00 sec 111 MBytes 933 Mbits/sec 2 450 KBytes
[ 5] 6.00-7.00 sec 111 MBytes 933 Mbits/sec 0 570 KBytes
[ 5] 7.00-8.00 sec 111 MBytes 933 Mbits/sec 0 673 KBytes
[ 5] 8.00-9.00 sec 111 MBytes 933 Mbits/sec 2 551 KBytes
[ 5] 9.00-10.00 sec 112 MBytes 944 Mbits/sec 1 471 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.09 GBytes 937 Mbits/sec 8 sender
[ 5] 0.00-10.00 sec 1.09 GBytes 933 Mbits/sec receiver

iperf Done.

2.5G speed
host@EHL$ iperf3 -c 192.168.1.1
Connecting to host 192.168.1.1, port 5201
[ 5] local 192.168.1.2 port 58650 connected to 192.168.1.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 192 MBytes 1.61 Gbits/sec 0 710 KBytes
[ 5] 1.00-2.00 sec 190 MBytes 1.59 Gbits/sec 0 710 KBytes
[ 5] 2.00-3.00 sec 190 MBytes 1.59 Gbits/sec 0 710 KBytes
[ 5] 3.00-4.00 sec 189 MBytes 1.58 Gbits/sec 0 795 KBytes
[ 5] 4.00-5.00 sec 190 MBytes 1.59 Gbits/sec 0 795 KBytes
[ 5] 5.00-6.00 sec 189 MBytes 1.58 Gbits/sec 0 795 KBytes
[ 5] 6.00-7.00 sec 190 MBytes 1.59 Gbits/sec 0 840 KBytes
[ 5] 7.00-8.00 sec 190 MBytes 1.59 Gbits/sec 0 840 KBytes
[ 5] 8.00-9.00 sec 189 MBytes 1.58 Gbits/sec 0 840 KBytes
[ 5] 9.00-10.00 sec 190 MBytes 1.59 Gbits/sec 0 840 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.85 GBytes 1.59 Gbits/sec 0 sender
[ 5] 0.00-10.01 sec 1.85 GBytes 1.59 Gbits/sec receiver

iperf Done.
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=0.458 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.395 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.374 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.343 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.346 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=0.347 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=0.347 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=0.363 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=0.347 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=0.340 ms

--- 192.168.1.1 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9218ms
rtt min/avg/max/mdev = 0.340/0.366/0.458/0.034 ms

Voon Weifeng (2):
net: stmmac: enable 2.5Gbps link speed
net: pcs: configure xpcs 2.5G speed mode

.../net/ethernet/stmicro/stmmac/dwmac-intel.c | 44 ++++++++++++++++++-
.../net/ethernet/stmicro/stmmac/dwmac-intel.h | 13 ++++++
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 1 +
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 35 ++++++++++++++-
drivers/net/pcs/pcs-xpcs.c | 23 ++++++++++
drivers/net/phy/phylink.c | 2 +
include/linux/pcs/pcs-xpcs.h | 1 +
include/linux/stmmac.h | 2 +
8 files changed, 118 insertions(+), 3 deletions(-)

--
2.17.1


2021-03-25 08:45:02

by Sit, Michael Wei Hong

[permalink] [raw]
Subject: [PATCH net-next v3 1/2] net: stmmac: enable 2.5Gbps link speed

From: Voon Weifeng <[email protected]>

The MAC support 2.5G mode when the PCS is in 1000BASE-T mode. The
2.5G mode of operation is functionally same as 1000BASE-T mode,
except that the clock rate is 2.5 times the original rate.
In this mode, the serdes/PHY operates at a serial baud rate of
3.125 Gbps and the PCS data path and GMII interface of the MAC
operate at 312.5 MHz instead of 125 MHz.

The MAC running in 10M/100M/1G mode or 2.5G mode depends on
the link speed mode in the serdes.

Signed-off-by: Voon Weifeng <[email protected]>
Signed-off-by: Michael Sit Wei Hong <[email protected]>
---
.../net/ethernet/stmicro/stmmac/dwmac-intel.c | 44 ++++++++++++++++++-
.../net/ethernet/stmicro/stmmac/dwmac-intel.h | 13 ++++++
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 1 +
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 35 ++++++++++++++-
include/linux/stmmac.h | 2 +
5 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 8e4dbfdca237..750e7b7c554e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -96,6 +96,22 @@ static int intel_serdes_powerup(struct net_device *ndev, void *priv_data)

serdes_phy_addr = intel_priv->mdio_adhoc_addr;

+ /* Set the serdes rate and the PCLK rate */
+ data = mdiobus_read(priv->mii, serdes_phy_addr,
+ SERDES_GCR0);
+
+ data &= ~SERDES_RATE_MASK;
+ data &= ~SERDES_PCLK_MASK;
+
+ if (priv->plat->speed_2500_en)
+ data |= SERDES_RATE_PCIE_GEN2 << SERDES_RATE_PCIE_SHIFT |
+ SERDES_PCLK_37p5MHZ << SERDES_PCLK_SHIFT;
+ else
+ data |= SERDES_RATE_PCIE_GEN1 << SERDES_RATE_PCIE_SHIFT |
+ SERDES_PCLK_70MHZ << SERDES_PCLK_SHIFT;
+
+ mdiobus_write(priv->mii, serdes_phy_addr, SERDES_GCR0, data);
+
/* assert clk_req */
data = mdiobus_read(priv->mii, serdes_phy_addr, SERDES_GCR0);
data |= SERDES_PLL_CLK;
@@ -214,6 +230,28 @@ static void intel_serdes_powerdown(struct net_device *ndev, void *intel_data)
}
}

+static bool intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
+{
+ struct intel_priv_data *intel_priv = intel_data;
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int serdes_phy_addr = 0;
+ u32 data = 0;
+
+ serdes_phy_addr = intel_priv->mdio_adhoc_addr;
+
+ /* Determine the link speed mode: 2.5Gbps/1Gbps */
+ data = mdiobus_read(priv->mii, serdes_phy_addr,
+ SERDES_GCR);
+
+ if (((data & SERDES_LINK_MODE_MASK) >> SERDES_LINK_MODE_SHIFT) ==
+ SERDES_LINK_MODE_2G5) {
+ dev_info(priv->device, "Link Speed Mode: 2.5Gbps\n");
+ return true;
+ } else {
+ return false;
+ }
+}
+
/* Program PTP Clock Frequency for different variant of
* Intel mGBE that has slightly different GPO mapping
*/
@@ -405,7 +443,7 @@ static int ehl_sgmii_data(struct pci_dev *pdev,
{
plat->bus_id = 1;
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
-
+ plat->speed_mode_2500 = intel_speed_mode_2500;
plat->serdes_powerup = intel_serdes_powerup;
plat->serdes_powerdown = intel_serdes_powerdown;

@@ -456,6 +494,7 @@ static int ehl_pse0_sgmii1g_data(struct pci_dev *pdev,
struct plat_stmmacenet_data *plat)
{
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+ plat->speed_mode_2500 = intel_speed_mode_2500;
plat->serdes_powerup = intel_serdes_powerup;
plat->serdes_powerdown = intel_serdes_powerdown;
return ehl_pse0_common_data(pdev, plat);
@@ -492,6 +531,7 @@ static int ehl_pse1_sgmii1g_data(struct pci_dev *pdev,
struct plat_stmmacenet_data *plat)
{
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+ plat->speed_mode_2500 = intel_speed_mode_2500;
plat->serdes_powerup = intel_serdes_powerup;
plat->serdes_powerdown = intel_serdes_powerdown;
return ehl_pse1_common_data(pdev, plat);
@@ -516,6 +556,7 @@ static int tgl_sgmii_phy0_data(struct pci_dev *pdev,
{
plat->bus_id = 1;
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+ plat->speed_mode_2500 = intel_speed_mode_2500;
plat->serdes_powerup = intel_serdes_powerup;
plat->serdes_powerdown = intel_serdes_powerdown;
return tgl_common_data(pdev, plat);
@@ -530,6 +571,7 @@ static int tgl_sgmii_phy1_data(struct pci_dev *pdev,
{
plat->bus_id = 2;
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+ plat->speed_mode_2500 = intel_speed_mode_2500;
plat->serdes_powerup = intel_serdes_powerup;
plat->serdes_powerdown = intel_serdes_powerdown;
return tgl_common_data(pdev, plat);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h
index e723096c0b15..021a5c178d97 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h
@@ -9,6 +9,7 @@
#define POLL_DELAY_US 8

/* SERDES Register */
+#define SERDES_GCR 0x0 /* Global Conguration */
#define SERDES_GSR0 0x5 /* Global Status Reg0 */
#define SERDES_GCR0 0xb /* Global Configuration Reg0 */

@@ -16,8 +17,20 @@
#define SERDES_PLL_CLK BIT(0) /* PLL clk valid signal */
#define SERDES_RST BIT(2) /* Serdes Reset */
#define SERDES_PWR_ST_MASK GENMASK(6, 4) /* Serdes Power state*/
+#define SERDES_RATE_MASK GENMASK(9, 8)
+#define SERDES_PCLK_MASK GENMASK(14, 12) /* PCLK rate to PHY */
+#define SERDES_LINK_MODE_MASK GENMASK(2, 1)
+#define SERDES_LINK_MODE_SHIFT 1
#define SERDES_PWR_ST_SHIFT 4
#define SERDES_PWR_ST_P0 0x0
#define SERDES_PWR_ST_P3 0x3
+#define SERDES_LINK_MODE_2G5 0x3
+#define SERSED_LINK_MODE_1G 0x2
+#define SERDES_PCLK_37p5MHZ 0x0
+#define SERDES_PCLK_70MHZ 0x1
+#define SERDES_RATE_PCIE_GEN1 0x0
+#define SERDES_RATE_PCIE_GEN2 0x1
+#define SERDES_RATE_PCIE_SHIFT 8
+#define SERDES_PCLK_SHIFT 12

#endif /* __DWMAC_INTEL_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 29f765a246a0..cbfc4de7e9a3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -1349,6 +1349,7 @@ int dwmac4_setup(struct stmmac_priv *priv)
mac->link.speed10 = GMAC_CONFIG_PS;
mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
mac->link.speed1000 = 0;
+ mac->link.speed2500 = GMAC_CONFIG_FES;
mac->link.speed_mask = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
mac->mii.addr = GMAC_MDIO_ADDR;
mac->mii.data = GMAC_MDIO_DATA;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c89f0421bfdb..df582ad7892a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -877,6 +877,25 @@ static void stmmac_validate(struct phylink_config *config,
phylink_set(mac_supported, Asym_Pause);
phylink_set_port_modes(mac_supported);

+ if (priv->plat->has_gmac ||
+ priv->plat->has_gmac4 ||
+ priv->plat->has_xgmac) {
+ phylink_set(mac_supported, 1000baseT_Half);
+ phylink_set(mac_supported, 1000baseT_Full);
+ phylink_set(mac_supported, 1000baseKX_Full);
+ }
+
+ /* 2.5G mode only support 2500baseT full duplex only */
+ if (priv->plat->has_gmac4 && priv->plat->speed_2500_en) {
+ phylink_set(mac_supported, 2500baseT_Full);
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ phylink_set(mask, 1000baseT_Half);
+ phylink_set(mask, 1000baseT_Full);
+ }
+
/* Cut down 1G if asked to */
if ((max_speed > 0) && (max_speed < 1000)) {
phylink_set(mask, 1000baseT_Full);
@@ -1166,8 +1185,14 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
priv->phylink_config.dev = &priv->dev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
priv->phylink_config.pcs_poll = true;
- priv->phylink_config.ovr_an_inband =
- priv->plat->mdio_bus_data->xpcs_an_inband;
+ /* For 2.5G, we do not use SGMII in-band AN */
+ if (priv->plat->speed_2500_en) {
+ priv->phylink_config.ovr_an_inband = false;
+ } else {
+ priv->phylink_config.ovr_an_inband =
+ priv->plat->mdio_bus_data->xpcs_an_inband;
+ }
+

if (!fwnode)
fwnode = dev_fwnode(priv->device);
@@ -5284,6 +5309,12 @@ int stmmac_dvr_probe(struct device *device,
}
}

+ if (priv->plat->speed_mode_2500) {
+ priv->plat->speed_2500_en = priv->plat->speed_mode_2500(ndev,
+ priv->plat->bsp_priv);
+ priv->hw->xpcs_args.speed_2500_en = priv->plat->speed_2500_en;
+ }
+
ret = stmmac_phy_setup(priv);
if (ret) {
netdev_err(ndev, "failed to setup phy (%d)\n", ret);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index bf73982f92b3..d68805a57eb4 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -182,6 +182,7 @@ struct plat_stmmacenet_data {
void (*fix_mac_speed)(void *priv, unsigned int speed);
int (*serdes_powerup)(struct net_device *ndev, void *priv);
void (*serdes_powerdown)(struct net_device *ndev, void *priv);
+ bool (*speed_mode_2500)(struct net_device *ndev, void *priv);
void (*ptp_clk_freq_config)(void *priv);
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
@@ -205,6 +206,7 @@ struct plat_stmmacenet_data {
int has_xgmac;
bool vlan_fail_q_en;
u8 vlan_fail_q;
+ bool speed_2500_en;
unsigned int eee_usecs_rate;
struct pci_dev *pdev;
bool has_safety_feat;
--
2.17.1

2021-03-25 08:45:23

by Sit, Michael Wei Hong

[permalink] [raw]
Subject: [PATCH net-next v3 2/2] net: pcs: configure xpcs 2.5G speed mode

From: Voon Weifeng <[email protected]>

Besides setting 2.5G configuration, this patch will also disable
automatic speed mode change. This is due to the 2.5G mode is
using the same functionality as 1G mode except the clock rate is
2.5 times the original rate. Hence, auto-negotiation is disabled
to make sure it will only be in 2.5G mode.

Signed-off-by: Voon Weifeng <[email protected]>
Signed-off-by: Michael Sit Wei Hong <[email protected]>
---
drivers/net/pcs/pcs-xpcs.c | 23 +++++++++++++++++++++++
drivers/net/phy/phylink.c | 2 ++
include/linux/pcs/pcs-xpcs.h | 1 +
3 files changed, 26 insertions(+)

diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 944ba105cac1..e52bcb9a9199 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -60,10 +60,14 @@

/* Clause 37 Defines */
/* VR MII MMD registers offsets */
+#define DW_VR_MII_MMD_CTRL 0x0000
#define DW_VR_MII_DIG_CTRL1 0x8000
#define DW_VR_MII_AN_CTRL 0x8001
#define DW_VR_MII_AN_INTR_STS 0x8002

+/* Enable 2.5G Mode */
+#define DW_VR_MII_DIG_CTRL1_2G5_EN BIT(2)
+
/* VR_MII_DIG_CTRL1 */
#define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)

@@ -86,6 +90,11 @@
#define DW_VR_MII_C37_ANSGM_SP_1000 0x2
#define DW_VR_MII_C37_ANSGM_SP_LNKSTS BIT(4)

+/* SR MII MMD Control defines */
+#define AN_CL37_EN BIT(12) /* Enable Clause 37 auto-nego */
+#define SGMII_SPEED_SS13 BIT(13) /* SGMII speed along with SS6 */
+#define SGMII_SPEED_SS6 BIT(6) /* SGMII speed along with SS13 */
+
static const int xpcs_usxgmii_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@@ -141,6 +150,7 @@ static const int xpcs_sgmii_features[] = {
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
__ETHTOOL_LINK_MODE_MASK_NBITS,
};

@@ -654,6 +664,19 @@ static int xpcs_config_aneg_c37_sgmii(struct mdio_xpcs_args *xpcs)
{
int ret;

+ if (xpcs->speed_2500_en) {
+ ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
+ ret |= DW_VR_MII_DIG_CTRL1_2G5_EN;
+ ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
+ xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
+
+ ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
+ ret &= ~AN_CL37_EN;
+ ret |= SGMII_SPEED_SS6;
+ ret &= ~SGMII_SPEED_SS13;
+ return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret);
+ }
+
/* For AN for C37 SGMII mode, the settings are :-
* 1) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN)
* 2) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 12a047d47dec..c95dfe4e5310 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -290,6 +290,8 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)

switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
+ phylink_set(pl->supported, 2500baseT_Full);
+ fallthrough;
case PHY_INTERFACE_MODE_QSGMII:
phylink_set(pl->supported, 10baseT_Half);
phylink_set(pl->supported, 10baseT_Full);
diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h
index 2cb5188a7ef1..6b94b2a48e0c 100644
--- a/include/linux/pcs/pcs-xpcs.h
+++ b/include/linux/pcs/pcs-xpcs.h
@@ -19,6 +19,7 @@ struct mdio_xpcs_args {
struct mii_bus *bus;
int addr;
int an_mode;
+ bool speed_2500_en;
};

struct mdio_xpcs_ops {
--
2.17.1

2021-03-25 09:01:25

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH net-next v3 2/2] net: pcs: configure xpcs 2.5G speed mode

On Thu, Mar 25, 2021 at 04:38:06PM +0800, Michael Sit Wei Hong wrote:
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 12a047d47dec..c95dfe4e5310 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -290,6 +290,8 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
>
> switch (pl->link_config.interface) {
> case PHY_INTERFACE_MODE_SGMII:
> + phylink_set(pl->supported, 2500baseT_Full);
> + fallthrough;

This is wrong. "SGMII" here means 1G SGMII. See the documentation in
Documentation/networking/phy.rst.

If we want to have this at 2.5G speed, then we need a separate
enumeration for that mode, just like we make a distinction between
1000BASE-X and 2500BASE-X.

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!