linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RE: [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
@ 2019-06-04 14:09 ` Jose Abreu
  2019-06-04 18:58 ` [PATCH net-next v6 1/5] net: stmmac: enable clause 45 mdio support Voon Weifeng
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jose Abreu @ 2019-06-04 14:09 UTC (permalink / raw)
  To: Voon Weifeng, David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Giuseppe Cavallaro, Andrew Lunn,
	Florian Fainelli, Alexandre Torgue, biao huang, Ong Boon Leong,
	Kweh Hock Leong

From: Voon Weifeng <weifeng.voon@intel.com>

> This patch-set is to enable Ethernet controller
> (DW Ethernet QoS and DW Ethernet PCS) with SGMII interface in Elkhart Lake.
> The DW Ethernet PCS is the Physical Coding Sublayer that is between Ethernet
> MAC and PHY and uses MDIO Clause-45 as Communication.
> 
> Selttests results:
> root@intel-corei7-64:~# ethtool -t eth0
> The test result is PASS
> The test extra info:
>  1. MAC Loopback                 0
>  2. PHY Loopback                 -95
>  3. MMC Counters                 0
>  4. EEE                          -95
>  5. Hash Filter MC               0
>  6. Perfect Filter UC            0
>  7. MC Filter                    0
>  8. UC Filter                    0
>  9. Flow Control                 0

Thanks for testing and addressing all review comments!

Acked-by: Jose Abreu <joabreu@synopsys.com>

Thanks,
Jose Miguel 
Abreu

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII
@ 2019-06-04 18:58 Voon Weifeng
  2019-06-04 14:09 ` Jose Abreu
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

This patch-set is to enable Ethernet controller
(DW Ethernet QoS and DW Ethernet PCS) with SGMII interface in Elkhart Lake.
The DW Ethernet PCS is the Physical Coding Sublayer that is between Ethernet
MAC and PHY and uses MDIO Clause-45 as Communication.

Selttests results:
root@intel-corei7-64:~# ethtool -t eth0
The test result is PASS
The test extra info:
 1. MAC Loopback                 0
 2. PHY Loopback                 -95
 3. MMC Counters                 0
 4. EEE                          -95
 5. Hash Filter MC               0
 6. Perfect Filter UC            0
 7. MC Filter                    0
 8. UC Filter                    0
 9. Flow Control                 0

Kweh Hock Leong (1):
  net: stmmac: enable clause 45 mdio support

Ong Boon Leong (3):
  net: stmmac: introducing support for DWC xPCS logics
  net: stmmac: add xpcs function hooks into main driver and ethtool
  net: stmmac: add xPCS functions for device with DWMACv5.1

Voon Weifeng (1):
  net: stmmac: add EHL SGMII 1Gbps PCI info and PCI ID

 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 drivers/net/ethernet/stmicro/stmmac/common.h       |   1 +
 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c  |  34 ++++
 drivers/net/ethernet/stmicro/stmmac/dwxpcs.c       | 208 +++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/dwxpcs.h       |  51 +++++
 drivers/net/ethernet/stmicro/stmmac/hwif.c         |  42 ++++-
 drivers/net/ethernet/stmicro/stmmac/hwif.h         |  21 +++
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   2 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |  50 +++--
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 139 ++++++++++----
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  |  40 +++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c   | 111 +++++++++++
 include/linux/phy.h                                |   2 +
 include/linux/stmmac.h                             |   3 +
 14 files changed, 648 insertions(+), 58 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.h

-- 
Changelog v6:
*Added missing selftests entry in dwmac510_xpcs_ops
*Applied more reversed christmas tree
Changelog v5:
*Cosmetic touch up
*Change axi_wr_osr_lmt and axi_rd_osr_lmt value to 1 since the register
 has a default value of 1
Changelog v4:
*Rebased to latest net-next
Changelog v3:
*Applied reversed christmas tree
Changelog v2:
*Added support for the C37 AN for 1000BASE-X and SGMII (MAC side SGMII only)
*removed and submitted the fix patch to net
 "net: stmmac: dma channel control register need to be init first"
*Squash the following 2 patches and move it to the end of the patch set:
 "net: stmmac: add EHL SGMII 1Gbps platform data and PCI ID"
 "net: stmmac: add xPCS platform data for EHL"
1.9.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 1/5] net: stmmac: enable clause 45 mdio support
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
  2019-06-04 14:09 ` Jose Abreu
@ 2019-06-04 18:58 ` Voon Weifeng
  2019-06-04 18:58 ` [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics Voon Weifeng
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

From: Kweh Hock Leong <hock.leong.kweh@intel.com>

DWMAC4 is capable to support clause 45 mdio communication.
This patch enable the feature on stmmac_mdio_write() and
stmmac_mdio_read() by following phy_write_mmd() and
phy_read_mmd() mdiobus read write implementation format.

Reviewed-by: Li, Yifan <yifan2.li@intel.com>
Signed-off-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: Weifeng Voon <weifeng.voon@intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 40 ++++++++++++++++++-----
 include/linux/phy.h                               |  2 ++
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 093a223fe408..073078c7a7d0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -34,11 +34,27 @@
 
 #define MII_BUSY 0x00000001
 #define MII_WRITE 0x00000002
+#define MII_DATA_MASK GENMASK(15, 0)
 
 /* GMAC4 defines */
 #define MII_GMAC4_GOC_SHIFT		2
+#define MII_GMAC4_REG_ADDR_SHIFT	16
 #define MII_GMAC4_WRITE			(1 << MII_GMAC4_GOC_SHIFT)
 #define MII_GMAC4_READ			(3 << MII_GMAC4_GOC_SHIFT)
+#define MII_GMAC4_C45E			BIT(1)
+
+static void stmmac_mdio_c45_setup(struct stmmac_priv *priv, int phyreg,
+				  u32 *val, u32 *data)
+{
+	unsigned int reg_shift = priv->hw->mii.reg_shift;
+	unsigned int reg_mask = priv->hw->mii.reg_mask;
+
+	*val |= MII_GMAC4_C45E;
+	*val &= ~reg_mask;
+	*val |= ((phyreg >> MII_DEVADDR_C45_SHIFT) << reg_shift) & reg_mask;
+
+	*data |= (phyreg & MII_REGADDR_C45_MASK) << MII_GMAC4_REG_ADDR_SHIFT;
+}
 
 /* XGMAC defines */
 #define MII_XGMAC_SADDR			BIT(18)
@@ -165,22 +181,26 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	unsigned int mii_address = priv->hw->mii.addr;
 	unsigned int mii_data = priv->hw->mii.data;
-	u32 v;
-	int data;
 	u32 value = MII_BUSY;
+	int data = 0;
+	u32 v;
 
 	value |= (phyaddr << priv->hw->mii.addr_shift)
 		& priv->hw->mii.addr_mask;
 	value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
 	value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
 		& priv->hw->mii.clk_csr_mask;
-	if (priv->plat->has_gmac4)
+	if (priv->plat->has_gmac4) {
 		value |= MII_GMAC4_READ;
+		if (phyreg & MII_ADDR_C45)
+			stmmac_mdio_c45_setup(priv, phyreg, &value, &data);
+	}
 
 	if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
 			       100, 10000))
 		return -EBUSY;
 
+	writel(data, priv->ioaddr + mii_data);
 	writel(value, priv->ioaddr + mii_address);
 
 	if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
@@ -188,7 +208,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
 		return -EBUSY;
 
 	/* Read the data from the MII data register */
-	data = (int)readl(priv->ioaddr + mii_data);
+	data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
 
 	return data;
 }
@@ -208,8 +228,9 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	unsigned int mii_address = priv->hw->mii.addr;
 	unsigned int mii_data = priv->hw->mii.data;
-	u32 v;
 	u32 value = MII_BUSY;
+	int data = phydata;
+	u32 v;
 
 	value |= (phyaddr << priv->hw->mii.addr_shift)
 		& priv->hw->mii.addr_mask;
@@ -217,10 +238,13 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
 
 	value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
 		& priv->hw->mii.clk_csr_mask;
-	if (priv->plat->has_gmac4)
+	if (priv->plat->has_gmac4) {
 		value |= MII_GMAC4_WRITE;
-	else
+		if (phyreg & MII_ADDR_C45)
+			stmmac_mdio_c45_setup(priv, phyreg, &value, &data);
+	} else {
 		value |= MII_WRITE;
+	}
 
 	/* Wait until any existing MII operation is complete */
 	if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
@@ -228,7 +252,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
 		return -EBUSY;
 
 	/* Set the MII address register to write */
-	writel(phydata, priv->ioaddr + mii_data);
+	writel(data, priv->ioaddr + mii_data);
 	writel(value, priv->ioaddr + mii_address);
 
 	/* Wait until any existing MII operation is complete */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index dc4b51060ebc..a2c25a975661 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -200,6 +200,8 @@ static inline const char *phy_modes(phy_interface_t interface)
 /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
    IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */
 #define MII_ADDR_C45 (1<<30)
+#define MII_DEVADDR_C45_SHIFT	16
+#define MII_REGADDR_C45_MASK	GENMASK(15, 0)
 
 struct device;
 struct phylink;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
  2019-06-04 14:09 ` Jose Abreu
  2019-06-04 18:58 ` [PATCH net-next v6 1/5] net: stmmac: enable clause 45 mdio support Voon Weifeng
