From b65bb47eba7d51bd1fbb696ab22f0febcb0b2144 Mon Sep 17 00:00:00 2001
From: Grygorii Strashko <grygorii.strashko@ti.com>
Date: Tue, 12 Oct 2021 13:54:43 +0300
Subject: [PATCH] net: ethernet: icssg-prueth: sr2.0: add support for half
 duplex operation

This patch adds support for half duplex operation at 10M and 100M link
speeds for AM654x ICSS-G SR2.0 devices.
- Driver configures rand_seed, a random number, in DMEM HD_RAND_SEED_OFFSET
field, which will be used by firmware for Back off time calculation.
- Driver informs FW about half duplex link operation in DMEM
PORT_LINK_SPEED_OFFSET field by setting bit 7 for 10/100M HD.

Hence, the half duplex operation depends on board design the
"ti,half-duplex-capable" property has to be enabled for ICSS-G ports if HW
is capable to perform half duplex.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/net/ethernet/ti/icssg_config.c     | 30 ++++++++++++++++++++++
 drivers/net/ethernet/ti/icssg_prueth.c     | 11 +-------
 drivers/net/ethernet/ti/icssg_prueth.h     |  2 ++
 drivers/net/ethernet/ti/icssg_switch_map.h |  3 +++
 4 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg_config.c b/drivers/net/ethernet/ti/icssg_config.c
index 905c743e8e11..50acf4e31008 100644
--- a/drivers/net/ethernet/ti/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg_config.c
@@ -420,6 +420,9 @@ void icssg_config_set_speed(struct prueth_emac *emac)
 {
 	u8 fw_speed;
 
+	if (emac->is_sr1)
+		return;
+
 	switch (emac->speed) {
 	case SPEED_1000:
 		fw_speed = FW_LINK_SPEED_1G;
@@ -436,5 +439,32 @@ void icssg_config_set_speed(struct prueth_emac *emac)
 		return;
 	}
 
+	if (emac->duplex == DUPLEX_HALF)
+		fw_speed |= FW_LINK_SPEED_HD;
+
 	writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET);
 }
+
+static void icssg_config_half_duplex_sr1(struct prueth_emac *emac)
+{
+	int slice = prueth_emac_slice(emac);
+	struct icssg_config_sr1 *config;
+	u32 val = get_random_int();
+	void __iomem *va;
+
+	va = emac->prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
+	config = (struct icssg_config_sr1 *)va;
+
+	writel(val, &config->rand_seed);
+}
+
+void icssg_config_half_duplex(struct prueth_emac *emac)
+{
+	u32 val;
+
+	if (emac->is_sr1)
+		icssg_config_half_duplex_sr1(emac);
+
+	val = get_random_int();
+	writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+}
diff --git a/drivers/net/ethernet/ti/icssg_prueth.c b/drivers/net/ethernet/ti/icssg_prueth.c
index 635eec1fd6ee..e33aafc9e029 100644
--- a/drivers/net/ethernet/ti/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg_prueth.c
@@ -1232,15 +1232,6 @@ static void prueth_emac_stop(struct prueth_emac *emac)
 	rproc_shutdown(prueth->pru[slice]);
 }
 
-static void icssg_config_half_duplex(struct prueth *prueth, int slice)
-{
-	void __iomem *va = prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
-	struct icssg_config_sr1 *config = (struct icssg_config_sr1 *)va;
-	u32 val = get_random_int();
-
-	writel(val, &config->rand_seed);
-}
-
 /* called back by PHY layer if there is change in link state of hw port*/
 static void emac_adjust_link(struct net_device *ndev)
 {
@@ -1285,7 +1276,7 @@ static void emac_adjust_link(struct net_device *ndev)
 		 */
 		if (emac->link) {
 			if (emac->duplex == DUPLEX_HALF)
-				icssg_config_half_duplex(prueth, prueth_emac_slice(emac));
+				icssg_config_half_duplex(emac);
 			/* Set the RGMII cfg for gig en and full duplex */
 			icssg_update_rgmii_cfg(prueth->miig_rt, emac->speed,
 					       emac->duplex, slice);
diff --git a/drivers/net/ethernet/ti/icssg_prueth.h b/drivers/net/ethernet/ti/icssg_prueth.h
index 917c6f9a2514..0ff9e9680b57 100644
--- a/drivers/net/ethernet/ti/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg_prueth.h
@@ -282,6 +282,8 @@ int icssg_config_sr2(struct prueth *prueth, struct prueth_emac *emac,
 int emac_set_port_state(struct prueth_emac *emac,
 			enum icssg_port_state_cmd state);
 void icssg_config_set_speed(struct prueth_emac *emac);
+void icssg_config_half_duplex(struct prueth_emac *emac);
+
 #define prueth_napi_to_tx_chn(pnapi) \
 	container_of(pnapi, struct prueth_tx_chn, napi_tx)
 
diff --git a/drivers/net/ethernet/ti/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg_switch_map.h
index 644a22b53424..99225d0f1582 100644
--- a/drivers/net/ethernet/ti/icssg_switch_map.h
+++ b/drivers/net/ethernet/ti/icssg_switch_map.h
@@ -16,6 +16,7 @@
 #define FW_LINK_SPEED_1G                           (0x00)
 #define FW_LINK_SPEED_100M                         (0x01)
 #define FW_LINK_SPEED_10M                          (0x02)
+#define FW_LINK_SPEED_HD                           (0x80)
 
 /*Time after which FDB entries are checked for aged out values. Value in nanoseconds*/
 #define FDB_AGEING_TIMEOUT_OFFSET                          0x0014
@@ -154,6 +155,8 @@
 #define HOST_RX_Q_PRE_CONTEXT_OFFSET                       0x0684
 /*Buffer for 8 FDB entries to be added by 'Add Multiple FDB entries IOCTL*/
 #define FDB_CMD_BUFFER                                     0x0894
+/*Used by FW to generate random number with the SEED value*/
+#define HD_RAND_SEED_OFFSET                                0x0934
 
 /* Memory Usage of : DMEM1
  *
