diff mbox series

[3/3] net: ethernet: add support for high speed mac and usxgmii pcs

Message ID 20190222201309.GA23470@lvlogina.cadence.com
State Changes Requested
Delegated to: David Miller
Headers show
Series Cover letter: Add support for high speed MAC in Cadence controller driver | expand

Commit Message

Parshuram Raju Thombare Feb. 22, 2019, 8:13 p.m. UTC
This patch add support for (10G) high speed mac, usxgmii pcs
and usxgmii interface in Cadence ethernet controller driver.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/net/ethernet/cadence/macb.h      |   33 +++++++++
 drivers/net/ethernet/cadence/macb_main.c |  110 ++++++++++++++++++++++++++++--
 include/linux/phy.h                      |    3 +
 3 files changed, 140 insertions(+), 6 deletions(-)

Comments

Andrew Lunn Feb. 22, 2019, 9:44 p.m. UTC | #1
>  	if (macb_is_gem(bp)) {
> -		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
> -		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
> -			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
> -					 phydev->supported);
> +		if (bp->caps & MACB_CAPS_HIGH_SPEED) {
> +			linkmode_copy(phydev->supported, PHY_10GBIT_FEATURES);
> +		} else {
> +			u32 bitmask = ETHTOOL_LINK_MODE_2500baseT_Full_BIT;
> +
> +			linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
> +				linkmode_set_bit(bitmask, phydev->supported);
> +		}

Same issue again. Somebody could be using a 10G MAC with a 2.5G PHY.

     Andrew
Parshuram Raju Thombare Feb. 23, 2019, 6:24 a.m. UTC | #2
>>  	if (macb_is_gem(bp)) {
>> -		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
>> -		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>> -
>	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>> -					 phydev->supported);
>> +		if (bp->caps & MACB_CAPS_HIGH_SPEED) {
>> +			linkmode_copy(phydev->supported,
>PHY_10GBIT_FEATURES);
>> +		} else {
>> +			u32 bitmask =
>ETHTOOL_LINK_MODE_2500baseT_Full_BIT;
>> +
>> +			linkmode_copy(phydev->supported,
>PHY_GBIT_FEATURES);
>> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>> +				linkmode_set_bit(bitmask, phydev->supported);
>> +		}
>
>Same issue again. Somebody could be using a 10G MAC with a 2.5G PHY.
>
>     Andrew
Hi Andrew,

Ok, I think this should have been logical AND. I will modify to use phy_set_max_speed() 
instead of directly copying linkmodes.

Regards,
Parshuram Thombare
diff mbox series

Patch

diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 59c23e0..34df014 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -84,6 +84,7 @@ 
 #define GEM_USRIO		0x000c /* User IO */
 #define GEM_DMACFG		0x0010 /* DMA Configuration */
 #define GEM_JML			0x0048 /* Jumbo Max Length */
+#define GEM_HS_MAC_CONFIG	0x0050 /* GEM high speed config */
 #define GEM_HRB			0x0080 /* Hash Bottom */
 #define GEM_HRT			0x0084 /* Hash Top */
 #define GEM_SA1B		0x0088 /* Specific1 Bottom */
@@ -168,6 +169,9 @@ 
 #define GEM_DCFG7		0x0298 /* Design Config 7 */
 #define GEM_DCFG8		0x029C /* Design Config 8 */
 #define GEM_DCFG10		0x02A4 /* Design Config 10 */
+#define GEM_DCFG12		0x02AC /* Design Config 12 */
+#define GEM_USX_CONTROL		0x0A80 /* USXGMII control register */
+#define GEM_USX_STATUS		0x0A88 /* USXGMII status register */
 
 #define GEM_TXBDCTRL	0x04cc /* TX Buffer Descriptor control register */
 #define GEM_RXBDCTRL	0x04d0 /* RX Buffer Descriptor control register */
@@ -275,6 +279,8 @@ 
 #define MACB_IRXFCS_SIZE	1
 
 /* GEM specific NCR bitfields. */
+#define GEM_ENABLE_HS_MAC_OFFSET	31
+#define GEM_ENABLE_HS_MAC_SIZE		1
 #define GEM_TWO_PT_FIVE_GIG_OFFSET	29
 #define GEM_TWO_PT_FIVE_GIG_SIZE	1
 
@@ -463,6 +469,10 @@ 
 #define MACB_REV_OFFSET				0
 #define MACB_REV_SIZE				16
 
+/* Bitfield in HS_MAC_CONFIG */
+#define GEM_HS_MAC_SPEED_OFFSET			0
+#define GEM_HS_MAC_SPEED_SIZE			3
+
 /* Bitfields in DCFG1. */
 #define GEM_IRQCOR_OFFSET			23
 #define GEM_IRQCOR_SIZE				1
