1 /*
2  * Samsung EXYNOS5 SoC series USB DRD PHY driver
3  *
4  * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
5  *
6  * Copyright (C) 2014 Samsung Electronics Co., Ltd.
7  * Author: Vivek Gautam <gautam.vivek@samsung.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/of_address.h>
21 #include <linux/of_device.h>
22 #include <linux/phy/phy.h>
23 #include <linux/platform_device.h>
24 #include <linux/mutex.h>
25 #include <linux/mfd/syscon.h>
26 #include <linux/regmap.h>
27 #include <linux/regulator/consumer.h>
28 #include <linux/soc/samsung/exynos-regs-pmu.h>
29 
30 /* Exynos USB PHY registers */
31 #define EXYNOS5_FSEL_9MHZ6		0x0
32 #define EXYNOS5_FSEL_10MHZ		0x1
33 #define EXYNOS5_FSEL_12MHZ		0x2
34 #define EXYNOS5_FSEL_19MHZ2		0x3
35 #define EXYNOS5_FSEL_20MHZ		0x4
36 #define EXYNOS5_FSEL_24MHZ		0x5
37 #define EXYNOS5_FSEL_50MHZ		0x7
38 
39 /* EXYNOS5: USB 3.0 DRD PHY registers */
40 #define EXYNOS5_DRD_LINKSYSTEM			0x04
41 
42 #define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
43 #define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
44 #define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)
45 
46 #define EXYNOS5_DRD_PHYUTMI			0x08
47 
48 #define PHYUTMI_OTGDISABLE			BIT(6)
49 #define PHYUTMI_FORCESUSPEND			BIT(1)
50 #define PHYUTMI_FORCESLEEP			BIT(0)
51 
52 #define EXYNOS5_DRD_PHYPIPE			0x0c
53 
54 #define EXYNOS5_DRD_PHYCLKRST			0x10
55 
56 #define PHYCLKRST_EN_UTMISUSPEND		BIT(31)
57 
58 #define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
59 #define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
60 
61 #define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
62 #define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
63 
64 #define PHYCLKRST_SSC_EN			BIT(20)
65 #define PHYCLKRST_REF_SSP_EN			BIT(19)
66 #define PHYCLKRST_REF_CLKDIV2			BIT(18)
67 
68 #define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
69 #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
70 #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x32 << 11)
71 #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
72 #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
73 #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
74 
75 #define PHYCLKRST_FSEL_UTMI_MASK		(0x7 << 5)
76 #define PHYCLKRST_FSEL_PIPE_MASK		(0x7 << 8)
77 #define PHYCLKRST_FSEL(_x)			((_x) << 5)
78 #define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
79 #define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
80 #define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
81 #define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
82 
83 #define PHYCLKRST_RETENABLEN			BIT(4)
84 
85 #define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
86 #define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
87 #define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
88 
89 #define PHYCLKRST_PORTRESET			BIT(1)
90 #define PHYCLKRST_COMMONONN			BIT(0)
91 
92 #define EXYNOS5_DRD_PHYREG0			0x14
93 #define EXYNOS5_DRD_PHYREG1			0x18
94 
95 #define EXYNOS5_DRD_PHYPARAM0			0x1c
96 
97 #define PHYPARAM0_REF_USE_PAD			BIT(31)
98 #define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
99 #define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
100 
101 #define EXYNOS5_DRD_PHYPARAM1			0x20
102 
103 #define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
104 #define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
105 
106 #define EXYNOS5_DRD_PHYTERM			0x24
107 
108 #define EXYNOS5_DRD_PHYTEST			0x28
109 
110 #define PHYTEST_POWERDOWN_SSP			BIT(3)
111 #define PHYTEST_POWERDOWN_HSP			BIT(2)
112 
113 #define EXYNOS5_DRD_PHYADP			0x2c
114 
115 #define EXYNOS5_DRD_PHYUTMICLKSEL		0x30
116 
117 #define PHYUTMICLKSEL_UTMI_CLKSEL		BIT(2)
118 
119 #define EXYNOS5_DRD_PHYRESUME			0x34
120 #define EXYNOS5_DRD_LINKPORT			0x44
121 
122 #define KHZ	1000
123 #define MHZ	(KHZ * KHZ)
124 
125 enum exynos5_usbdrd_phy_id {
126 	EXYNOS5_DRDPHY_UTMI,
127 	EXYNOS5_DRDPHY_PIPE3,
128 	EXYNOS5_DRDPHYS_NUM,
129 };
130 
131 struct phy_usb_instance;
132 struct exynos5_usbdrd_phy;
133 
134 struct exynos5_usbdrd_phy_config {
135 	u32 id;
136 	void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
137 	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
138 	unsigned int (*set_refclk)(struct phy_usb_instance *inst);
139 };
140 
141 struct exynos5_usbdrd_phy_drvdata {
142 	const struct exynos5_usbdrd_phy_config *phy_cfg;
143 	u32 pmu_offset_usbdrd0_phy;
144 	u32 pmu_offset_usbdrd1_phy;
145 	bool has_common_clk_gate;
146 };
147 
148 /**
149  * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
150  * @dev: pointer to device instance of this platform device
151  * @reg_phy: usb phy controller register memory base
152  * @clk: phy clock for register access
153  * @pipeclk: clock for pipe3 phy
154  * @utmiclk: clock for utmi+ phy
155  * @itpclk: clock for ITP generation
156  * @drv_data: pointer to SoC level driver data structure
157  * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
158  *	    instances each with its 'phy' and 'phy_cfg'.
159  * @extrefclk: frequency select settings when using 'separate
160  *	       reference clocks' for SS and HS operations
161  * @ref_clk: reference clock to PHY block from which PHY's
162  *	     operational clocks are derived
163  * vbus: VBUS regulator for phy
164  * vbus_boost: Boost regulator for VBUS present on few Exynos boards
165  */
166 struct exynos5_usbdrd_phy {
167 	struct device *dev;
168 	void __iomem *reg_phy;
169 	struct clk *clk;
170 	struct clk *pipeclk;
171 	struct clk *utmiclk;
172 	struct clk *itpclk;
173 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
174 	struct phy_usb_instance {
175 		struct phy *phy;
176 		u32 index;
177 		struct regmap *reg_pmu;
178 		u32 pmu_offset;
179 		const struct exynos5_usbdrd_phy_config *phy_cfg;
180 	} phys[EXYNOS5_DRDPHYS_NUM];
181 	u32 extrefclk;
182 	struct clk *ref_clk;
183 	struct regulator *vbus;
184 	struct regulator *vbus_boost;
185 };
186 
187 static inline
188 struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
189 {
190 	return container_of((inst), struct exynos5_usbdrd_phy,
191 			    phys[(inst)->index]);
192 }
193 
194 /*
195  * exynos5_rate_to_clk() converts the supplied clock rate to the value that
196  * can be written to the phy register.
197  */
198 static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
199 {
200 	/* EXYNOS5_FSEL_MASK */
201 
202 	switch (rate) {
203 	case 9600 * KHZ:
204 		*reg = EXYNOS5_FSEL_9MHZ6;
205 		break;
206 	case 10 * MHZ:
207 		*reg = EXYNOS5_FSEL_10MHZ;
208 		break;
209 	case 12 * MHZ:
210 		*reg = EXYNOS5_FSEL_12MHZ;
211 		break;
212 	case 19200 * KHZ:
213 		*reg = EXYNOS5_FSEL_19MHZ2;
214 		break;
215 	case 20 * MHZ:
216 		*reg = EXYNOS5_FSEL_20MHZ;
217 		break;
218 	case 24 * MHZ:
219 		*reg = EXYNOS5_FSEL_24MHZ;
220 		break;
221 	case 50 * MHZ:
222 		*reg = EXYNOS5_FSEL_50MHZ;
223 		break;
224 	default:
225 		return -EINVAL;
226 	}
227 
228 	return 0;
229 }
230 
231 static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
232 						unsigned int on)
233 {
234 	unsigned int val;
235 
236 	if (!inst->reg_pmu)
237 		return;
238 
239 	val = on ? 0 : EXYNOS4_PHY_ENABLE;
240 
241 	regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
242 			   EXYNOS4_PHY_ENABLE, val);
243 }
244 
245 /*
246  * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
247  * from clock core. Further sets multiplier values and spread spectrum
248  * clock settings for SuperSpeed operations.
249  */
250 static unsigned int
251 exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
252 {
253 	u32 reg;
254 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
255 
256 	/* restore any previous reference clock settings */
257 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
258 
259 	/* Use EXTREFCLK as ref clock */
260 	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
261 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
262 
263 	/* FSEL settings corresponding to reference clock */
264 	reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
265 		PHYCLKRST_MPLL_MULTIPLIER_MASK |
266 		PHYCLKRST_SSC_REFCLKSEL_MASK;
267 	switch (phy_drd->extrefclk) {
268 	case EXYNOS5_FSEL_50MHZ:
269 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
270 			PHYCLKRST_SSC_REFCLKSEL(0x00));
271 		break;
272 	case EXYNOS5_FSEL_24MHZ:
273 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
274 			PHYCLKRST_SSC_REFCLKSEL(0x88));
275 		break;
276 	case EXYNOS5_FSEL_20MHZ:
277 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
278 			PHYCLKRST_SSC_REFCLKSEL(0x00));
279 		break;
280 	case EXYNOS5_FSEL_19MHZ2:
281 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
282 			PHYCLKRST_SSC_REFCLKSEL(0x88));
283 		break;
284 	default:
285 		dev_dbg(phy_drd->dev, "unsupported ref clk\n");
286 		break;
287 	}
288 
289 	return reg;
290 }
291 
292 /*
293  * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
294  * from clock core. Further sets the FSEL values for HighSpeed operations.
295  */
296 static unsigned int
297 exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
298 {
299 	u32 reg;
300 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
301 
302 	/* restore any previous reference clock settings */
303 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
304 
305 	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
306 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
307 
308 	reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
309 		PHYCLKRST_MPLL_MULTIPLIER_MASK |
310 		PHYCLKRST_SSC_REFCLKSEL_MASK;
311 	reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
312 
313 	return reg;
314 }
315 
316 static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
317 {
318 	u32 reg;
319 
320 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
321 	/* Set Tx De-Emphasis level */
322 	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
323 	reg |=	PHYPARAM1_PCS_TXDEEMPH;
324 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
325 
326 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
327 	reg &= ~PHYTEST_POWERDOWN_SSP;
328 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
329 }
330 
331 static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
332 {
333 	u32 reg;
334 
335 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
336 	/* Set Loss-of-Signal Detector sensitivity */
337 	reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
338 	reg |=	PHYPARAM0_REF_LOSLEVEL;
339 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
340 
341 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
342 	/* Set Tx De-Emphasis level */
343 	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
344 	reg |=	PHYPARAM1_PCS_TXDEEMPH;
345 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
346 
347 	/* UTMI Power Control */
348 	writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
349 
350 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
351 	reg &= ~PHYTEST_POWERDOWN_HSP;
352 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
353 }
354 
355 static int exynos5_usbdrd_phy_init(struct phy *phy)
356 {
357 	int ret;
358 	u32 reg;
359 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
360 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
361 
362 	ret = clk_prepare_enable(phy_drd->clk);
363 	if (ret)
364 		return ret;
365 
366 	/* Reset USB 3.0 PHY */
367 	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
368 	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
369 
370 	/*
371 	 * Setting the Frame length Adj value[6:1] to default 0x20
372 	 * See xHCI 1.0 spec, 5.2.4
373 	 */
374 	reg =	LINKSYSTEM_XHCI_VERSION_CONTROL |
375 		LINKSYSTEM_FLADJ(0x20);
376 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
377 
378 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
379 	/* Select PHY CLK source */
380 	reg &= ~PHYPARAM0_REF_USE_PAD;
381 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
382 
383 	/* This bit must be set for both HS and SS operations */
384 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
385 	reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
386 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
387 
388 	/* UTMI or PIPE3 specific init */
389 	inst->phy_cfg->phy_init(phy_drd);
390 
391 	/* reference clock settings */
392 	reg = inst->phy_cfg->set_refclk(inst);
393 
394 		/* Digital power supply in normal operating mode */
395 	reg |=	PHYCLKRST_RETENABLEN |
396 		/* Enable ref clock for SS function */
397 		PHYCLKRST_REF_SSP_EN |
398 		/* Enable spread spectrum */
399 		PHYCLKRST_SSC_EN |
400 		/* Power down HS Bias and PLL blocks in suspend mode */
401 		PHYCLKRST_COMMONONN |
402 		/* Reset the port */
403 		PHYCLKRST_PORTRESET;
404 
405 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
406 
407 	udelay(10);
408 
409 	reg &= ~PHYCLKRST_PORTRESET;
410 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
411 
412 	clk_disable_unprepare(phy_drd->clk);
413 
414 	return 0;
415 }
416 
417 static int exynos5_usbdrd_phy_exit(struct phy *phy)
418 {
419 	int ret;
420 	u32 reg;
421 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
422 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
423 
424 	ret = clk_prepare_enable(phy_drd->clk);
425 	if (ret)
426 		return ret;
427 
428 	reg =	PHYUTMI_OTGDISABLE |
429 		PHYUTMI_FORCESUSPEND |
430 		PHYUTMI_FORCESLEEP;
431 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
432 
433 	/* Resetting the PHYCLKRST enable bits to reduce leakage current */
434 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
435 	reg &= ~(PHYCLKRST_REF_SSP_EN |
436 		 PHYCLKRST_SSC_EN |
437 		 PHYCLKRST_COMMONONN);
438 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
439 
440 	/* Control PHYTEST to remove leakage current */
441 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
442 	reg |=	PHYTEST_POWERDOWN_SSP |
443 		PHYTEST_POWERDOWN_HSP;
444 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
445 
446 	clk_disable_unprepare(phy_drd->clk);
447 
448 	return 0;
449 }
450 
451 static int exynos5_usbdrd_phy_power_on(struct phy *phy)
452 {
453 	int ret;
454 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
455 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
456 
457 	dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
458 
459 	clk_prepare_enable(phy_drd->ref_clk);
460 	if (!phy_drd->drv_data->has_common_clk_gate) {
461 		clk_prepare_enable(phy_drd->pipeclk);
462 		clk_prepare_enable(phy_drd->utmiclk);
463 		clk_prepare_enable(phy_drd->itpclk);
464 	}
465 
466 	/* Enable VBUS supply */
467 	if (phy_drd->vbus_boost) {
468 		ret = regulator_enable(phy_drd->vbus_boost);
469 		if (ret) {
470 			dev_err(phy_drd->dev,
471 				"Failed to enable VBUS boost supply\n");
472 			goto fail_vbus;
473 		}
474 	}
475 
476 	if (phy_drd->vbus) {
477 		ret = regulator_enable(phy_drd->vbus);
478 		if (ret) {
479 			dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
480 			goto fail_vbus_boost;
481 		}
482 	}
483 
484 	/* Power-on PHY*/
485 	inst->phy_cfg->phy_isol(inst, 0);
486 
487 	return 0;
488 
489 fail_vbus_boost:
490 	if (phy_drd->vbus_boost)
491 		regulator_disable(phy_drd->vbus_boost);
492 
493 fail_vbus:
494 	clk_disable_unprepare(phy_drd->ref_clk);
495 	if (!phy_drd->drv_data->has_common_clk_gate) {
496 		clk_disable_unprepare(phy_drd->itpclk);
497 		clk_disable_unprepare(phy_drd->utmiclk);
498 		clk_disable_unprepare(phy_drd->pipeclk);
499 	}
500 
501 	return ret;
502 }
503 
504 static int exynos5_usbdrd_phy_power_off(struct phy *phy)
505 {
506 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
507 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
508 
509 	dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
510 
511 	/* Power-off the PHY */
512 	inst->phy_cfg->phy_isol(inst, 1);
513 
514 	/* Disable VBUS supply */
515 	if (phy_drd->vbus)
516 		regulator_disable(phy_drd->vbus);
517 	if (phy_drd->vbus_boost)
518 		regulator_disable(phy_drd->vbus_boost);
519 
520 	clk_disable_unprepare(phy_drd->ref_clk);
521 	if (!phy_drd->drv_data->has_common_clk_gate) {
522 		clk_disable_unprepare(phy_drd->itpclk);
523 		clk_disable_unprepare(phy_drd->pipeclk);
524 		clk_disable_unprepare(phy_drd->utmiclk);
525 	}
526 
527 	return 0;
528 }
529 
530 static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
531 					struct of_phandle_args *args)
532 {
533 	struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
534 
535 	if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
536 		return ERR_PTR(-ENODEV);
537 
538 	return phy_drd->phys[args->args[0]].phy;
539 }
540 
541 static const struct phy_ops exynos5_usbdrd_phy_ops = {
542 	.init		= exynos5_usbdrd_phy_init,
543 	.exit		= exynos5_usbdrd_phy_exit,
544 	.power_on	= exynos5_usbdrd_phy_power_on,
545 	.power_off	= exynos5_usbdrd_phy_power_off,
546 	.owner		= THIS_MODULE,
547 };
548 
549 static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
550 {
551 	unsigned long ref_rate;
552 	int ret;
553 
554 	phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
555 	if (IS_ERR(phy_drd->clk)) {
556 		dev_err(phy_drd->dev, "Failed to get phy clock\n");
557 		return PTR_ERR(phy_drd->clk);
558 	}
559 
560 	phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
561 	if (IS_ERR(phy_drd->ref_clk)) {
562 		dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
563 		return PTR_ERR(phy_drd->ref_clk);
564 	}
565 	ref_rate = clk_get_rate(phy_drd->ref_clk);
566 
567 	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
568 	if (ret) {
569 		dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
570 			ref_rate);
571 		return ret;
572 	}
573 
574 	if (!phy_drd->drv_data->has_common_clk_gate) {
575 		phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
576 		if (IS_ERR(phy_drd->pipeclk)) {
577 			dev_info(phy_drd->dev,
578 				 "PIPE3 phy operational clock not specified\n");
579 			phy_drd->pipeclk = NULL;
580 		}
581 
582 		phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
583 		if (IS_ERR(phy_drd->utmiclk)) {
584 			dev_info(phy_drd->dev,
585 				 "UTMI phy operational clock not specified\n");
586 			phy_drd->utmiclk = NULL;
587 		}
588 
589 		phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
590 		if (IS_ERR(phy_drd->itpclk)) {
591 			dev_info(phy_drd->dev,
592 				 "ITP clock from main OSC not specified\n");
593 			phy_drd->itpclk = NULL;
594 		}
595 	}
596 
597 	return 0;
598 }
599 
600 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
601 	{
602 		.id		= EXYNOS5_DRDPHY_UTMI,
603 		.phy_isol	= exynos5_usbdrd_phy_isol,
604 		.phy_init	= exynos5_usbdrd_utmi_init,
605 		.set_refclk	= exynos5_usbdrd_utmi_set_refclk,
606 	},
607 	{
608 		.id		= EXYNOS5_DRDPHY_PIPE3,
609 		.phy_isol	= exynos5_usbdrd_phy_isol,
610 		.phy_init	= exynos5_usbdrd_pipe3_init,
611 		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,
612 	},
613 };
614 
615 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
616 	.phy_cfg		= phy_cfg_exynos5,
617 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
618 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
619 	.has_common_clk_gate	= true,
620 };
621 
622 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
623 	.phy_cfg		= phy_cfg_exynos5,
624 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
625 	.has_common_clk_gate	= true,
626 };
627 
628 static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
629 	.phy_cfg		= phy_cfg_exynos5,
630 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
631 	.pmu_offset_usbdrd1_phy	= EXYNOS5433_USBHOST30_PHY_CONTROL,
632 	.has_common_clk_gate	= false,
633 };
634 
635 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
636 	.phy_cfg		= phy_cfg_exynos5,
637 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
638 	.has_common_clk_gate	= false,
639 };
640 
641 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
642 	{
643 		.compatible = "samsung,exynos5250-usbdrd-phy",
644 		.data = &exynos5250_usbdrd_phy
645 	}, {
646 		.compatible = "samsung,exynos5420-usbdrd-phy",
647 		.data = &exynos5420_usbdrd_phy
648 	}, {
649 		.compatible = "samsung,exynos5433-usbdrd-phy",
650 		.data = &exynos5433_usbdrd_phy
651 	}, {
652 		.compatible = "samsung,exynos7-usbdrd-phy",
653 		.data = &exynos7_usbdrd_phy
654 	},
655 	{ },
656 };
657 MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
658 
659 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
660 {
661 	struct device *dev = &pdev->dev;
662 	struct device_node *node = dev->of_node;
663 	struct exynos5_usbdrd_phy *phy_drd;
664 	struct phy_provider *phy_provider;
665 	struct resource *res;
666 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
667 	struct regmap *reg_pmu;
668 	u32 pmu_offset;
669 	int i, ret;
670 	int channel;
671 
672 	phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
673 	if (!phy_drd)
674 		return -ENOMEM;
675 
676 	dev_set_drvdata(dev, phy_drd);
677 	phy_drd->dev = dev;
678 
679 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
680 	phy_drd->reg_phy = devm_ioremap_resource(dev, res);
681 	if (IS_ERR(phy_drd->reg_phy))
682 		return PTR_ERR(phy_drd->reg_phy);
683 
684 	drv_data = of_device_get_match_data(dev);
685 	if (!drv_data)
686 		return -EINVAL;
687 
688 	phy_drd->drv_data = drv_data;
689 
690 	ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
691 	if (ret) {
692 		dev_err(dev, "Failed to initialize clocks\n");
693 		return ret;
694 	}
695 
696 	reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
697 						   "samsung,pmu-syscon");
698 	if (IS_ERR(reg_pmu)) {
699 		dev_err(dev, "Failed to lookup PMU regmap\n");
700 		return PTR_ERR(reg_pmu);
701 	}
702 
703 	/*
704 	 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
705 	 * each having separate power control registers.
706 	 * 'channel' facilitates to set such registers.
707 	 */
708 	channel = of_alias_get_id(node, "usbdrdphy");
709 	if (channel < 0)
710 		dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
711 
712 	switch (channel) {
713 	case 1:
714 		pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
715 		break;
716 	case 0:
717 	default:
718 		pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
719 		break;
720 	}
721 
722 	/* Get Vbus regulators */
723 	phy_drd->vbus = devm_regulator_get(dev, "vbus");
724 	if (IS_ERR(phy_drd->vbus)) {
725 		ret = PTR_ERR(phy_drd->vbus);
726 		if (ret == -EPROBE_DEFER)
727 			return ret;
728 
729 		dev_warn(dev, "Failed to get VBUS supply regulator\n");
730 		phy_drd->vbus = NULL;
731 	}
732 
733 	phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
734 	if (IS_ERR(phy_drd->vbus_boost)) {
735 		ret = PTR_ERR(phy_drd->vbus_boost);
736 		if (ret == -EPROBE_DEFER)
737 			return ret;
738 
739 		dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
740 		phy_drd->vbus_boost = NULL;
741 	}
742 
743 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
744 
745 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
746 		struct phy *phy = devm_phy_create(dev, NULL,
747 						  &exynos5_usbdrd_phy_ops);
748 		if (IS_ERR(phy)) {
749 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
750 			return PTR_ERR(phy);
751 		}
752 
753 		phy_drd->phys[i].phy = phy;
754 		phy_drd->phys[i].index = i;
755 		phy_drd->phys[i].reg_pmu = reg_pmu;
756 		phy_drd->phys[i].pmu_offset = pmu_offset;
757 		phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
758 		phy_set_drvdata(phy, &phy_drd->phys[i]);
759 	}
760 
761 	phy_provider = devm_of_phy_provider_register(dev,
762 						     exynos5_usbdrd_phy_xlate);
763 	if (IS_ERR(phy_provider)) {
764 		dev_err(phy_drd->dev, "Failed to register phy provider\n");
765 		return PTR_ERR(phy_provider);
766 	}
767 
768 	return 0;
769 }
770 
771 static struct platform_driver exynos5_usb3drd_phy = {
772 	.probe	= exynos5_usbdrd_phy_probe,
773 	.driver = {
774 		.of_match_table	= exynos5_usbdrd_phy_of_match,
775 		.name		= "exynos5_usb3drd_phy",
776 	}
777 };
778 
779 module_platform_driver(exynos5_usb3drd_phy);
780 MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver");
781 MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
782 MODULE_LICENSE("GPL v2");
783 MODULE_ALIAS("platform:exynos5_usb3drd_phy");
784