Message ID | 20210401150152.22444-2-michael.wei.hong.sit@intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Enable 2.5Gbps speed for stmmac | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 1 maintainers not CCed: tee.min.tan@intel.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 22 this patch: 22 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | warning | WARNING: line length of 94 exceeds 80 columns |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 22 this patch: 22 |
netdev/header_inline | success | Link |
On Thu, Apr 01, 2021 at 11:01:51PM +0800, Michael Sit Wei Hong wrote: > + /* 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); > + phylink_set(mask, 1000baseKX_Full); Why? This seems at odds to the comment above? What about 2500baseX_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); > > + phylink_set(mask, 1000baseKX_Full); > > Why? This seems at odds to the comment above? > What about 2500baseX_Full ? The comments explain that the PCS<->PHY link is in 2500BASE-X and why 10/100/1000 link speed is mutually exclusive with 2500. But the connected external PHY are twisted pair cable which only supports 2500baseT_full. Weifeng
On Fri, Apr 02, 2021 at 07:45:04AM +0000, Voon, Weifeng wrote: > > > + /* 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); > > > + phylink_set(mask, 1000baseKX_Full); > > > > Why? This seems at odds to the comment above? > > > What about 2500baseX_Full ? > > The comments explain that the PCS<->PHY link is in 2500BASE-X > and why 10/100/1000 link speed is mutually exclusive with 2500. > But the connected external PHY are twisted pair cable which only > supports 2500baseT_full. The PHY should indicate what modes its supports. The PHY drivers get_features() call should set supported to only 2500baseT_Full, if that is all it supports. What modes are actually used should then be the intersect of what both the MAC and the PHY indicate they can do. Andrew
> On Fri, Apr 02, 2021 at 07:45:04AM +0000, Voon, Weifeng wrote: > > > > + /* 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); > > > > + phylink_set(mask, 1000baseKX_Full); > > > > > > Why? This seems at odds to the comment above? > > > > > What about 2500baseX_Full ? > > > > The comments explain that the PCS<->PHY link is in 2500BASE-X and why > > 10/100/1000 link speed is mutually exclusive with 2500. > > But the connected external PHY are twisted pair cable which only > > supports 2500baseT_full. > > The PHY should indicate what modes its supports. The PHY drivers > get_features() call should set supported to only 2500baseT_Full, if that is > all it supports. > > What modes are actually used should then be the intersect of what both the > MAC and the PHY indicate they can do. Noted Andrew. Instead of masking the 10/100/1000 mode support in the MAC, we will set the supported modes in the PCS.
On Mon, Apr 05, 2021 at 09:07:34AM +0000, Voon, Weifeng wrote: > > On Fri, Apr 02, 2021 at 07:45:04AM +0000, Voon, Weifeng wrote: > > > > > + /* 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); > > > > > + phylink_set(mask, 1000baseKX_Full); > > > > > > > > Why? This seems at odds to the comment above? > > > > > > > What about 2500baseX_Full ? > > > > > > The comments explain that the PCS<->PHY link is in 2500BASE-X and why > > > 10/100/1000 link speed is mutually exclusive with 2500. > > > But the connected external PHY are twisted pair cable which only > > > supports 2500baseT_full. > > > > The PHY should indicate what modes its supports. The PHY drivers > > get_features() call should set supported to only 2500baseT_Full, if that is > > all it supports. > > > > What modes are actually used should then be the intersect of what both the > > MAC and the PHY indicate they can do. > > Noted Andrew. Instead of masking the 10/100/1000 mode support in the MAC, we will > set the supported modes in the PCS. PCS? You said: > > > But the connected external PHY are twisted pair cable which only > > > supports 2500baseT_full. So it should be the PHY, not the PCS, which indicates it only supports 2500baseT_full. Andrew
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 3d9a57043af2..4f70a12b42f9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -102,6 +102,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; @@ -220,6 +236,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 */ @@ -540,7 +578,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; @@ -593,6 +631,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); @@ -631,6 +670,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); @@ -655,6 +695,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); @@ -669,6 +710,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 95864f014ffa..4c3f27a9e8b2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -1357,6 +1357,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 d34388b1ffcc..e182f9be4247 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -882,6 +882,18 @@ static void stmmac_validate(struct phylink_config *config, phylink_set(mac_supported, Asym_Pause); phylink_set_port_modes(mac_supported); + /* 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); + phylink_set(mask, 1000baseKX_Full); + } + /* Cut down 1G if asked to */ if ((max_speed > 0) && (max_speed < 1000)) { phylink_set(mask, 1000baseT_Full); @@ -1192,8 +1204,13 @@ 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); @@ -5815,6 +5832,11 @@ 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); + } + 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 e338ef7abc00..a43ce24d2a42 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -209,6 +209,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); @@ -234,6 +235,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_crossts;