1644930cbSLubomir Rintel // SPDX-License-Identifier: GPL-2.0
2644930cbSLubomir Rintel /*
3644930cbSLubomir Rintel  * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
4644930cbSLubomir Rintel  * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>
5644930cbSLubomir Rintel  */
6644930cbSLubomir Rintel 
7644930cbSLubomir Rintel #include <dt-bindings/phy/phy.h>
8644930cbSLubomir Rintel #include <linux/clk.h>
9644930cbSLubomir Rintel #include <linux/delay.h>
10644930cbSLubomir Rintel #include <linux/io.h>
11644930cbSLubomir Rintel #include <linux/module.h>
12644930cbSLubomir Rintel #include <linux/of_address.h>
13644930cbSLubomir Rintel #include <linux/phy/phy.h>
14644930cbSLubomir Rintel #include <linux/platform_device.h>
15644930cbSLubomir Rintel 
16644930cbSLubomir Rintel /* phy regs */
17644930cbSLubomir Rintel #define UTMI_REVISION		0x0
18644930cbSLubomir Rintel #define UTMI_CTRL		0x4
19644930cbSLubomir Rintel #define UTMI_PLL		0x8
20644930cbSLubomir Rintel #define UTMI_TX			0xc
21644930cbSLubomir Rintel #define UTMI_RX			0x10
22644930cbSLubomir Rintel #define UTMI_IVREF		0x14
23644930cbSLubomir Rintel #define UTMI_T0			0x18
24644930cbSLubomir Rintel #define UTMI_T1			0x1c
25644930cbSLubomir Rintel #define UTMI_T2			0x20
26644930cbSLubomir Rintel #define UTMI_T3			0x24
27644930cbSLubomir Rintel #define UTMI_T4			0x28
28644930cbSLubomir Rintel #define UTMI_T5			0x2c
29644930cbSLubomir Rintel #define UTMI_RESERVE		0x30
30644930cbSLubomir Rintel #define UTMI_USB_INT		0x34
31644930cbSLubomir Rintel #define UTMI_DBG_CTL		0x38
32644930cbSLubomir Rintel #define UTMI_OTG_ADDON		0x3c
33644930cbSLubomir Rintel 
34644930cbSLubomir Rintel /* For UTMICTRL Register */
35644930cbSLubomir Rintel #define UTMI_CTRL_USB_CLK_EN                    (1 << 31)
36644930cbSLubomir Rintel /* pxa168 */
37644930cbSLubomir Rintel #define UTMI_CTRL_SUSPEND_SET1                  (1 << 30)
38644930cbSLubomir Rintel #define UTMI_CTRL_SUSPEND_SET2                  (1 << 29)
39644930cbSLubomir Rintel #define UTMI_CTRL_RXBUF_PDWN                    (1 << 24)
40644930cbSLubomir Rintel #define UTMI_CTRL_TXBUF_PDWN                    (1 << 11)
41644930cbSLubomir Rintel 
42644930cbSLubomir Rintel #define UTMI_CTRL_INPKT_DELAY_SHIFT             30
43644930cbSLubomir Rintel #define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT		28
44644930cbSLubomir Rintel #define UTMI_CTRL_PU_REF_SHIFT			20
45644930cbSLubomir Rintel #define UTMI_CTRL_ARC_PULLDN_SHIFT              12
46644930cbSLubomir Rintel #define UTMI_CTRL_PLL_PWR_UP_SHIFT              1
47644930cbSLubomir Rintel #define UTMI_CTRL_PWR_UP_SHIFT                  0
48644930cbSLubomir Rintel 
49644930cbSLubomir Rintel /* For UTMI_PLL Register */
50644930cbSLubomir Rintel #define UTMI_PLL_PLLCALI12_SHIFT		29
51644930cbSLubomir Rintel #define UTMI_PLL_PLLCALI12_MASK			(0x3 << 29)
52644930cbSLubomir Rintel 
53644930cbSLubomir Rintel #define UTMI_PLL_PLLVDD18_SHIFT			27
54644930cbSLubomir Rintel #define UTMI_PLL_PLLVDD18_MASK			(0x3 << 27)
55644930cbSLubomir Rintel 
56644930cbSLubomir Rintel #define UTMI_PLL_PLLVDD12_SHIFT			25
57644930cbSLubomir Rintel #define UTMI_PLL_PLLVDD12_MASK			(0x3 << 25)
58644930cbSLubomir Rintel 
59644930cbSLubomir Rintel #define UTMI_PLL_CLK_BLK_EN_SHIFT               24
60644930cbSLubomir Rintel #define CLK_BLK_EN                              (0x1 << 24)
61644930cbSLubomir Rintel #define PLL_READY                               (0x1 << 23)
62644930cbSLubomir Rintel #define KVCO_EXT                                (0x1 << 22)
63644930cbSLubomir Rintel #define VCOCAL_START                            (0x1 << 21)
64644930cbSLubomir Rintel 
65644930cbSLubomir Rintel #define UTMI_PLL_KVCO_SHIFT			15
66644930cbSLubomir Rintel #define UTMI_PLL_KVCO_MASK                      (0x7 << 15)
67644930cbSLubomir Rintel 
68644930cbSLubomir Rintel #define UTMI_PLL_ICP_SHIFT			12
69644930cbSLubomir Rintel #define UTMI_PLL_ICP_MASK                       (0x7 << 12)
70644930cbSLubomir Rintel 
71644930cbSLubomir Rintel #define UTMI_PLL_FBDIV_SHIFT                    4
72644930cbSLubomir Rintel #define UTMI_PLL_FBDIV_MASK                     (0xFF << 4)
73644930cbSLubomir Rintel 
74644930cbSLubomir Rintel #define UTMI_PLL_REFDIV_SHIFT                   0
75644930cbSLubomir Rintel #define UTMI_PLL_REFDIV_MASK                    (0xF << 0)
76644930cbSLubomir Rintel 
77644930cbSLubomir Rintel /* For UTMI_TX Register */
78644930cbSLubomir Rintel #define UTMI_TX_REG_EXT_FS_RCAL_SHIFT		27
79644930cbSLubomir Rintel #define UTMI_TX_REG_EXT_FS_RCAL_MASK		(0xf << 27)
80644930cbSLubomir Rintel 
81644930cbSLubomir Rintel #define UTMI_TX_REG_EXT_FS_RCAL_EN_SHIFT	26
82644930cbSLubomir Rintel #define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK		(0x1 << 26)
83644930cbSLubomir Rintel 
84644930cbSLubomir Rintel #define UTMI_TX_TXVDD12_SHIFT                   22
85644930cbSLubomir Rintel #define UTMI_TX_TXVDD12_MASK                    (0x3 << 22)
86644930cbSLubomir Rintel 
87644930cbSLubomir Rintel #define UTMI_TX_CK60_PHSEL_SHIFT                17
88644930cbSLubomir Rintel #define UTMI_TX_CK60_PHSEL_MASK                 (0xf << 17)
89644930cbSLubomir Rintel 
90644930cbSLubomir Rintel #define UTMI_TX_IMPCAL_VTH_SHIFT                14
91644930cbSLubomir Rintel #define UTMI_TX_IMPCAL_VTH_MASK                 (0x7 << 14)
92644930cbSLubomir Rintel 
93644930cbSLubomir Rintel #define REG_RCAL_START                          (0x1 << 12)
94644930cbSLubomir Rintel 
95644930cbSLubomir Rintel #define UTMI_TX_LOW_VDD_EN_SHIFT                11
96644930cbSLubomir Rintel 
97644930cbSLubomir Rintel #define UTMI_TX_AMP_SHIFT			0
98644930cbSLubomir Rintel #define UTMI_TX_AMP_MASK			(0x7 << 0)
99644930cbSLubomir Rintel 
100644930cbSLubomir Rintel /* For UTMI_RX Register */
101644930cbSLubomir Rintel #define UTMI_REG_SQ_LENGTH_SHIFT                15
102644930cbSLubomir Rintel #define UTMI_REG_SQ_LENGTH_MASK                 (0x3 << 15)
103644930cbSLubomir Rintel 
104644930cbSLubomir Rintel #define UTMI_RX_SQ_THRESH_SHIFT                 4
105644930cbSLubomir Rintel #define UTMI_RX_SQ_THRESH_MASK                  (0xf << 4)
106644930cbSLubomir Rintel 
107644930cbSLubomir Rintel #define UTMI_OTG_ADDON_OTG_ON			(1 << 0)
108644930cbSLubomir Rintel 
109644930cbSLubomir Rintel enum pxa_usb_phy_version {
110644930cbSLubomir Rintel 	PXA_USB_PHY_MMP2,
111644930cbSLubomir Rintel 	PXA_USB_PHY_PXA910,
112644930cbSLubomir Rintel 	PXA_USB_PHY_PXA168,
113644930cbSLubomir Rintel };
114644930cbSLubomir Rintel 
115644930cbSLubomir Rintel struct pxa_usb_phy {
116644930cbSLubomir Rintel 	struct phy *phy;
117644930cbSLubomir Rintel 	void __iomem *base;
118644930cbSLubomir Rintel 	enum pxa_usb_phy_version version;
119644930cbSLubomir Rintel };
120644930cbSLubomir Rintel 
121644930cbSLubomir Rintel /*****************************************************************************
122644930cbSLubomir Rintel  * The registers read/write routines
123644930cbSLubomir Rintel  *****************************************************************************/
124644930cbSLubomir Rintel 
u2o_get(void __iomem * base,unsigned int offset)125644930cbSLubomir Rintel static unsigned int u2o_get(void __iomem *base, unsigned int offset)
126644930cbSLubomir Rintel {
127644930cbSLubomir Rintel 	return readl_relaxed(base + offset);
128644930cbSLubomir Rintel }
129644930cbSLubomir Rintel 
u2o_set(void __iomem * base,unsigned int offset,unsigned int value)130644930cbSLubomir Rintel static void u2o_set(void __iomem *base, unsigned int offset,
131644930cbSLubomir Rintel 		unsigned int value)
132644930cbSLubomir Rintel {
133644930cbSLubomir Rintel 	u32 reg;
134644930cbSLubomir Rintel 
135644930cbSLubomir Rintel 	reg = readl_relaxed(base + offset);
136644930cbSLubomir Rintel 	reg |= value;
137644930cbSLubomir Rintel 	writel_relaxed(reg, base + offset);
138644930cbSLubomir Rintel 	readl_relaxed(base + offset);
139644930cbSLubomir Rintel }
140644930cbSLubomir Rintel 
u2o_clear(void __iomem * base,unsigned int offset,unsigned int value)141644930cbSLubomir Rintel static void u2o_clear(void __iomem *base, unsigned int offset,
142644930cbSLubomir Rintel 		unsigned int value)
143644930cbSLubomir Rintel {
144644930cbSLubomir Rintel 	u32 reg;
145644930cbSLubomir Rintel 
146644930cbSLubomir Rintel 	reg = readl_relaxed(base + offset);
147644930cbSLubomir Rintel 	reg &= ~value;
148644930cbSLubomir Rintel 	writel_relaxed(reg, base + offset);
149644930cbSLubomir Rintel 	readl_relaxed(base + offset);
150644930cbSLubomir Rintel }
151644930cbSLubomir Rintel 
u2o_write(void __iomem * base,unsigned int offset,unsigned int value)152644930cbSLubomir Rintel static void u2o_write(void __iomem *base, unsigned int offset,
153644930cbSLubomir Rintel 		unsigned int value)
154644930cbSLubomir Rintel {
155644930cbSLubomir Rintel 	writel_relaxed(value, base + offset);
156644930cbSLubomir Rintel 	readl_relaxed(base + offset);
157644930cbSLubomir Rintel }
158644930cbSLubomir Rintel 
pxa_usb_phy_init(struct phy * phy)159644930cbSLubomir Rintel static int pxa_usb_phy_init(struct phy *phy)
160644930cbSLubomir Rintel {
161644930cbSLubomir Rintel 	struct pxa_usb_phy *pxa_usb_phy = phy_get_drvdata(phy);
162644930cbSLubomir Rintel 	void __iomem *base = pxa_usb_phy->base;
163644930cbSLubomir Rintel 	int loops;
164644930cbSLubomir Rintel 
165644930cbSLubomir Rintel 	dev_info(&phy->dev, "initializing Marvell PXA USB PHY");
166644930cbSLubomir Rintel 
167644930cbSLubomir Rintel 	/* Initialize the USB PHY power */
168644930cbSLubomir Rintel 	if (pxa_usb_phy->version == PXA_USB_PHY_PXA910) {
169644930cbSLubomir Rintel 		u2o_set(base, UTMI_CTRL, (1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT)
170644930cbSLubomir Rintel 			| (1<<UTMI_CTRL_PU_REF_SHIFT));
171644930cbSLubomir Rintel 	}
172644930cbSLubomir Rintel 
173644930cbSLubomir Rintel 	u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
174644930cbSLubomir Rintel 	u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
175644930cbSLubomir Rintel 
176644930cbSLubomir Rintel 	/* UTMI_PLL settings */
177644930cbSLubomir Rintel 	u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK
178644930cbSLubomir Rintel 		| UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK
179644930cbSLubomir Rintel 		| UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK
180644930cbSLubomir Rintel 		| UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK);
181644930cbSLubomir Rintel 
182644930cbSLubomir Rintel 	u2o_set(base, UTMI_PLL, 0xee<<UTMI_PLL_FBDIV_SHIFT
183644930cbSLubomir Rintel 		| 0xb<<UTMI_PLL_REFDIV_SHIFT | 3<<UTMI_PLL_PLLVDD18_SHIFT
184644930cbSLubomir Rintel 		| 3<<UTMI_PLL_PLLVDD12_SHIFT | 3<<UTMI_PLL_PLLCALI12_SHIFT
185644930cbSLubomir Rintel 		| 1<<UTMI_PLL_ICP_SHIFT | 3<<UTMI_PLL_KVCO_SHIFT);
186644930cbSLubomir Rintel 
187644930cbSLubomir Rintel 	/* UTMI_TX */
188644930cbSLubomir Rintel 	u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK
189644930cbSLubomir Rintel 		| UTMI_TX_TXVDD12_MASK | UTMI_TX_CK60_PHSEL_MASK
190644930cbSLubomir Rintel 		| UTMI_TX_IMPCAL_VTH_MASK | UTMI_TX_REG_EXT_FS_RCAL_MASK
191644930cbSLubomir Rintel 		| UTMI_TX_AMP_MASK);
192644930cbSLubomir Rintel 	u2o_set(base, UTMI_TX, 3<<UTMI_TX_TXVDD12_SHIFT
193644930cbSLubomir Rintel 		| 4<<UTMI_TX_CK60_PHSEL_SHIFT | 4<<UTMI_TX_IMPCAL_VTH_SHIFT
194644930cbSLubomir Rintel 		| 8<<UTMI_TX_REG_EXT_FS_RCAL_SHIFT | 3<<UTMI_TX_AMP_SHIFT);
195644930cbSLubomir Rintel 
196644930cbSLubomir Rintel 	/* UTMI_RX */
197644930cbSLubomir Rintel 	u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK
198644930cbSLubomir Rintel 		| UTMI_REG_SQ_LENGTH_MASK);
199644930cbSLubomir Rintel 	u2o_set(base, UTMI_RX, 7<<UTMI_RX_SQ_THRESH_SHIFT
200644930cbSLubomir Rintel 		| 2<<UTMI_REG_SQ_LENGTH_SHIFT);
201644930cbSLubomir Rintel 
202644930cbSLubomir Rintel 	/* UTMI_IVREF */
203644930cbSLubomir Rintel 	if (pxa_usb_phy->version == PXA_USB_PHY_PXA168) {
204644930cbSLubomir Rintel 		/*
205644930cbSLubomir Rintel 		 * fixing Microsoft Altair board interface with NEC hub issue -
206644930cbSLubomir Rintel 		 * Set UTMI_IVREF from 0x4a3 to 0x4bf
207644930cbSLubomir Rintel 		 */
208644930cbSLubomir Rintel 		u2o_write(base, UTMI_IVREF, 0x4bf);
209644930cbSLubomir Rintel 	}
210644930cbSLubomir Rintel 
211644930cbSLubomir Rintel 	/* toggle VCOCAL_START bit of UTMI_PLL */
212644930cbSLubomir Rintel 	udelay(200);
213644930cbSLubomir Rintel 	u2o_set(base, UTMI_PLL, VCOCAL_START);
214644930cbSLubomir Rintel 	udelay(40);
215644930cbSLubomir Rintel 	u2o_clear(base, UTMI_PLL, VCOCAL_START);
216644930cbSLubomir Rintel 
217644930cbSLubomir Rintel 	/* toggle REG_RCAL_START bit of UTMI_TX */
218644930cbSLubomir Rintel 	udelay(400);
219644930cbSLubomir Rintel 	u2o_set(base, UTMI_TX, REG_RCAL_START);
220644930cbSLubomir Rintel 	udelay(40);
221644930cbSLubomir Rintel 	u2o_clear(base, UTMI_TX, REG_RCAL_START);
222644930cbSLubomir Rintel 	udelay(400);
223644930cbSLubomir Rintel 
224644930cbSLubomir Rintel 	/* Make sure PHY PLL is ready */
225644930cbSLubomir Rintel 	loops = 0;
226644930cbSLubomir Rintel 	while ((u2o_get(base, UTMI_PLL) & PLL_READY) == 0) {
227644930cbSLubomir Rintel 		mdelay(1);
228644930cbSLubomir Rintel 		loops++;
229644930cbSLubomir Rintel 		if (loops > 100) {
230644930cbSLubomir Rintel 			dev_warn(&phy->dev, "calibrate timeout, UTMI_PLL %x\n",
231644930cbSLubomir Rintel 						u2o_get(base, UTMI_PLL));
232644930cbSLubomir Rintel 			break;
233644930cbSLubomir Rintel 		}
234644930cbSLubomir Rintel 	}
235644930cbSLubomir Rintel 
236644930cbSLubomir Rintel 	if (pxa_usb_phy->version == PXA_USB_PHY_PXA168) {
237644930cbSLubomir Rintel 		u2o_set(base, UTMI_RESERVE, 1 << 5);
238644930cbSLubomir Rintel 		/* Turn on UTMI PHY OTG extension */
239644930cbSLubomir Rintel 		u2o_write(base, UTMI_OTG_ADDON, 1);
240644930cbSLubomir Rintel 	}
241644930cbSLubomir Rintel 
242644930cbSLubomir Rintel 	return 0;
243644930cbSLubomir Rintel 
244644930cbSLubomir Rintel }
245644930cbSLubomir Rintel 
pxa_usb_phy_exit(struct phy * phy)246644930cbSLubomir Rintel static int pxa_usb_phy_exit(struct phy *phy)
247644930cbSLubomir Rintel {
248644930cbSLubomir Rintel 	struct pxa_usb_phy *pxa_usb_phy = phy_get_drvdata(phy);
249644930cbSLubomir Rintel 	void __iomem *base = pxa_usb_phy->base;
250644930cbSLubomir Rintel 
251644930cbSLubomir Rintel 	dev_info(&phy->dev, "deinitializing Marvell PXA USB PHY");
252644930cbSLubomir Rintel 
253644930cbSLubomir Rintel 	if (pxa_usb_phy->version == PXA_USB_PHY_PXA168)
254644930cbSLubomir Rintel 		u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON);
255644930cbSLubomir Rintel 
256644930cbSLubomir Rintel 	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN);
257644930cbSLubomir Rintel 	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN);
258644930cbSLubomir Rintel 	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN);
259644930cbSLubomir Rintel 	u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
260644930cbSLubomir Rintel 	u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
261644930cbSLubomir Rintel 
262644930cbSLubomir Rintel 	return 0;
263644930cbSLubomir Rintel }
264644930cbSLubomir Rintel 
265644930cbSLubomir Rintel static const struct phy_ops pxa_usb_phy_ops = {
266644930cbSLubomir Rintel 	.init	= pxa_usb_phy_init,
267644930cbSLubomir Rintel 	.exit	= pxa_usb_phy_exit,
268644930cbSLubomir Rintel 	.owner	= THIS_MODULE,
269644930cbSLubomir Rintel };
270644930cbSLubomir Rintel 
271644930cbSLubomir Rintel static const struct of_device_id pxa_usb_phy_of_match[] = {
272644930cbSLubomir Rintel 	{
273644930cbSLubomir Rintel 		.compatible = "marvell,mmp2-usb-phy",
274644930cbSLubomir Rintel 		.data = (void *)PXA_USB_PHY_MMP2,
275644930cbSLubomir Rintel 	}, {
276644930cbSLubomir Rintel 		.compatible = "marvell,pxa910-usb-phy",
277644930cbSLubomir Rintel 		.data = (void *)PXA_USB_PHY_PXA910,
278644930cbSLubomir Rintel 	}, {
279644930cbSLubomir Rintel 		.compatible = "marvell,pxa168-usb-phy",
280644930cbSLubomir Rintel 		.data = (void *)PXA_USB_PHY_PXA168,
281644930cbSLubomir Rintel 	},
282644930cbSLubomir Rintel 	{ },
283644930cbSLubomir Rintel };
284644930cbSLubomir Rintel MODULE_DEVICE_TABLE(of, pxa_usb_phy_of_match);
285644930cbSLubomir Rintel 
pxa_usb_phy_probe(struct platform_device * pdev)286644930cbSLubomir Rintel static int pxa_usb_phy_probe(struct platform_device *pdev)
287644930cbSLubomir Rintel {
288644930cbSLubomir Rintel 	struct device *dev = &pdev->dev;
289644930cbSLubomir Rintel 	struct pxa_usb_phy *pxa_usb_phy;
290644930cbSLubomir Rintel 	struct phy_provider *provider;
291644930cbSLubomir Rintel 	const struct of_device_id *of_id;
292644930cbSLubomir Rintel 
293644930cbSLubomir Rintel 	pxa_usb_phy = devm_kzalloc(dev, sizeof(struct pxa_usb_phy), GFP_KERNEL);
294644930cbSLubomir Rintel 	if (!pxa_usb_phy)
295644930cbSLubomir Rintel 		return -ENOMEM;
296644930cbSLubomir Rintel 
297644930cbSLubomir Rintel 	of_id = of_match_node(pxa_usb_phy_of_match, dev->of_node);
298644930cbSLubomir Rintel 	if (of_id)
299*7451eecfSKrzysztof Kozlowski 		pxa_usb_phy->version = (uintptr_t)of_id->data;
300644930cbSLubomir Rintel 	else
301644930cbSLubomir Rintel 		pxa_usb_phy->version = PXA_USB_PHY_MMP2;
302644930cbSLubomir Rintel 
303ee55b501SChunfeng Yun 	pxa_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);
304644930cbSLubomir Rintel 	if (IS_ERR(pxa_usb_phy->base)) {
305644930cbSLubomir Rintel 		dev_err(dev, "failed to remap PHY regs\n");
306644930cbSLubomir Rintel 		return PTR_ERR(pxa_usb_phy->base);
307644930cbSLubomir Rintel 	}
308644930cbSLubomir Rintel 
309644930cbSLubomir Rintel 	pxa_usb_phy->phy = devm_phy_create(dev, NULL, &pxa_usb_phy_ops);
310644930cbSLubomir Rintel 	if (IS_ERR(pxa_usb_phy->phy)) {
311644930cbSLubomir Rintel 		dev_err(dev, "failed to create PHY\n");
312644930cbSLubomir Rintel 		return PTR_ERR(pxa_usb_phy->phy);
313644930cbSLubomir Rintel 	}
314644930cbSLubomir Rintel 
315644930cbSLubomir Rintel 	phy_set_drvdata(pxa_usb_phy->phy, pxa_usb_phy);
316644930cbSLubomir Rintel 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
317644930cbSLubomir Rintel 	if (IS_ERR(provider)) {
318644930cbSLubomir Rintel 		dev_err(dev, "failed to register PHY provider\n");
319644930cbSLubomir Rintel 		return PTR_ERR(provider);
320644930cbSLubomir Rintel 	}
321644930cbSLubomir Rintel 
322644930cbSLubomir Rintel 	if (!dev->of_node) {
323644930cbSLubomir Rintel 		phy_create_lookup(pxa_usb_phy->phy, "usb", "mv-udc");
324644930cbSLubomir Rintel 		phy_create_lookup(pxa_usb_phy->phy, "usb", "pxa-u2oehci");
325644930cbSLubomir Rintel 		phy_create_lookup(pxa_usb_phy->phy, "usb", "mv-otg");
326644930cbSLubomir Rintel 	}
327644930cbSLubomir Rintel 
328644930cbSLubomir Rintel 	dev_info(dev, "Marvell PXA USB PHY");
329644930cbSLubomir Rintel 	return 0;
330644930cbSLubomir Rintel }
331644930cbSLubomir Rintel 
332644930cbSLubomir Rintel static struct platform_driver pxa_usb_phy_driver = {
333644930cbSLubomir Rintel 	.probe		= pxa_usb_phy_probe,
334644930cbSLubomir Rintel 	.driver		= {
335644930cbSLubomir Rintel 		.name	= "pxa-usb-phy",
336644930cbSLubomir Rintel 		.of_match_table = pxa_usb_phy_of_match,
337644930cbSLubomir Rintel 	},
338644930cbSLubomir Rintel };
339644930cbSLubomir Rintel module_platform_driver(pxa_usb_phy_driver);
340644930cbSLubomir Rintel 
341644930cbSLubomir Rintel MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
342644930cbSLubomir Rintel MODULE_DESCRIPTION("Marvell PXA USB PHY Driver");
343644930cbSLubomir Rintel MODULE_LICENSE("GPL v2");
344