blob: 05eb7388e11525f50ca7d26b08fe954d8ef115d3 [file] [log] [blame]
developer8cdcb262022-10-27 14:36:15 +08001From a2eaa93a5887ddd20af0373244481139627d0d77 Mon Sep 17 00:00:00 2001
developer44e1bbf2022-01-28 17:20:00 +08002From: Zhanyong Wang <zhanyong.wang@mediatek.com>
3Date: Mon, 8 Nov 2021 14:51:38 +0800
developer8cdcb262022-10-27 14:36:15 +08004Subject: [PATCH 2/8] phy: phy-mtk-tphy: add support efuse setting
developer44e1bbf2022-01-28 17:20:00 +08005
6Due to some SoCs have a bit shift issue that will drop a bit for usb3
7phy or pcie phy, fix it by adding software efuse reading and setting,
8but only support it optionally for versoin.
9
10Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
11Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
12Change-Id: Ibf88868668b3889f18c7930531981400cac732f1
13---
developer8cdcb262022-10-27 14:36:15 +080014 drivers/phy/mediatek/phy-mtk-tphy.c | 195 ++++++++++++++++++++++++++++
15 1 file changed, 195 insertions(+)
developer44e1bbf2022-01-28 17:20:00 +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 a59fe65f69e5..ce2731b2f5ff 100644
developer44e1bbf2022-01-28 17:20:00 +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@@ -12,6 +12,7 @@
developer44e1bbf2022-01-28 17:20:00 +080022 #include <linux/iopoll.h>
developer8cdcb262022-10-27 14:36:15 +080023 #include <linux/mfd/syscon.h>
developer44e1bbf2022-01-28 17:20:00 +080024 #include <linux/module.h>
25+#include <linux/nvmem-consumer.h>
26 #include <linux/of_address.h>
27 #include <linux/of_device.h>
28 #include <linux/phy/phy.h>
developer8cdcb262022-10-27 14:36:15 +080029@@ -39,11 +40,16 @@
developer44e1bbf2022-01-28 17:20:00 +080030 #define SSUSB_SIFSLV_V2_U3PHYD 0x200
31 #define SSUSB_SIFSLV_V2_U3PHYA 0x400
32
33+#define U3P_MISC_REG1 0x04
34+#define MR1_EFUSE_AUTO_LOAD_DIS BIT(6)
35+
36 #define U3P_USBPHYACR0 0x000
37 #define PA0_RG_U2PLL_FORCE_ON BIT(15)
38 #define PA0_RG_USB20_INTR_EN BIT(5)
39
40 #define U3P_USBPHYACR1 0x004
41+#define PA1_RG_INTR_CAL GENMASK(23, 19)
42+#define PA1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19)
43 #define PA1_RG_VRT_SEL GENMASK(14, 12)
44 #define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12)
45 #define PA1_RG_TERM_SEL GENMASK(10, 8)
developer8cdcb262022-10-27 14:36:15 +080046@@ -115,6 +121,8 @@
developer44e1bbf2022-01-28 17:20:00 +080047 #define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
48
49 #define U3P_U3_PHYA_REG0 0x000
50+#define P3A_RG_IEXT_INTR GENMASK(15, 10)
51+#define P3A_RG_IEXT_INTR_VAL(x) ((0x3f & (x)) << 10)
52 #define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
53 #define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
54
developer8cdcb262022-10-27 14:36:15 +080055@@ -169,6 +177,25 @@
developer44e1bbf2022-01-28 17:20:00 +080056 #define P3D_RG_FWAKE_TH GENMASK(21, 16)
57 #define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
58
59+#define U3P_U3_PHYD_IMPCAL0 0x010
60+#define P3D_RG_FORCE_TX_IMPEL BIT(31)
61+#define P3D_RG_TX_IMPEL GENMASK(28, 24)
62+#define P3D_RG_TX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
63+
64+#define U3P_U3_PHYD_IMPCAL1 0x014
65+#define P3D_RG_FORCE_RX_IMPEL BIT(31)
66+#define P3D_RG_RX_IMPEL GENMASK(28, 24)
67+#define P3D_RG_RX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
68+
69+#define U3P_U3_PHYD_RX0 0x02c
70+
71+#define U3P_U3_PHYD_T2RLB 0x030
72+
73+#define U3P_U3_PHYD_PIPE0 0x040
74+
75+#define U3P_U3_PHYD_RSV 0x054
76+#define P3D_RG_EFUSE_AUTO_LOAD_DIS BIT(12)
77+
78 #define U3P_U3_PHYD_CDR1 0x05c
79 #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
80 #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
developer8cdcb262022-10-27 14:36:15 +080081@@ -275,11 +302,23 @@
developer44e1bbf2022-01-28 17:20:00 +080082 enum mtk_phy_version {
83 MTK_PHY_V1 = 1,
84 MTK_PHY_V2,
85+ MTK_PHY_V3,
86 };
87
88 struct mtk_phy_pdata {
89 /* avoid RX sensitivity level degradation only for mt8173 */
90 bool avoid_rx_sen_degradation;
91+ /*
92+ * u2phy should use integer mode instead of fractional mode of
93+ * 48M PLL, fix it by switching PLL to 26M from default 48M
94+ * for mt8195
95+ */
96+ bool sx_pll_48m_to_26m;
97+ /*
98+ * Some SoCs (e.g. mt8195) drop a bit when use auto load efuse,
99+ * support sw way, also support it for v2/v3 optionally.
100+ */
101+ bool sw_efuse_supported;
102 enum mtk_phy_version version;
103 };
104
developer8cdcb262022-10-27 14:36:15 +0800105@@ -304,6 +343,10 @@ struct mtk_phy_instance {
developer44e1bbf2022-01-28 17:20:00 +0800106 struct u3phy_banks u3_banks;
107 };
108 struct clk *ref_clk; /* reference clock of anolog phy */
109+ u32 efuse_sw_en;
110+ u32 efuse_intr;
111+ u32 efuse_tx_imp;
112+ u32 efuse_rx_imp;
113 u32 index;
developer8cdcb262022-10-27 14:36:15 +0800114 u32 type;
115 struct regmap *type_sw;
116@@ -960,6 +1003,139 @@ static int phy_type_set(struct mtk_phy_instance *instance)
117 return 0;
developer44e1bbf2022-01-28 17:20:00 +0800118 }
119
120+static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instance)
121+{
122+ struct device *dev = &instance->phy->dev;
123+ int ret = 0;
124+
125+ dev_err(dev, "try to get sw efuse\n");
126+
127+ /* tphy v1 doesn't support sw efuse, skip it */
128+ if (!tphy->pdata->sw_efuse_supported) {
129+ instance->efuse_sw_en = 0;
130+ return 0;
131+ }
132+
133+ /* software efuse is optional */
134+ instance->efuse_sw_en = device_property_read_bool(dev, "nvmem-cells");
135+ if (!instance->efuse_sw_en)
136+ return 0;
137+
138+ dev_err(dev, "try to get sw efuse+\n");
139+
140+ switch (instance->type) {
141+ case PHY_TYPE_USB2:
142+ ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr);
143+ if (ret) {
144+ dev_err(dev, "fail to get u2 intr efuse, %d\n", ret);
145+ break;
146+ }
147+
148+ /* no efuse, ignore it */
149+ if (!instance->efuse_intr) {
150+ dev_warn(dev, "no u2 intr efuse, but dts enable it\n");
151+ instance->efuse_sw_en = 0;
152+ break;
153+ }
154+
155+ dev_info(dev, "u2 efuse - intr %x\n", instance->efuse_intr);
156+ break;
157+ case PHY_TYPE_USB3:
158+ case PHY_TYPE_PCIE:
159+ ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr);
160+ if (ret) {
161+ dev_err(dev, "fail to get u3 intr efuse, %d\n", ret);
162+ break;
163+ }
164+
165+ ret = nvmem_cell_read_variable_le_u32(dev, "rx_imp", &instance->efuse_rx_imp);
166+ if (ret) {
167+ dev_err(dev, "fail to get u3 rx_imp efuse, %d\n", ret);
168+ break;
169+ }
170+
171+ ret = nvmem_cell_read_variable_le_u32(dev, "tx_imp", &instance->efuse_tx_imp);
172+ if (ret) {
173+ dev_err(dev, "fail to get u3 tx_imp efuse, %d\n", ret);
174+ break;
175+ }
176+
177+ /* no efuse, ignore it */
178+ if (!instance->efuse_intr &&
179+ !instance->efuse_rx_imp &&
180+ !instance->efuse_tx_imp) {
181+ dev_warn(dev, "no u3 intr efuse, but dts enable it\n");
182+ instance->efuse_sw_en = 0;
183+ break;
184+ }
185+
186+ dev_info(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n",
187+ instance->efuse_intr, instance->efuse_rx_imp,
188+ instance->efuse_tx_imp);
189+ break;
190+ default:
191+ dev_err(dev, "no sw efuse for type %d\n", instance->type);
192+ ret = -EINVAL;
193+ }
194+
195+ return ret;
196+}
197+
198+static void phy_efuse_set(struct mtk_phy_instance *instance)
199+{
200+ struct device *dev = &instance->phy->dev;
201+ struct u2phy_banks *u2_banks = &instance->u2_banks;
202+ struct u3phy_banks *u3_banks = &instance->u3_banks;
203+ u32 tmp;
204+
205+ if (!instance->efuse_sw_en)
206+ return;
207+
208+ switch (instance->type) {
209+ case PHY_TYPE_USB2:
210+ tmp = readl(u2_banks->misc + U3P_MISC_REG1);
211+ tmp |= MR1_EFUSE_AUTO_LOAD_DIS;
212+ writel(tmp, u2_banks->misc + U3P_MISC_REG1);
213+
214+ tmp = readl(u2_banks->com + U3P_USBPHYACR1);
215+ tmp &= ~PA1_RG_INTR_CAL;
216+ tmp |= PA1_RG_INTR_CAL_VAL(instance->efuse_intr);
217+ writel(tmp, u2_banks->com + U3P_USBPHYACR1);
218+ pr_err("%s set efuse intr %x\n", __func__, instance->efuse_intr);
219+
220+ break;
221+ case PHY_TYPE_USB3:
222+ case PHY_TYPE_PCIE:
223+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
224+ tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS;
225+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV);
226+
227+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
228+ tmp &= ~P3D_RG_TX_IMPEL;
229+ tmp |= P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp);
230+ tmp |= P3D_RG_FORCE_TX_IMPEL;
231+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
232+
233+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
234+ tmp &= ~P3D_RG_RX_IMPEL;
235+ tmp |= P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp);
236+ tmp |= P3D_RG_FORCE_RX_IMPEL;
237+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
238+
239+ tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
240+ tmp &= ~P3A_RG_IEXT_INTR;
241+ tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr);
242+ writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0);
243+ pr_err("%s set efuse, tx_imp %x, rx_imp %x intr %x\n",
244+ __func__, instance->efuse_tx_imp,
245+ instance->efuse_rx_imp, instance->efuse_intr);
246+ break;
247+ default:
248+ dev_warn(dev, "no sw efuse for type %d\n", instance->type);
249+ }
250+}
251+
developer8cdcb262022-10-27 14:36:15 +0800252+
developer44e1bbf2022-01-28 17:20:00 +0800253 static int mtk_phy_init(struct phy *phy)
254 {
255 struct mtk_phy_instance *instance = phy_get_drvdata(phy);
developer8cdcb262022-10-27 14:36:15 +0800256@@ -978,6 +1154,8 @@ static int mtk_phy_init(struct phy *phy)
developer44e1bbf2022-01-28 17:20:00 +0800257 return ret;
258 }
259
260+ phy_efuse_set(instance);
261+
262 switch (instance->type) {
263 case PHY_TYPE_USB2:
264 u2_phy_instance_init(tphy, instance);
developer8cdcb262022-10-27 14:36:15 +0800265@@ -1062,6 +1240,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
developer44e1bbf2022-01-28 17:20:00 +0800266 struct mtk_phy_instance *instance = NULL;
267 struct device_node *phy_np = args->np;
268 int index;
269+ int ret;
270
271 if (args->args_count != 1) {
272 dev_err(dev, "invalid number of cells in 'phy' property\n");
developer8cdcb262022-10-27 14:36:15 +0800273@@ -1098,6 +1277,10 @@ static struct phy *mtk_phy_xlate(struct device *dev,
developer44e1bbf2022-01-28 17:20:00 +0800274 return ERR_PTR(-EINVAL);
275 }
276
277+ ret = phy_efuse_get(tphy, instance);
278+ if (ret)
279+ return ERR_PTR(ret);
280+
281 phy_parse_property(tphy, instance);
developer8cdcb262022-10-27 14:36:15 +0800282 phy_type_set(instance);
developer44e1bbf2022-01-28 17:20:00 +0800283
developer8cdcb262022-10-27 14:36:15 +0800284@@ -1120,14 +1303,26 @@ static const struct mtk_phy_pdata tphy_v1_pdata = {
developer44e1bbf2022-01-28 17:20:00 +0800285
286 static const struct mtk_phy_pdata tphy_v2_pdata = {
287 .avoid_rx_sen_degradation = false,
288+ .sw_efuse_supported = true,
289 .version = MTK_PHY_V2,
290 };
291
292+static const struct mtk_phy_pdata tphy_v3_pdata = {
293+ .sw_efuse_supported = true,
294+ .version = MTK_PHY_V3,
295+};
296+
297 static const struct mtk_phy_pdata mt8173_pdata = {
298 .avoid_rx_sen_degradation = true,
299 .version = MTK_PHY_V1,
300 };
301
302+static const struct mtk_phy_pdata mt8195_pdata = {
303+ .sx_pll_48m_to_26m = true,
304+ .sw_efuse_supported = true,
305+ .version = MTK_PHY_V3,
306+};
307+
308 static const struct of_device_id mtk_tphy_id_table[] = {
309 { .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
310 { .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
311--
3122.18.0
313