@ 2019-06-04 18:58 ` Voon Weifeng
  2019-06-04 20:46   ` Florian Fainelli
  2019-06-04 18:58 ` [PATCH net-next v6 3/5] net: stmmac: add xpcs function hooks into main driver and ethtool Voon Weifeng
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

From: Ong Boon Leong <boon.leong.ong@intel.com>

xPCS is DWC Ethernet Physical Coding Sublayer that may be integrated
into a GbE controller that uses DWC EQoS MAC controller. An example of
HW configuration is shown below:-

  <-----------------GBE Controller---------->|<--External PHY chip-->

  +----------+         +----+    +---+               +--------------+
  |   EQoS   | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE |
  |   MAC    |         |xPCS|    |IF |               | PHY Chip     |
  +----------+         +----+    +---+               +--------------+
         ^               ^                                  ^
         |               |                                  |
         +---------------------MDIO-------------------------+

xPCS is a Clause-45 MDIO Manageable Device (MMD) and we need a way to
differentiate it from external PHY chip that is discovered over MDIO.
Therefore, xpcs_phy_addr is introduced in stmmac platform data
(plat_stmmacenet_data) for differentiating xPCS from 'phy_addr' that
belongs to external PHY.

Basic functionalities for initializing xPCS and configuring auto
negotiation (AN), loopback, link status, AN advertisement and Link
Partner ability are implemented. The implementation supports the C37
AN for 1000BASE-X and SGMII (MAC side SGMII only).

Tested-by: Tan, Tee Min <tee.min.tan@intel.com>
Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
Reviewed-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile |   2 +-
 drivers/net/ethernet/stmicro/stmmac/common.h |   1 +
 drivers/net/ethernet/stmicro/stmmac/dwxpcs.c | 208 +++++++++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/dwxpcs.h |  51 +++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.h   |  19 +++
 include/linux/stmmac.h                       |   1 +
 6 files changed, 281 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.h

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index c59926d96bcc..f007fb873455 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
 	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
 	      stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
-	      $(stmmac-y)
+	      dwxpcs.o $(stmmac-y)
 
 stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1961fe9144ca..83df093c4636 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -419,6 +419,7 @@ struct mii_regs {
 
 struct mac_device_info {
 	const struct stmmac_ops *mac;
+	const struct stmmac_xpcs_ops *xpcs;
 	const struct stmmac_desc_ops *desc;
 	const struct stmmac_dma_ops *dma;
 	const struct stmmac_mode_ops *mode;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
new file mode 100644
index 000000000000..7e850b9dd7b7
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Intel Corporation.
+ * DWC Ethernet Physical Coding Sublayer
+ */
+#include <linux/bitops.h>
+#include <linux/mdio.h>
+#include "dwxpcs.h"
+#include "stmmac.h"
+
+/* DW xPCS mdiobus_read and mdiobus_write helper functions */
+#define xpcs_read(dev, reg) \
+	mdiobus_read(priv->mii, xpcs_phy_addr, \
+		     MII_ADDR_C45 | (reg) | \
+		     ((dev) << MII_DEVADDR_C45_SHIFT))
+#define xpcs_write(dev, reg, val) \
+	mdiobus_write(priv->mii, xpcs_phy_addr, \
+		      MII_ADDR_C45 | (reg) | \
+		      ((dev) << MII_DEVADDR_C45_SHIFT), val)
+
+static void dw_xpcs_init(struct net_device *ndev, int pcs_mode)
+{
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int xpcs_phy_addr;
+	int phydata;
+
+	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
+
+	if (pcs_mode == AN_CTRL_PCS_MD_C37_SGMII) {
+		/* For AN for 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)
+		 *    DW xPCS used with DW EQoS MAC is always MAC
+		 *    side SGMII.
+		 * 3) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt
+		 *    enabled)
+		 * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic
+		 *    speed mode change after SGMII AN complete)
+		 * Note: Since it is MAC side SGMII, there is no need to set
+		 *	 SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config
+		 *	 from PHY about the link state change after C28 AN
+		 *	 is completed between PHY and Link Partner.
+		 */
+		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL);
+		phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD;
+		phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN |
+			   (AN_CTRL_PCS_MD_C37_SGMII <<
+			    MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT &
+			    MDIO_MII_MMD_AN_CTRL_PCS_MD) |
+			   (AN_CTRL_TX_CONF_MAC_SIDE_SGMII <<
+			    MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT);
+		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata);
+
+		phydata = xpcs_read(XPCS_MDIO_MII_MMD,
+				    MDIO_MII_MMD_DIGITAL_CTRL_1);
+		phydata |= MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW;
+		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_DIGITAL_CTRL_1,
+			   phydata);
+	} else {
+		/* For AN for 1000BASE-X mode, the settings are :-
+		 * 1) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
+		 * 2) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt
+		 *    enabled)
+		 * 3) SR_MII_AN_ADV Bit(6)[FD] = 1b (Full Duplex)
+		 *    Note: Half Duplex is rarely used, so don't advertise.
+		 * 4) SR_MII_AN_ADV Bit(8:7)[PSE] = 11b (Sym & Asym Pause)
+		 */
+		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL);
+		phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD;
+		phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN |
+			   (AN_CTRL_PCS_MD_C37_1000BASEX <<
+			    MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT &
+			    MDIO_MII_MMD_AN_CTRL_PCS_MD);
+		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata);
+
+		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_ADVERTISE);
+		phydata |= MDIO_MII_MMD_FD |
+			   (MDIO_MII_MMD_PSE_BOTH << MDIO_MII_MMD_PSE_SHIFT);
+		xpcs_write(XPCS_MDIO_MII_MMD, MII_ADVERTISE, phydata);
+	}
+}
+
+static void dw_xpcs_ctrl_ane(struct net_device *ndev, bool ane,
+			     bool loopback)
+{
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int xpcs_phy_addr;
+	int phydata;
+
+	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
+	phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_BMCR);
+
+	if (ane)
+		phydata |= (BMCR_ANENABLE | BMCR_ANRESTART);
+
+	if (loopback)
+		phydata |= BMCR_LOOPBACK;
+
+	xpcs_write(XPCS_MDIO_MII_MMD, MII_BMCR, phydata);
+}
+
+static void dw_xpcs_get_adv_lp(struct net_device *ndev,
+			       struct rgmii_adv *adv_lp,
+			       int pcs_mode)
+{
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int xpcs_phy_addr;
+	int value;
+
+	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
+
+	/* AN Advertisement Ability */
+	value = xpcs_read(XPCS_MDIO_MII_MMD, MII_ADVERTISE);
+
+	if (value & MDIO_MII_MMD_FD)
+		adv_lp->duplex = DUPLEX_FULL;
+	if (value & MDIO_MII_MMD_HD)
+		adv_lp->duplex = DUPLEX_HALF;
+	adv_lp->pause = (u32)((value & MDIO_MII_MMD_PSE) >>
+			      MDIO_MII_MMD_PSE_SHIFT);
+
+	/* Link Partner Ability - 1000BASE-X only*/
+	if (pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX) {
+		value = xpcs_read(XPCS_MDIO_MII_MMD, MII_LPA);
+		if (value & MDIO_MII_MMD_FD)
+			adv_lp->lp_duplex = DUPLEX_FULL;
+		if (value & MDIO_MII_MMD_HD)
+			adv_lp->lp_duplex = DUPLEX_HALF;
+		adv_lp->lp_pause = (u32)((value & MDIO_MII_MMD_PSE) >>
+					 MDIO_MII_MMD_PSE_SHIFT);
+	}
+}
+
+static void dw_xpcs_get_linkstatus(struct net_device *ndev,
+				   u16 an_stat,
+				   struct stmmac_extra_stats *x)
+{
+	/* Check the SGMII AN link status */
+	if (an_stat & AN_STAT_SGMII_AN_LNKSTS) {
+		int speed_value;
+
+		x->pcs_link = 1;
+
+		speed_value = ((an_stat & AN_STAT_SGMII_AN_SPEED) >>
+				AN_STAT_SGMII_AN_SPEED_SHIFT);
+		if (speed_value == AN_STAT_SGMII_AN_1000MBPS)
+			x->pcs_speed = SPEED_1000;
+		else if (speed_value == AN_STAT_SGMII_AN_100MBPS)
+			x->pcs_speed = SPEED_100;
+		else
+			x->pcs_speed = SPEED_10;
+
+		if (an_stat & AN_STAT_SGMII_AN_FD)
+			x->pcs_duplex = 1;
+		else
+			x->pcs_duplex = 0;
+
+		netdev_info(ndev, "Link is Up - %d/%s\n", (int)x->pcs_speed,
+			    x->pcs_duplex ? "Full" : "Half");
+	} else {
+		x->pcs_link = 0;
+		netdev_info(ndev, "Link is Down\n");
+	}
+}
+
+static int dw_xpcs_irq_status(struct net_device *ndev,
+			      struct stmmac_extra_stats *x,
+			      int pcs_mode)
+{
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int ret = IRQ_NONE;
+	int xpcs_phy_addr;
+	int an_stat;
+
+	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
+
+	/* AN status */
+	an_stat = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT);
+
+	if (an_stat & AN_STAT_SGMII_AN_CMPLT) {
+		x->irq_pcs_ane_n++;
+
+		if (pcs_mode == AN_CTRL_PCS_MD_C37_SGMII) {
+			dw_xpcs_get_linkstatus(ndev, an_stat, x);
+		} else {
+			/* For 1000BASE-X AN, DW xPCS does not have register
+			 * to read the link state of 1000BASE-X C37 AN and
+			 * since 1000BASE-X is always 1000Mbps and FD, we
+			 * just set the default link here.
+			 */
+			x->pcs_link = 1;
+			x->pcs_duplex = 1;
+			x->pcs_speed = SPEED_1000;
+		}
+
+		/* Clear C37 AN complete status by writing zero */
+		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT, 0);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+const struct stmmac_xpcs_ops xpcs_ops = {
+	.xpcs_init = dw_xpcs_init,
+	.xpcs_ctrl_ane = dw_xpcs_ctrl_ane,
+	.xpcs_get_adv_lp = dw_xpcs_get_adv_lp,
+	.xpcs_irq_status = dw_xpcs_irq_status,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h
new file mode 100644
index 000000000000..bd52ce80bf4e
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019, Intel Corporation.
+ * DWC Ethernet Physical Coding Sublayer
+ */
+#ifndef __DW_XPCS_H__
+#define __DW_XPCS_H__
+
+/* XPCS MII MMD Device Addresses */
+#define XPCS_MDIO_MII_MMD	MDIO_MMD_VEND2
+
+/* MII MMD registers offsets */
+#define MDIO_MII_MMD_DIGITAL_CTRL_1	0x8000	/* Digital Control 1 */
+#define MDIO_MII_MMD_AN_CTRL		0x8001	/* AN Control */
+#define MDIO_MII_MMD_AN_STAT		0x8002	/* AN Status */
+
+/* MII MMD SR AN Advertisement & Link Partner Ability are slightly
+ * different from MII_ADVERTISEMENT & MII_LPA in below fields:
+ */
+#define MDIO_MII_MMD_HD			BIT(6)	/* Half duplex */
+#define MDIO_MII_MMD_FD			BIT(5)	/* Full duplex */
+#define MDIO_MII_MMD_PSE_SHIFT		7	/* Pause Ability shift */
+#define MDIO_MII_MMD_PSE		GENMASK(8, 7)	/* Pause Ability */
+#define MDIO_MII_MMD_PSE_NO		0x0
+#define MDIO_MII_MMD_PSE_ASYM		0x1
+#define MDIO_MII_MMD_PSE_SYM		0x2
+#define MDIO_MII_MMD_PSE_BOTH		0x3
+
+/* Automatic Speed Mode Change for MAC side SGMII AN */
+#define MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW	BIT(9)
+
+/* MII MMD AN Control defines */
+#define MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT	3 /* TX Config shift */
+#define AN_CTRL_TX_CONF_PHY_SIDE_SGMII		0x1 /* PHY side SGMII mode */
+#define AN_CTRL_TX_CONF_MAC_SIDE_SGMII		0x0 /* MAC side SGMII mode */
+#define MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT	1  /* PCS Mode shift */
+#define MDIO_MII_MMD_AN_CTRL_PCS_MD	GENMASK(2, 1) /* PCS Mode */
+#define AN_CTRL_PCS_MD_C37_1000BASEX	0x0	/* C37 AN for 1000BASE-X */
+#define AN_CTRL_PCS_MD_C37_SGMII	0x2	/* C37 AN for SGMII */
+#define MDIO_MII_MMD_AN_CTRL_AN_INTR_EN	BIT(0)	/* AN Complete Intr Enable */
+
+/* MII MMD AN Status defines for SGMII AN Status */
+#define AN_STAT_SGMII_AN_CMPLT		BIT(0)	/* AN Complete Intr */
+#define AN_STAT_SGMII_AN_FD		BIT(1)	/* Full Duplex */
+#define AN_STAT_SGMII_AN_SPEED_SHIFT	2	/* AN Speed shift */
+#define AN_STAT_SGMII_AN_SPEED		GENMASK(3, 2)	/* AN Speed */
+#define AN_STAT_SGMII_AN_10MBPS		0x0	/* 10 Mbps */
+#define AN_STAT_SGMII_AN_100MBPS	0x1	/* 100 Mbps */
+#define AN_STAT_SGMII_AN_1000MBPS	0x2	/* 1000 Mbps */
+#define AN_STAT_SGMII_AN_LNKSTS		BIT(4)	/* Link Status */
+
+#endif /* __DW_XPCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 2acfbc70e3c8..431cf4261264 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -398,6 +398,25 @@ struct stmmac_ops {
 #define stmmac_set_mac_loopback(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, set_mac_loopback, __args)
 
+/* Helpers for DW xPCS */
+struct stmmac_xpcs_ops {
+	void (*xpcs_init)(struct net_device *ndev, int pcs_mode);
+	void (*xpcs_ctrl_ane)(struct net_device *ndev, bool ane, bool loopback);
+	void (*xpcs_get_adv_lp)(struct net_device *ndev, struct rgmii_adv *adv,
+				int pcs_mode);
+	int (*xpcs_irq_status)(struct net_device *ndev,
+			       struct stmmac_extra_stats *x, int pcs_mode);
+};
+
+#define stmmac_xpcs_init(__priv, __args...) \
+	stmmac_do_void_callback(__priv, xpcs, xpcs_init, __args)
+#define stmmac_xpcs_ctrl_ane(__priv, __args...) \
+	stmmac_do_void_callback(__priv, xpcs, xpcs_ctrl_ane, __args)
+#define stmmac_xpcs_get_adv_lp(__priv, __args...) \
+	stmmac_do_void_callback(__priv, xpcs, xpcs_get_adv_lp, __args)
+#define stmmac_xpcs_irq_status(__priv, __args...) \
+	stmmac_do_callback(__priv, xpcs, xpcs_irq_status, __args)
+
 /* PTP and HW Timer helpers */
 struct stmmac_hwtimestamp {
 	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 4335bd771ce5..b00e7951a66d 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -148,6 +148,7 @@ struct stmmac_txq_cfg {
 struct plat_stmmacenet_data {
 	int bus_id;
 	int phy_addr;
+	int xpcs_phy_addr;
 	int interface;
 	struct stmmac_mdio_bus_data *mdio_bus_data;
 	struct device_node *phy_node;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 3/5] net: stmmac: add xpcs function hooks into main driver and ethtool
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
                   ` (2 preceding siblings ...)
  2019-06-04 18:58 ` [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics Voon Weifeng
@ 2019-06-04 18:58 ` Voon Weifeng
  2019-06-04 18:58 ` [PATCH net-next v6 4/5] net: stmmac: add xPCS functions for device with DWMACv5.1 Voon Weifeng
  2019-06-04 18:58 ` [PATCH net-next v6 5/5] net: stmmac: add EHL SGMII 1Gbps PCI info and PCI ID Voon Weifeng
  5 siblings, 0 replies; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

