[][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/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/target/linux/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
new file mode 100644
index 0000000..c20e930
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
@@ -0,0 +1,142 @@
+diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
+index 8c51131..e77092c 100644
+--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
++++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
+@@ -12,10 +12,12 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ 
+ /* u2 phy banks */
+ #define SSUSB_SIFSLV_MISC		0x000
+@@ -88,12 +90,22 @@
+ #define XSP_SR_COEF_DIVISOR	1000
+ #define XSP_FM_DET_CYCLE_CNT	1024
+ 
++/* PHY switch between pcie/usb3/sgmii */
++#define USB_PHY_SWITCH_CTRL	0x0
++#define RG_PHY_SW_TYPE		GENMASK(3, 0)
++#define RG_PHY_SW_PCIE		0x0
++#define RG_PHY_SW_USB3		0x1
++#define RG_PHY_SW_SGMII		0x2
++
+ struct xsphy_instance {
+ 	struct phy *phy;
+ 	void __iomem *port_base;
+ 	struct clk *ref_clk;	/* reference clock of anolog phy */
+ 	u32 index;
+ 	u32 type;
++	struct regmap *type_sw;
++	u32 type_sw_reg;
++	u32 type_sw_index;
+ 	/* only for HQA test */
+ 	int efuse_intr;
+ 	int efuse_tx_imp;
+@@ -365,6 +377,62 @@ static void u3_phy_props_set(struct mtk_xsphy *xsphy,
+ 	}
+ }
+ 
++/* type switch for usb3/pcie/sgmii */
++static int phy_type_syscon_get(struct xsphy_instance *instance,
++			       struct device_node *dn)
++{
++	struct of_phandle_args args;
++	int ret;
++
++	/* type switch function is optional */
++	if (!of_property_read_bool(dn, "mediatek,syscon-type"))
++		return 0;
++
++	ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
++					       2, 0, &args);
++	if (ret)
++		return ret;
++
++	instance->type_sw_reg = args.args[0];
++	instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
++	instance->type_sw = syscon_node_to_regmap(args.np);
++	of_node_put(args.np);
++	dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
++		 instance->type_sw_reg, instance->type_sw_index);
++
++	return PTR_ERR_OR_ZERO(instance->type_sw);
++}
++
++static int phy_type_set(struct xsphy_instance *instance)
++{
++	int type;
++	u32 offset;
++
++	if (!instance->type_sw)
++		return 0;
++
++	switch (instance->type) {
++	case PHY_TYPE_USB3:
++		type = RG_PHY_SW_USB3;
++		break;
++	case PHY_TYPE_PCIE:
++		type = RG_PHY_SW_PCIE;
++		break;
++	case PHY_TYPE_SGMII:
++		type = RG_PHY_SW_SGMII;
++		break;
++	case PHY_TYPE_USB2:
++	default:
++		return 0;
++	}
++
++	offset = instance->type_sw_index * BITS_PER_BYTE;
++	regmap_update_bits(instance->type_sw, instance->type_sw_reg,
++			   RG_PHY_SW_TYPE << offset, type << offset);
++
++	return 0;
++}
++
+ static int mtk_phy_init(struct phy *phy)
+ {
+ 	struct xsphy_instance *inst = phy_get_drvdata(phy);
+@@ -385,6 +453,10 @@ static int mtk_phy_init(struct phy *phy)
+ 	case PHY_TYPE_USB3:
+ 		u3_phy_props_set(xsphy, inst);
+ 		break;
++	case PHY_TYPE_PCIE:
++	case PHY_TYPE_SGMII:
++		/* nothing to do, only used to set type */
++		break;
+ 	default:
+ 		dev_err(xsphy->dev, "incompatible phy type\n");
+ 		clk_disable_unprepare(inst->ref_clk);
+@@ -463,12 +535,15 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+ 
+ 	inst->type = args->args[0];
+ 	if (!(inst->type == PHY_TYPE_USB2 ||
+-	      inst->type == PHY_TYPE_USB3)) {
++	      inst->type == PHY_TYPE_USB3 ||
++	      inst->type == PHY_TYPE_PCIE ||
++	      inst->type == PHY_TYPE_SGMII)) {
+ 		dev_err(dev, "unsupported phy type: %d\n", inst->type);
+ 		return ERR_PTR(-EINVAL);
+ 	}
+ 
+ 	phy_parse_property(xsphy, inst);
++	phy_type_set(inst);
+ 
+ 	return inst->phy;
+ }
+@@ -575,6 +650,10 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
+ 			retval = PTR_ERR(inst->ref_clk);
+ 			goto put_child;
+ 		}
++
++		retval = phy_type_syscon_get(inst, child_np);
++		if (retval)
++			goto put_child;
+ 	}
+ 
+ 	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);