xref: /linux/drivers/usb/dwc3/dwc3-qcom.c (revision 3ea5eb68b9d624935108b5e696859304edfac202)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018, The Linux Foundation. All rights reserved.
3  *
4  * Inspired by dwc3-of-simple.c
5  */
6 
7 #include <linux/cleanup.h>
8 #include <linux/io.h>
9 #include <linux/of.h>
10 #include <linux/clk.h>
11 #include <linux/irq.h>
12 #include <linux/of_clk.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/extcon.h>
16 #include <linux/interconnect.h>
17 #include <linux/of_platform.h>
18 #include <linux/platform_device.h>
19 #include <linux/phy/phy.h>
20 #include <linux/usb/of.h>
21 #include <linux/reset.h>
22 #include <linux/iopoll.h>
23 #include <linux/usb/hcd.h>
24 #include <linux/usb.h>
25 #include "core.h"
26 
27 /* USB QSCRATCH Hardware registers */
28 #define QSCRATCH_HS_PHY_CTRL			0x10
29 #define UTMI_OTG_VBUS_VALID			BIT(20)
30 #define SW_SESSVLD_SEL				BIT(28)
31 
32 #define QSCRATCH_SS_PHY_CTRL			0x30
33 #define LANE0_PWR_PRESENT			BIT(24)
34 
35 #define QSCRATCH_GENERAL_CFG			0x08
36 #define PIPE_UTMI_CLK_SEL			BIT(0)
37 #define PIPE3_PHYSTATUS_SW			BIT(3)
38 #define PIPE_UTMI_CLK_DIS			BIT(8)
39 
40 #define PWR_EVNT_LPM_IN_L2_MASK			BIT(4)
41 #define PWR_EVNT_LPM_OUT_L2_MASK		BIT(5)
42 
43 #define SDM845_QSCRATCH_BASE_OFFSET		0xf8800
44 #define SDM845_QSCRATCH_SIZE			0x400
45 #define SDM845_DWC3_CORE_SIZE			0xcd00
46 
47 /* Interconnect path bandwidths in MBps */
48 #define USB_MEMORY_AVG_HS_BW MBps_to_icc(240)
49 #define USB_MEMORY_PEAK_HS_BW MBps_to_icc(700)
50 #define USB_MEMORY_AVG_SS_BW  MBps_to_icc(1000)
51 #define USB_MEMORY_PEAK_SS_BW MBps_to_icc(2500)
52 #define APPS_USB_AVG_BW 0
53 #define APPS_USB_PEAK_BW MBps_to_icc(40)
54 
55 /* Qualcomm SoCs with multiport support has up to 4 ports */
56 #define DWC3_QCOM_MAX_PORTS	4
57 
58 static const u32 pwr_evnt_irq_stat_reg[DWC3_QCOM_MAX_PORTS] = {
59 	0x58,
60 	0x1dc,
61 	0x228,
62 	0x238,
63 };
64 
65 struct dwc3_qcom_port {
66 	int			qusb2_phy_irq;
67 	int			dp_hs_phy_irq;
68 	int			dm_hs_phy_irq;
69 	int			ss_phy_irq;
70 	enum usb_device_speed	usb2_speed;
71 };
72 
73 struct dwc3_qcom {
74 	struct device		*dev;
75 	void __iomem		*qscratch_base;
76 	struct platform_device	*dwc3;
77 	struct clk		**clks;
78 	int			num_clocks;
79 	struct reset_control	*resets;
80 	struct dwc3_qcom_port	ports[DWC3_QCOM_MAX_PORTS];
81 	u8			num_ports;
82 
83 	struct extcon_dev	*edev;
84 	struct extcon_dev	*host_edev;
85 	struct notifier_block	vbus_nb;
86 	struct notifier_block	host_nb;
87 
88 	enum usb_dr_mode	mode;
89 	bool			is_suspended;
90 	bool			pm_suspended;
91 	struct icc_path		*icc_path_ddr;
92 	struct icc_path		*icc_path_apps;
93 };
94 
95 static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
96 {
97 	u32 reg;
98 
99 	reg = readl(base + offset);
100 	reg |= val;
101 	writel(reg, base + offset);
102 
103 	/* ensure that above write is through */
104 	readl(base + offset);
105 }
106 
107 static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
108 {
109 	u32 reg;
110 
111 	reg = readl(base + offset);
112 	reg &= ~val;
113 	writel(reg, base + offset);
114 
115 	/* ensure that above write is through */
116 	readl(base + offset);
117 }
118 
119 static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
120 {
121 	if (enable) {
122 		dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
123 				  LANE0_PWR_PRESENT);
124 		dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
125 				  UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
126 	} else {
127 		dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
128 				  LANE0_PWR_PRESENT);
129 		dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
130 				  UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
131 	}
132 }
133 
134 static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
135 				   unsigned long event, void *ptr)
136 {
137 	struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
138 
139 	/* enable vbus override for device mode */
140 	dwc3_qcom_vbus_override_enable(qcom, event);
141 	qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
142 
143 	return NOTIFY_DONE;
144 }
145 
146 static int dwc3_qcom_host_notifier(struct notifier_block *nb,
147 				   unsigned long event, void *ptr)
148 {
149 	struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
150 
151 	/* disable vbus override in host mode */
152 	dwc3_qcom_vbus_override_enable(qcom, !event);
153 	qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
154 
155 	return NOTIFY_DONE;
156 }
157 
158 static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
159 {
160 	struct device		*dev = qcom->dev;
161 	struct extcon_dev	*host_edev;
162 	int			ret;
163 
164 	if (!of_property_read_bool(dev->of_node, "extcon"))
165 		return 0;
166 
167 	qcom->edev = extcon_get_edev_by_phandle(dev, 0);
168 	if (IS_ERR(qcom->edev))
169 		return dev_err_probe(dev, PTR_ERR(qcom->edev),
170 				     "Failed to get extcon\n");
171 
172 	qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier;
173 
174 	qcom->host_edev = extcon_get_edev_by_phandle(dev, 1);
175 	if (IS_ERR(qcom->host_edev))
176 		qcom->host_edev = NULL;
177 
178 	ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB,
179 					    &qcom->vbus_nb);
180 	if (ret < 0) {
181 		dev_err(dev, "VBUS notifier register failed\n");
182 		return ret;
183 	}
184 
185 	if (qcom->host_edev)
186 		host_edev = qcom->host_edev;
187 	else
188 		host_edev = qcom->edev;
189 
190 	qcom->host_nb.notifier_call = dwc3_qcom_host_notifier;
191 	ret = devm_extcon_register_notifier(dev, host_edev, EXTCON_USB_HOST,
192 					    &qcom->host_nb);
193 	if (ret < 0) {
194 		dev_err(dev, "Host notifier register failed\n");
195 		return ret;
196 	}
197 
198 	/* Update initial VBUS override based on extcon state */
199 	if (extcon_get_state(qcom->edev, EXTCON_USB) ||
200 	    !extcon_get_state(host_edev, EXTCON_USB_HOST))
201 		dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev);
202 	else
203 		dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev);
204 
205 	return 0;
206 }
207 
208 static int dwc3_qcom_interconnect_enable(struct dwc3_qcom *qcom)
209 {
210 	int ret;
211 
212 	ret = icc_enable(qcom->icc_path_ddr);
213 	if (ret)
214 		return ret;
215 
216 	ret = icc_enable(qcom->icc_path_apps);
217 	if (ret)
218 		icc_disable(qcom->icc_path_ddr);
219 
220 	return ret;
221 }
222 
223 static int dwc3_qcom_interconnect_disable(struct dwc3_qcom *qcom)
224 {
225 	int ret;
226 
227 	ret = icc_disable(qcom->icc_path_ddr);
228 	if (ret)
229 		return ret;
230 
231 	ret = icc_disable(qcom->icc_path_apps);
232 	if (ret)
233 		icc_enable(qcom->icc_path_ddr);
234 
235 	return ret;
236 }
237 
238 /**
239  * dwc3_qcom_interconnect_init() - Get interconnect path handles
240  * and set bandwidth.
241  * @qcom:			Pointer to the concerned usb core.
242  *
243  */
244 static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
245 {
246 	enum usb_device_speed max_speed;
247 	struct device *dev = qcom->dev;
248 	int ret;
249 
250 	qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr");
251 	if (IS_ERR(qcom->icc_path_ddr)) {
252 		return dev_err_probe(dev, PTR_ERR(qcom->icc_path_ddr),
253 				     "failed to get usb-ddr path\n");
254 	}
255 
256 	qcom->icc_path_apps = of_icc_get(dev, "apps-usb");
257 	if (IS_ERR(qcom->icc_path_apps)) {
258 		ret = dev_err_probe(dev, PTR_ERR(qcom->icc_path_apps),
259 				    "failed to get apps-usb path\n");
260 		goto put_path_ddr;
261 	}
262 
263 	max_speed = usb_get_maximum_speed(&qcom->dwc3->dev);
264 	if (max_speed >= USB_SPEED_SUPER || max_speed == USB_SPEED_UNKNOWN) {
265 		ret = icc_set_bw(qcom->icc_path_ddr,
266 				USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
267 	} else {
268 		ret = icc_set_bw(qcom->icc_path_ddr,
269 				USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW);
270 	}
271 	if (ret) {
272 		dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret);
273 		goto put_path_apps;
274 	}
275 
276 	ret = icc_set_bw(qcom->icc_path_apps, APPS_USB_AVG_BW, APPS_USB_PEAK_BW);
277 	if (ret) {
278 		dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret);
279 		goto put_path_apps;
280 	}
281 
282 	return 0;
283 
284 put_path_apps:
285 	icc_put(qcom->icc_path_apps);
286 put_path_ddr:
287 	icc_put(qcom->icc_path_ddr);
288 	return ret;
289 }
290 
291 /**
292  * dwc3_qcom_interconnect_exit() - Release interconnect path handles
293  * @qcom:			Pointer to the concerned usb core.
294  *
295  * This function is used to release interconnect path handle.
296  */
297 static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
298 {
299 	icc_put(qcom->icc_path_ddr);
300 	icc_put(qcom->icc_path_apps);
301 }
302 
303 /* Only usable in contexts where the role can not change. */
304 static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom)
305 {
306 	struct dwc3 *dwc;
307 
308 	/*
309 	 * FIXME: Fix this layering violation.
310 	 */
311 	dwc = platform_get_drvdata(qcom->dwc3);
312 
313 	/* Core driver may not have probed yet. */
314 	if (!dwc)
315 		return false;
316 
317 	return dwc->xhci;
318 }
319 
320 static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom, int port_index)
321 {
322 	struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
323 	struct usb_device *udev;
324 	struct usb_hcd __maybe_unused *hcd;
325 
326 	/*
327 	 * FIXME: Fix this layering violation.
328 	 */
329 	hcd = platform_get_drvdata(dwc->xhci);
330 
331 #ifdef CONFIG_USB
332 	udev = usb_hub_find_child(hcd->self.root_hub, port_index + 1);
333 #else
334 	udev = NULL;
335 #endif
336 	if (!udev)
337 		return USB_SPEED_UNKNOWN;
338 
339 	return udev->speed;
340 }
341 
342 static void dwc3_qcom_enable_wakeup_irq(int irq, unsigned int polarity)
343 {
344 	if (!irq)
345 		return;
346 
347 	if (polarity)
348 		irq_set_irq_type(irq, polarity);
349 
350 	enable_irq(irq);
351 	enable_irq_wake(irq);
352 }
353 
354 static void dwc3_qcom_disable_wakeup_irq(int irq)
355 {
356 	if (!irq)
357 		return;
358 
359 	disable_irq_wake(irq);
360 	disable_irq_nosync(irq);
361 }
362 
363 static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port)
364 {
365 	dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq);
366 
367 	if (port->usb2_speed == USB_SPEED_LOW) {
368 		dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq);
369 	} else if ((port->usb2_speed == USB_SPEED_HIGH) ||
370 			(port->usb2_speed == USB_SPEED_FULL)) {
371 		dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq);
372 	} else {
373 		dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq);
374 		dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq);
375 	}
376 
377 	dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq);
378 }
379 
380 static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port)
381 {
382 	dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0);
383 
384 	/*
385 	 * Configure DP/DM line interrupts based on the USB2 device attached to
386 	 * the root hub port. When HS/FS device is connected, configure the DP line
387 	 * as falling edge to detect both disconnect and remote wakeup scenarios. When
388 	 * LS device is connected, configure DM line as falling edge to detect both
389 	 * disconnect and remote wakeup. When no device is connected, configure both
390 	 * DP and DM lines as rising edge to detect HS/HS/LS device connect scenario.
391 	 */
392 
393 	if (port->usb2_speed == USB_SPEED_LOW) {
394 		dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq,
395 					    IRQ_TYPE_EDGE_FALLING);
396 	} else if ((port->usb2_speed == USB_SPEED_HIGH) ||
397 			(port->usb2_speed == USB_SPEED_FULL)) {
398 		dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq,
399 					    IRQ_TYPE_EDGE_FALLING);
400 	} else {
401 		dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq,
402 					    IRQ_TYPE_EDGE_RISING);
403 		dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq,
404 					    IRQ_TYPE_EDGE_RISING);
405 	}
406 
407 	dwc3_qcom_enable_wakeup_irq(port->ss_phy_irq, 0);
408 }
409 
410 static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
411 {
412 	int i;
413 
414 	for (i = 0; i < qcom->num_ports; i++)
415 		dwc3_qcom_disable_port_interrupts(&qcom->ports[i]);
416 }
417 
418 static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
419 {
420 	int i;
421 
422 	for (i = 0; i < qcom->num_ports; i++)
423 		dwc3_qcom_enable_port_interrupts(&qcom->ports[i]);
424 }
425 
426 static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
427 {
428 	u32 val;
429 	int i, ret;
430 
431 	if (qcom->is_suspended)
432 		return 0;
433 
434 	for (i = 0; i < qcom->num_ports; i++) {
435 		val = readl(qcom->qscratch_base + pwr_evnt_irq_stat_reg[i]);
436 		if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
437 			dev_err(qcom->dev, "port-%d HS-PHY not in L2\n", i + 1);
438 	}
439 
440 	for (i = qcom->num_clocks - 1; i >= 0; i--)
441 		clk_disable_unprepare(qcom->clks[i]);
442 
443 	ret = dwc3_qcom_interconnect_disable(qcom);
444 	if (ret)
445 		dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
446 
447 	/*
448 	 * The role is stable during suspend as role switching is done from a
449 	 * freezable workqueue.
450 	 */
451 	if (dwc3_qcom_is_host(qcom) && wakeup) {
452 		for (i = 0; i < qcom->num_ports; i++)
453 			qcom->ports[i].usb2_speed = dwc3_qcom_read_usb2_speed(qcom, i);
454 		dwc3_qcom_enable_interrupts(qcom);
455 	}
456 
457 	qcom->is_suspended = true;
458 
459 	return 0;
460 }
461 
462 static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
463 {
464 	int ret;
465 	int i;
466 
467 	if (!qcom->is_suspended)
468 		return 0;
469 
470 	if (dwc3_qcom_is_host(qcom) && wakeup)
471 		dwc3_qcom_disable_interrupts(qcom);
472 
473 	for (i = 0; i < qcom->num_clocks; i++) {
474 		ret = clk_prepare_enable(qcom->clks[i]);
475 		if (ret < 0) {
476 			while (--i >= 0)
477 				clk_disable_unprepare(qcom->clks[i]);
478 			return ret;
479 		}
480 	}
481 
482 	ret = dwc3_qcom_interconnect_enable(qcom);
483 	if (ret)
484 		dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret);
485 
486 	/* Clear existing events from PHY related to L2 in/out */
487 	for (i = 0; i < qcom->num_ports; i++) {
488 		dwc3_qcom_setbits(qcom->qscratch_base,
489 				  pwr_evnt_irq_stat_reg[i],
490 				  PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
491 	}
492 
493 	qcom->is_suspended = false;
494 
495 	return 0;
496 }
497 
498 static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
499 {
500 	struct dwc3_qcom *qcom = data;
501 	struct dwc3	*dwc = platform_get_drvdata(qcom->dwc3);
502 
503 	/* If pm_suspended then let pm_resume take care of resuming h/w */
504 	if (qcom->pm_suspended)
505 		return IRQ_HANDLED;
506 
507 	/*
508 	 * This is safe as role switching is done from a freezable workqueue
509 	 * and the wakeup interrupts are disabled as part of resume.
510 	 */
511 	if (dwc3_qcom_is_host(qcom))
512 		pm_runtime_resume(&dwc->xhci->dev);
513 
514 	return IRQ_HANDLED;
515 }
516 
517 static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom)
518 {
519 	/* Configure dwc3 to use UTMI clock as PIPE clock not present */
520 	dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
521 			  PIPE_UTMI_CLK_DIS);
522 
523 	usleep_range(100, 1000);
524 
525 	dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
526 			  PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
527 
528 	usleep_range(100, 1000);
529 
530 	dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
531 			  PIPE_UTMI_CLK_DIS);
532 }
533 
534 static int dwc3_qcom_request_irq(struct dwc3_qcom *qcom, int irq,
535 				 const char *name)
536 {
537 	int ret;
538 
539 	/* Keep wakeup interrupts disabled until suspend */
540 	ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
541 					qcom_dwc3_resume_irq,
542 					IRQF_ONESHOT | IRQF_NO_AUTOEN,
543 					name, qcom);
544 	if (ret)
545 		dev_err(qcom->dev, "failed to request irq %s: %d\n", name, ret);
546 
547 	return ret;
548 }
549 
550 static int dwc3_qcom_setup_port_irq(struct platform_device *pdev, int port_index, bool is_multiport)
551 {
552 	struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
553 	const char *irq_name;
554 	int irq;
555 	int ret;
556 
557 	if (is_multiport)
558 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_%d", port_index + 1);
559 	else
560 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_irq");
561 	if (!irq_name)
562 		return -ENOMEM;
563 
564 	irq = platform_get_irq_byname_optional(pdev, irq_name);
565 	if (irq > 0) {
566 		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
567 		if (ret)
568 			return ret;
569 		qcom->ports[port_index].dp_hs_phy_irq = irq;
570 	}
571 
572 	if (is_multiport)
573 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_%d", port_index + 1);
574 	else
575 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_irq");
576 	if (!irq_name)
577 		return -ENOMEM;
578 
579 	irq = platform_get_irq_byname_optional(pdev, irq_name);
580 	if (irq > 0) {
581 		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
582 		if (ret)
583 			return ret;
584 		qcom->ports[port_index].dm_hs_phy_irq = irq;
585 	}
586 
587 	if (is_multiport)
588 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_%d", port_index + 1);
589 	else
590 		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_irq");
591 	if (!irq_name)
592 		return -ENOMEM;
593 
594 	irq = platform_get_irq_byname_optional(pdev, irq_name);
595 	if (irq > 0) {
596 		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
597 		if (ret)
598 			return ret;
599 		qcom->ports[port_index].ss_phy_irq = irq;
600 	}
601 
602 	if (is_multiport)
603 		return 0;
604 
605 	irq = platform_get_irq_byname_optional(pdev, "qusb2_phy");
606 	if (irq > 0) {
607 		ret = dwc3_qcom_request_irq(qcom, irq, "qusb2_phy");
608 		if (ret)
609 			return ret;
610 		qcom->ports[port_index].qusb2_phy_irq = irq;
611 	}
612 
613 	return 0;
614 }
615 
616 static int dwc3_qcom_find_num_ports(struct platform_device *pdev)
617 {
618 	char irq_name[14];
619 	int port_num;
620 	int irq;
621 
622 	irq = platform_get_irq_byname_optional(pdev, "dp_hs_phy_1");
623 	if (irq <= 0)
624 		return 1;
625 
626 	for (port_num = 2; port_num <= DWC3_QCOM_MAX_PORTS; port_num++) {
627 		sprintf(irq_name, "dp_hs_phy_%d", port_num);
628 
629 		irq = platform_get_irq_byname_optional(pdev, irq_name);
630 		if (irq <= 0)
631 			return port_num - 1;
632 	}
633 
634 	return DWC3_QCOM_MAX_PORTS;
635 }
636 
637 static int dwc3_qcom_setup_irq(struct platform_device *pdev)
638 {
639 	struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
640 	bool is_multiport;
641 	int ret;
642 	int i;
643 
644 	qcom->num_ports = dwc3_qcom_find_num_ports(pdev);
645 	is_multiport = (qcom->num_ports > 1);
646 
647 	for (i = 0; i < qcom->num_ports; i++) {
648 		ret = dwc3_qcom_setup_port_irq(pdev, i, is_multiport);
649 		if (ret)
650 			return ret;
651 	}
652 
653 	return 0;
654 }
655 
656 static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count)
657 {
658 	struct device		*dev = qcom->dev;
659 	struct device_node	*np = dev->of_node;
660 	int			i;
661 
662 	if (!np || !count)
663 		return 0;
664 
665 	if (count < 0)
666 		return count;
667 
668 	qcom->num_clocks = count;
669 
670 	qcom->clks = devm_kcalloc(dev, qcom->num_clocks,
671 				  sizeof(struct clk *), GFP_KERNEL);
672 	if (!qcom->clks)
673 		return -ENOMEM;
674 
675 	for (i = 0; i < qcom->num_clocks; i++) {
676 		struct clk	*clk;
677 		int		ret;
678 
679 		clk = of_clk_get(np, i);
680 		if (IS_ERR(clk)) {
681 			while (--i >= 0)
682 				clk_put(qcom->clks[i]);
683 			return PTR_ERR(clk);
684 		}
685 
686 		ret = clk_prepare_enable(clk);
687 		if (ret < 0) {
688 			while (--i >= 0) {
689 				clk_disable_unprepare(qcom->clks[i]);
690 				clk_put(qcom->clks[i]);
691 			}
692 			clk_put(clk);
693 
694 			return ret;
695 		}
696 
697 		qcom->clks[i] = clk;
698 	}
699 
700 	return 0;
701 }
702 
703 static int dwc3_qcom_of_register_core(struct platform_device *pdev)
704 {
705 	struct dwc3_qcom	*qcom = platform_get_drvdata(pdev);
706 	struct device_node	*np = pdev->dev.of_node;
707 	struct device		*dev = &pdev->dev;
708 	int			ret;
709 
710 	struct device_node *dwc3_np __free(device_node) = of_get_compatible_child(np,
711 										  "snps,dwc3");
712 	if (!dwc3_np) {
713 		dev_err(dev, "failed to find dwc3 core child\n");
714 		return -ENODEV;
715 	}
716 
717 	ret = of_platform_populate(np, NULL, NULL, dev);
718 	if (ret) {
719 		dev_err(dev, "failed to register dwc3 core - %d\n", ret);
720 		return ret;
721 	}
722 
723 	qcom->dwc3 = of_find_device_by_node(dwc3_np);
724 	if (!qcom->dwc3) {
725 		ret = -ENODEV;
726 		dev_err(dev, "failed to get dwc3 platform device\n");
727 		of_platform_depopulate(dev);
728 	}
729 
730 	return ret;
731 }
732 
733 static int dwc3_qcom_probe(struct platform_device *pdev)
734 {
735 	struct device_node	*np = pdev->dev.of_node;
736 	struct device		*dev = &pdev->dev;
737 	struct dwc3_qcom	*qcom;
738 	int			ret, i;
739 	bool			ignore_pipe_clk;
740 	bool			wakeup_source;
741 
742 	qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
743 	if (!qcom)
744 		return -ENOMEM;
745 
746 	platform_set_drvdata(pdev, qcom);
747 	qcom->dev = &pdev->dev;
748 
749 	qcom->resets = devm_reset_control_array_get_optional_exclusive(dev);
750 	if (IS_ERR(qcom->resets)) {
751 		return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets),
752 				     "failed to get resets\n");
753 	}
754 
755 	ret = reset_control_assert(qcom->resets);
756 	if (ret) {
757 		dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret);
758 		return ret;
759 	}
760 
761 	usleep_range(10, 1000);
762 
763 	ret = reset_control_deassert(qcom->resets);
764 	if (ret) {
765 		dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret);
766 		goto reset_assert;
767 	}
768 
769 	ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
770 	if (ret) {
771 		dev_err_probe(dev, ret, "failed to get clocks\n");
772 		goto reset_assert;
773 	}
774 
775 	qcom->qscratch_base = devm_platform_ioremap_resource(pdev, 0);
776 	if (IS_ERR(qcom->qscratch_base)) {
777 		ret = PTR_ERR(qcom->qscratch_base);
778 		goto clk_disable;
779 	}
780 
781 	ret = dwc3_qcom_setup_irq(pdev);
782 	if (ret) {
783 		dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
784 		goto clk_disable;
785 	}
786 
787 	/*
788 	 * Disable pipe_clk requirement if specified. Used when dwc3
789 	 * operates without SSPHY and only HS/FS/LS modes are supported.
790 	 */
791 	ignore_pipe_clk = device_property_read_bool(dev,
792 				"qcom,select-utmi-as-pipe-clk");
793 	if (ignore_pipe_clk)
794 		dwc3_qcom_select_utmi_clk(qcom);
795 
796 	ret = dwc3_qcom_of_register_core(pdev);
797 	if (ret) {
798 		dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
799 		goto clk_disable;
800 	}
801 
802 	ret = dwc3_qcom_interconnect_init(qcom);
803 	if (ret)
804 		goto depopulate;
805 
806 	qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
807 
808 	/* enable vbus override for device mode */
809 	if (qcom->mode != USB_DR_MODE_HOST)
810 		dwc3_qcom_vbus_override_enable(qcom, true);
811 
812 	/* register extcon to override sw_vbus on Vbus change later */
813 	ret = dwc3_qcom_register_extcon(qcom);
814 	if (ret)
815 		goto interconnect_exit;
816 
817 	wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source");
818 	device_init_wakeup(&pdev->dev, wakeup_source);
819 	device_init_wakeup(&qcom->dwc3->dev, wakeup_source);
820 
821 	qcom->is_suspended = false;
822 	pm_runtime_set_active(dev);
823 	pm_runtime_enable(dev);
824 	pm_runtime_forbid(dev);
825 
826 	return 0;
827 
828 interconnect_exit:
829 	dwc3_qcom_interconnect_exit(qcom);
830 depopulate:
831 	of_platform_depopulate(&pdev->dev);
832 	platform_device_put(qcom->dwc3);
833 clk_disable:
834 	for (i = qcom->num_clocks - 1; i >= 0; i--) {
835 		clk_disable_unprepare(qcom->clks[i]);
836 		clk_put(qcom->clks[i]);
837 	}
838 reset_assert:
839 	reset_control_assert(qcom->resets);
840 
841 	return ret;
842 }
843 
844 static void dwc3_qcom_remove(struct platform_device *pdev)
845 {
846 	struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
847 	struct device *dev = &pdev->dev;
848 	int i;
849 
850 	of_platform_depopulate(&pdev->dev);
851 	platform_device_put(qcom->dwc3);
852 
853 	for (i = qcom->num_clocks - 1; i >= 0; i--) {
854 		clk_disable_unprepare(qcom->clks[i]);
855 		clk_put(qcom->clks[i]);
856 	}
857 	qcom->num_clocks = 0;
858 
859 	dwc3_qcom_interconnect_exit(qcom);
860 	reset_control_assert(qcom->resets);
861 
862 	pm_runtime_allow(dev);
863 	pm_runtime_disable(dev);
864 }
865 
866 static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
867 {
868 	struct dwc3_qcom *qcom = dev_get_drvdata(dev);
869 	bool wakeup = device_may_wakeup(dev);
870 	int ret;
871 
872 	ret = dwc3_qcom_suspend(qcom, wakeup);
873 	if (ret)
874 		return ret;
875 
876 	qcom->pm_suspended = true;
877 
878 	return 0;
879 }
880 
881 static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
882 {
883 	struct dwc3_qcom *qcom = dev_get_drvdata(dev);
884 	bool wakeup = device_may_wakeup(dev);
885 	int ret;
886 
887 	ret = dwc3_qcom_resume(qcom, wakeup);
888 	if (ret)
889 		return ret;
890 
891 	qcom->pm_suspended = false;
892 
893 	return 0;
894 }
895 
896 static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
897 {
898 	struct dwc3_qcom *qcom = dev_get_drvdata(dev);
899 
900 	return dwc3_qcom_suspend(qcom, true);
901 }
902 
903 static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
904 {
905 	struct dwc3_qcom *qcom = dev_get_drvdata(dev);
906 
907 	return dwc3_qcom_resume(qcom, true);
908 }
909 
910 static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
911 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume)
912 	SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume,
913 			   NULL)
914 };
915 
916 static const struct of_device_id dwc3_qcom_of_match[] = {
917 	{ .compatible = "qcom,dwc3" },
918 	{ }
919 };
920 MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
921 
922 static struct platform_driver dwc3_qcom_driver = {
923 	.probe		= dwc3_qcom_probe,
924 	.remove_new	= dwc3_qcom_remove,
925 	.driver		= {
926 		.name	= "dwc3-qcom",
927 		.pm	= &dwc3_qcom_dev_pm_ops,
928 		.of_match_table	= dwc3_qcom_of_match,
929 	},
930 };
931 
932 module_platform_driver(dwc3_qcom_driver);
933 
934 MODULE_LICENSE("GPL v2");
935 MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver");
936