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