[][openwrt][mt7988][integration][Add basic Filogic 880 SoC support]

[Description]
Add basic filogic 880 SoC support to openwrt 21.02

[Release-log]

Change-Id: I57791df2e9f9f4729cb2d32f734090de52c370f2
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6592143
Build: srv_hbgsm110
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
index 7253042..854a586 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
@@ -7,6 +7,10 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/hrtimer.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
 
 #include "mt753x.h"
 #include "mt753x_regs.h"
@@ -682,6 +686,24 @@
 	return -ENODEV;
 }
 
+static int mt7988_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev)
+{
+	const char *model;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "mediatek,mt7988-switch");
+	if (!np)
+		return -ENODEV;
+
+	of_node_put(np);
+
+	crev->rev = 0;
+	crev->name = "MT7988";
+	gsw->direct_access = true;
+
+	return 0;
+}
+
 static void pinmux_set_mux_7531(struct gsw_mt753x *gsw, u32 pin, u32 mode)
 {
 	u32 val;
@@ -810,7 +832,8 @@
 	u32 val;
 
 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
-		mt7531_phy_100m_eye_diag_setting(gsw, i);
+		if (!gsw->direct_access)
+			mt7531_phy_100m_eye_diag_setting(gsw, i);
 
 		/* Enable HW auto downshift */
 		gsw->mii_write(gsw, i, 0x1f, 0x1);
@@ -834,10 +857,14 @@
 		val |= PHY_LINKDOWN_POWER_SAVING_EN;
 		gsw->mii_write(gsw, i, PHY_EXT_REG_17, val);
 
-		val = gsw->mmd_read(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6);
-		val &= ~PHY_POWER_SAVING_M;
-		val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
-		gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6, val);
+		if (!gsw->direct_access) {
+			val = gsw->mmd_read(gsw, i, PHY_DEV1E,
+					    PHY_DEV1E_REG_0C6);
+			val &= ~PHY_POWER_SAVING_M;
+			val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
+			gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6,
+				       val);
+		}
 
 		/* Timing Recovery for GbE slave mode */
 		mt753x_tr_write(gsw, i, PMA_CH, PMA_NOD, PMA_01, 0x6fb90a);
@@ -952,7 +979,8 @@
 	gsw->mmd_read = mt753x_mmd_read;
 	gsw->mmd_write = mt753x_mmd_write;
 
-	gsw->hw_phy_cal = of_property_read_bool(gsw->dev->of_node, "mediatek,hw_phy_cal");
+	gsw->hw_phy_cal = of_property_read_bool(gsw->dev->of_node,
+						"mediatek,hw_phy_cal");
 
 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
 		val = gsw->mii_read(gsw, i, MII_BMCR);
@@ -966,7 +994,7 @@
 
 	/* Switch soft reset */
 	mt753x_reg_write(gsw, SYS_CTRL, SW_SYS_RST | SW_REG_RST);
-	usleep_range(10, 20);
+	udelay(20);
 
 	/* Enable MDC input Schmitt Trigger */
 	val = mt753x_reg_read(gsw, SMT0_IOLB);
@@ -976,6 +1004,7 @@
 	mt7531_set_gpio_pinmux(gsw);
 
 	mt7531_core_pll_setup(gsw);
+
 	mt7531_mac_port_setup(gsw, 5, &gsw->port5_cfg);
 	mt7531_mac_port_setup(gsw, 6, &gsw->port6_cfg);
 
@@ -999,6 +1028,89 @@
 	return 0;
 }
 
