blob: fcd38acb6924c4e94344fbb401934f8243813814 [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 50cefacc6c001eea1d9b1c78ba27304566f304f1 Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:26 +0800
4Subject: [PATCH]
5 [high-speed-io][999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch]
6
7---
8 drivers/phy/mediatek/phy-mtk-xsphy.c | 81 +++++++++++++++++++++++++++-
9 1 file changed, 80 insertions(+), 1 deletion(-)
10
developer2cdaeb12022-10-04 20:25:05 +080011diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
developer5d148cb2023-06-02 13:08:11 +080012index 8c5113194..e77092c3e 100644
developer2cdaeb12022-10-04 20:25:05 +080013--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
14+++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
15@@ -12,10 +12,12 @@
16 #include <linux/delay.h>
17 #include <linux/io.h>
18 #include <linux/iopoll.h>
19+#include <linux/mfd/syscon.h>
20 #include <linux/module.h>
21 #include <linux/of_address.h>
22 #include <linux/phy/phy.h>
23 #include <linux/platform_device.h>
24+#include <linux/regmap.h>
25
26 /* u2 phy banks */
27 #define SSUSB_SIFSLV_MISC 0x000
28@@ -88,12 +90,22 @@
29 #define XSP_SR_COEF_DIVISOR 1000
30 #define XSP_FM_DET_CYCLE_CNT 1024
31
32+/* PHY switch between pcie/usb3/sgmii */
33+#define USB_PHY_SWITCH_CTRL 0x0
34+#define RG_PHY_SW_TYPE GENMASK(3, 0)
35+#define RG_PHY_SW_PCIE 0x0
36+#define RG_PHY_SW_USB3 0x1
37+#define RG_PHY_SW_SGMII 0x2
38+
39 struct xsphy_instance {
40 struct phy *phy;
41 void __iomem *port_base;
42 struct clk *ref_clk; /* reference clock of anolog phy */
43 u32 index;
44 u32 type;
45+ struct regmap *type_sw;
46+ u32 type_sw_reg;
47+ u32 type_sw_index;
48 /* only for HQA test */
49 int efuse_intr;
50 int efuse_tx_imp;
51@@ -365,6 +377,62 @@ static void u3_phy_props_set(struct mtk_xsphy *xsphy,
52 }
53 }
54
55+/* type switch for usb3/pcie/sgmii */
56+static int phy_type_syscon_get(struct xsphy_instance *instance,
57+ struct device_node *dn)
58+{
59+ struct of_phandle_args args;
60+ int ret;
61+
62+ /* type switch function is optional */
63+ if (!of_property_read_bool(dn, "mediatek,syscon-type"))
64+ return 0;
65+
66+ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
67+ 2, 0, &args);
68+ if (ret)
69+ return ret;
70+
71+ instance->type_sw_reg = args.args[0];
72+ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
73+ instance->type_sw = syscon_node_to_regmap(args.np);
74+ of_node_put(args.np);
75+ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
76+ instance->type_sw_reg, instance->type_sw_index);
77+
78+ return PTR_ERR_OR_ZERO(instance->type_sw);
79+}
80+
81+static int phy_type_set(struct xsphy_instance *instance)
82+{
83+ int type;
84+ u32 offset;
85+
86+ if (!instance->type_sw)
87+ return 0;
88+
89+ switch (instance->type) {
90+ case PHY_TYPE_USB3:
91+ type = RG_PHY_SW_USB3;
92+ break;
93+ case PHY_TYPE_PCIE:
94+ type = RG_PHY_SW_PCIE;
95+ break;
96+ case PHY_TYPE_SGMII:
97+ type = RG_PHY_SW_SGMII;
98+ break;
99+ case PHY_TYPE_USB2:
100+ default:
101+ return 0;
102+ }
103+
104+ offset = instance->type_sw_index * BITS_PER_BYTE;
105+ regmap_update_bits(instance->type_sw, instance->type_sw_reg,
106+ RG_PHY_SW_TYPE << offset, type << offset);
107+
108+ return 0;
109+}
110+
111 static int mtk_phy_init(struct phy *phy)
112 {
113 struct xsphy_instance *inst = phy_get_drvdata(phy);
114@@ -385,6 +453,10 @@ static int mtk_phy_init(struct phy *phy)
115 case PHY_TYPE_USB3:
116 u3_phy_props_set(xsphy, inst);
117 break;
118+ case PHY_TYPE_PCIE:
119+ case PHY_TYPE_SGMII:
120+ /* nothing to do, only used to set type */
121+ break;
122 default:
123 dev_err(xsphy->dev, "incompatible phy type\n");
124 clk_disable_unprepare(inst->ref_clk);
125@@ -463,12 +535,15 @@ static struct phy *mtk_phy_xlate(struct device *dev,
126
127 inst->type = args->args[0];
128 if (!(inst->type == PHY_TYPE_USB2 ||
129- inst->type == PHY_TYPE_USB3)) {
130+ inst->type == PHY_TYPE_USB3 ||
131+ inst->type == PHY_TYPE_PCIE ||
132+ inst->type == PHY_TYPE_SGMII)) {
133 dev_err(dev, "unsupported phy type: %d\n", inst->type);
134 return ERR_PTR(-EINVAL);
135 }
136
137 phy_parse_property(xsphy, inst);
138+ phy_type_set(inst);
139
140 return inst->phy;
141 }
142@@ -575,6 +650,10 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
143 retval = PTR_ERR(inst->ref_clk);
144 goto put_child;
145 }
146+
147+ retval = phy_type_syscon_get(inst, child_np);
148+ if (retval)
149+ goto put_child;
150 }
151
152 provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
developer5d148cb2023-06-02 13:08:11 +0800153--
1542.34.1
155