[openwrt/openwrt] mediatek: add patch for xsphy driver to support pcie2 on MT7988

LEDE Commits lede-commits at lists.infradead.org
Thu Feb 15 11:35:01 PST 2024


dangole pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/6d76f1c73368e176bad070e489eefe2d1c75bcc4

commit 6d76f1c73368e176bad070e489eefe2d1c75bcc4
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Fri Dec 8 01:04:39 2023 +0000

    mediatek: add patch for xsphy driver to support pcie2 on MT7988
    
    Import patch from MediaTek SDK which allows using the third
    PCIe host controller of the MT7988 SoC.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 ...-mtk-xsphy-support-type-switch-by-pericfg.patch | 167 +++++++++++++++++++++
 1 file changed, 167 insertions(+)

diff --git a/target/linux/mediatek/patches-6.1/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/target/linux/mediatek/patches-6.1/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
new file mode 100644
index 0000000000..a597f70caa
--- /dev/null
+++ b/target/linux/mediatek/patches-6.1/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
@@ -0,0 +1,167 @@
+From 50cefacc6c001eea1d9b1c78ba27304566f304f1 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Fri, 2 Jun 2023 13:06:26 +0800
+Subject: [PATCH] phy: mediatek: xsphy: support type switch by pericfg
+
+Patch from Sam Shih <sam.shih at mediatek.com> found in MediaTek SDK
+released under GPL.
+
+Get syscon and use it to set the PHY type.
+Extend support to PCIe and SGMII mode in addition to USB2 and USB3.
+
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/phy/mediatek/phy-mtk-xsphy.c | 81 +++++++++++++++++++++++++++-
+ 1 file changed, 80 insertions(+), 1 deletion(-)
+
+--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
++++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
+@@ -11,10 +11,12 @@
+ #include <linux/clk.h>
+ #include <linux/delay.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>
+ 
+ #include "phy-mtk-io.h"
+ 
+@@ -81,12 +83,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;
+@@ -259,6 +271,10 @@ static void phy_parse_property(struct mt
+ 			inst->efuse_intr, inst->efuse_tx_imp,
+ 			inst->efuse_rx_imp);
+ 		break;
++	case PHY_TYPE_PCIE:
++	case PHY_TYPE_SGMII:
++		/* nothing to do */
++		break;
+ 	default:
+ 		dev_err(xsphy->dev, "incompatible phy type\n");
+ 		return;
+@@ -305,6 +321,62 @@ static void u3_phy_props_set(struct mtk_
+ 				     RG_XTP_LN0_RX_IMPSEL, inst->efuse_rx_imp);
+ }
+ 
++/* 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);
+@@ -325,6 +397,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);
+@@ -403,12 +479,15 @@ static struct phy *mtk_phy_xlate(struct
+ 
+ 	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;
+ }
+@@ -515,6 +594,10 @@ static int mtk_xsphy_probe(struct platfo
+ 			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);




More information about the lede-commits mailing list