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