1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright 2017-2026 NXP. */
3
4 #include <linux/bitfield.h>
5 #include <linux/clk.h>
6 #include <linux/delay.h>
7 #include <linux/io.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/phy/phy.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_domain.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/regmap.h>
16 #include <linux/usb/typec_mux.h>
17
18 #define PHY_CTRL0 0x0
19 #define PHY_CTRL0_REF_SSP_EN BIT(2)
20 #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5)
21 #define PHY_CTRL0_FSEL_24M 0x2a
22 #define PHY_CTRL0_FSEL_100M 0x27
23 #define PHY_CTRL0_SSC_RANGE_MASK GENMASK(23, 21)
24 #define PHY_CTRL0_SSC_RANGE_4003PPM 0x2
25 #define PHY_CTRL0_SSC_RANGE_4492PPM 0x1
26 #define PHY_CTRL0_SSC_RANGE_4980PPM 0x0
27
28 #define PHY_CTRL1 0x4
29 #define PHY_CTRL1_RESET BIT(0)
30 #define PHY_CTRL1_COMMONONN BIT(1)
31 #define PHY_CTRL1_ATERESET BIT(3)
32 #define PHY_CTRL1_VDATSRCENB0 BIT(19)
33 #define PHY_CTRL1_VDATDETENB0 BIT(20)
34
35 #define PHY_CTRL2 0x8
36 #define PHY_CTRL2_TXENABLEN0 BIT(8)
37 #define PHY_CTRL2_OTG_DISABLE BIT(9)
38
39 #define PHY_CTRL3 0xc
40 #define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0)
41 #define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15)
42 #define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20)
43 #define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22)
44 #define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29)
45
46 #define PHY_CTRL4 0x10
47 #define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15)
48
49 #define PHY_CTRL5 0x14
50 #define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23)
51 #define PHY_CTRL5_DMPWD_OVERRIDE BIT(22)
52 #define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21)
53 #define PHY_CTRL5_DPPWD_OVERRIDE BIT(20)
54 #define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0)
55
56 #define PHY_CTRL6 0x18
57 #define PHY_CTRL6_RXTERM_OVERRIDE_SEL BIT(29)
58 #define PHY_CTRL6_ALT_CLK_EN BIT(1)
59 #define PHY_CTRL6_ALT_CLK_SEL BIT(0)
60
61 #define PHY_CRCTL 0x30
62
63 #define PHY_TUNE_DEFAULT 0xffffffff
64
65 #define TCA_CLK_RST 0x00
66 #define TCA_CLK_RST_SW BIT(9)
67 #define TCA_CLK_RST_REF_CLK_EN BIT(1)
68 #define TCA_CLK_RST_SUSPEND_CLK_EN BIT(0)
69
70 #define TCA_INTR_EN 0x04
71 #define TCA_INTR_STS 0x08
72
73 #define TCA_GCFG 0x10
74 #define TCA_GCFG_ROLE_HSTDEV BIT(4)
75 #define TCA_GCFG_OP_MODE GENMASK(1, 0)
76 #define TCA_GCFG_OP_MODE_SYSMODE 0
77 #define TCA_GCFG_OP_MODE_SYNCMODE 1
78
79 #define TCA_TCPC 0x14
80 #define TCA_TCPC_VALID BIT(4)
81 #define TCA_TCPC_LOW_POWER_EN BIT(3)
82 #define TCA_TCPC_ORIENTATION_NORMAL BIT(2)
83 #define TCA_TCPC_MUX_CONTRL GENMASK(1, 0)
84 #define TCA_TCPC_MUX_CONTRL_NO_CONN 0
85 #define TCA_TCPC_MUX_CONTRL_USB_CONN 1
86
87 #define TCA_SYSMODE_CFG 0x18
88 #define TCA_SYSMODE_TCPC_DISABLE BIT(3)
89 #define TCA_SYSMODE_TCPC_FLIP BIT(2)
90
91 #define TCA_CTRLSYNCMODE_CFG0 0x20
92 #define TCA_CTRLSYNCMODE_CFG1 0x20
93
94 #define TCA_PSTATE 0x30
95 #define TCA_PSTATE_CM_STS BIT(4)
96 #define TCA_PSTATE_TX_STS BIT(3)
97 #define TCA_PSTATE_RX_PLL_STS BIT(2)
98 #define TCA_PSTATE_PIPE0_POWER_DOWN GENMASK(1, 0)
99
100 #define TCA_GEN_STATUS 0x34
101 #define TCA_GEN_DEV_POR BIT(12)
102 #define TCA_GEN_REF_CLK_SEL BIT(8)
103 #define TCA_GEN_TYPEC_FLIP_INVERT BIT(4)
104 #define TCA_GEN_PHY_TYPEC_DISABLE BIT(3)
105 #define TCA_GEN_PHY_TYPEC_FLIP BIT(2)
106
107 #define TCA_VBUS_CTRL 0x40
108 #define TCA_VBUS_STATUS 0x44
109
110 #define TCA_INFO 0xfc
111
112 struct tca_blk {
113 struct typec_switch_dev *sw;
114 void __iomem *base;
115 struct mutex mutex;
116 enum typec_orientation orientation;
117 };
118
119 struct imx8mq_usb_phy {
120 struct phy *phy;
121 struct clk *clk;
122 struct clk *alt_clk;
123 void __iomem *base;
124 struct regulator *vbus;
125 struct tca_blk *tca;
126 struct regmap *cr_regmap;
127 u32 pcs_tx_swing_full;
128 u32 pcs_tx_deemph_3p5db;
129 u32 tx_vref_tune;
130 u32 tx_rise_tune;
131 u32 tx_preemp_amp_tune;
132 u32 tx_vboost_level;
133 u32 comp_dis_tune;
134 };
135
136 struct imx8mq_usb_phy_drvdata {
137 const struct phy_ops *ops;
138 bool need_genpd_rpm_on;
139 };
140
141 static void tca_blk_orientation_set(struct tca_blk *tca,
142 enum typec_orientation orientation);
143
tca_blk_typec_switch_set(struct typec_switch_dev * sw,enum typec_orientation orientation)144 static int tca_blk_typec_switch_set(struct typec_switch_dev *sw,
145 enum typec_orientation orientation)
146 {
147 struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
148 struct tca_blk *tca = imx_phy->tca;
149
150 if (tca->orientation == orientation)
151 return 0;
152
153 PM_RUNTIME_ACQUIRE_IF_ENABLED(&imx_phy->phy->dev, pm);
154 if (PM_RUNTIME_ACQUIRE_ERR(&pm))
155 return -ENXIO;
156
157 tca_blk_orientation_set(tca, orientation);
158
159 return 0;
160 }
161
tca_blk_get_typec_switch(struct platform_device * pdev,struct imx8mq_usb_phy * imx_phy)162 static struct typec_switch_dev *tca_blk_get_typec_switch(struct platform_device *pdev,
163 struct imx8mq_usb_phy *imx_phy)
164 {
165 struct device *dev = &pdev->dev;
166 struct typec_switch_dev *sw;
167 struct typec_switch_desc sw_desc = { };
168
169 sw_desc.drvdata = imx_phy;
170 sw_desc.fwnode = dev->fwnode;
171 sw_desc.set = tca_blk_typec_switch_set;
172 sw_desc.name = NULL;
173
174 sw = typec_switch_register(dev, &sw_desc);
175 if (IS_ERR(sw)) {
176 dev_err(dev, "Error register tca orientation switch: %ld",
177 PTR_ERR(sw));
178 return NULL;
179 }
180
181 return sw;
182 }
183
tca_blk_put_typec_switch(void * data)184 static void tca_blk_put_typec_switch(void *data)
185 {
186 typec_switch_unregister(data);
187 }
188
tca_blk_orientation_set(struct tca_blk * tca,enum typec_orientation orientation)189 static void tca_blk_orientation_set(struct tca_blk *tca,
190 enum typec_orientation orientation)
191 {
192 u32 val;
193
194 mutex_lock(&tca->mutex);
195
196 if (orientation == TYPEC_ORIENTATION_NONE) {
197 /*
198 * use Controller Synced Mode for TCA low power enable and
199 * put PHY to USB safe state.
200 */
201 val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYNCMODE);
202 writel(val, tca->base + TCA_GCFG);
203
204 val = TCA_TCPC_VALID | TCA_TCPC_LOW_POWER_EN;
205 writel(val, tca->base + TCA_TCPC);
206
207 goto out;
208 }
209
210 /* use System Configuration Mode for TCA mux control. */
211 val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYSMODE);
212 writel(val, tca->base + TCA_GCFG);
213
214 /* Disable TCA module */
215 val = readl(tca->base + TCA_SYSMODE_CFG);
216 val |= TCA_SYSMODE_TCPC_DISABLE;
217 writel(val, tca->base + TCA_SYSMODE_CFG);
218
219 if (orientation == TYPEC_ORIENTATION_REVERSE)
220 val |= TCA_SYSMODE_TCPC_FLIP;
221 else if (orientation == TYPEC_ORIENTATION_NORMAL)
222 val &= ~TCA_SYSMODE_TCPC_FLIP;
223
224 writel(val, tca->base + TCA_SYSMODE_CFG);
225
226 /* Enable TCA module */
227 val &= ~TCA_SYSMODE_TCPC_DISABLE;
228 writel(val, tca->base + TCA_SYSMODE_CFG);
229
230 out:
231 tca->orientation = orientation;
232 mutex_unlock(&tca->mutex);
233 }
234
tca_blk_init(struct tca_blk * tca)235 static void tca_blk_init(struct tca_blk *tca)
236 {
237 u32 val;
238
239 /* reset XBar block */
240 val = readl(tca->base + TCA_CLK_RST);
241 val &= ~TCA_CLK_RST_SW;
242 writel(val, tca->base + TCA_CLK_RST);
243
244 udelay(100);
245
246 /* clear reset */
247 val |= TCA_CLK_RST_SW;
248 writel(val, tca->base + TCA_CLK_RST);
249
250 tca_blk_orientation_set(tca, tca->orientation);
251 }
252
imx95_usb_phy_get_tca(struct platform_device * pdev,struct imx8mq_usb_phy * imx_phy)253 static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
254 struct imx8mq_usb_phy *imx_phy)
255 {
256 struct device *dev = &pdev->dev;
257 struct resource *res;
258 struct tca_blk *tca;
259 int ret;
260
261 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
262 if (!res)
263 return NULL;
264
265 tca = devm_kzalloc(dev, sizeof(*tca), GFP_KERNEL);
266 if (!tca)
267 return ERR_PTR(-ENOMEM);
268
269 tca->base = devm_ioremap_resource(&pdev->dev, res);
270 if (IS_ERR(tca->base))
271 return ERR_CAST(tca->base);
272
273 mutex_init(&tca->mutex);
274
275 tca->orientation = TYPEC_ORIENTATION_NORMAL;
276 tca->sw = tca_blk_get_typec_switch(pdev, imx_phy);
277
278 ret = devm_add_action_or_reset(&pdev->dev, tca_blk_put_typec_switch, tca->sw);
279 if (ret)
280 return ERR_PTR(ret);
281
282 return tca;
283 }
284
phy_tx_vref_tune_from_property(u32 percent)285 static u32 phy_tx_vref_tune_from_property(u32 percent)
286 {
287 percent = clamp(percent, 94U, 124U);
288
289 return DIV_ROUND_CLOSEST(percent - 94U, 2);
290 }
291
imx95_phy_tx_vref_tune_from_property(u32 percent)292 static u32 imx95_phy_tx_vref_tune_from_property(u32 percent)
293 {
294 percent = clamp(percent, 90U, 108U);
295
296 switch (percent) {
297 case 90 ... 91:
298 percent = 0;
299 break;
300 case 92 ... 96:
301 percent -= 91;
302 break;
303 case 97 ... 104:
304 percent -= 92;
305 break;
306 case 105 ... 108:
307 percent -= 93;
308 break;
309 }
310
311 return percent;
312 }
313
phy_tx_rise_tune_from_property(u32 percent)314 static u32 phy_tx_rise_tune_from_property(u32 percent)
315 {
316 switch (percent) {
317 case 0 ... 98:
318 return 3;
319 case 99:
320 return 2;
321 case 100 ... 101:
322 return 1;
323 default:
324 return 0;
325 }
326 }
327
imx95_phy_tx_rise_tune_from_property(u32 percent)328 static u32 imx95_phy_tx_rise_tune_from_property(u32 percent)
329 {
330 percent = clamp(percent, 90U, 120U);
331
332 switch (percent) {
333 case 90 ... 99:
334 return 3;
335 case 101 ... 115:
336 return 1;
337 case 116 ... 120:
338 return 0;
339 default:
340 return 2;
341 }
342 }
343
phy_tx_preemp_amp_tune_from_property(u32 microamp)344 static u32 phy_tx_preemp_amp_tune_from_property(u32 microamp)
345 {
346 microamp = min(microamp, 1800U);
347
348 return microamp / 600;
349 }
350
phy_tx_vboost_level_from_property(u32 microvolt)351 static u32 phy_tx_vboost_level_from_property(u32 microvolt)
352 {
353 switch (microvolt) {
354 case 1156:
355 return 5;
356 case 844:
357 return 3;
358 default:
359 return 4;
360 }
361 }
362
phy_pcs_tx_deemph_3p5db_from_property(u32 decibel)363 static u32 phy_pcs_tx_deemph_3p5db_from_property(u32 decibel)
364 {
365 return min(decibel, 36U);
366 }
367
phy_comp_dis_tune_from_property(u32 percent)368 static u32 phy_comp_dis_tune_from_property(u32 percent)
369 {
370 switch (percent) {
371 case 0 ... 92:
372 return 0;
373 case 93 ... 95:
374 return 1;
375 case 96 ... 97:
376 return 2;
377 case 98 ... 102:
378 return 3;
379 case 103 ... 105:
380 return 4;
381 case 106 ... 109:
382 return 5;
383 case 110 ... 113:
384 return 6;
385 default:
386 return 7;
387 }
388 }
389
imx95_phy_comp_dis_tune_from_property(u32 percent)390 static u32 imx95_phy_comp_dis_tune_from_property(u32 percent)
391 {
392 percent = clamp(percent, 94, 104);
393
394 switch (percent) {
395 case 94 ... 95:
396 percent = 0;
397 break;
398 case 96 ... 98:
399 percent -= 95;
400 break;
401 case 99 ... 102:
402 percent -= 96;
403 break;
404 case 103 ... 104:
405 percent -= 97;
406 break;
407 }
408
409 return percent;
410 }
411
phy_pcs_tx_swing_full_from_property(u32 percent)412 static u32 phy_pcs_tx_swing_full_from_property(u32 percent)
413 {
414 percent = min(percent, 100U);
415
416 return (percent * 127) / 100;
417 }
418
imx8m_get_phy_tuning_data(struct imx8mq_usb_phy * imx_phy)419 static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy)
420 {
421 struct device *dev = imx_phy->phy->dev.parent;
422 bool is_imx95 = false;
423
424 if (device_is_compatible(dev, "fsl,imx95-usb-phy"))
425 is_imx95 = true;
426
427 if (device_property_read_u32(dev, "fsl,phy-tx-vref-tune-percent",
428 &imx_phy->tx_vref_tune))
429 imx_phy->tx_vref_tune = PHY_TUNE_DEFAULT;
430 else if (is_imx95)
431 imx_phy->tx_vref_tune =
432 imx95_phy_tx_vref_tune_from_property(imx_phy->tx_vref_tune);
433 else
434 imx_phy->tx_vref_tune =
435 phy_tx_vref_tune_from_property(imx_phy->tx_vref_tune);
436
437 if (device_property_read_u32(dev, "fsl,phy-tx-rise-tune-percent",
438 &imx_phy->tx_rise_tune))
439 imx_phy->tx_rise_tune = PHY_TUNE_DEFAULT;
440 else if (is_imx95)
441 imx_phy->tx_rise_tune =
442 imx95_phy_tx_rise_tune_from_property(imx_phy->tx_rise_tune);
443 else
444 imx_phy->tx_rise_tune =
445 phy_tx_rise_tune_from_property(imx_phy->tx_rise_tune);
446
447 if (device_property_read_u32(dev, "fsl,phy-tx-preemp-amp-tune-microamp",
448 &imx_phy->tx_preemp_amp_tune))
449 imx_phy->tx_preemp_amp_tune = PHY_TUNE_DEFAULT;
450 else
451 imx_phy->tx_preemp_amp_tune =
452 phy_tx_preemp_amp_tune_from_property(imx_phy->tx_preemp_amp_tune);
453
454 if (device_property_read_u32(dev, "fsl,phy-tx-vboost-level-microvolt",
455 &imx_phy->tx_vboost_level))
456 imx_phy->tx_vboost_level = PHY_TUNE_DEFAULT;
457 else
458 imx_phy->tx_vboost_level =
459 phy_tx_vboost_level_from_property(imx_phy->tx_vboost_level);
460
461 if (device_property_read_u32(dev, "fsl,phy-comp-dis-tune-percent",
462 &imx_phy->comp_dis_tune))
463 imx_phy->comp_dis_tune = PHY_TUNE_DEFAULT;
464 else if (is_imx95)
465 imx_phy->comp_dis_tune =
466 imx95_phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune);
467 else
468 imx_phy->comp_dis_tune =
469 phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune);
470
471 if (device_property_read_u32(dev, "fsl,phy-pcs-tx-deemph-3p5db-attenuation-db",
472 &imx_phy->pcs_tx_deemph_3p5db))
473 imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT;
474 else
475 imx_phy->pcs_tx_deemph_3p5db =
476 phy_pcs_tx_deemph_3p5db_from_property(imx_phy->pcs_tx_deemph_3p5db);
477
478 if (device_property_read_u32(dev, "fsl,phy-pcs-tx-swing-full-percent",
479 &imx_phy->pcs_tx_swing_full))
480 imx_phy->pcs_tx_swing_full = PHY_TUNE_DEFAULT;
481 else
482 imx_phy->pcs_tx_swing_full =
483 phy_pcs_tx_swing_full_from_property(imx_phy->pcs_tx_swing_full);
484 }
485
imx8m_phy_tune(struct imx8mq_usb_phy * imx_phy)486 static void imx8m_phy_tune(struct imx8mq_usb_phy *imx_phy)
487 {
488 u32 value;
489
490 /* PHY tuning */
491 if (imx_phy->pcs_tx_deemph_3p5db != PHY_TUNE_DEFAULT) {
492 value = readl(imx_phy->base + PHY_CTRL4);
493 value &= ~PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK;
494 value |= FIELD_PREP(PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK,
495 imx_phy->pcs_tx_deemph_3p5db);
496 writel(value, imx_phy->base + PHY_CTRL4);
497 }
498
499 if (imx_phy->pcs_tx_swing_full != PHY_TUNE_DEFAULT) {
500 value = readl(imx_phy->base + PHY_CTRL5);
501 value &= ~PHY_CTRL5_PCS_TX_SWING_FULL_MASK;
502 value |= FIELD_PREP(PHY_CTRL5_PCS_TX_SWING_FULL_MASK,
503 imx_phy->pcs_tx_swing_full);
504 writel(value, imx_phy->base + PHY_CTRL5);
505 }
506
507 if ((imx_phy->tx_vref_tune & imx_phy->tx_rise_tune &
508 imx_phy->tx_preemp_amp_tune & imx_phy->comp_dis_tune &
509 imx_phy->tx_vboost_level) == PHY_TUNE_DEFAULT)
510 /* If all are the default values, no need update. */
511 return;
512
513 value = readl(imx_phy->base + PHY_CTRL3);
514
515 if (imx_phy->tx_vref_tune != PHY_TUNE_DEFAULT) {
516 value &= ~PHY_CTRL3_TXVREF_TUNE_MASK;
517 value |= FIELD_PREP(PHY_CTRL3_TXVREF_TUNE_MASK,
518 imx_phy->tx_vref_tune);
519 }
520
521 if (imx_phy->tx_rise_tune != PHY_TUNE_DEFAULT) {
522 value &= ~PHY_CTRL3_TXRISE_TUNE_MASK;
523 value |= FIELD_PREP(PHY_CTRL3_TXRISE_TUNE_MASK,
524 imx_phy->tx_rise_tune);
525 }
526
527 if (imx_phy->tx_preemp_amp_tune != PHY_TUNE_DEFAULT) {
528 value &= ~PHY_CTRL3_TXPREEMP_TUNE_MASK;
529 value |= FIELD_PREP(PHY_CTRL3_TXPREEMP_TUNE_MASK,
530 imx_phy->tx_preemp_amp_tune);
531 }
532
533 if (imx_phy->comp_dis_tune != PHY_TUNE_DEFAULT) {
534 value &= ~PHY_CTRL3_COMPDISTUNE_MASK;
535 value |= FIELD_PREP(PHY_CTRL3_COMPDISTUNE_MASK,
536 imx_phy->comp_dis_tune);
537 }
538
539 if (imx_phy->tx_vboost_level != PHY_TUNE_DEFAULT) {
540 value &= ~PHY_CTRL3_TX_VBOOST_LEVEL_MASK;
541 value |= FIELD_PREP(PHY_CTRL3_TX_VBOOST_LEVEL_MASK,
542 imx_phy->tx_vboost_level);
543 }
544
545 writel(value, imx_phy->base + PHY_CTRL3);
546 }
547
imx8mq_usb_phy_init(struct phy * phy)548 static int imx8mq_usb_phy_init(struct phy *phy)
549 {
550 struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
551 u32 value;
552
553 value = readl(imx_phy->base + PHY_CTRL1);
554 value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0 |
555 PHY_CTRL1_COMMONONN);
556 value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
557 writel(value, imx_phy->base + PHY_CTRL1);
558
559 value = readl(imx_phy->base + PHY_CTRL0);
560 value |= PHY_CTRL0_REF_SSP_EN;
561 writel(value, imx_phy->base + PHY_CTRL0);
562
563 value = readl(imx_phy->base + PHY_CTRL2);
564 value |= PHY_CTRL2_TXENABLEN0;
565 writel(value, imx_phy->base + PHY_CTRL2);
566
567 value = readl(imx_phy->base + PHY_CTRL1);
568 value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
569 writel(value, imx_phy->base + PHY_CTRL1);
570
571 return 0;
572 }
573
imx8mp_usb_phy_init(struct phy * phy)574 static int imx8mp_usb_phy_init(struct phy *phy)
575 {
576 struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
577 u32 value;
578
579 /* USB3.0 PHY signal fsel for 24M ref */
580 value = readl(imx_phy->base + PHY_CTRL0);
581 value &= ~PHY_CTRL0_FSEL_MASK;
582 value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, imx_phy->alt_clk ?
583 PHY_CTRL0_FSEL_100M : PHY_CTRL0_FSEL_24M);
584 writel(value, imx_phy->base + PHY_CTRL0);
585
586 /* Disable alt_clk_en and use internal MPLL clocks */
587 value = readl(imx_phy->base + PHY_CTRL6);
588 value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN);
589 writel(value, imx_phy->base + PHY_CTRL6);
590
591 value = readl(imx_phy->base + PHY_CTRL1);
592 value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0);
593 value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
594 writel(value, imx_phy->base + PHY_CTRL1);
595
596 value = readl(imx_phy->base + PHY_CTRL0);
597 value |= PHY_CTRL0_REF_SSP_EN;
598 value &= ~PHY_CTRL0_SSC_RANGE_MASK;
599 value |= FIELD_PREP(PHY_CTRL0_SSC_RANGE_MASK,
600 PHY_CTRL0_SSC_RANGE_4003PPM);
601 writel(value, imx_phy->base + PHY_CTRL0);
602
603 value = readl(imx_phy->base + PHY_CTRL2);
604 value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE;
605 writel(value, imx_phy->base + PHY_CTRL2);
606
607 udelay(10);
608
609 value = readl(imx_phy->base + PHY_CTRL1);
610 value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
611 writel(value, imx_phy->base + PHY_CTRL1);
612
613 imx8m_phy_tune(imx_phy);
614
615 if (imx_phy->tca)
616 tca_blk_init(imx_phy->tca);
617
618 return 0;
619 }
620
imx8mq_phy_power_on(struct phy * phy)621 static int imx8mq_phy_power_on(struct phy *phy)
622 {
623 struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
624 u32 value;
625 int ret;
626
627 ret = regulator_enable(imx_phy->vbus);
628 if (ret)
629 return ret;
630
631 /* Disable rx term override */
632 value = readl(imx_phy->base + PHY_CTRL6);
633 value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
634 writel(value, imx_phy->base + PHY_CTRL6);
635
636 return 0;
637 }
638
imx8mq_phy_power_off(struct phy * phy)639 static int imx8mq_phy_power_off(struct phy *phy)
640 {
641 struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
642 u32 value;
643
644 /* Override rx term to be 0 */
645 value = readl(imx_phy->base + PHY_CTRL6);
646 value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
647 writel(value, imx_phy->base + PHY_CTRL6);
648
649 regulator_disable(imx_phy->vbus);
650
651 return 0;
652 }
653
654 static const struct phy_ops imx8mq_usb_phy_ops = {
655 .init = imx8mq_usb_phy_init,
656 .power_on = imx8mq_phy_power_on,
657 .power_off = imx8mq_phy_power_off,
658 .owner = THIS_MODULE,
659 };
660
661 static const struct phy_ops imx8mp_usb_phy_ops = {
662 .init = imx8mp_usb_phy_init,
663 .power_on = imx8mq_phy_power_on,
664 .power_off = imx8mq_phy_power_off,
665 .owner = THIS_MODULE,
666 };
667
668 static const struct imx8mq_usb_phy_drvdata imx8mq_usb_phy_data = {
669 .ops = &imx8mq_usb_phy_ops,
670 };
671
672 static const struct imx8mq_usb_phy_drvdata imx8mp_usb_phy_data = {
673 .ops = &imx8mp_usb_phy_ops,
674 .need_genpd_rpm_on = true,
675 };
676
677 static const struct imx8mq_usb_phy_drvdata imx95_usb_phy_data = {
678 .ops = &imx8mp_usb_phy_ops,
679 };
680
681 static const struct of_device_id imx8mq_usb_phy_of_match[] = {
682 {.compatible = "fsl,imx8mq-usb-phy",
683 .data = &imx8mq_usb_phy_data,},
684 {.compatible = "fsl,imx8mp-usb-phy",
685 .data = &imx8mp_usb_phy_data,},
686 {.compatible = "fsl,imx95-usb-phy",
687 .data = &imx95_usb_phy_data,},
688 { }
689 };
690 MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
691
692 static const struct regmap_config imx_cr_regmap_config = {
693 .name = "cr",
694 .reg_bits = 32,
695 .val_bits = 32,
696 .reg_stride = 4,
697 .max_register = 0x7,
698 };
699
imx8mq_usb_phy_probe(struct platform_device * pdev)700 static int imx8mq_usb_phy_probe(struct platform_device *pdev)
701 {
702 struct phy_provider *phy_provider;
703 struct device *dev = &pdev->dev;
704 struct imx8mq_usb_phy *imx_phy;
705 const struct imx8mq_usb_phy_drvdata *phy_data;
706 int ret;
707
708 imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
709 if (!imx_phy)
710 return -ENOMEM;
711
712 platform_set_drvdata(pdev, imx_phy);
713
714 imx_phy->clk = devm_clk_get_enabled(dev, "phy");
715 if (IS_ERR(imx_phy->clk)) {
716 dev_err(dev, "failed to get imx8mq usb phy clock\n");
717 return PTR_ERR(imx_phy->clk);
718 }
719
720 imx_phy->alt_clk = devm_clk_get_optional_enabled(dev, "alt");
721 if (IS_ERR(imx_phy->alt_clk))
722 return dev_err_probe(dev, PTR_ERR(imx_phy->alt_clk),
723 "Failed to get alt clk\n");
724
725 imx_phy->base = devm_platform_ioremap_resource(pdev, 0);
726 if (IS_ERR(imx_phy->base))
727 return PTR_ERR(imx_phy->base);
728
729 imx_phy->cr_regmap = devm_regmap_init_mmio(dev, imx_phy->base + PHY_CRCTL,
730 &imx_cr_regmap_config);
731 if (IS_ERR(imx_phy->cr_regmap)) {
732 dev_warn(dev, "Fail to init debug register regmap\n");
733 imx_phy->cr_regmap = NULL;
734 }
735
736 imx_phy->vbus = devm_regulator_get(dev, "vbus");
737 if (IS_ERR(imx_phy->vbus))
738 return dev_err_probe(dev, PTR_ERR(imx_phy->vbus), "failed to get vbus\n");
739
740 phy_data = of_device_get_match_data(dev);
741 if (!phy_data)
742 return -EINVAL;
743
744 if (phy_data->need_genpd_rpm_on) {
745 ret = dev_pm_genpd_rpm_always_on(dev, true);
746 if (ret && ret != -EOPNOTSUPP)
747 dev_warn(dev, "failed to set genpd rpm always on\n");
748 }
749
750 pm_runtime_set_active(dev);
751 pm_runtime_enable(dev);
752
753 imx_phy->phy = devm_phy_create(dev, NULL, phy_data->ops);
754 if (IS_ERR(imx_phy->phy)) {
755 ret = dev_err_probe(dev, PTR_ERR(imx_phy->phy),
756 "failed to create PHY\n");
757 goto disable_rpm;
758 }
759
760 phy_set_drvdata(imx_phy->phy, imx_phy);
761
762 imx_phy->tca = imx95_usb_phy_get_tca(pdev, imx_phy);
763 if (IS_ERR(imx_phy->tca)) {
764 ret = dev_err_probe(dev, PTR_ERR(imx_phy->tca),
765 "failed to get tca\n");
766 goto disable_rpm;
767 }
768
769 imx8m_get_phy_tuning_data(imx_phy);
770 device_set_wakeup_capable(dev, true);
771
772 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
773 if (IS_ERR(phy_provider)) {
774 ret = dev_err_probe(dev, PTR_ERR(phy_provider),
775 "failed to register phy provider\n");
776 goto disable_rpm;
777 }
778
779 return 0;
780
781 disable_rpm:
782 pm_runtime_disable(dev);
783 return ret;
784 }
785
imx8mq_usb_phy_remove(struct platform_device * pdev)786 static void imx8mq_usb_phy_remove(struct platform_device *pdev)
787 {
788 struct device *dev = &pdev->dev;
789 int ret;
790
791 ret = pm_runtime_get_sync(dev);
792 if (ret < 0)
793 dev_warn(dev, "failed to resume on remove: %d\n", ret);
794
795 pm_runtime_disable(dev);
796 pm_runtime_put_noidle(dev);
797 }
798
imx8mq_usb_phy_runtime_suspend(struct device * dev)799 static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
800 {
801 struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
802
803 if (imx_phy->cr_regmap)
804 regcache_cache_only(imx_phy->cr_regmap, true);
805
806 clk_disable_unprepare(imx_phy->alt_clk);
807 clk_disable_unprepare(imx_phy->clk);
808
809 return 0;
810 }
811
imx8mq_usb_phy_runtime_resume(struct device * dev)812 static int imx8mq_usb_phy_runtime_resume(struct device *dev)
813 {
814 struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
815 int ret;
816
817 ret = clk_prepare_enable(imx_phy->clk);
818 if (ret)
819 return ret;
820
821 ret = clk_prepare_enable(imx_phy->alt_clk);
822 if (ret) {
823 clk_disable_unprepare(imx_phy->clk);
824 return ret;
825 }
826
827 if (imx_phy->cr_regmap)
828 regcache_cache_only(imx_phy->cr_regmap, false);
829
830 return 0;
831 }
832
833 static DEFINE_RUNTIME_DEV_PM_OPS(imx8mq_usb_phy_pm_ops, imx8mq_usb_phy_runtime_suspend,
834 imx8mq_usb_phy_runtime_resume, NULL);
835
836 static struct platform_driver imx8mq_usb_phy_driver = {
837 .probe = imx8mq_usb_phy_probe,
838 .remove = imx8mq_usb_phy_remove,
839 .driver = {
840 .name = "imx8mq-usb-phy",
841 .of_match_table = imx8mq_usb_phy_of_match,
842 .pm = pm_ptr(&imx8mq_usb_phy_pm_ops),
843 .suppress_bind_attrs = true,
844 }
845 };
846 module_platform_driver(imx8mq_usb_phy_driver);
847
848 MODULE_DESCRIPTION("FSL IMX8MQ USB PHY driver");
849 MODULE_LICENSE("GPL");
850