[][kernel][mt7988][eth][Change XGAMC force-link control flow and add XGMAC reset flow]

[Description]
Change XGAMC force-link control flow and add XGMAC reset flow.

After PHY link-down or link-up event,
it will cause noise interference to XGMAC.

These noises will cause XFI counter error.
If the noise is like start-of-frame signal,
it will make XGMAC enter the wrong finite-state.
XGMAC will start to wait for the end-of-frame
but the data buffer is filled with other noises.
When the first packet is receive,
only the end-of-frame signal is preserved,
so the data of the first packet will be lost.


Therefore, we will reset XGMAC after PHY link-up event
and clear all XFI counter values after the reset.
Changing XGMAC force-link flow is to
protect XGDM from being affected when XGMAC resets.

Without this patch, the first packet will be randomly lost after link-up
and the wrong XFI count values will appear.

[Release-log]
N/A


Change-Id: I669d4d6a25fae718966840233bcff9915d25919e
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7784606
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 0c94e93..353b656 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -586,7 +586,7 @@
 					   phylink_config);
 	struct mtk_eth *eth = mac->hw;
 	u32 sid, i;
-	int val = 0, ge_mode, force_link, err = 0;
+	int val = 0, ge_mode, err = 0;
 	unsigned int mac_type = mac->type;
 
 	/* MT76x8 has no hardware settings between for the MAC */
@@ -747,43 +747,14 @@
 		mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
 
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
-			switch (mac->id) {
-			case MTK_GMAC1_ID:
+			if (mac->id == MTK_GMAC1_ID)
 				mtk_setup_bridge_switch(eth);
-				break;
-			case MTK_GMAC2_ID:
-				force_link = (mac->interface ==
-					      PHY_INTERFACE_MODE_XGMII) ?
-					      MTK_XGMAC_FORCE_LINK(mac->id) : 0;
-				val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
-				mtk_w32(eth, val | force_link,
-					MTK_XGMAC_STS(mac->id));
-				break;
-			case MTK_GMAC3_ID:
-				val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
-				mtk_w32(eth,
-					val | MTK_XGMAC_FORCE_LINK(mac->id),
-					MTK_XGMAC_STS(mac->id));
-				break;
-			}
 		}
 	} else if (mac->type == MTK_GDM_TYPE) {
 		val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac->id));
 		mtk_w32(eth, val & ~MTK_GDMA_XGDM_SEL,
 			MTK_GDMA_EG_CTRL(mac->id));
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
-			switch (mac->id) {
-			case MTK_GMAC2_ID:
-			case MTK_GMAC3_ID:
-				val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
-				mtk_w32(eth,
-					val & ~MTK_XGMAC_FORCE_LINK(mac->id),
-					MTK_XGMAC_STS(mac->id));
-				break;
-			}
-		}
-
 		/* FIXME: In current hardware design, we have to reset FE
 		 * when swtiching XGDM to GDM. Therefore, here trigger an SER
 		 * to let GDM go back to the initial state.
@@ -915,7 +886,7 @@
 {
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
-	u32 mcr;
+	u32 mcr, sts;
 
 	if (mac->type == MTK_GDM_TYPE) {
 		mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
@@ -927,6 +898,10 @@
 		mcr &= 0xfffffff0;
 		mcr |= XMAC_MCR_TRX_DISABLE;
 		mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+
+		sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+		sts &= ~MTK_XGMAC_FORCE_LINK(mac->id);
+		mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
 	}
 }
 
@@ -936,7 +911,7 @@
 {
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
-	u32 mcr, mcr_cur;
+	u32 mcr, mcr_cur, sts, force_link;
 
 	mac->speed = speed;
 
@@ -981,6 +956,28 @@
 		if (mode == MLO_AN_PHY && phy)
 			mtk_setup_eee(mac, phy_init_eee(phy, false) >= 0);
 	} else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+		/* Eliminate the interference(before link-up) caused by PHY noise */
+		mtk_m32(mac->hw, XMAC_LOGIC_RST, 0x0, MTK_XMAC_LOGIC_RST(mac->id));
+		mdelay(20);
+		mtk_m32(mac->hw, XMAC_GLB_CNTCLR, 0x1, MTK_XMAC_CNT_CTRL(mac->id));
+
+		switch (mac->id) {
+		case MTK_GMAC2_ID:
+			force_link = (mac->interface ==
+				      PHY_INTERFACE_MODE_XGMII) ?
+				      MTK_XGMAC_FORCE_LINK(mac->id) : 0;
+			sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+			mtk_w32(mac->hw, sts | force_link,
+				MTK_XGMAC_STS(mac->id));
+			break;
+		case MTK_GMAC3_ID:
+			sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+			mtk_w32(mac->hw,
+				sts | MTK_XGMAC_FORCE_LINK(mac->id),
+				MTK_XGMAC_STS(mac->id));
+			break;
+		}
+
 		mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
 
 		mcr &= ~(XMAC_MCR_FORCE_TX_FC |	XMAC_MCR_FORCE_RX_FC);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index fd328e5..57bf7b1 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -699,11 +699,20 @@
 #define MAC_MCR_FORCE_LINK_DOWN	(MAC_MCR_FORCE_MODE)
 
 /* XFI Mac control registers */
-#define MTK_XMAC_MCR(x)		(0x12000 + ((x - 1) * 0x1000))
+#define MTK_XMAC_BASE(x)	(0x12000 + ((x - 1) * 0x1000))
+#define MTK_XMAC_MCR(x)		(MTK_XMAC_BASE(x))
 #define XMAC_MCR_TRX_DISABLE	0xf
 #define XMAC_MCR_FORCE_TX_FC	BIT(5)
 #define XMAC_MCR_FORCE_RX_FC	BIT(4)
 
+/* XFI Mac logic reset registers */
+#define MTK_XMAC_LOGIC_RST(x)	(MTK_XMAC_BASE(x) + 0x10)
+#define XMAC_LOGIC_RST		BIT(0)
+
+/* XFI Mac count global control */
+#define MTK_XMAC_CNT_CTRL(x)	(MTK_XMAC_BASE(x) + 0x100)
+#define XMAC_GLB_CNTCLR		BIT(0)
+
 /* Mac EEE control registers */
 #define MTK_MAC_EEE(x)		(0x10104 + (x * 0x100))
 #define MAC_EEE_WAKEUP_TIME_1000	GENMASK(31, 24)