+static int mt7988_sw_init(struct gsw_mt753x *gsw)
+{
+	struct device_node *switch_node = NULL;
+	struct platform_device *pdev;
+	int i;
+	u32 val;
+	u32 pmcr;
+	u32 speed;
+
+	switch_node = of_find_node_by_name(NULL, "switch0");
+	if (switch_node == NULL) {
+		dev_err(&pdev->dev, "switch node invaild\n");
+		return -ENOENT;
+	}
+
+	gsw->base = of_iomap(switch_node, 0);
+	if (IS_ERR(gsw->base)) {
+		dev_err(&pdev->dev, "switch ioremap failed\n");
+		return -EIO;
+	}
+
+	pdev = container_of(gsw->dev, struct platform_device, dev);
+	gsw->sysctrl_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+							"mediatek,sysctrl");
+	if (IS_ERR(gsw->sysctrl_base)) {
+		dev_err(&pdev->dev, "no sysctl regmap found\n");
+		return -ENODEV;
+	}
+
+	/* reset control */
+	regmap_write(gsw->sysctrl_base, ETH_RESET, 0x200);
+	udelay(20);
+	regmap_write(gsw->sysctrl_base, ETH_RESET, 0);
+	udelay(20);
+
+	gsw->phy_base = (gsw->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
+
+	gsw->mii_read = mt753x_mii_read;
+	gsw->mii_write = mt753x_mii_write;
+	gsw->mmd_read = mt753x_mmd_read;
+	gsw->mmd_write = mt753x_mmd_write;
+
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		val = gsw->mii_read(gsw, i, MII_BMCR);
+		val |= BMCR_ISOLATE;
+		gsw->mii_write(gsw, i, MII_BMCR, val);
+	}
+
+	speed = MAC_SPD_1000;
+	pmcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
+		MAC_MODE | MAC_TX_EN | MAC_RX_EN | BKOFF_EN |
+		BACKPR_EN | FORCE_MODE_LNK | FORCE_LINK | FORCE_MODE_SPD |
+		FORCE_MODE_DPX | FORCE_MODE_RX_FC | FORCE_MODE_TX_FC |
+		FORCE_RX_FC | FORCE_TX_FC | (speed << FORCE_SPD_S) | FORCE_DPX;
+
+	mt753x_reg_write(gsw, PMCR(6), pmcr);
+
+	/* Global mac control settings */
+	mt753x_reg_write(gsw, GMACCR,
+			 (15 << MTCC_LMT_S) | (15 << MAX_RX_JUMBO_S) |
+			 RX_PKT_LEN_MAX_JUMBO);
+
+	/* Enable Collision Poll */
+	val = mt753x_reg_read(gsw, CPGC_CTRL);
+	val |= COL_CLK_EN;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+	val |= COL_RST_N;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+	val |= COL_EN;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+
+	/* Disable AFIFO reset for extra short IPG */
+	mt7531_afifo_reset(gsw, 0);
+
+	/* PHY force slave 1G*/
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		gsw->mii_write(gsw, i, MII_CTRL1000, 0x1200);
+		gsw->mii_write(gsw, i, MII_BMCR, 0x140);
+	}
+
+	return 0;
+}
+
 static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
 {
 	int i;
@@ -1016,7 +1128,8 @@
 	val |= POWER_ON_OFF;
 	gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
 
-	mt7531_phy_pll_setup(gsw);
+	if (!gsw->direct_access)
+		mt7531_phy_pll_setup(gsw);
 
 	/* Enable Internal PHYs before phy setting */
 	val = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403);
@@ -1041,7 +1154,14 @@
 	for (i = 0; i < MT753X_NUM_PHYS; i++)
 		gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_141, 0x0);
 
-	mt7531_internal_phy_calibration(gsw);
+	if (!gsw->direct_access)
+		mt7531_internal_phy_calibration(gsw);
+
+	/* PHY force slave disable, restart AN*/
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		gsw->mii_write(gsw, i, MII_CTRL1000, 0x200);
+		gsw->mii_write(gsw, i, MII_BMCR, 0x1240);
+	}
 
 	return 0;
 }
@@ -1053,6 +1173,13 @@
 	.post_init = mt7531_sw_post_init
 };
 
+struct mt753x_sw_id mt7988_id = {
+	.model = MT7988,
+	.detect = mt7988_sw_detect,
+	.init = mt7988_sw_init,
+	.post_init = mt7531_sw_post_init
+};
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Zhanguo Ju <zhanguo.ju@mediatek.com>");
 MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");