blob: 032ef3540b20965dcd4edd5ce8e8181ff15f6a8d [file] [log] [blame]
developer8cdcb262022-10-27 14:36:15 +08001From 34687407776d46f08926b91f118adc484c4ac231 Mon Sep 17 00:00:00 2001
developerc66d4ac2021-09-17 16:27:09 +08002From: Zhanyong Wang <zhanyong.wang@mediatek.com>
3Date: Fri, 17 Sep 2021 15:56:53 +0800
developer8cdcb262022-10-27 14:36:15 +08004Subject: [PATCH 1/8] phy: phy-mtk-tphy: support type switch by pericfg
developerc66d4ac2021-09-17 16:27:09 +08005
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---
developer8cdcb262022-10-27 14:36:15 +080014 drivers/phy/mediatek/phy-mtk-tphy.c | 83 ++++++++++++++++++++++++++++-
15 1 file changed, 81 insertions(+), 2 deletions(-)
developerc66d4ac2021-09-17 16:27:09 +080016
17diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
developer8cdcb262022-10-27 14:36:15 +080018index cb2ed3b25068..a59fe65f69e5 100644
developerc66d4ac2021-09-17 16:27:09 +080019--- a/drivers/phy/mediatek/phy-mtk-tphy.c
20+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
developer8cdcb262022-10-27 14:36:15 +080021@@ -10,6 +10,7 @@
developerc66d4ac2021-09-17 16:27:09 +080022 #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>
developer8cdcb262022-10-27 14:36:15 +080029@@ -263,6 +264,14 @@
30 #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
31 #define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
developerc66d4ac2021-09-17 16:27:09 +080032
33+/* PHY switch between pcie/usb3/sgmii/sata */
34+#define USB_PHY_SWITCH_CTRL 0x0
35+#define RG_PHY_SW_TYPE GENMASK(3, 0)
36+#define RG_PHY_SW_PCIE 0x0
37+#define RG_PHY_SW_USB3 0x1
38+#define RG_PHY_SW_SGMII 0x2
39+#define RG_PHY_SW_SATA 0x3
40+
41 enum mtk_phy_version {
42 MTK_PHY_V1 = 1,
43 MTK_PHY_V2,
developer8cdcb262022-10-27 14:36:15 +080044@@ -296,7 +305,10 @@ struct mtk_phy_instance {
developerc66d4ac2021-09-17 16:27:09 +080045 };
46 struct clk *ref_clk; /* reference clock of anolog phy */
47 u32 index;
48- u8 type;
49+ u32 type;
50+ struct regmap *type_sw;
51+ u32 type_sw_reg;
52+ u32 type_sw_index;
53 int eye_src;
54 int eye_vrt;
55 int eye_term;
developer8cdcb262022-10-27 14:36:15 +080056@@ -890,6 +902,64 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
developerc66d4ac2021-09-17 16:27:09 +080057 }
58 }
59
60+/* type switch for usb3/pcie/sgmii/sata */
61+static int phy_type_syscon_get(struct mtk_phy_instance *instance,
62+ struct device_node *dn)
63+{
64+ struct of_phandle_args args;
65+ int ret;
66+
67+ /* type switch function is optional */
68+ if (!of_property_read_bool(dn, "mediatek,syscon-type"))
69+ return 0;
70+
71+ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
72+ 2, 0, &args);
73+ if (ret)
74+ return ret;
75+
76+ instance->type_sw_reg = args.args[0];
77+ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
78+ instance->type_sw = syscon_node_to_regmap(args.np);
79+ of_node_put(args.np);
80+ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
81+ instance->type_sw_reg, instance->type_sw_index);
82+
83+ return PTR_ERR_OR_ZERO(instance->type_sw);
84+}
85+
86+static int phy_type_set(struct mtk_phy_instance *instance)
87+{
88+ int type;
89+ u32 mask;
90+
91+ if (!instance->type_sw)
92+ return 0;
93+
94+ switch (instance->type) {
95+ case PHY_TYPE_USB3:
96+ type = RG_PHY_SW_USB3;
97+ break;
98+ case PHY_TYPE_PCIE:
99+ type = RG_PHY_SW_PCIE;
100+ break;
101+ case PHY_TYPE_SGMII:
102+ type = RG_PHY_SW_SGMII;
103+ break;
104+ case PHY_TYPE_SATA:
105+ type = RG_PHY_SW_SATA;
106+ break;
107+ case PHY_TYPE_USB2:
108+ default:
109+ return 0;
110+ }
111+
112+ mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE);
113+ regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type);
114+
115+ return 0;
116+}
117+
118 static int mtk_phy_init(struct phy *phy)
119 {
120 struct mtk_phy_instance *instance = phy_get_drvdata(phy);
developer8cdcb262022-10-27 14:36:15 +0800121@@ -922,6 +992,9 @@ static int mtk_phy_init(struct phy *phy)
developerc66d4ac2021-09-17 16:27:09 +0800122 case PHY_TYPE_SATA:
123 sata_phy_instance_init(tphy, instance);
124 break;
125+ case PHY_TYPE_SGMII:
126+ /* nothing to do, only used to set type */
127+ break;
128 default:
129 dev_err(tphy->dev, "incompatible PHY type\n");
130 return -EINVAL;
developer8cdcb262022-10-27 14:36:15 +0800131@@ -1010,7 +1083,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
developerc66d4ac2021-09-17 16:27:09 +0800132 if (!(instance->type == PHY_TYPE_USB2 ||
133 instance->type == PHY_TYPE_USB3 ||
134 instance->type == PHY_TYPE_PCIE ||
135- instance->type == PHY_TYPE_SATA)) {
136+ instance->type == PHY_TYPE_SATA ||
137+ instance->type == PHY_TYPE_SGMII)) {
138 dev_err(dev, "unsupported device type: %d\n", instance->type);
139 return ERR_PTR(-EINVAL);
140 }
developer8cdcb262022-10-27 14:36:15 +0800141@@ -1025,6 +1099,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
developerc66d4ac2021-09-17 16:27:09 +0800142 }
143
144 phy_parse_property(tphy, instance);
145+ phy_type_set(instance);
146
147 return instance->phy;
148 }
developer8cdcb262022-10-27 14:36:15 +0800149@@ -1163,6 +1238,10 @@ static int mtk_tphy_probe(struct platform_device *pdev)
developerc66d4ac2021-09-17 16:27:09 +0800150 retval = PTR_ERR(instance->ref_clk);
151 goto put_child;
152 }
153+
154+ retval = phy_type_syscon_get(instance, child_np);
155+ if (retval)
156+ goto put_child;
157 }
158
159 provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
160--
1612.18.0
162