From: Ong Boon Leong <boon.leong.ong@intel.com>

With xPCS functions now ready, we add them into the main driver and
ethtool logics. To differentiate from EQoS MAC PCS and DWC Ethernet
xPCS, we introduce 'has_xpcs' in platform data as a mean to indicate
whether GBE controller includes xPCS or not.

To support platform-specific C37 AN PCS mode selection for MII MMD,
we introduce 'pcs_mode' in platform data.

The basic framework for xPCS interrupt handling is implemented too.

Reviewed-by: Chuah Kim Tatt <kim.tatt.chuah@intel.com>
Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
Reviewed-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Baoli Zhang <baoli.zhang@intel.com>
Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   2 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |  50 ++++++--
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 139 +++++++++++++++------
 include/linux/stmmac.h                             |   2 +
 4 files changed, 145 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a16ada8b8507..999311236521 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -36,6 +36,7 @@ struct stmmac_resources {
 	const char *mac;
 	int wol_irq;
 	int lpi_irq;
+	int xpcs_irq;
 	int irq;
 };
 
@@ -168,6 +169,7 @@ struct stmmac_priv {
 	int clk_csr;
 	struct timer_list eee_ctrl_timer;
 	int lpi_irq;
+	int xpcs_irq;
 	int eee_enabled;
 	int eee_active;
 	int tx_lpi_timer;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index cec51ba34296..be6edbe3d658 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -28,6 +28,7 @@
 
 #include "stmmac.h"
 #include "dwmac_dma.h"
+#include "dwxpcs.h"
 
 #define REG_SPACE_SIZE	0x1060
 #define MAC100_ETHTOOL_NAME	"st_mac100"
@@ -277,7 +278,8 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
 	struct phy_device *phy = dev->phydev;
 
 	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
-	    priv->hw->pcs & STMMAC_PCS_SGMII) {
+	    priv->hw->pcs & STMMAC_PCS_SGMII ||
+	    priv->plat->pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX) {
 		struct rgmii_adv adv;
 		u32 supported, advertising, lp_advertising;
 
@@ -294,6 +296,11 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
 		if (stmmac_pcs_get_adv_lp(priv, priv->ioaddr, &adv))
 			return -EOPNOTSUPP;	/* should never happen indeed */
 
+		/* Get ADV & LPA is only application for 1000BASE-X C37.
+		 * For MAC side SGMII AN, get ADV & LPA from PHY.
+		 */
+		stmmac_xpcs_get_adv_lp(priv, dev, &adv, priv->plat->pcs_mode);
+
 		/* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
 
 		ethtool_convert_link_mode_to_legacy_u32(
@@ -376,22 +383,23 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
 	int rc;
 
 	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
-	    priv->hw->pcs & STMMAC_PCS_SGMII) {
-		u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
-
+	    priv->hw->pcs & STMMAC_PCS_SGMII ||
+	    priv->plat->pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX) {
 		/* Only support ANE */
 		if (cmd->base.autoneg != AUTONEG_ENABLE)
 			return -EINVAL;
 
-		mask &= (ADVERTISED_1000baseT_Half |
-			ADVERTISED_1000baseT_Full |
-			ADVERTISED_100baseT_Half |
-			ADVERTISED_100baseT_Full |
-			ADVERTISED_10baseT_Half |
-			ADVERTISED_10baseT_Full);
-
 		mutex_lock(&priv->lock);
 		stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, priv->hw->ps, 0);
+
+		/* For 1000BASE-X C37 AN, it is always 1000Mbps. And, we only
+		 * support FD which is set by default in SR_MII_AN_ADV
+		 * during XPCS init. So, we don't need to set FD again.
+		 * For SGMII C37 AN, we let user to change link settings
+		 * through PHY since it is MAC side SGMII.
+		 */
+		stmmac_xpcs_ctrl_ane(priv, dev, 1, 0);
+
 		mutex_unlock(&priv->lock);
 
 		return 0;
@@ -457,6 +465,16 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
 		pause->autoneg = 1;
 		if (!adv_lp.pause)
 			return;
+	} else if (priv->plat->pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX &&
+		   !stmmac_xpcs_get_adv_lp(priv, netdev, &adv_lp,
+					   priv->plat->pcs_mode)) {
+		/* DW xPCS 1000BASE-X C37 AN mode only because for MAC side
+		 * SGMII C37 AN, xPCS AN ADV is not set. See more comment in
+		 * dw_xpcs_init()
+		 */
+		pause->autoneg = 1;
+		if (!adv_lp.pause)
+			return;
 	} else {
 		if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
 				       netdev->phydev->supported) ||
@@ -488,6 +506,16 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
 		pause->autoneg = 1;
 		if (!adv_lp.pause)
 			return -EOPNOTSUPP;
