Przeglądaj źródła

net: ti: icssg_prueth: Add 10M Full/Half Duplex and 100M Half Duplex

Currently ICSSG PRUETH driver doesn't support following Link types:-
 - 10M Full/Half Duplex
 - 100M Half Duplex
This patch add these link types. Driver also adds the random seed value
in the config structure for firmware use.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Murali Karicheri 6 lat temu
rodzic
commit
612d0d525a

+ 23 - 9
drivers/net/ethernet/ti/icss_mii_rt.h

@@ -98,24 +98,34 @@
 #define RGMII_CFG_GIG_EN_MII1	BIT(21)
 #define RGMII_CFG_FULL_DUPLEX_MII0	BIT(18)
 #define RGMII_CFG_FULL_DUPLEX_MII1	BIT(22)
+#define RGMII_CFG_RGMII0_INBAND	BIT(16)
+#define RGMII_CFG_RGMII1_INBAND	BIT(20)
 
-static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, bool gig_en,
+static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, int speed,
 					  bool full_duplex, int mii)
 {
-	u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0;
+	u32 gig_en_mask, val = 0, full_duplex_mask, inband;
 
 	gig_en_mask = (mii == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 :
 					RGMII_CFG_GIG_EN_MII1;
-	if (gig_en)
-		gig_val = gig_en_mask;
-	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val);
+	inband = (mii == ICSS_MII0) ? RGMII_CFG_RGMII0_INBAND :
+					RGMII_CFG_RGMII1_INBAND;
+	if (speed == SPEED_1000)
+		val = gig_en_mask;
+
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, val);
+
+	val = 0;
+	if (speed != SPEED_1000)
+		val = inband;
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband, val);
 
 	full_duplex_mask = (mii == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 :
 					   RGMII_CFG_FULL_DUPLEX_MII1;
+	val = 0;
 	if (full_duplex)
-		full_duplex_val = full_duplex_mask;
-	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask,
-			   full_duplex_val);
+		val = full_duplex_mask;
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask, val);
 }
 
 static inline void icssg_update_mii_rt_cfg(struct regmap *mii_rt, int speed,
@@ -132,8 +142,12 @@ static inline void icssg_update_mii_rt_cfg(struct regmap *mii_rt, int speed,
 	case SPEED_100:
 		val = MII_RT_TX_IPG_100M;
 		break;
+	case SPEED_10:
+		/* IPG is not available for this speed in this version of
+		 * ICSSG. Firmware use a hardcoded value for 10M link
+		 */
+		return;
 	default:
-		/* Other links speeds not supported */
 		pr_err("Unsupported link speed\n");
 		return;
 	}

+ 4 - 0
drivers/net/ethernet/ti/icssg_config.h

@@ -26,6 +26,10 @@ struct icssg_config {
 	__le32 n_burst;		/* for debug */
 	__le32 rtu_status;	/* RTU status */
 	__le32 info;		/* reserved */
+	__le32 reserve;
+	__le32 rand_seed;	/* Used for the random number
+				 * generation at firmware
+				 */
 } __packed;
 
 #endif /* __NET_TI_ICSSG_CONFIG_H */

+ 16 - 11
drivers/net/ethernet/ti/icssg_prueth.c

@@ -883,6 +883,7 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
 	config->num_tx_threads = 0;
 	config->rx_flow_id = emac->rx_flow_id_base; /* flow id for host port */
 	config->rx_mgr_flow_id = emac->rx_mgm_flow_id_base; /* for mgm ch */
+	config->rand_seed = get_random_int();
 
 	/* set buffer sizes for the pools. 0-7 are not used for dual-emac */
 	for (i = PRUETH_EMAC_BUF_POOL_START;
@@ -937,9 +938,9 @@ static void emac_adjust_link(struct net_device *ndev)
 {
 	struct prueth_emac *emac = netdev_priv(ndev);
 	struct phy_device *phydev = emac->phydev;
-	bool gig_en = false, full_duplex = false;
 	struct prueth *prueth = emac->prueth;
 	int slice = prueth_emac_slice(emac);
+	bool full_duplex = false;
 	bool new_state = false;
 	unsigned long flags;
 
@@ -963,11 +964,7 @@ static void emac_adjust_link(struct net_device *ndev)
 		new_state = true;
 		emac->link = 0;
 		/* defaults for no link */
-
-		/* f/w should support 100 & 1000 */
 		emac->speed = SPEED_1000;
-
-		/* half duplex may not be supported by f/w */
 		emac->duplex = DUPLEX_FULL;
 	}
 
@@ -978,21 +975,29 @@ static void emac_adjust_link(struct net_device *ndev)
 		 * values
 		 */
 		if (emac->link) {
-			if (phydev->speed == SPEED_1000)
-				gig_en = true;
-
 			if (phydev->duplex == DUPLEX_FULL)
 				full_duplex = true;
 
+			if (!full_duplex) {
+				void __iomem *va = prueth->shram.va +
+					slice * ICSSG_CONFIG_OFFSET_SLICE1;
+				struct icssg_config *config =
+					(struct icssg_config *)va;
+				u32 val = get_random_int();
+
+				writel(val, &config->rand_seed);
+			}
+
 			/* Set the RGMII cfg for gig en and full duplex */
-			icssg_update_rgmii_cfg(prueth->miig_rt, gig_en,
+			icssg_update_rgmii_cfg(prueth->miig_rt, emac->speed,
 					       full_duplex, slice);
+
 			/* update the Tx IPG based on 100M/1G speed */
 			icssg_update_mii_rt_cfg(prueth->mii_rt, emac->speed,
 						slice);
 		} else {
-			icssg_update_rgmii_cfg(prueth->miig_rt, true, true,
-					       slice);
+			icssg_update_rgmii_cfg(prueth->miig_rt, emac->speed,
+					       true, slice);
 			icssg_update_mii_rt_cfg(prueth->mii_rt, emac->speed,
 						slice);
 		}