blob: 4ae49913d27c49018fac05aa0e6f78a94e36ec76 [file] [log] [blame]
developerc66d4ac2021-09-17 16:27:09 +08001From ddeda571f3d79dcccef6541b6413cb184de40afd Mon Sep 17 00:00:00 2001
2From: Zhanyong Wang <zhanyong.wang@mediatek.com>
3Date: Fri, 17 Sep 2021 15:56:53 +0800
4Subject: [PATCH] phy: phy-mtk-tphy: support type switch by pericfg
5
6Add support type switch between USB3, PCIe, SATA and SGMII by
7pericfg register, this is used to take the place of efuse or
8jumper.
9
10Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
11Signed-off-by: Vinod Koul <vkoul@kernel.org>
12Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
13---
14 drivers/phy/mediatek/phy-mtk-tphy.c | 84 +++++++++++++++++++++++++++--
15 1 file changed, 81 insertions(+), 3 deletions(-)
16
17diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
18index d1ecf088032b..759e1c0c370a 100644
19--- a/drivers/phy/mediatek/phy-mtk-tphy.c
20+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
21@@ -10,12 +10,12 @@
22 #include <linux/delay.h>
23 #include <linux/io.h>
24 #include <linux/iopoll.h>
25+#include <linux/mfd/syscon.h>
26 #include <linux/module.h>
27 #include <linux/of_address.h>
28 #include <linux/of_device.h>
29 #include <linux/phy/phy.h>
30 #include <linux/platform_device.h>
31-#include <linux/mfd/syscon.h>
32 #include <linux/regmap.h>
33
34 /* version V1 sub-banks offset base address */
35@@ -268,6 +268,14 @@
36 #define HIF_SYSCFG1 0x14
37 #define HIF_SYSCFG1_PHY2_MASK (0x3 << 20)
38
39+/* PHY switch between pcie/usb3/sgmii/sata */
40+#define USB_PHY_SWITCH_CTRL 0x0
41+#define RG_PHY_SW_TYPE GENMASK(3, 0)
42+#define RG_PHY_SW_PCIE 0x0
43+#define RG_PHY_SW_USB3 0x1
44+#define RG_PHY_SW_SGMII 0x2
45+#define RG_PHY_SW_SATA 0x3
46+
47 enum mtk_phy_version {
48 MTK_PHY_V1 = 1,
49 MTK_PHY_V2,
50@@ -301,7 +309,10 @@ struct mtk_phy_instance {
51 };
52 struct clk *ref_clk; /* reference clock of anolog phy */
53 u32 index;
54- u8 type;
55+ u32 type;
56+ struct regmap *type_sw;
57+ u32 type_sw_reg;
58+ u32 type_sw_index;
59 int eye_src;
60 int eye_vrt;
61 int eye_term;
62@@ -900,6 +911,64 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
63 }
64 }
65
66+/* type switch for usb3/pcie/sgmii/sata */
67+static int phy_type_syscon_get(struct mtk_phy_instance *instance,
68+ struct device_node *dn)
69+{
70+ struct of_phandle_args args;
71+ int ret;
72+
73+ /* type switch function is optional */
74+ if (!of_property_read_bool(dn, "mediatek,syscon-type"))
75+ return 0;
76+
77+ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
78+ 2, 0, &args);
79+ if (ret)
80+ return ret;
81+
82+ instance->type_sw_reg = args.args[0];
83+ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
84+ instance->type_sw = syscon_node_to_regmap(args.np);
85+ of_node_put(args.np);
86+ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
87+ instance->type_sw_reg, instance->type_sw_index);
88+
89+ return PTR_ERR_OR_ZERO(instance->type_sw);
90+}
91+
92+static int phy_type_set(struct mtk_phy_instance *instance)
93+{
94+ int type;
95+ u32 mask;
96+
97+ if (!instance->type_sw)
98+ return 0;
99+
100+ switch (instance->type) {
101+ case PHY_TYPE_USB3:
102+ type = RG_PHY_SW_USB3;
103+ break;
104+ case PHY_TYPE_PCIE:
105+ type = RG_PHY_SW_PCIE;
106+ break;
107+ case PHY_TYPE_SGMII:
108+ type = RG_PHY_SW_SGMII;
109+ break;
110+ case PHY_TYPE_SATA:
111+ type = RG_PHY_SW_SATA;
112+ break;
113+ case PHY_TYPE_USB2:
114+ default:
115+ return 0;
116+ }
117+
118+ mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE);
119+ regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type);
120+
121+ return 0;
122+}
123+
124 static int mtk_phy_init(struct phy *phy)
125 {
126 struct mtk_phy_instance *instance = phy_get_drvdata(phy);
127@@ -932,6 +1001,9 @@ static int mtk_phy_init(struct phy *phy)
128 case PHY_TYPE_SATA:
129 sata_phy_instance_init(tphy, instance);
130 break;
131+ case PHY_TYPE_SGMII:
132+ /* nothing to do, only used to set type */
133+ break;
134 default:
135 dev_err(tphy->dev, "incompatible PHY type\n");
136 return -EINVAL;
137@@ -1020,7 +1092,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
138 if (!(instance->type == PHY_TYPE_USB2 ||
139 instance->type == PHY_TYPE_USB3 ||
140 instance->type == PHY_TYPE_PCIE ||
141- instance->type == PHY_TYPE_SATA)) {
142+ instance->type == PHY_TYPE_SATA ||
143+ instance->type == PHY_TYPE_SGMII)) {
144 dev_err(dev, "unsupported device type: %d\n", instance->type);
145 return ERR_PTR(-EINVAL);
146 }
147@@ -1035,6 +1108,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
148 }
149
150 phy_parse_property(tphy, instance);
151+ phy_type_set(instance);
152
153 return instance->phy;
154 }
155@@ -1183,6 +1257,10 @@ static int mtk_tphy_probe(struct platform_device *pdev)
156 retval = PTR_ERR(instance->ref_clk);
157 goto put_child;
158 }
159+
160+ retval = phy_type_syscon_get(instance, child_np);
161+ if (retval)
162+ goto put_child;
163 }
164
165 provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
166--
1672.18.0
168