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