+	} else if (priv->plat->pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX &&
+		   !stmmac_xpcs_get_adv_lp(priv, netdev, &adv_lp,
+					   priv->plat->pcs_mode)) {
+		/* DW xPCS 1000BASE-X C37 AN mode only because for MAC side
+		 * SGMII C37 AN, xPCS AN ADV is not set. See more comment in
+		 * dw_xpcs_init()
+		 */
+		pause->autoneg = 1;
+		if (!adv_lp.pause)
+			return -EOPNOTSUPP;
 	} else {
 		if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
 				       phy->supported) ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 268af79e2632..67bbfb615dcb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -112,6 +112,7 @@
 MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
 
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+static irqreturn_t xpcs_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_DEBUG_FS
 static int stmmac_init_fs(struct net_device *dev);
@@ -848,6 +849,54 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
 			priv->pause, tx_cnt);
 }
 
+static bool mac_adjust_link(struct stmmac_priv *priv,
+			    int *speed, int *duplex)
+{
+	u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
+	bool new_state = false;
+
+	/* Now we make sure that we can be in full duplex mode.
+	 * If not, we operate in half-duplex mode.
+	 */
+	if (*duplex != priv->oldduplex) {
+		new_state = true;
+		if (!*duplex)
+			ctrl &= ~priv->hw->link.duplex;
+		else
+			ctrl |= priv->hw->link.duplex;
+		priv->oldduplex = *duplex;
+	}
+
+	if (*speed != priv->speed) {
+		new_state = true;
+		ctrl &= ~priv->hw->link.speed_mask;
+		switch (*speed) {
+		case SPEED_1000:
+			ctrl |= priv->hw->link.speed1000;
+			break;
+		case SPEED_100:
+			ctrl |= priv->hw->link.speed100;
+			break;
+		case SPEED_10:
+			ctrl |= priv->hw->link.speed10;
+			break;
+		default:
+			netif_warn(priv, link, priv->dev,
+				   "broken speed: %d\n", *speed);
+			*speed = SPEED_UNKNOWN;
+			break;
+		}
+		if (*speed != SPEED_UNKNOWN)
+			stmmac_hw_fix_mac_speed(priv);
+
+		priv->speed = *speed;
+	}
+
+	writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
+
+	return new_state;
+}
+
 /**
  * stmmac_adjust_link - adjusts the link parameters
  * @dev: net device structure
@@ -869,47 +918,12 @@ static void stmmac_adjust_link(struct net_device *dev)
 	mutex_lock(&priv->lock);
 
 	if (phydev->link) {
-		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
-
-		/* Now we make sure that we can be in full duplex mode.
-		 * If not, we operate in half-duplex mode. */
-		if (phydev->duplex != priv->oldduplex) {
-			new_state = true;
-			if (!phydev->duplex)
-				ctrl &= ~priv->hw->link.duplex;
-			else
-				ctrl |= priv->hw->link.duplex;
-			priv->oldduplex = phydev->duplex;
-		}
 		/* Flow Control operation */
 		if (phydev->pause)
 			stmmac_mac_flow_ctrl(priv, phydev->duplex);
 
-		if (phydev->speed != priv->speed) {
-			new_state = true;
-			ctrl &= ~priv->hw->link.speed_mask;
-			switch (phydev->speed) {
-			case SPEED_1000:
-				ctrl |= priv->hw->link.speed1000;
-				break;
-			case SPEED_100:
-				ctrl |= priv->hw->link.speed100;
-				break;
-			case SPEED_10:
-				ctrl |= priv->hw->link.speed10;
-				break;
-			default:
-				netif_warn(priv, link, priv->dev,
-					   "broken speed: %d\n", phydev->speed);
-				phydev->speed = SPEED_UNKNOWN;
-				break;
-			}
-			if (phydev->speed != SPEED_UNKNOWN)
-				stmmac_hw_fix_mac_speed(priv);
-			priv->speed = phydev->speed;
-		}
-
-		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
+		new_state = mac_adjust_link(priv, &phydev->speed,
+					    &phydev->duplex);
 
 		if (!priv->oldlink) {
 			new_state = true;
@@ -2541,6 +2555,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
 	/* Initialize MTL*/
 	stmmac_mtl_configuration(priv);
 
+	/* Initialize the xPCS PHY */
+	stmmac_xpcs_init(priv, dev, priv->plat->pcs_mode);
+
 	/* Initialize Safety Features */
 	stmmac_safety_feat_configuration(priv);
 
@@ -2582,6 +2599,8 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
 	if (priv->hw->pcs)
 		stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0);
 
+	stmmac_xpcs_ctrl_ane(priv, dev, 1, 0);
+
 	/* set TX and RX rings length */
 	stmmac_set_rings_length(priv);
 
@@ -2697,11 +2716,27 @@ static int stmmac_open(struct net_device *dev)
 		}
 	}
 
+	/* xPCS IRQ line */
+	if (priv->xpcs_irq > 0) {
+		ret = request_irq(priv->xpcs_irq, xpcs_interrupt, IRQF_SHARED,
+				  dev->name, dev);
+		if (unlikely(ret < 0)) {
+			netdev_err(priv->dev,
+				   "%s: ERROR: allocating the xPCS IRQ %d (%d)\n",
+				   __func__, priv->xpcs_irq, ret);
+			goto xpcsirq_error;
+		}
+	}
+
 	stmmac_enable_all_queues(priv);
 	stmmac_start_all_queues(priv);
 
 	return 0;
 
+xpcsirq_error:
+	if (priv->lpi_irq > 0)
+		free_irq(priv->lpi_irq, dev);
+
 lpiirq_error:
 	if (priv->wol_irq != dev->irq)
 		free_irq(priv->wol_irq, dev);
@@ -3776,6 +3811,35 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t xpcs_interrupt(int irq, void *dev_id)
+{
+	struct net_device *ndev = (struct net_device *)dev_id;
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	irqreturn_t ret = IRQ_NONE;
+
+	/* To handle xPCS interrupts */
+	ret = stmmac_xpcs_irq_status(priv, ndev, &priv->xstats,
+				     priv->plat->pcs_mode);
+
+	if (ret == IRQ_HANDLED) {
+		/* Keep the MAC's speed & duplex consistent with DW xPCS
+		 * because AN in DW xPCS does not update DW EQoS MAC
+		 * directly.
+		 */
+		int speed = (int)priv->xstats.pcs_speed;
+		int duplex = (int)priv->xstats.pcs_speed;
+
+		mac_adjust_link(priv, &speed, &duplex);
+
+		if (priv->xstats.pcs_link)
+			netif_carrier_on(ndev);
+		else
+			netif_carrier_off(ndev);
+	}
+
+	return ret;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* Polling receive - used by NETCONSOLE and other diagnostic tools
  * to allow network I/O with interrupts disabled.
@@ -4264,6 +4328,7 @@ int stmmac_dvr_probe(struct device *device,
 	priv->dev->irq = res->irq;
 	priv->wol_irq = res->wol_irq;
 	priv->lpi_irq = res->lpi_irq;
+	priv->xpcs_irq = res->xpcs_irq;
 
 	if (!IS_ERR_OR_NULL(res->mac))
 		memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index b00e7951a66d..c6778abd41c5 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -189,6 +189,8 @@ struct plat_stmmacenet_data {
 	struct reset_control *stmmac_rst;
 	struct stmmac_axi *axi;
 	int has_gmac4;
+	bool has_xpcs;
+	int pcs_mode;
 	bool has_sun8i;
 	bool tso_en;
 	int mac_port_sel_speed;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 4/5] net: stmmac: add xPCS functions for device with DWMACv5.1
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
                   ` (3 preceding siblings ...)
  2019-06-04 18:58 ` [PATCH net-next v6 3/5] net: stmmac: add xpcs function hooks into main driver and ethtool Voon Weifeng
@ 2019-06-04 18:58 ` Voon Weifeng
  2019-06-04 18:58 ` [PATCH net-next v6 5/5] net: stmmac: add EHL SGMII 1Gbps PCI info and PCI ID Voon Weifeng
  5 siblings, 0 replies; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

From: Ong Boon Leong <boon.leong.ong@intel.com>

We introduce support for driver that has v5.10 IP and is also using
xPCS as MMD. This can be easily enabled for other product that integrates
xPCS that is not using v5.00 IP.

Reviewed-by: Chuah Kim Tatt <kim.tatt.chuah@intel.com>
Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
Reviewed-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Baoli Zhang <baoli.zhang@intel.com>
Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
Acked-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 34 ++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.c        | 42 ++++++++++++++++++++++-
 drivers/net/ethernet/stmicro/stmmac/hwif.h        |  2 ++
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 5e98da4e14f9..ccc5f8355dda 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -824,6 +824,40 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
 	.set_mac_loopback = dwmac4_set_mac_loopback,
 };
 
+const struct stmmac_ops dwmac510_xpcs_ops = {
+	.core_init = dwmac4_core_init,
+	.set_mac = stmmac_dwmac4_set_mac,
+	.rx_ipc = dwmac4_rx_ipc_enable,
+	.rx_queue_enable = dwmac4_rx_queue_enable,
+	.rx_queue_prio = dwmac4_rx_queue_priority,
+	.tx_queue_prio = dwmac4_tx_queue_priority,
+	.rx_queue_routing = dwmac4_rx_queue_routing,
+	.prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms,
+	.prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms,
+	.set_mtl_tx_queue_weight = dwmac4_set_mtl_tx_queue_weight,
+	.map_mtl_to_dma = dwmac4_map_mtl_dma,
+	.config_cbs = dwmac4_config_cbs,
+	.dump_regs = dwmac4_dump_regs,
+	.host_irq_status = dwmac4_irq_status,
+	.host_mtl_irq_status = dwmac4_irq_mtl_status,
+	.flow_ctrl = dwmac4_flow_ctrl,
+	.pmt = dwmac4_pmt,
+	.set_umac_addr = dwmac4_set_umac_addr,
+	.get_umac_addr = dwmac4_get_umac_addr,
+	.set_eee_mode = dwmac4_set_eee_mode,
+	.reset_eee_mode = dwmac4_reset_eee_mode,
+	.set_eee_timer = dwmac4_set_eee_timer,
+	.set_eee_pls = dwmac4_set_eee_pls,
+	.debug = dwmac4_debug,
+	.set_filter = dwmac4_set_filter,
+	.safety_feat_config = dwmac5_safety_feat_config,
+	.safety_feat_irq_status = dwmac5_safety_feat_irq_status,
+	.safety_feat_dump = dwmac5_safety_feat_dump,
+	.rxp_config = dwmac5_rxp_config,
+	.flex_pps_config = dwmac5_flex_pps_config,
+	.set_mac_loopback = dwmac4_set_mac_loopback,
+};
+
 int dwmac4_setup(struct stmmac_priv *priv)
 {
 	struct mac_device_info *mac = priv->hw;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 6c61b753b55e..052a000feeb5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -73,11 +73,13 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 	bool gmac;
 	bool gmac4;
 	bool xgmac;
+	bool has_xpcs;
 	u32 min_id;
 	const struct stmmac_regs_off regs;
 	const void *desc;
 	const void *dma;
 	const void *mac;
+	const void *xpcs;
 	const void *hwtimestamp;
 	const void *mode;
 	const void *tc;
@@ -90,6 +92,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -98,6 +101,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = NULL,
 		.dma = &dwmac100_dma_ops,
 		.mac = &dwmac100_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = NULL,
 		.tc = NULL,
@@ -108,6 +112,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = true,
 		.gmac4 = false,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -116,6 +121,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = NULL,
 		.dma = &dwmac1000_dma_ops,
 		.mac = &dwmac1000_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = NULL,
 		.tc = NULL,
@@ -126,6 +132,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -133,6 +140,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		},
 		.desc = &dwmac4_desc_ops,
 		.dma = &dwmac4_dma_ops,
+		.xpcs = NULL,
 		.mac = &dwmac4_ops,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = NULL,
@@ -144,6 +152,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = DWMAC_CORE_4_00,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -152,6 +161,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = &dwmac4_desc_ops,
 		.dma = &dwmac4_dma_ops,
 		.mac = &dwmac410_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = &dwmac4_ring_mode_ops,
 		.tc = &dwmac510_tc_ops,
@@ -162,6 +172,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = DWMAC_CORE_4_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -170,6 +181,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = &dwmac4_desc_ops,
 		.dma = &dwmac410_dma_ops,
 		.mac = &dwmac410_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = &dwmac4_ring_mode_ops,
 		.tc = &dwmac510_tc_ops,
@@ -180,6 +192,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.has_xpcs = false,
 		.min_id = DWMAC_CORE_5_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -188,6 +201,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = &dwmac4_desc_ops,
 		.dma = &dwmac410_dma_ops,
 		.mac = &dwmac510_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = &dwmac4_ring_mode_ops,
 		.tc = &dwmac510_tc_ops,
@@ -198,6 +212,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = true,
+		.has_xpcs = false,
 		.min_id = DWXGMAC_CORE_2_10,
 		.regs = {
 			.ptp_off = PTP_XGMAC_OFFSET,
@@ -206,13 +221,34 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 		.desc = &dwxgmac210_desc_ops,
 		.dma = &dwxgmac210_dma_ops,
 		.mac = &dwxgmac210_ops,
+		.xpcs = NULL,
 		.hwtimestamp = &stmmac_ptp,
 		.mode = NULL,
 		.tc = &dwmac510_tc_ops,
 		.mmc = NULL,
 		.setup = dwxgmac2_setup,
 		.quirks = NULL,
-	},
+	}, {
+		.gmac = false,
+		.gmac4 = true,
+		.xgmac = false,
+		.has_xpcs = true,
+		.min_id = DWMAC_CORE_5_10,
+		.regs = {
+			.ptp_off = PTP_GMAC4_OFFSET,
+			.mmc_off = MMC_GMAC4_OFFSET,
+		},
+		.desc = &dwmac4_desc_ops,
+		.dma = &dwmac410_dma_ops,
+		.mac = &dwmac510_xpcs_ops,
+		.xpcs = &xpcs_ops,
+		.hwtimestamp = &stmmac_ptp,
+		.mode = &dwmac4_ring_mode_ops,
+		.tc = &dwmac510_tc_ops,
+		.mmc = &dwmac_mmc_ops,
+		.setup = dwmac4_setup,
+		.quirks = NULL,
+	}
 };
 
 int stmmac_hwif_init(struct stmmac_priv *priv)
