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