@@ -504,6 +514,28 @@ 
 #define GEM_RXBD_RDBUFF_OFFSET			8
 #define GEM_RXBD_RDBUFF_SIZE			4
 
+/* Bitfields in DCFG12. */
+#define GEM_HIGH_SPEED_OFFSET			26
+#define GEM_HIGH_SPEED_SIZE			1
+
+/* Bitfields in USX_CONTROL. */
+#define GEM_USX_CTRL_SPEED_OFFSET		14
+#define GEM_USX_CTRL_SPEED_SIZE			3
+#define GEM_SERDES_RATE_OFFSET			12
+#define GEM_SERDES_RATE_SIZE			2
+#define GEM_TX_EN_OFFSET			1
+#define GEM_TX_EN_SIZE				1
+#define GEM_SIGNAL_OK_OFFSET			0
+#define GEM_SIGNAL_OK_SIZE			1
+
+/* Bitfields in USX_STATUS. */
+#define GEM_USX_TX_FAULT_OFFSET			28
+#define GEM_USX_TX_FAULT_SIZE			1
+#define GEM_USX_RX_FAULT_OFFSET			27
+#define GEM_USX_RX_FAULT_SIZE			1
+#define GEM_USX_BLOCK_LOCK_OFFSET		0
+#define GEM_USX_BLOCK_LOCK_SIZE			1
+
 /* Bitfields in TISUBN */
 #define GEM_SUBNSINCR_OFFSET			0
 #define GEM_SUBNSINCR_SIZE			16
@@ -664,6 +696,7 @@ 
 #define MACB_CAPS_MACB_IS_GEM			0x80000000
 #define MACB_CAPS_PCS				0x01000000
 #define MACB_CAPS_TWO_PT_FIVE_GIG_SPEED		0x02000000
+#define MACB_CAPS_HIGH_SPEED			0x04000000
 
 #define MACB_GEM7010_IDNUM			0x009
 #define MACB_GEM7014_IDNUM			0x107
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 2494abf..0e0acf9 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -79,6 +79,21 @@ 
  */
 #define MACB_HALT_TIMEOUT	1230
 
+enum {
+	HS_MAC_SPEED_100M,
+	HS_MAC_SPEED_1000M,
+	HS_MAC_SPEED_2500M,
+	HS_MAC_SPEED_5000M,
+	HS_MAC_SPEED_10000M,
+	HS_MAC_SPEED_25000M,
+};
+
+enum {
+	MACB_SERDES_RATE_5_PT_15625Gbps,
+	MACB_SERDES_RATE_10_PT_3125Gbps,
+	MACB_SERDES_RATE_25_PT_78125Gbps,
+};
+
 /* DMA buffer descriptor might be different size
  * depends on hardware configuration:
  *
@@ -443,6 +458,20 @@  static void macb_set_tx_clk(struct clk *clk, int speed,
 		default:
 		return;
 		}
+	} else if (interface == PHY_INTERFACE_MODE_USXGMII) {
+		struct macb *bp = netdev_priv(dev);
+		u32 serdes_rate = GEM_BFEXT(SERDES_RATE,
+					    gem_readl(bp, USX_CONTROL));
+		switch (serdes_rate) {
+		case MACB_SERDES_RATE_5_PT_15625Gbps:
+		rate = 78125000;
+		break;
+		case MACB_SERDES_RATE_10_PT_3125Gbps:
+		rate = 156250000;
+		break;
+		default:
+		return;
+		}
 	} else {
 		return;
 	}
@@ -475,7 +504,7 @@  static void macb_handle_link_change(struct net_device *dev)
 
 	if (phydev->link && (bp->speed != phydev->speed ||
 			     bp->duplex != phydev->duplex)) {
-		u32 reg;
+		u32 reg, speed;
 
 		reg = macb_readl(bp, NCFGR);
 		reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
@@ -485,7 +514,53 @@  static void macb_handle_link_change(struct net_device *dev)
 			reg |= MACB_BIT(FD);
 		macb_or_gem_writel(bp, NCFGR, reg);
 
-		if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
+		if ((bp->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+		     bp->phy_interface == PHY_INTERFACE_MODE_XGMII) &&
+			phydev->speed >= SPEED_100) {
+			gem_writel(bp, NCR, gem_readl(bp, NCR) |
+					GEM_BIT(ENABLE_HS_MAC));
+			if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+				/* Setup USXGMII PCS */
+				reg = gem_readl(bp, USX_CONTROL);
+				reg = GEM_BFINS(SERDES_RATE,
+						MACB_SERDES_RATE_5_PT_15625Gbps,
+						reg);
+				gem_writel(bp, USX_CONTROL, reg |
+						GEM_BIT(TX_EN) |
+						GEM_BIT(SIGNAL_OK));
+				while (!GEM_BFEXT(USX_BLOCK_LOCK,
+						  gem_readl(bp, USX_STATUS)))
+					cpu_relax();
+			}
+			switch (phydev->speed) {
+			case SPEED_10000:
+			speed = HS_MAC_SPEED_10000M;
+			break;
+
+			case SPEED_5000:
+			speed = HS_MAC_SPEED_5000M;
+			break;
+
+			case SPEED_2500:
+			speed = HS_MAC_SPEED_2500M;
+			break;
+
+			case SPEED_1000:
+			speed = HS_MAC_SPEED_1000M;
+			break;
+
+			default:
+			case SPEED_100:
+			speed = HS_MAC_SPEED_100M;
+			break;
+			}
+			gem_writel(bp, HS_MAC_CONFIG,
+				   GEM_BFINS(HS_MAC_SPEED, speed,
+					     gem_readl(bp, HS_MAC_CONFIG)));
+			gem_writel(bp, USX_CONTROL,
+				   GEM_BFINS(USX_CTRL_SPEED, speed,
+					     gem_readl(bp, USX_CONTROL)));
+		} else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
 		    (phydev->speed == SPEED_1000 ||
 		     phydev->speed == SPEED_2500)) {
 			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
@@ -627,10 +702,15 @@  static int macb_mii_probe(struct net_device *dev)
 
 	/* mask with MAC supported features */
 	if (macb_is_gem(bp)) {
-		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
-		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
-			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
-					 phydev->supported);
+		if (bp->caps & MACB_CAPS_HIGH_SPEED) {
+			linkmode_copy(phydev->supported, PHY_10GBIT_FEATURES);
+		} else {
+			u32 bitmask = ETHTOOL_LINK_MODE_2500baseT_Full_BIT;
+
+			linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
+			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
+				linkmode_set_bit(bitmask, phydev->supported);
+		}
 	} else {
 		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
 	}
