[][kernel][mt7988][eth][Add PHYA reset for HSGMII]

[Description]
Add PHYA reset for HSGMII.

If without this patch, HSGMII might work abnormally
which prevents GMAC from receiving packets.

[Release-log]
N/A


Change-Id: I32e041a0a05dae77220469e3ee448cfad599bc7c
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6889368
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 45b2e24..2f54f96 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
@@ -861,6 +861,16 @@
 #define CO_QPHY_SEL            BIT(0)
 #define GEPHY_MAC_SEL          BIT(1)
 
+/* Toprgu subsystem config registers */
+#define TOPRGU_SWSYSRST		0x18
+#define SWSYSRST_UNLOCK_KEY	GENMASK(31, 24)
+#define SWSYSRST_XFI_PLL_GRST	BIT(16)
+#define SWSYSRST_XFI_PEXPT1_GRST	BIT(15)
+#define SWSYSRST_XFI_PEXPT0_GRST	BIT(14)
+#define SWSYSRST_SGMII1_GRST	BIT(2)
+#define SWSYSRST_SGMII0_GRST	BIT(1)
+#define TOPRGU_SWSYSRST_EN		0xFC
+
 /* Top misc registers */
 #define TOP_MISC_NETSYS_PCS_MUX	0x84
 #define NETSYS_PCS_MUX_MASK	GENMASK(1, 0)
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 64a6353..ac77ef2 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -37,6 +37,79 @@
 	return 0;
 }
 
+void mtk_sgmii_reset(struct mtk_xgmii *ss, int mac_id)
+{
+	struct mtk_eth *eth = ss->eth;
+	u32 id = mtk_mac2xgmii_id(eth, mac_id);
+	u32 val = 0;
+
+	if (id >= MTK_MAX_DEVS || !eth->toprgu)
+		return;
+
+	switch (mac_id) {
+	case MTK_GMAC2_ID:
+		/* Enable software reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
+		val |= SWSYSRST_XFI_PEXPT1_GRST |
+		       SWSYSRST_SGMII1_GRST;
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
+
+		/* Assert SGMII reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
+		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
+		       SWSYSRST_XFI_PEXPT1_GRST |
+		       SWSYSRST_SGMII1_GRST;
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
+
+		udelay(100);
+
+		/* De-assert SGMII reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
+		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
+		val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
+			 SWSYSRST_SGMII1_GRST);
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
+
+		/* Disable software reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
+		val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
+			 SWSYSRST_SGMII1_GRST);
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
+		break;
+	case MTK_GMAC3_ID:
+		/* Enable Software reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
+		val |= SWSYSRST_XFI_PEXPT0_GRST |
+		       SWSYSRST_SGMII0_GRST;
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
+
+		/* Assert SGMII reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
+		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
+		       SWSYSRST_XFI_PEXPT0_GRST |
+		       SWSYSRST_SGMII0_GRST;
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
+
+		udelay(100);
+
+		/* De-assert SGMII reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
+		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
+		val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
+			 SWSYSRST_SGMII0_GRST);
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
+
+		/* Disable software reset */
+		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
+		val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
+			 SWSYSRST_SGMII0_GRST);
+		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
+		break;
+	}
+
+	mdelay(1);
+}
+
 void mtk_sgmii_setup_phya_gen1(struct mtk_xgmii *ss, int mac_id)
 {
 	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
@@ -167,8 +240,10 @@
 	if (!ss->regmap_sgmii[id])
 		return -EINVAL;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		mtk_xfi_pll_enable(ss);
+		mtk_sgmii_reset(ss, mac_id);
+	}
 
 	/* Assert PHYA power down state */
 	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
@@ -222,8 +297,10 @@
 	if (!ss->regmap_sgmii[id])
 		return -EINVAL;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		mtk_xfi_pll_enable(ss);
+		mtk_sgmii_reset(ss, mac_id);
+	}
 
 	/* Assert PHYA power down state */
 	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);