1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/clk.h>
7 #include <linux/delay.h>
8 #include <linux/err.h>
9 #include <linux/io.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/reset.h>
18 #include <linux/slab.h>
19 
20 #define USB2_PHY_USB_PHY_UTMI_CTRL0		(0x3c)
21 #define SLEEPM					BIT(0)
22 #define OPMODE_MASK				GENMASK(4, 3)
23 #define OPMODE_NORMAL				(0x00)
24 #define OPMODE_NONDRIVING			BIT(3)
25 #define TERMSEL					BIT(5)
26 
27 #define USB2_PHY_USB_PHY_UTMI_CTRL1		(0x40)
28 #define XCVRSEL					BIT(0)
29 
30 #define USB2_PHY_USB_PHY_UTMI_CTRL5		(0x50)
31 #define POR					BIT(1)
32 
33 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
34 #define SIDDQ					BIT(2)
35 #define RETENABLEN				BIT(3)
36 #define FSEL_MASK				GENMASK(6, 4)
37 #define FSEL_DEFAULT				(0x3 << 4)
38 
39 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1	(0x58)
40 #define VBUSVLDEXTSEL0				BIT(4)
41 #define PLLBTUNE				BIT(5)
42 
43 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2	(0x5c)
44 #define VREGBYPASS				BIT(0)
45 
46 #define USB2_PHY_USB_PHY_HS_PHY_CTRL1		(0x60)
47 #define VBUSVLDEXT0				BIT(0)
48 
49 #define USB2_PHY_USB_PHY_HS_PHY_CTRL2		(0x64)
50 #define USB2_AUTO_RESUME			BIT(0)
51 #define USB2_SUSPEND_N				BIT(2)
52 #define USB2_SUSPEND_N_SEL			BIT(3)
53 
54 #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0		(0x6c)
55 #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1		(0x70)
56 #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2		(0x74)
57 #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3		(0x78)
58 #define PARAM_OVRD_MASK				0xFF
59 
60 #define USB2_PHY_USB_PHY_CFG0			(0x94)
61 #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN	BIT(0)
62 #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN		BIT(1)
63 
64 #define USB2_PHY_USB_PHY_REFCLK_CTRL		(0xa0)
65 #define REFCLK_SEL_MASK				GENMASK(1, 0)
66 #define REFCLK_SEL_DEFAULT			(0x2 << 0)
67 
68 #define HS_DISCONNECT_MASK			GENMASK(2, 0)
69 #define SQUELCH_DETECTOR_MASK			GENMASK(7, 5)
70 
71 #define HS_AMPLITUDE_MASK			GENMASK(3, 0)
72 #define PREEMPHASIS_DURATION_MASK		BIT(5)
73 #define PREEMPHASIS_AMPLITUDE_MASK		GENMASK(7, 6)
74 
75 #define HS_RISE_FALL_MASK			GENMASK(1, 0)
76 #define HS_CROSSOVER_VOLTAGE_MASK		GENMASK(3, 2)
77 #define HS_OUTPUT_IMPEDANCE_MASK		GENMASK(5, 4)
78 
79 #define LS_FS_OUTPUT_IMPEDANCE_MASK		GENMASK(3, 0)
80 
81 static const char * const qcom_snps_hsphy_vreg_names[] = {
82 	"vdda-pll", "vdda33", "vdda18",
83 };
84 
85 #define SNPS_HS_NUM_VREGS		ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
86 
87 struct override_param {
88 	s32	value;
89 	u8	reg_val;
90 };
91 
92 struct override_param_map {
93 	const char *prop_name;
94 	const struct override_param *param_table;
95 	u8 table_size;
96 	u8 reg_offset;
97 	u8 param_mask;
98 };
99 
100 struct phy_override_seq {
101 	bool	need_update;
102 	u8	offset;
103 	u8	value;
104 	u8	mask;
105 };
106 
107 #define NUM_HSPHY_TUNING_PARAMS	(9)
108 
109 /**
110  * struct qcom_snps_hsphy - snps hs phy attributes
111  *
112  * @dev: device structure
113  *
114  * @phy: generic phy
115  * @base: iomapped memory space for snps hs phy
116  *
117  * @num_clks: number of clocks
118  * @clks: array of clocks
119  * @phy_reset: phy reset control
120  * @vregs: regulator supplies bulk data
121  * @phy_initialized: if PHY has been initialized correctly
122  * @mode: contains the current mode the PHY is in
123  * @update_seq_cfg: tuning parameters for phy init
124  */
125 struct qcom_snps_hsphy {
126 	struct device *dev;
127 
128 	struct phy *phy;
129 	void __iomem *base;
130 
131 	int num_clks;
132 	struct clk_bulk_data *clks;
133 	struct reset_control *phy_reset;
134 	struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
135 
136 	bool phy_initialized;
137 	enum phy_mode mode;
138 	struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
139 };
140 
141 static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
142 {
143 	struct device *dev = hsphy->dev;
144 
145 	hsphy->num_clks = 2;
146 	hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
147 	if (!hsphy->clks)
148 		return -ENOMEM;
149 
150 	/*
151 	 * TODO: Currently no device tree instantiation of the PHY is using the clock.
152 	 * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
153 	 */
154 	hsphy->clks[0].id = "cfg_ahb";
155 	hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
156 	if (IS_ERR(hsphy->clks[0].clk))
157 		return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
158 				     "failed to get cfg_ahb clk\n");
159 
160 	hsphy->clks[1].id = "ref";
161 	hsphy->clks[1].clk = devm_clk_get(dev, "ref");
162 	if (IS_ERR(hsphy->clks[1].clk))
163 		return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
164 				     "failed to get ref clk\n");
165 
166 	return 0;
167 }
168 
169 static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
170 						u32 mask, u32 val)
171 {
172 	u32 reg;
173 
174 	reg = readl_relaxed(base + offset);
175 	reg &= ~mask;
176 	reg |= val & mask;
177 	writel_relaxed(reg, base + offset);
178 
179 	/* Ensure above write is completed */
180 	readl_relaxed(base + offset);
181 }
182 
183 static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
184 {
185 	dev_dbg(&hsphy->phy->dev, "Suspend QCOM SNPS PHY\n");
186 
187 	if (hsphy->mode == PHY_MODE_USB_HOST) {
188 		/* Enable auto-resume to meet remote wakeup timing */
189 		qcom_snps_hsphy_write_mask(hsphy->base,
190 					   USB2_PHY_USB_PHY_HS_PHY_CTRL2,
191 					   USB2_AUTO_RESUME,
192 					   USB2_AUTO_RESUME);
193 		usleep_range(500, 1000);
194 		qcom_snps_hsphy_write_mask(hsphy->base,
195 					   USB2_PHY_USB_PHY_HS_PHY_CTRL2,
196 					   0, USB2_AUTO_RESUME);
197 	}
198 
199 	return 0;
200 }
201 
202 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
203 {
204 	dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
205 
206 	return 0;
207 }
208 
209 static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
210 {
211 	struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
212 
213 	if (!hsphy->phy_initialized)
214 		return 0;
215 
216 	return qcom_snps_hsphy_suspend(hsphy);
217 }
218 
219 static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
220 {
221 	struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
222 
223 	if (!hsphy->phy_initialized)
224 		return 0;
225 
226 	return qcom_snps_hsphy_resume(hsphy);
227 }
228 
229 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
230 				    int submode)
231 {
232 	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
233 
234 	hsphy->mode = mode;
235 	return 0;
236 }
237 
238 static const struct override_param hs_disconnect_sc7280[] = {
239 	{ -272, 0 },
240 	{ 0, 1 },
241 	{ 317, 2 },
242 	{ 630, 3 },
243 	{ 973, 4 },
244 	{ 1332, 5 },
245 	{ 1743, 6 },
246 	{ 2156, 7 },
247 };
248 
249 static const struct override_param squelch_det_threshold_sc7280[] = {
250 	{ -2090, 7 },
251 	{ -1560, 6 },
252 	{ -1030, 5 },
253 	{ -530, 4 },
254 	{ 0, 3 },
255 	{ 530, 2 },
256 	{ 1060, 1 },
257 	{ 1590, 0 },
258 };
259 
260 static const struct override_param hs_amplitude_sc7280[] = {
261 	{ -660, 0 },
262 	{ -440, 1 },
263 	{ -220, 2 },
264 	{ 0, 3 },
265 	{ 230, 4 },
266 	{ 440, 5 },
267 	{ 650, 6 },
268 	{ 890, 7 },
269 	{ 1110, 8 },
270 	{ 1330, 9 },
271 	{ 1560, 10 },
272 	{ 1780, 11 },
273 	{ 2000, 12 },
274 	{ 2220, 13 },
275 	{ 2430, 14 },
276 	{ 2670, 15 },
277 };
278 
279 static const struct override_param preemphasis_duration_sc7280[] = {
280 	{ 10000, 1 },
281 	{ 20000, 0 },
282 };
283 
284 static const struct override_param preemphasis_amplitude_sc7280[] = {
285 	{ 10000, 1 },
286 	{ 20000, 2 },
287 	{ 30000, 3 },
288 	{ 40000, 0 },
289 };
290 
291 static const struct override_param hs_rise_fall_time_sc7280[] = {
292 	{ -4100, 3 },
293 	{ 0, 2 },
294 	{ 2810, 1 },
295 	{ 5430, 0 },
296 };
297 
298 static const struct override_param hs_crossover_voltage_sc7280[] = {
299 	{ -31000, 1 },
300 	{ 0, 3 },
301 	{ 28000, 2 },
302 };
303 
304 static const struct override_param hs_output_impedance_sc7280[] = {
305 	{ -2300000, 3 },
306 	{ 0, 2 },
307 	{ 2600000, 1 },
308 	{ 6100000, 0 },
309 };
310 
311 static const struct override_param ls_fs_output_impedance_sc7280[] = {
312 	{ -1053, 15 },
313 	{ -557, 7 },
314 	{ 0, 3 },
315 	{ 612, 1 },
316 	{ 1310, 0 },
317 };
318 
319 static const struct override_param_map sc7280_snps_7nm_phy[] = {
320 	{
321 		"qcom,hs-disconnect-bp",
322 		hs_disconnect_sc7280,
323 		ARRAY_SIZE(hs_disconnect_sc7280),
324 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
325 		HS_DISCONNECT_MASK
326 	},
327 	{
328 		"qcom,squelch-detector-bp",
329 		squelch_det_threshold_sc7280,
330 		ARRAY_SIZE(squelch_det_threshold_sc7280),
331 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
332 		SQUELCH_DETECTOR_MASK
333 	},
334 	{
335 		"qcom,hs-amplitude-bp",
336 		hs_amplitude_sc7280,
337 		ARRAY_SIZE(hs_amplitude_sc7280),
338 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
339 		HS_AMPLITUDE_MASK
340 	},
341 	{
342 		"qcom,pre-emphasis-duration-bp",
343 		preemphasis_duration_sc7280,
344 		ARRAY_SIZE(preemphasis_duration_sc7280),
345 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
346 		PREEMPHASIS_DURATION_MASK,
347 	},
348 	{
349 		"qcom,pre-emphasis-amplitude-bp",
350 		preemphasis_amplitude_sc7280,
351 		ARRAY_SIZE(preemphasis_amplitude_sc7280),
352 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
353 		PREEMPHASIS_AMPLITUDE_MASK,
354 	},
355 	{
356 		"qcom,hs-rise-fall-time-bp",
357 		hs_rise_fall_time_sc7280,
358 		ARRAY_SIZE(hs_rise_fall_time_sc7280),
359 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
360 		HS_RISE_FALL_MASK
361 	},
362 	{
363 		"qcom,hs-crossover-voltage-microvolt",
364 		hs_crossover_voltage_sc7280,
365 		ARRAY_SIZE(hs_crossover_voltage_sc7280),
366 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
367 		HS_CROSSOVER_VOLTAGE_MASK
368 	},
369 	{
370 		"qcom,hs-output-impedance-micro-ohms",
371 		hs_output_impedance_sc7280,
372 		ARRAY_SIZE(hs_output_impedance_sc7280),
373 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
374 		HS_OUTPUT_IMPEDANCE_MASK,
375 	},
376 	{
377 		"qcom,ls-fs-output-impedance-bp",
378 		ls_fs_output_impedance_sc7280,
379 		ARRAY_SIZE(ls_fs_output_impedance_sc7280),
380 		USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3,
381 		LS_FS_OUTPUT_IMPEDANCE_MASK,
382 	},
383 	{},
384 };
385 
386 static int qcom_snps_hsphy_init(struct phy *phy)
387 {
388 	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
389 	int ret, i;
390 
391 	dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
392 
393 	ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
394 	if (ret)
395 		return ret;
396 
397 	ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
398 	if (ret) {
399 		dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
400 		goto poweroff_phy;
401 	}
402 
403 	ret = reset_control_assert(hsphy->phy_reset);
404 	if (ret) {
405 		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
406 		goto disable_clks;
407 	}
408 
409 	usleep_range(100, 150);
410 
411 	ret = reset_control_deassert(hsphy->phy_reset);
412 	if (ret) {
413 		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
414 		goto disable_clks;
415 	}
416 
417 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
418 					UTMI_PHY_CMN_CTRL_OVERRIDE_EN,
419 					UTMI_PHY_CMN_CTRL_OVERRIDE_EN);
420 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
421 							POR, POR);
422 	qcom_snps_hsphy_write_mask(hsphy->base,
423 					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
424 					FSEL_MASK, 0);
425 	qcom_snps_hsphy_write_mask(hsphy->base,
426 					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
427 					PLLBTUNE, PLLBTUNE);
428 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL,
429 					REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK);
430 	qcom_snps_hsphy_write_mask(hsphy->base,
431 					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
432 					VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
433 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
434 					VBUSVLDEXT0, VBUSVLDEXT0);
435 
436 	for (i = 0; i < ARRAY_SIZE(hsphy->update_seq_cfg); i++) {
437 		if (hsphy->update_seq_cfg[i].need_update)
438 			qcom_snps_hsphy_write_mask(hsphy->base,
439 					hsphy->update_seq_cfg[i].offset,
440 					hsphy->update_seq_cfg[i].mask,
441 					hsphy->update_seq_cfg[i].value);
442 	}
443 
444 	qcom_snps_hsphy_write_mask(hsphy->base,
445 					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
446 					VREGBYPASS, VREGBYPASS);
447 
448 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
449 					USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
450 					USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
451 
452 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0,
453 					SLEEPM, SLEEPM);
454 
455 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
456 				   SIDDQ, 0);
457 
458 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
459 					POR, 0);
460 
461 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
462 					USB2_SUSPEND_N_SEL, 0);
463 
464 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
465 					UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0);
466 
467 	hsphy->phy_initialized = true;
468 
469 	return 0;
470 
471 disable_clks:
472 	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
473 poweroff_phy:
474 	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
475 
476 	return ret;
477 }
478 
479 static int qcom_snps_hsphy_exit(struct phy *phy)
480 {
481 	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
482 
483 	reset_control_assert(hsphy->phy_reset);
484 	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
485 	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
486 	hsphy->phy_initialized = false;
487 
488 	return 0;
489 }
490 
491 static const struct phy_ops qcom_snps_hsphy_gen_ops = {
492 	.init		= qcom_snps_hsphy_init,
493 	.exit		= qcom_snps_hsphy_exit,
494 	.set_mode	= qcom_snps_hsphy_set_mode,
495 	.owner		= THIS_MODULE,
496 };
497 
498 static const struct of_device_id qcom_snps_hsphy_of_match_table[] = {
499 	{ .compatible	= "qcom,sm8150-usb-hs-phy", },
500 	{ .compatible	= "qcom,usb-snps-hs-5nm-phy", },
501 	{
502 		.compatible	= "qcom,usb-snps-hs-7nm-phy",
503 		.data		= &sc7280_snps_7nm_phy,
504 	},
505 	{ .compatible	= "qcom,usb-snps-femto-v2-phy",	},
506 	{ }
507 };
508 MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table);
509 
510 static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = {
511 	SET_RUNTIME_PM_OPS(qcom_snps_hsphy_runtime_suspend,
512 			   qcom_snps_hsphy_runtime_resume, NULL)
513 };
514 
515 static void qcom_snps_hsphy_override_param_update_val(
516 			const struct override_param_map map,
517 			s32 dt_val, struct phy_override_seq *seq_entry)
518 {
519 	int i;
520 
521 	/*
522 	 * Param table for each param is in increasing order
523 	 * of dt values. We need to iterate over the list to
524 	 * select the entry that matches the dt value and pick
525 	 * up the corresponding register value.
526 	 */
527 	for (i = 0; i < map.table_size - 1; i++) {
528 		if (map.param_table[i].value == dt_val)
529 			break;
530 	}
531 
532 	seq_entry->need_update = true;
533 	seq_entry->offset = map.reg_offset;
534 	seq_entry->mask = map.param_mask;
535 	seq_entry->value = map.param_table[i].reg_val << __ffs(map.param_mask);
536 }
537 
538 static void qcom_snps_hsphy_read_override_param_seq(struct device *dev)
539 {
540 	struct device_node *node = dev->of_node;
541 	s32 val;
542 	int ret, i;
543 	struct qcom_snps_hsphy *hsphy;
544 	const struct override_param_map *cfg = of_device_get_match_data(dev);
545 
546 	if (!cfg)
547 		return;
548 
549 	hsphy = dev_get_drvdata(dev);
550 
551 	for (i = 0; cfg[i].prop_name != NULL; i++) {
552 		ret = of_property_read_s32(node, cfg[i].prop_name, &val);
553 		if (ret)
554 			continue;
555 
556 		qcom_snps_hsphy_override_param_update_val(cfg[i], val,
557 					&hsphy->update_seq_cfg[i]);
558 		dev_dbg(&hsphy->phy->dev, "Read param: %s dt_val: %d reg_val: 0x%x\n",
559 			cfg[i].prop_name, val, hsphy->update_seq_cfg[i].value);
560 
561 	}
562 }
563 
564 static int qcom_snps_hsphy_probe(struct platform_device *pdev)
565 {
566 	struct device *dev = &pdev->dev;
567 	struct qcom_snps_hsphy *hsphy;
568 	struct phy_provider *phy_provider;
569 	struct phy *generic_phy;
570 	int ret, i;
571 	int num;
572 
573 	hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL);
574 	if (!hsphy)
575 		return -ENOMEM;
576 
577 	hsphy->dev = dev;
578 
579 	hsphy->base = devm_platform_ioremap_resource(pdev, 0);
580 	if (IS_ERR(hsphy->base))
581 		return PTR_ERR(hsphy->base);
582 
583 	ret = qcom_snps_hsphy_clk_init(hsphy);
584 	if (ret)
585 		return dev_err_probe(dev, ret, "failed to initialize clocks\n");
586 
587 	hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
588 	if (IS_ERR(hsphy->phy_reset)) {
589 		dev_err(dev, "failed to get phy core reset\n");
590 		return PTR_ERR(hsphy->phy_reset);
591 	}
592 
593 	num = ARRAY_SIZE(hsphy->vregs);
594 	for (i = 0; i < num; i++)
595 		hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i];
596 
597 	ret = devm_regulator_bulk_get(dev, num, hsphy->vregs);
598 	if (ret)
599 		return dev_err_probe(dev, ret,
600 				     "failed to get regulator supplies\n");
601 
602 	pm_runtime_set_active(dev);
603 	pm_runtime_enable(dev);
604 	/*
605 	 * Prevent runtime pm from being ON by default. Users can enable
606 	 * it using power/control in sysfs.
607 	 */
608 	pm_runtime_forbid(dev);
609 
610 	generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops);
611 	if (IS_ERR(generic_phy)) {
612 		ret = PTR_ERR(generic_phy);
613 		dev_err(dev, "failed to create phy, %d\n", ret);
614 		return ret;
615 	}
616 	hsphy->phy = generic_phy;
617 
618 	dev_set_drvdata(dev, hsphy);
619 	phy_set_drvdata(generic_phy, hsphy);
620 	qcom_snps_hsphy_read_override_param_seq(dev);
621 
622 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
623 	if (!IS_ERR(phy_provider))
624 		dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
625 	else
626 		pm_runtime_disable(dev);
627 
628 	return PTR_ERR_OR_ZERO(phy_provider);
629 }
630 
631 static struct platform_driver qcom_snps_hsphy_driver = {
632 	.probe		= qcom_snps_hsphy_probe,
633 	.driver = {
634 		.name	= "qcom-snps-hs-femto-v2-phy",
635 		.pm = &qcom_snps_hsphy_pm_ops,
636 		.of_match_table = qcom_snps_hsphy_of_match_table,
637 	},
638 };
639 
640 module_platform_driver(qcom_snps_hsphy_driver);
641 
642 MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver");
643 MODULE_LICENSE("GPL v2");
644