@@ -220,6 +256,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
 	bool needs_xgmac = priv->plat->has_xgmac;
 	bool needs_gmac4 = priv->plat->has_gmac4;
 	bool needs_gmac = priv->plat->has_gmac;
+	bool needs_xpcs = priv->plat->has_xpcs;
 	const struct stmmac_hwif_entry *entry;
 	struct mac_device_info *mac;
 	bool needs_setup = true;
@@ -264,6 +301,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
 			continue;
 		if (needs_xgmac ^ entry->xgmac)
 			continue;
+		if (needs_xpcs ^ entry->has_xpcs)
+			continue;
 		/* Use synopsys_id var because some setups can override this */
 		if (priv->synopsys_id < entry->min_id)
 			continue;
@@ -272,6 +311,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
 		mac->desc = mac->desc ? : entry->desc;
 		mac->dma = mac->dma ? : entry->dma;
 		mac->mac = mac->mac ? : entry->mac;
+		mac->xpcs = mac->xpcs ? : entry->xpcs;
 		mac->ptp = mac->ptp ? : entry->hwtimestamp;
 		mac->mode = mac->mode ? : entry->mode;
 		mac->tc = mac->tc ? : entry->tc;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 431cf4261264..ebc7f9048094 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -509,6 +509,7 @@ struct stmmac_regs_off {
 };
 
 extern const struct stmmac_ops dwmac100_ops;
+extern const struct stmmac_xpcs_ops xpcs_ops;
 extern const struct stmmac_dma_ops dwmac100_dma_ops;
 extern const struct stmmac_ops dwmac1000_ops;
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
@@ -517,6 +518,7 @@ struct stmmac_regs_off {
 extern const struct stmmac_ops dwmac410_ops;
 extern const struct stmmac_dma_ops dwmac410_dma_ops;
 extern const struct stmmac_ops dwmac510_ops;
+extern const struct stmmac_ops dwmac510_xpcs_ops;
 extern const struct stmmac_tc_ops dwmac510_tc_ops;
 extern const struct stmmac_ops dwxgmac210_ops;
 extern const struct stmmac_dma_ops dwxgmac210_dma_ops;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next v6 5/5] net: stmmac: add EHL SGMII 1Gbps PCI info and PCI ID
  2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
                   ` (4 preceding siblings ...)
  2019-06-04 18:58 ` [PATCH net-next v6 4/5] net: stmmac: add xPCS functions for device with DWMACv5.1 Voon Weifeng