@@ -3344,6 +3424,9 @@  static void macb_configure_caps(struct macb *bp,
 			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
 		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
 			bp->caps |= MACB_CAPS_PCS;
+		dcfg = gem_readl(bp, DCFG12);
+		if (GEM_BFEXT(HIGH_SPEED, dcfg) == 1)
+			bp->caps |= MACB_CAPS_HIGH_SPEED;
 		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
 		case MACB_GEM7016_IDNUM:
 		case MACB_GEM7017_IDNUM:
@@ -4215,6 +4298,21 @@  static int macb_probe(struct platform_device *pdev)
 			bp->phy_interface = PHY_INTERFACE_MODE_MII;
 	} else {
 		switch (err) {
+		case PHY_INTERFACE_MODE_USXGMII:
+		if ((bp->caps & MACB_CAPS_HIGH_SPEED) &&
+		    (bp->caps & MACB_CAPS_PCS)) {
+			bp->phy_interface = PHY_INTERFACE_MODE_USXGMII;
+			break;
+		}
+		/* Fallthrough */
+
+		case PHY_INTERFACE_MODE_XGMII:
+		if (bp->caps & MACB_CAPS_HIGH_SPEED) {
+			bp->phy_interface = PHY_INTERFACE_MODE_XGMII;
+			break;
+		}
+		/* Fallthrough */
+
 		case PHY_INTERFACE_MODE_SGMII:
 		if (bp->caps & MACB_CAPS_PCS) {
 			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 8e9fc57..b627e30 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -94,6 +94,7 @@ 
 	PHY_INTERFACE_MODE_RTBI,
 	PHY_INTERFACE_MODE_SMII,
 	PHY_INTERFACE_MODE_XGMII,
+	PHY_INTERFACE_MODE_USXGMII,
 	PHY_INTERFACE_MODE_MOCA,
 	PHY_INTERFACE_MODE_QSGMII,
 	PHY_INTERFACE_MODE_TRGMII,
@@ -162,6 +163,8 @@  unsigned int phy_supported_speeds(struct phy_device *phy,
 		return "smii";
 	case PHY_INTERFACE_MODE_XGMII:
 		return "xgmii";
+	case PHY_INTERFACE_MODE_USXGMII:
+		return "usxgmii";
 	case PHY_INTERFACE_MODE_MOCA:
 		return "moca";
 	case PHY_INTERFACE_MODE_QSGMII: