1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform
4 *
5 * Copyright (C) 2017-2020 Hilisicon Electronics Co., Ltd.
6 *		http://www.huawei.com
7 *
8 * Authors: Yu Chen <chenyu56@huawei.com>
9 */
10
11#include <linux/bitfield.h>
12#include <linux/clk.h>
13#include <linux/kernel.h>
14#include <linux/mfd/syscon.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/phy/phy.h>
18#include <linux/platform_device.h>
19#include <linux/regmap.h>
20
21#define SCTRL_SCDEEPSLEEPED		(0x0)
22#define USB_CLK_SELECTED		BIT(20)
23
24#define PERI_CRG_PEREN0			(0x00)
25#define PERI_CRG_PERDIS0		(0x04)
26#define PERI_CRG_PEREN4			(0x40)
27#define PERI_CRG_PERDIS4		(0x44)
28#define PERI_CRG_PERRSTEN4		(0x90)
29#define PERI_CRG_PERRSTDIS4		(0x94)
30#define PERI_CRG_ISODIS			(0x148)
31#define PERI_CRG_PEREN6			(0x410)
32#define PERI_CRG_PERDIS6		(0x414)
33
34#define USB_REFCLK_ISO_EN		BIT(25)
35
36#define GT_CLK_USB2PHY_REF		BIT(19)
37
38#define PCTRL_PERI_CTRL3		(0x10)
39#define PCTRL_PERI_CTRL3_MSK_START	(16)
40#define USB_TCXO_EN			BIT(1)
41
42#define PCTRL_PERI_CTRL24		(0x64)
43#define SC_CLK_USB3PHY_3MUX1_SEL	BIT(25)
44
45#define USB3OTG_CTRL0			(0x00)
46#define USB3OTG_CTRL3			(0x0c)
47#define USB3OTG_CTRL4			(0x10)
48#define USB3OTG_CTRL5			(0x14)
49#define USB3OTG_CTRL7			(0x1c)
50#define USB_MISC_CFG50			(0x50)
51#define USB_MISC_CFG54			(0x54)
52#define USB_MISC_CFG58			(0x58)
53#define USB_MISC_CFG5C			(0x5c)
54#define USB_MISC_CFGA0			(0xa0)
55#define TCA_CLK_RST			(0x200)
56#define TCA_INTR_EN			(0x204)
57#define TCA_INTR_STS			(0x208)
58#define TCA_GCFG			(0x210)
59#define TCA_TCPC			(0x214)
60#define TCA_SYSMODE_CFG			(0x218)
61#define TCA_VBUS_CTRL			(0x240)
62
63#define CTRL0_USB3_VBUSVLD		BIT(7)
64#define CTRL0_USB3_VBUSVLD_SEL		BIT(6)
65
66#define CTRL3_USB2_VBUSVLDEXT0		BIT(6)
67#define CTRL3_USB2_VBUSVLDEXTSEL0	BIT(5)
68
69#define CTRL5_USB2_SIDDQ		BIT(0)
70
71#define CTRL7_USB2_REFCLKSEL_MASK	GENMASK(4, 3)
72#define CTRL7_USB2_REFCLKSEL_ABB	(BIT(4) | BIT(3))
73#define CTRL7_USB2_REFCLKSEL_PAD	BIT(4)
74
75#define CFG50_USB3_PHY_TEST_POWERDOWN	BIT(23)
76
77#define CFG54_USB31PHY_CR_ADDR_MASK	GENMASK(31, 16)
78
79#define CFG54_USB3PHY_REF_USE_PAD	BIT(12)
80#define CFG54_PHY0_PMA_PWR_STABLE	BIT(11)
81#define CFG54_PHY0_PCS_PWR_STABLE	BIT(9)
82#define CFG54_USB31PHY_CR_ACK		BIT(7)
83#define CFG54_USB31PHY_CR_WR_EN		BIT(5)
84#define CFG54_USB31PHY_CR_SEL		BIT(4)
85#define CFG54_USB31PHY_CR_RD_EN		BIT(3)
86#define CFG54_USB31PHY_CR_CLK		BIT(2)
87#define CFG54_USB3_PHY0_ANA_PWR_EN	BIT(1)
88
89#define CFG58_USB31PHY_CR_DATA_MASK     GENMASK(31, 16)
90
91#define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN	BIT(1)
92
93#define CFGA0_VAUX_RESET		BIT(9)
94#define CFGA0_USB31C_RESET		BIT(8)
95#define CFGA0_USB2PHY_REFCLK_SELECT	BIT(4)
96#define CFGA0_USB3PHY_RESET		BIT(1)
97#define CFGA0_USB2PHY_POR		BIT(0)
98
99#define INTR_EN_XA_TIMEOUT_EVT_EN	BIT(1)
100#define INTR_EN_XA_ACK_EVT_EN		BIT(0)
101
102#define CLK_RST_TCA_REF_CLK_EN		BIT(1)
103#define CLK_RST_SUSPEND_CLK_EN		BIT(0)
104
105#define GCFG_ROLE_HSTDEV		BIT(4)
106#define GCFG_OP_MODE			GENMASK(1, 0)
107#define GCFG_OP_MODE_CTRL_SYNC_MODE	BIT(0)
108
109#define TCPC_VALID			BIT(4)
110#define TCPC_LOW_POWER_EN		BIT(3)
111#define TCPC_MUX_CONTROL_MASK		GENMASK(1, 0)
112#define TCPC_MUX_CONTROL_USB31		BIT(0)
113
114#define SYSMODE_CFG_TYPEC_DISABLE	BIT(3)
115
116#define VBUS_CTRL_POWERPRESENT_OVERRD	GENMASK(3, 2)
117#define VBUS_CTRL_VBUSVALID_OVERRD	GENMASK(1, 0)
118
119#define KIRIN970_USB_DEFAULT_PHY_PARAM	(0xfdfee4)
120#define KIRIN970_USB_DEFAULT_PHY_VBOOST	(0x5)
121
122#define TX_VBOOST_LVL_REG		(0xf)
123#define TX_VBOOST_LVL_START		(6)
124#define TX_VBOOST_LVL_ENABLE		BIT(9)
125
126struct hi3670_priv {
127	struct device *dev;
128	struct regmap *peri_crg;
129	struct regmap *pctrl;
130	struct regmap *sctrl;
131	struct regmap *usb31misc;
132
133	u32 eye_diagram_param;
134	u32 tx_vboost_lvl;
135
136	u32 peri_crg_offset;
137	u32 pctrl_offset;
138	u32 usb31misc_offset;
139};
140
141static int hi3670_phy_cr_clk(struct regmap *usb31misc)
142{
143	int ret;
144
145	/* Clock up */
146	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
147				 CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK);
148	if (ret)
149		return ret;
150
151	/* Clock down */
152	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
153				  CFG54_USB31PHY_CR_CLK, 0);
154}
155
156static int hi3670_phy_cr_set_sel(struct regmap *usb31misc)
157{
158	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
159				  CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL);
160}
161
162static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction)
163{
164	int ret, reg;
165
166	if (direction)
167		reg = CFG54_USB31PHY_CR_WR_EN;
168	else
169		reg = CFG54_USB31PHY_CR_RD_EN;
170
171	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, reg, reg);
172
173	if (ret)
174		return ret;
175
176	ret = hi3670_phy_cr_clk(usb31misc);
177	if (ret)
178		return ret;
179
180	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
181				  CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0);
182}
183
184static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc)
185{
186	u32 reg;
187	int retry = 10;
188	int ret;
189
190	while (retry-- > 0) {
191		ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
192		if (ret)
193			return ret;
194		if ((reg & CFG54_USB31PHY_CR_ACK) == CFG54_USB31PHY_CR_ACK)
195			return 0;
196
197		ret = hi3670_phy_cr_clk(usb31misc);
198		if (ret)
199			return ret;
200
201		usleep_range(10, 20);
202	}
203
204	return -ETIMEDOUT;
205}
206
207static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr)
208{
209	u32 reg;
210	int ret;
211
212	ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
213	if (ret)
214		return ret;
215
216	reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr);
217
218	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
219				  CFG54_USB31PHY_CR_ADDR_MASK, reg);
220}
221
222static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val)
223{
224	int reg, i, ret;
225
226	for (i = 0; i < 100; i++) {
227		ret = hi3670_phy_cr_clk(usb31misc);
228		if (ret)
229			return ret;
230	}
231
232	ret = hi3670_phy_cr_set_sel(usb31misc);
233	if (ret)
234		return ret;
235
236	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
237	if (ret)
238		return ret;
239
240	ret = hi3670_phy_cr_start(usb31misc, 0);
241	if (ret)
242		return ret;
243
244	ret = hi3670_phy_cr_wait_ack(usb31misc);
245	if (ret)
246		return ret;
247
248	ret = regmap_read(usb31misc, USB_MISC_CFG58, &reg);
249	if (ret)
250		return ret;
251
252	*val = FIELD_GET(CFG58_USB31PHY_CR_DATA_MASK, reg);
253
254	return 0;
255}
256
257static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val)
258{
259	int i;
260	int ret;
261
262	for (i = 0; i < 100; i++) {
263		ret = hi3670_phy_cr_clk(usb31misc);
264		if (ret)
265			return ret;
266	}
267
268	ret = hi3670_phy_cr_set_sel(usb31misc);
269	if (ret)
270		return ret;
271
272	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
273	if (ret)
274		return ret;
275
276	ret = regmap_write(usb31misc, USB_MISC_CFG58,
277			   FIELD_PREP(CFG58_USB31PHY_CR_DATA_MASK, val));
278	if (ret)
279		return ret;
280
281	ret = hi3670_phy_cr_start(usb31misc, 1);
282	if (ret)
283		return ret;
284
285	return hi3670_phy_cr_wait_ack(usb31misc);
286}
287
288static int hi3670_phy_set_params(struct hi3670_priv *priv)
289{
290	u32 reg;
291	int ret;
292	int retry = 3;
293
294	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL4,
295			   priv->eye_diagram_param);
296	if (ret) {
297		dev_err(priv->dev, "set USB3OTG_CTRL4 failed\n");
298		return ret;
299	}
300
301	while (retry-- > 0) {
302		ret = hi3670_phy_cr_read(priv->usb31misc,
303					 TX_VBOOST_LVL_REG, &reg);
304		if (!ret)
305			break;
306
307		if (ret != -ETIMEDOUT) {
308			dev_err(priv->dev, "read TX_VBOOST_LVL_REG failed\n");
309			return ret;
310		}
311	}
312	if (ret)
313		return ret;
314
315	reg |= (TX_VBOOST_LVL_ENABLE | (priv->tx_vboost_lvl << TX_VBOOST_LVL_START));
316	ret = hi3670_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg);
317	if (ret)
318		dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n");
319
320	return ret;
321}
322
323static bool hi3670_is_abbclk_selected(struct hi3670_priv *priv)
324{
325	u32 reg;
326
327	if (!priv->sctrl) {
328		dev_err(priv->dev, "priv->sctrl is null!\n");
329		return false;
330	}
331
332	if (regmap_read(priv->sctrl, SCTRL_SCDEEPSLEEPED, &reg)) {
333		dev_err(priv->dev, "SCTRL_SCDEEPSLEEPED read failed!\n");
334		return false;
335	}
336
337	if ((reg & USB_CLK_SELECTED) == 0)
338		return false;
339
340	return true;
341}
342
343static int hi3670_config_phy_clock(struct hi3670_priv *priv)
344{
345	u32 val, mask;
346	int ret;
347
348	if (!hi3670_is_abbclk_selected(priv)) {
349		/* usb refclk iso disable */
350		ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS,
351				   USB_REFCLK_ISO_EN);
352		if (ret)
353			goto out;
354
355		/* enable usb_tcxo_en */
356		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
357				   USB_TCXO_EN |
358				   (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START));
359
360		/* select usbphy clk from abb */
361		mask = SC_CLK_USB3PHY_3MUX1_SEL;
362		ret = regmap_update_bits(priv->pctrl,
363					 PCTRL_PERI_CTRL24, mask, 0);
364		if (ret)
365			goto out;
366
367		ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
368					 CFGA0_USB2PHY_REFCLK_SELECT, 0);
369		if (ret)
370			goto out;
371
372		ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
373		if (ret)
374			goto out;
375		val &= ~CTRL7_USB2_REFCLKSEL_MASK;
376		val |= CTRL7_USB2_REFCLKSEL_ABB;
377		ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
378		if (ret)
379			goto out;
380
381		return 0;
382	}
383
384	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
385				 CFG54_USB3PHY_REF_USE_PAD,
386				 CFG54_USB3PHY_REF_USE_PAD);
387	if (ret)
388		goto out;
389
390	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
391				 CFGA0_USB2PHY_REFCLK_SELECT,
392				 CFGA0_USB2PHY_REFCLK_SELECT);
393	if (ret)
394		goto out;
395
396	ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
397	if (ret)
398		goto out;
399	val &= ~CTRL7_USB2_REFCLKSEL_MASK;
400	val |= CTRL7_USB2_REFCLKSEL_PAD;
401	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
402	if (ret)
403		goto out;
404
405	ret = regmap_write(priv->peri_crg,
406			   PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF);
407	if (ret)
408		goto out;
409
410	return 0;
411out:
412	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
413	return ret;
414}
415
416static int hi3670_config_tca(struct hi3670_priv *priv)
417{
418	u32 val, mask;
419	int ret;
420
421	ret = regmap_write(priv->usb31misc, TCA_INTR_STS, 0xffff);
422	if (ret)
423		goto out;
424
425	ret = regmap_write(priv->usb31misc, TCA_INTR_EN,
426			   INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN);
427	if (ret)
428		goto out;
429
430	mask = CLK_RST_TCA_REF_CLK_EN | CLK_RST_SUSPEND_CLK_EN;
431	ret = regmap_update_bits(priv->usb31misc, TCA_CLK_RST, mask, 0);
432	if (ret)
433		goto out;
434
435	ret = regmap_update_bits(priv->usb31misc, TCA_GCFG,
436				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE,
437				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE);
438	if (ret)
439		goto out;
440
441	ret = regmap_update_bits(priv->usb31misc, TCA_SYSMODE_CFG,
442				 SYSMODE_CFG_TYPEC_DISABLE, 0);
443	if (ret)
444		goto out;
445
446	ret = regmap_read(priv->usb31misc, TCA_TCPC, &val);
447	if (ret)
448		goto out;
449	val &= ~(TCPC_VALID | TCPC_LOW_POWER_EN | TCPC_MUX_CONTROL_MASK);
450	val |= (TCPC_VALID | TCPC_MUX_CONTROL_USB31);
451	ret = regmap_write(priv->usb31misc, TCA_TCPC, val);
452	if (ret)
453		goto out;
454
455	ret = regmap_write(priv->usb31misc, TCA_VBUS_CTRL,
456			   VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD);
457	if (ret)
458		goto out;
459
460	return 0;
461out:
462	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
463	return ret;
464}
465
466static int hi3670_phy_init(struct phy *phy)
467{
468	struct hi3670_priv *priv = phy_get_drvdata(phy);
469	u32 val;
470	int ret;
471
472	/* assert controller */
473	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET |
474	      CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
475	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0);
476	if (ret)
477		goto out;
478
479	ret = hi3670_config_phy_clock(priv);
480	if (ret)
481		goto out;
482
483	/* Exit from IDDQ mode */
484	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL5,
485				 CTRL5_USB2_SIDDQ, 0);
486	if (ret)
487		goto out;
488
489	/* Release USB31 PHY out of TestPowerDown mode */
490	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG50,
491				 CFG50_USB3_PHY_TEST_POWERDOWN, 0);
492	if (ret)
493		goto out;
494
495	/* Deassert phy */
496	val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
497	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
498	if (ret)
499		goto out;
500
501	usleep_range(100, 120);
502
503	/* Tell the PHY power is stable */
504	val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE |
505	      CFG54_PHY0_PMA_PWR_STABLE;
506	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
507				 val, val);
508	if (ret)
509		goto out;
510
511	ret = hi3670_config_tca(priv);
512	if (ret)
513		goto out;
514
515	/* Enable SSC */
516	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG5C,
517				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN,
518				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN);
519	if (ret)
520		goto out;
521
522	/* Deassert controller */
523	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET;
524	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
525	if (ret)
526		goto out;
527
528	usleep_range(100, 120);
529
530	/* Set fake vbus valid signal */
531	val = CTRL0_USB3_VBUSVLD | CTRL0_USB3_VBUSVLD_SEL;
532	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL0, val, val);
533	if (ret)
534		goto out;
535
536	val = CTRL3_USB2_VBUSVLDEXT0 | CTRL3_USB2_VBUSVLDEXTSEL0;
537	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL3, val, val);
538	if (ret)
539		goto out;
540
541	usleep_range(100, 120);
542
543	ret = hi3670_phy_set_params(priv);
544	if (ret)
545		goto out;
546
547	return 0;
548out:
549	dev_err(priv->dev, "failed to init phy ret: %d\n", ret);
550	return ret;
551}
552
553static int hi3670_phy_exit(struct phy *phy)
554{
555	struct hi3670_priv *priv = phy_get_drvdata(phy);
556	u32 mask;
557	int ret;
558
559	/* Assert phy */
560	mask = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
561	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, mask, 0);
562	if (ret)
563		goto out;
564
565	if (!hi3670_is_abbclk_selected(priv)) {
566		/* disable usb_tcxo_en */
567		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
568				   USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
569	} else {
570		ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6,
571				   GT_CLK_USB2PHY_REF);
572		if (ret)
573			goto out;
574	}
575
576	return 0;
577out:
578	dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);
579	return ret;
580}
581
582static const struct phy_ops hi3670_phy_ops = {
583	.init		= hi3670_phy_init,
584	.exit		= hi3670_phy_exit,
585	.owner		= THIS_MODULE,
586};
587
588static int hi3670_phy_probe(struct platform_device *pdev)
589{
590	struct phy_provider *phy_provider;
591	struct device *dev = &pdev->dev;
592	struct phy *phy;
593	struct hi3670_priv *priv;
594
595	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
596	if (!priv)
597		return -ENOMEM;
598
599	priv->dev = dev;
600	priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,
601							 "hisilicon,pericrg-syscon");
602	if (IS_ERR(priv->peri_crg)) {
603		dev_err(dev, "no hisilicon,pericrg-syscon\n");
604		return PTR_ERR(priv->peri_crg);
605	}
606
607	priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
608						      "hisilicon,pctrl-syscon");
609	if (IS_ERR(priv->pctrl)) {
610		dev_err(dev, "no hisilicon,pctrl-syscon\n");
611		return PTR_ERR(priv->pctrl);
612	}
613
614	priv->sctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
615						      "hisilicon,sctrl-syscon");
616	if (IS_ERR(priv->sctrl)) {
617		dev_err(dev, "no hisilicon,sctrl-syscon\n");
618		return PTR_ERR(priv->sctrl);
619	}
620
621	/* node of hi3670 phy is a sub-node of usb3_otg_bc */
622	priv->usb31misc = syscon_node_to_regmap(dev->parent->of_node);
623	if (IS_ERR(priv->usb31misc)) {
624		dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");
625		return PTR_ERR(priv->usb31misc);
626	}
627
628	if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param",
629				 &priv->eye_diagram_param))
630		priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM;
631
632	if (of_property_read_u32(dev->of_node, "hisilicon,tx-vboost-lvl",
633				 &priv->tx_vboost_lvl))
634		priv->tx_vboost_lvl = KIRIN970_USB_DEFAULT_PHY_VBOOST;
635
636	phy = devm_phy_create(dev, NULL, &hi3670_phy_ops);
637	if (IS_ERR(phy))
638		return PTR_ERR(phy);
639
640	phy_set_drvdata(phy, priv);
641	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
642	return PTR_ERR_OR_ZERO(phy_provider);
643}
644
645static const struct of_device_id hi3670_phy_of_match[] = {
646	{ .compatible = "hisilicon,hi3670-usb-phy" },
647	{ },
648};
649MODULE_DEVICE_TABLE(of, hi3670_phy_of_match);
650
651static struct platform_driver hi3670_phy_driver = {
652	.probe	= hi3670_phy_probe,
653	.driver = {
654		.name	= "hi3670-usb-phy",
655		.of_match_table	= hi3670_phy_of_match,
656	}
657};
658module_platform_driver(hi3670_phy_driver);
659
660MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
661MODULE_LICENSE("GPL v2");
662MODULE_DESCRIPTION("Hilisicon Kirin970 USB31 PHY Driver");
663