@ 2019-06-04 18:58 ` Voon Weifeng
  5 siblings, 0 replies; 11+ messages in thread
From: Voon Weifeng @ 2019-06-04 18:58 UTC (permalink / raw)
  To: David S. Miller, Maxime Coquelin
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Florian Fainelli, Alexandre Torgue, biao huang,
	Ong Boon Leong, Kweh Hock Leong, Voon Weifeng

Added EHL SGMII 1Gbps PCI ID. Different MII and speed will have
different PCI ID.

Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 111 +++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 7cbc01f316fa..1bdf716bfcbb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -23,6 +23,7 @@
 #include <linux/dmi.h>
 
 #include "stmmac.h"
+#include "dwxpcs.h"
 
 /*
  * This struct is used to associate PCI Function of MAC controller on a board,
@@ -118,6 +119,113 @@ static int stmmac_default_data(struct pci_dev *pdev,
 	.setup = stmmac_default_data,
 };
 
+static int ehl_common_data(struct pci_dev *pdev,
+			   struct plat_stmmacenet_data *plat)
+{
+	int i;
+
+	plat->bus_id = 1;
+	plat->phy_addr = 0;
+	plat->clk_csr = 5;
+	plat->has_gmac = 0;
+	plat->has_gmac4 = 1;
+	plat->xpcs_phy_addr = 0x16;
+	plat->pcs_mode = AN_CTRL_PCS_MD_C37_SGMII;
+	plat->force_sf_dma_mode = 0;
+	plat->tso_en = 1;
+
+	plat->rx_queues_to_use = 8;
+	plat->tx_queues_to_use = 8;
+	plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
+
+	for (i = 0; i < plat->rx_queues_to_use; i++) {
+		plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
+		plat->rx_queues_cfg[i].chan = i;
+
+		/* Disable Priority config by default */
+		plat->rx_queues_cfg[i].use_prio = false;
+
+		/* Disable RX queues routing by default */
+		plat->rx_queues_cfg[i].pkt_route = 0x0;
+	}
+
+	for (i = 0; i < plat->tx_queues_to_use; i++) {
+		plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
+
+		/* Disable Priority config by default */
+		plat->tx_queues_cfg[i].use_prio = false;
+	}
+
+	plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
+	plat->tx_queues_cfg[0].weight = 0x09;
+	plat->tx_queues_cfg[1].weight = 0x0A;
+	plat->tx_queues_cfg[2].weight = 0x0B;
+	plat->tx_queues_cfg[3].weight = 0x0C;
+	plat->tx_queues_cfg[4].weight = 0x0D;
+	plat->tx_queues_cfg[5].weight = 0x0E;
+	plat->tx_queues_cfg[6].weight = 0x0F;
+	plat->tx_queues_cfg[7].weight = 0x10;
+
+	plat->mdio_bus_data->phy_reset = NULL;
+	plat->mdio_bus_data->phy_mask = 0;
+
+	plat->dma_cfg->pbl = 32;
+	plat->dma_cfg->pblx8 = true;
+	plat->dma_cfg->fixed_burst = 0;
+	plat->dma_cfg->mixed_burst = 0;
+	plat->dma_cfg->aal = 0;
+
+	plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi),
+				 GFP_KERNEL);
+	if (!plat->axi)
+		return -ENOMEM;
+
+	plat->axi->axi_lpi_en = 0;
+	plat->axi->axi_xit_frm = 0;
+	plat->axi->axi_wr_osr_lmt = 1;
+	plat->axi->axi_rd_osr_lmt = 1;
+	plat->axi->axi_blen[0] = 4;
+	plat->axi->axi_blen[1] = 8;
+	plat->axi->axi_blen[2] = 16;
+
+	/* Set default value for multicast hash bins */
+	plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+	/* Set default value for unicast filter entries */
+	plat->unicast_filter_entries = 1;
+
+	/* Set the maxmtu to a default of JUMBO_LEN */
+	plat->maxmtu = JUMBO_LEN;
+
+	/* Set 32KB fifo size as the advertised fifo size in
+	 * the HW features is not the same as the HW implementation
+	 */
+	plat->tx_fifo_size = 32768;
+	plat->rx_fifo_size = 32768;
+
+	return 0;
+}
+
+static int ehl_sgmii1g_data(struct pci_dev *pdev,
+			    struct plat_stmmacenet_data *plat)
+{
+	int ret;
+
+	/* Set common default data first */
+	ret = ehl_common_data(pdev, plat);
+	if (ret)
+		return ret;
+
+	plat->interface = PHY_INTERFACE_MODE_SGMII;
+	plat->has_xpcs = 1;
+
+	return 0;
+}
+
+static struct stmmac_pci_info ehl_sgmii1g_pci_info = {
+	.setup = ehl_sgmii1g_data,
+};
+
 static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
 	{
 		.func = 6,
@@ -290,6 +398,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 	res.addr = pcim_iomap_table(pdev)[i];
 	res.wol_irq = pdev->irq;
 	res.irq = pdev->irq;
+	res.xpcs_irq = 0;
 
 	return stmmac_dvr_probe(&pdev->dev, plat, &res);
 }
@@ -359,6 +468,7 @@ static int __maybe_unused stmmac_pci_resume(struct device *dev)
 
 #define STMMAC_QUARK_ID  0x0937
 #define STMMAC_DEVICE_ID 0x1108
+#define STMMAC_EHL_SGMII1G_ID   0x4b31
 
 #define STMMAC_DEVICE(vendor_id, dev_id, info)	{	\
 	PCI_VDEVICE(vendor_id, dev_id),			\
@@ -369,6 +479,7 @@ static int __maybe_unused stmmac_pci_resume(struct device *dev)
 	STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info),
 	STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info),
 	STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info),
+	STMMAC_DEVICE(INTEL, STMMAC_EHL_SGMII1G_ID, ehl_sgmii1g_pci_info),
 	{}
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics
  2019-06-04 18:58 ` [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics Voon Weifeng
@ 2019-06-04 20:46   ` Florian Fainelli
  2019-06-05 13:13     ` Jose Abreu
  0 siblings, 1 reply; 11+ messages in thread
From: Florian Fainelli @ 2019-06-04 20:46 UTC (permalink / raw)
  To: Voon Weifeng, David S. Miller, Maxime Coquelin, Russell King
  Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro,
	Andrew Lunn, Alexandre Torgue, biao huang, Ong Boon Leong,
	Kweh Hock Leong

+Russell,

On 6/4/2019 11:58 AM, Voon Weifeng wrote:
> From: Ong Boon Leong <boon.leong.ong@intel.com>
> 
> xPCS is DWC Ethernet Physical Coding Sublayer that may be integrated
> into a GbE controller that uses DWC EQoS MAC controller. An example of
> HW configuration is shown below:-
> 
>   <-----------------GBE Controller---------->|<--External PHY chip-->
> 
>   +----------+         +----+    +---+               +--------------+
>   |   EQoS   | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE |
>   |   MAC    |         |xPCS|    |IF |               | PHY Chip     |
>   +----------+         +----+    +---+               +--------------+
>          ^               ^                                  ^
>          |               |                                  |
>          +---------------------MDIO-------------------------+
> 
> xPCS is a Clause-45 MDIO Manageable Device (MMD) and we need a way to
> differentiate it from external PHY chip that is discovered over MDIO.
> Therefore, xpcs_phy_addr is introduced in stmmac platform data
> (plat_stmmacenet_data) for differentiating xPCS from 'phy_addr' that
> belongs to external PHY.

Assuming this DW xPCS can be found with designs other than STMMAC would
not it make sense to model this as some kind of PHY/MDIO bridge? A
little bit like what drivers/net/phy/xilinx_gmii2rgmii.c tries to do?

> 
> Basic functionalities for initializing xPCS and configuring auto
> negotiation (AN), loopback, link status, AN advertisement and Link
> Partner ability are implemented. The implementation supports the C37
> AN for 1000BASE-X and SGMII (MAC side SGMII only).
> 
> Tested-by: Tan, Tee Min <tee.min.tan@intel.com>
> Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
> Reviewed-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
> Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/Makefile |   2 +-
>  drivers/net/ethernet/stmicro/stmmac/common.h |   1 +
>  drivers/net/ethernet/stmicro/stmmac/dwxpcs.c | 208 +++++++++++++++++++++++++++
>  drivers/net/ethernet/stmicro/stmmac/dwxpcs.h |  51 +++++++
>  drivers/net/ethernet/stmicro/stmmac/hwif.h   |  19 +++
>  include/linux/stmmac.h                       |   1 +
>  6 files changed, 281 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxpcs.h
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index c59926d96bcc..f007fb873455 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
>  	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
>  	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
>  	      stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
> -	      $(stmmac-y)
> +	      dwxpcs.o $(stmmac-y)
>  
>  stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 1961fe9144ca..83df093c4636 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -419,6 +419,7 @@ struct mii_regs {
>  
>  struct mac_device_info {
>  	const struct stmmac_ops *mac;
> +	const struct stmmac_xpcs_ops *xpcs;
>  	const struct stmmac_desc_ops *desc;
>  	const struct stmmac_dma_ops *dma;
>  	const struct stmmac_mode_ops *mode;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
> new file mode 100644
> index 000000000000..7e850b9dd7b7
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.c
> @@ -0,0 +1,208 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2019, Intel Corporation.
> + * DWC Ethernet Physical Coding Sublayer
> + */
> +#include <linux/bitops.h>
> +#include <linux/mdio.h>
> +#include "dwxpcs.h"
> +#include "stmmac.h"
> +
> +/* DW xPCS mdiobus_read and mdiobus_write helper functions */
> +#define xpcs_read(dev, reg) \
> +	mdiobus_read(priv->mii, xpcs_phy_addr, \
> +		     MII_ADDR_C45 | (reg) | \
> +		     ((dev) << MII_DEVADDR_C45_SHIFT))
> +#define xpcs_write(dev, reg, val) \
> +	mdiobus_write(priv->mii, xpcs_phy_addr, \
> +		      MII_ADDR_C45 | (reg) | \
> +		      ((dev) << MII_DEVADDR_C45_SHIFT), val)
> +
> +static void dw_xpcs_init(struct net_device *ndev, int pcs_mode)
> +{
> +	struct stmmac_priv *priv = netdev_priv(ndev);
> +	int xpcs_phy_addr;
> +	int phydata;
> +
> +	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
> +
> +	if (pcs_mode == AN_CTRL_PCS_MD_C37_SGMII) {
> +		/* For AN for 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)
> +		 *    DW xPCS used with DW EQoS MAC is always MAC
> +		 *    side SGMII.
> +		 * 3) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt
> +		 *    enabled)
> +		 * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic
> +		 *    speed mode change after SGMII AN complete)
> +		 * Note: Since it is MAC side SGMII, there is no need to set
> +		 *	 SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config
> +		 *	 from PHY about the link state change after C28 AN
> +		 *	 is completed between PHY and Link Partner.
> +		 */
> +		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL);
> +		phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD;
> +		phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN |
> +			   (AN_CTRL_PCS_MD_C37_SGMII <<
> +			    MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT &
> +			    MDIO_MII_MMD_AN_CTRL_PCS_MD) |
> +			   (AN_CTRL_TX_CONF_MAC_SIDE_SGMII <<
> +			    MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT);
> +		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata);
> +
> +		phydata = xpcs_read(XPCS_MDIO_MII_MMD,
> +				    MDIO_MII_MMD_DIGITAL_CTRL_1);
> +		phydata |= MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW;
> +		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_DIGITAL_CTRL_1,
> +			   phydata);
> +	} else {
> +		/* For AN for 1000BASE-X mode, the settings are :-
> +		 * 1) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
> +		 * 2) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt
> +		 *    enabled)
> +		 * 3) SR_MII_AN_ADV Bit(6)[FD] = 1b (Full Duplex)
> +		 *    Note: Half Duplex is rarely used, so don't advertise.
> +		 * 4) SR_MII_AN_ADV Bit(8:7)[PSE] = 11b (Sym & Asym Pause)
> +		 */
> +		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL);
> +		phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD;
> +		phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN |
> +			   (AN_CTRL_PCS_MD_C37_1000BASEX <<
> +			    MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT &
> +			    MDIO_MII_MMD_AN_CTRL_PCS_MD);
> +		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata);
> +
> +		phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_ADVERTISE);
> +		phydata |= MDIO_MII_MMD_FD |
> +			   (MDIO_MII_MMD_PSE_BOTH << MDIO_MII_MMD_PSE_SHIFT);
> +		xpcs_write(XPCS_MDIO_MII_MMD, MII_ADVERTISE, phydata);
> +	}
> +}
> +
> +static void dw_xpcs_ctrl_ane(struct net_device *ndev, bool ane,
> +			     bool loopback)
> +{
> +	struct stmmac_priv *priv = netdev_priv(ndev);
> +	int xpcs_phy_addr;
> +	int phydata;
> +
> +	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
> +	phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_BMCR);
> +
> +	if (ane)
> +		phydata |= (BMCR_ANENABLE | BMCR_ANRESTART);
> +
> +	if (loopback)
> +		phydata |= BMCR_LOOPBACK;
> +
> +	xpcs_write(XPCS_MDIO_MII_MMD, MII_BMCR, phydata);
> +}
> +
> +static void dw_xpcs_get_adv_lp(struct net_device *ndev,
> +			       struct rgmii_adv *adv_lp,
> +			       int pcs_mode)
> +{
> +	struct stmmac_priv *priv = netdev_priv(ndev);
> +	int xpcs_phy_addr;
> +	int value;
> +
> +	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
> +
> +	/* AN Advertisement Ability */
> +	value = xpcs_read(XPCS_MDIO_MII_MMD, MII_ADVERTISE);
> +
> +	if (value & MDIO_MII_MMD_FD)
> +		adv_lp->duplex = DUPLEX_FULL;
> +	if (value & MDIO_MII_MMD_HD)
> +		adv_lp->duplex = DUPLEX_HALF;
> +	adv_lp->pause = (u32)((value & MDIO_MII_MMD_PSE) >>
> +			      MDIO_MII_MMD_PSE_SHIFT);
> +
> +	/* Link Partner Ability - 1000BASE-X only*/
> +	if (pcs_mode == AN_CTRL_PCS_MD_C37_1000BASEX) {
> +		value = xpcs_read(XPCS_MDIO_MII_MMD, MII_LPA);
> +		if (value & MDIO_MII_MMD_FD)
> +			adv_lp->lp_duplex = DUPLEX_FULL;
> +		if (value & MDIO_MII_MMD_HD)
> +			adv_lp->lp_duplex = DUPLEX_HALF;
> +		adv_lp->lp_pause = (u32)((value & MDIO_MII_MMD_PSE) >>
> +					 MDIO_MII_MMD_PSE_SHIFT);
> +	}
> +}
> +
> +static void dw_xpcs_get_linkstatus(struct net_device *ndev,
> +				   u16 an_stat,
> +				   struct stmmac_extra_stats *x)
> +{
> +	/* Check the SGMII AN link status */
> +	if (an_stat & AN_STAT_SGMII_AN_LNKSTS) {
> +		int speed_value;
> +
> +		x->pcs_link = 1;
> +
> +		speed_value = ((an_stat & AN_STAT_SGMII_AN_SPEED) >>
> +				AN_STAT_SGMII_AN_SPEED_SHIFT);
> +		if (speed_value == AN_STAT_SGMII_AN_1000MBPS)
> +			x->pcs_speed = SPEED_1000;
> +		else if (speed_value == AN_STAT_SGMII_AN_100MBPS)
> +			x->pcs_speed = SPEED_100;
> +		else
> +			x->pcs_speed = SPEED_10;
> +
> +		if (an_stat & AN_STAT_SGMII_AN_FD)
> +			x->pcs_duplex = 1;
> +		else
> +			x->pcs_duplex = 0;
> +
> +		netdev_info(ndev, "Link is Up - %d/%s\n", (int)x->pcs_speed,
> +			    x->pcs_duplex ? "Full" : "Half");
> +	} else {
> +		x->pcs_link = 0;
> +		netdev_info(ndev, "Link is Down\n");
> +	}
> +}
> +
> +static int dw_xpcs_irq_status(struct net_device *ndev,
> +			      struct stmmac_extra_stats *x,
> +			      int pcs_mode)
> +{
> +	struct stmmac_priv *priv = netdev_priv(ndev);
> +	int ret = IRQ_NONE;
> +	int xpcs_phy_addr;
> +	int an_stat;
> +
> +	xpcs_phy_addr = priv->plat->xpcs_phy_addr;
> +
> +	/* AN status */
> +	an_stat = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT);
> +
> +	if (an_stat & AN_STAT_SGMII_AN_CMPLT) {
> +		x->irq_pcs_ane_n++;
> +
> +		if (pcs_mode == AN_CTRL_PCS_MD_C37_SGMII) {
> +			dw_xpcs_get_linkstatus(ndev, an_stat, x);
> +		} else {
> +			/* For 1000BASE-X AN, DW xPCS does not have register
> +			 * to read the link state of 1000BASE-X C37 AN and
> +			 * since 1000BASE-X is always 1000Mbps and FD, we
> +			 * just set the default link here.
> +			 */
> +			x->pcs_link = 1;
> +			x->pcs_duplex = 1;
> +			x->pcs_speed = SPEED_1000;
> +		}
> +
> +		/* Clear C37 AN complete status by writing zero */
> +		xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT, 0);
> +		ret = IRQ_HANDLED;
> +	}
> +
> +	return ret;
> +}
> +
> +const struct stmmac_xpcs_ops xpcs_ops = {
> +	.xpcs_init = dw_xpcs_init,
> +	.xpcs_ctrl_ane = dw_xpcs_ctrl_ane,
> +	.xpcs_get_adv_lp = dw_xpcs_get_adv_lp,
> +	.xpcs_irq_status = dw_xpcs_irq_status,
> +};
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h
> new file mode 100644
> index 000000000000..bd52ce80bf4e
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxpcs.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2019, Intel Corporation.
> + * DWC Ethernet Physical Coding Sublayer
> + */
> +#ifndef __DW_XPCS_H__
> +#define __DW_XPCS_H__
> +
> +/* XPCS MII MMD Device Addresses */
> +#define XPCS_MDIO_MII_MMD	MDIO_MMD_VEND2
> +
> +/* MII MMD registers offsets */
> +#define MDIO_MII_MMD_DIGITAL_CTRL_1	0x8000	/* Digital Control 1 */
> +#define MDIO_MII_MMD_AN_CTRL		0x8001	/* AN Control */
> +#define MDIO_MII_MMD_AN_STAT		0x8002	/* AN Status */
> +
> +/* MII MMD SR AN Advertisement & Link Partner Ability are slightly
> + * different from MII_ADVERTISEMENT & MII_LPA in below fields:
> + */
> +#define MDIO_MII_MMD_HD			BIT(6)	/* Half duplex */
> +#define MDIO_MII_MMD_FD			BIT(5)	/* Full duplex */
> +#define MDIO_MII_MMD_PSE_SHIFT		7	/* Pause Ability shift */
> +#define MDIO_MII_MMD_PSE		GENMASK(8, 7)	/* Pause Ability */
> +#define MDIO_MII_MMD_PSE_NO		0x0
> +#define MDIO_MII_MMD_PSE_ASYM		0x1
> +#define MDIO_MII_MMD_PSE_SYM		0x2
> +#define MDIO_MII_MMD_PSE_BOTH		0x3
> +
> +/* Automatic Speed Mode Change for MAC side SGMII AN */
> +#define MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW	BIT(9)
> +
> +/* MII MMD AN Control defines */
> +#define MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT	3 /* TX Config shift */
> +#define AN_CTRL_TX_CONF_PHY_SIDE_SGMII		0x1 /* PHY side SGMII mode */
> +#define AN_CTRL_TX_CONF_MAC_SIDE_SGMII		0x0 /* MAC side SGMII mode */
> +#define MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT	1  /* PCS Mode shift */
> +#define MDIO_MII_MMD_AN_CTRL_PCS_MD	GENMASK(2, 1) /* PCS Mode */
> +#define AN_CTRL_PCS_MD_C37_1000BASEX	0x0	/* C37 AN for 1000BASE-X */
> +#define AN_CTRL_PCS_MD_C37_SGMII	0x2	/* C37 AN for SGMII */
> +#define MDIO_MII_MMD_AN_CTRL_AN_INTR_EN	BIT(0)	/* AN Complete Intr Enable */
> +
> +/* MII MMD AN Status defines for SGMII AN Status */
> +#define AN_STAT_SGMII_AN_CMPLT		BIT(0)	/* AN Complete Intr */
> +#define AN_STAT_SGMII_AN_FD		BIT(1)	/* Full Duplex */
> +#define AN_STAT_SGMII_AN_SPEED_SHIFT	2	/* AN Speed shift */
> +#define AN_STAT_SGMII_AN_SPEED		GENMASK(3, 2)	/* AN Speed */
> +#define AN_STAT_SGMII_AN_10MBPS		0x0	/* 10 Mbps */
> +#define AN_STAT_SGMII_AN_100MBPS	0x1	/* 100 Mbps */
> +#define AN_STAT_SGMII_AN_1000MBPS	0x2	/* 1000 Mbps */
> +#define AN_STAT_SGMII_AN_LNKSTS		BIT(4)	/* Link Status */
> +
> +#endif /* __DW_XPCS_H__ */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 2acfbc70e3c8..431cf4261264 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -398,6 +398,25 @@ struct stmmac_ops {
>  #define stmmac_set_mac_loopback(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, mac, set_mac_loopback, __args)
>  
> +/* Helpers for DW xPCS */
> +struct stmmac_xpcs_ops {
> +	void (*xpcs_init)(struct net_device *ndev, int pcs_mode);
> +	void (*xpcs_ctrl_ane)(struct net_device *ndev, bool ane, bool loopback);
> +	void (*xpcs_get_adv_lp)(struct net_device *ndev, struct rgmii_adv *adv,
> +				int pcs_mode);
> +	int (*xpcs_irq_status)(struct net_device *ndev,
> +			       struct stmmac_extra_stats *x, int pcs_mode);
> +};
> +
> +#define stmmac_xpcs_init(__priv, __args...) \
> +	stmmac_do_void_callback(__priv, xpcs, xpcs_init, __args)
> +#define stmmac_xpcs_ctrl_ane(__priv, __args...) \
> +	stmmac_do_void_callback(__priv, xpcs, xpcs_ctrl_ane, __args)
> +#define stmmac_xpcs_get_adv_lp(__priv, __args...) \
> +	stmmac_do_void_callback(__priv, xpcs, xpcs_get_adv_lp, __args)
> +#define stmmac_xpcs_irq_status(__priv, __args...) \
> +	stmmac_do_callback(__priv, xpcs, xpcs_irq_status, __args)
> +
>  /* PTP and HW Timer helpers */
>  struct stmmac_hwtimestamp {
>  	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 4335bd771ce5..b00e7951a66d 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -148,6 +148,7 @@ struct stmmac_txq_cfg {
>  struct plat_stmmacenet_data {
>  	int bus_id;
>  	int phy_addr;
> +	int xpcs_phy_addr;
>  	int interface;
>  	struct stmmac_mdio_bus_data *mdio_bus_data;
>  	struct device_node *phy_node;
> 

-- 
Florian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics
  2019-06-04 20:46   ` Florian Fainelli
@ 2019-06-05 13:13     ` Jose Abreu
  2019-06-07  0:23       ` Ong, Boon Leong
  0 siblings, 1 reply; 11+ messages in thread
From: Jose Abreu @ 2019-06-05 13:13 UTC (permalink / raw)
  To: Florian Fainelli, Voon Weifeng, David S. Miller, Maxime Coquelin,
	Russell King
  Cc: netdev, linux-kernel, Giuseppe Cavallaro, Andrew Lunn,
	Alexandre Torgue, biao huang, Ong Boon Leong, Kweh Hock Leong

From: Florian Fainelli <f.fainelli@gmail.com>

> +Russell,
> 
> On 6/4/2019 11:58 AM, Voon Weifeng wrote:
> > From: Ong Boon Leong <boon.leong.ong@intel.com>
> > 
> > xPCS is DWC Ethernet Physical Coding Sublayer that may be integrated
> > into a GbE controller that uses DWC EQoS MAC controller. An example of
> > HW configuration is shown below:-
> > 
> >   <-----------------GBE Controller---------->|<--External PHY chip-->
> > 
> >   +----------+         +----+    +---+               +--------------+
> >   |   EQoS   | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE |
> >   |   MAC    |         |xPCS|    |IF |               | PHY Chip     |
> >   +----------+         +----+    +---+               +--------------+
> >          ^               ^                                  ^
> >          |               |                                  |
> >          +---------------------MDIO-------------------------+
> > 
> > xPCS is a Clause-45 MDIO Manageable Device (MMD) and we need a way to
> > differentiate it from external PHY chip that is discovered over MDIO.
> > Therefore, xpcs_phy_addr is introduced in stmmac platform data
> > (plat_stmmacenet_data) for differentiating xPCS from 'phy_addr' that
> > belongs to external PHY.
> 
> Assuming this DW xPCS can be found with designs other than STMMAC would
> not it make sense to model this as some kind of PHY/MDIO bridge? A
> little bit like what drivers/net/phy/xilinx_gmii2rgmii.c tries to do?

Yes, DW XPCS is a separate IP that can be sold without the MAC.

Thanks,
Jose Miguel Abreu

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics
  2019-06-05 13:13     ` Jose Abreu
@ 2019-06-07  0:23       ` Ong, Boon Leong
  2019-06-20  5:13         ` Ong, Boon Leong
  0 siblings, 1 reply; 11+ messages in thread
From: Ong, Boon Leong @ 2019-06-07  0:23 UTC (permalink / raw)
  To: Jose Abreu, Florian Fainelli, Voon, Weifeng, David S. Miller,
	Maxime Coquelin, Russell King
  Cc: netdev, linux-kernel, Giuseppe Cavallaro, Andrew Lunn,
	Alexandre Torgue, biao huang, Kweh, Hock Leong

>-----Original Message-----
>From: Jose Abreu [mailto:Jose.Abreu@synopsys.com]
>Sent: Wednesday, June 5, 2019 9:13 PM
>To: Florian Fainelli <f.fainelli@gmail.com>; Voon, Weifeng
><weifeng.voon@intel.com>; David S. Miller <davem@davemloft.net>;
>Maxime Coquelin <mcoquelin.stm32@gmail.com>; Russell King
><linux@armlinux.org.uk>
>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Giuseppe
>Cavallaro <peppe.cavallaro@st.com>; Andrew Lunn <andrew@lunn.ch>;
>Alexandre Torgue <alexandre.torgue@st.com>; biao huang
><biao.huang@mediatek.com>; Ong, Boon Leong
><boon.leong.ong@intel.com>; Kweh, Hock Leong
><hock.leong.kweh@intel.com>
>Subject: RE: [PATCH net-next v6 2/5] net: stmmac: introducing support for
>DWC xPCS logics
>
>From: Florian Fainelli <f.fainelli@gmail.com>
>
>> +Russell,
>>
>> On 6/4/2019 11:58 AM, Voon Weifeng wrote:
>> > From: Ong Boon Leong <boon.leong.ong@intel.com>
>> >
>> > xPCS is DWC Ethernet Physical Coding Sublayer that may be integrated
>> > into a GbE controller that uses DWC EQoS MAC controller. An example of
>> > HW configuration is shown below:-
>> >
>> >   <-----------------GBE Controller---------->|<--External PHY chip-->
>> >
>> >   +----------+         +----+    +---+               +--------------+
>> >   |   EQoS   | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE |
>> >   |   MAC    |         |xPCS|    |IF |               | PHY Chip     |
>> >   +----------+         +----+    +---+               +--------------+
>> >          ^               ^                                  ^
>> >          |               |                                  |
>> >          +---------------------MDIO-------------------------+
>> >
>> > xPCS is a Clause-45 MDIO Manageable Device (MMD) and we need a way
>to
>> > differentiate it from external PHY chip that is discovered over MDIO.
>> > Therefore, xpcs_phy_addr is introduced in stmmac platform data
>> > (plat_stmmacenet_data) for differentiating xPCS from 'phy_addr' that
>> > belongs to external PHY.
>>
>> Assuming this DW xPCS can be found with designs other than STMMAC
>would
>> not it make sense to model this as some kind of PHY/MDIO bridge? A
>> little bit like what drivers/net/phy/xilinx_gmii2rgmii.c tries to do?
>
>Yes, DW XPCS is a separate IP that can be sold without the MAC.

Hi Florian, thanks for pointing out the PHY driver for GMII to RGMII converter
implementation. It seems like community would like dwxpcs to take the
converter phy driver direction. 

We would like to check with community what is the MAC controller that is
using above PHY driver so that we can dig deeper into the PHY & MAC driver
architecture. We would like to map the existing usage of dwxpcs.c in 3/5 of
this series is architecturally ready for PHY driver framework or new APIs
would need to be defined. 

Thanks
Boon Leong

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics
  2019-06-07  0:23       ` Ong, Boon Leong
@ 2019-06-20  5:13         ` Ong, Boon Leong
  0 siblings, 0 replies; 11+ messages in thread
From: Ong, Boon Leong @ 2019-06-20  5:13 UTC (permalink / raw)
  To: Jose Abreu, Florian Fainelli, David S. Miller, biao huang, Andrew Lunn
  Cc: netdev, linux-kernel, Giuseppe Cavallaro, Alexandre Torgue, Kweh,
	Hock Leong, Maxime Coquelin, Russell King, Voon, Weifeng

>>From: Jose Abreu [mailto:Jose.Abreu@synopsys.com]
>>From: Florian Fainelli <f.fainelli@gmail.com>
>>
>>> +Russell,
>>>
>>> On 6/4/2019 11:58 AM, Voon Weifeng wrote:
>>> > From: Ong Boon Leong <boon.leong.ong@intel.com>
>>> >
>>> > xPCS is DWC Ethernet Physical Coding Sublayer that may be integrated
>>> > into a GbE controller that uses DWC EQoS MAC controller. An example of
>>> > HW configuration is shown below:-
>>> >
>>> >   <-----------------GBE Controller---------->|<--External PHY chip-->
>>> >
>>> >   +----------+         +----+    +---+               +--------------+
>>> >   |   EQoS   | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE |
>>> >   |   MAC    |         |xPCS|    |IF |               | PHY Chip     |
>>> >   +----------+         +----+    +---+               +--------------+
>>> >          ^               ^                                  ^
>>> >          |               |                                  |
>>> >          +---------------------MDIO-------------------------+
>>> >
>>> > xPCS is a Clause-45 MDIO Manageable Device (MMD) and we need a way
>>to
>>> > differentiate it from external PHY chip that is discovered over MDIO.
>>> > Therefore, xpcs_phy_addr is introduced in stmmac platform data
>>> > (plat_stmmacenet_data) for differentiating xPCS from 'phy_addr' that
>>> > belongs to external PHY.
>>>
>>> Assuming this DW xPCS can be found with designs other than STMMAC
>>would
>>> not it make sense to model this as some kind of PHY/MDIO bridge? A
>>> little bit like what drivers/net/phy/xilinx_gmii2rgmii.c tries to do?
>>
>>Yes, DW XPCS is a separate IP that can be sold without the MAC.
>
>Hi Florian, thanks for pointing out the PHY driver for GMII to RGMII converter
>implementation. It seems like community would like dwxpcs to take the
>converter phy driver direction.
>
>We would like to check with community what is the MAC controller that is
>using above PHY driver so that we can dig deeper into the PHY & MAC driver
>architecture. We would like to map the existing usage of dwxpcs.c in 3/5 of
>this series is architecturally ready for PHY driver framework or new APIs
>would need to be defined.

Just to cycle-back to this track, we are working towards getting the ACPI device
ID for this IP. Meanwhile, since the C45 MDIO patych is also needed by 
Biao, we plan to line up the below patch for merge.

[PATCH net-next v6 1/5] net: stmmac: enable clause 45 mdio support

Is there any concern with this approach? 

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-06-20  5:13 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-04 18:58 [PATCH net-next v6 0/5] net: stmmac: enable EHL SGMII Voon Weifeng
2019-06-04 14:09 ` Jose Abreu
2019-06-04 18:58 ` [PATCH net-next v6 1/5] net: stmmac: enable clause 45 mdio support Voon Weifeng
2019-06-04 18:58 ` [PATCH net-next v6 2/5] net: stmmac: introducing support for DWC xPCS logics Voon Weifeng
2019-06-04 20:46   ` Florian Fainelli
2019-06-05 13:13     ` Jose Abreu
2019-06-07  0:23       ` Ong, Boon Leong
2019-06-20  5:13         ` Ong, Boon Leong
2019-06-04 18:58 ` [PATCH net-next v6 3/5] net: stmmac: add xpcs function hooks into main driver and ethtool Voon Weifeng
2019-06-04 18:58 ` [PATCH net-next v6 4/5] net: stmmac: add xPCS functions for device with DWMACv5.1 Voon Weifeng
2019-06-04 18:58 ` [PATCH net-next v6 5/5] net: stmmac: add EHL SGMII 1Gbps PCI info and PCI ID Voon Weifeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).