Merge tag 'trace-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux/fpc-iii.git] / drivers / usb / dwc3 / dwc3-qcom.c
blobc703d552bbcfc9ea26ee9a2637b6c93b81ef6129
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 * Inspired by dwc3-of-simple.c
5 */
7 #include <linux/acpi.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>
24 #include "core.h"
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)
31 #define QSCRATCH_SS_PHY_CTRL 0x30
32 #define LANE0_PWR_PRESENT BIT(24)
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)
39 #define PWR_EVNT_IRQ_STAT_REG 0x58
40 #define PWR_EVNT_LPM_IN_L2_MASK BIT(4)
41 #define PWR_EVNT_LPM_OUT_L2_MASK BIT(5)
43 #define SDM845_QSCRATCH_BASE_OFFSET 0xf8800
44 #define SDM845_QSCRATCH_SIZE 0x400
45 #define SDM845_DWC3_CORE_SIZE 0xcd00
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)
55 struct dwc3_acpi_pdata {
56 u32 qscratch_base_offset;
57 u32 qscratch_base_size;
58 u32 dwc3_core_base_size;
59 int hs_phy_irq_index;
60 int dp_hs_phy_irq_index;
61 int dm_hs_phy_irq_index;
62 int ss_phy_irq_index;
65 struct dwc3_qcom {
66 struct device *dev;
67 void __iomem *qscratch_base;
68 struct platform_device *dwc3;
69 struct clk **clks;
70 int num_clocks;
71 struct reset_control *resets;
73 int hs_phy_irq;
74 int dp_hs_phy_irq;
75 int dm_hs_phy_irq;
76 int ss_phy_irq;
78 struct extcon_dev *edev;
79 struct extcon_dev *host_edev;
80 struct notifier_block vbus_nb;
81 struct notifier_block host_nb;
83 const struct dwc3_acpi_pdata *acpi_pdata;
85 enum usb_dr_mode mode;
86 bool is_suspended;
87 bool pm_suspended;
88 struct icc_path *icc_path_ddr;
89 struct icc_path *icc_path_apps;
92 static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
94 u32 reg;
96 reg = readl(base + offset);
97 reg |= val;
98 writel(reg, base + offset);
100 /* ensure that above write is through */
101 readl(base + offset);
104 static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
106 u32 reg;
108 reg = readl(base + offset);
109 reg &= ~val;
110 writel(reg, base + offset);
112 /* ensure that above write is through */
113 readl(base + offset);
116 static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable)
118 if (enable) {
119 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
120 LANE0_PWR_PRESENT);
121 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
122 UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
123 } else {
124 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
125 LANE0_PWR_PRESENT);
126 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
127 UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
131 static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
132 unsigned long event, void *ptr)
134 struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
136 /* enable vbus override for device mode */
137 dwc3_qcom_vbus_overrride_enable(qcom, event);
138 qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
140 return NOTIFY_DONE;
143 static int dwc3_qcom_host_notifier(struct notifier_block *nb,
144 unsigned long event, void *ptr)
146 struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
148 /* disable vbus override in host mode */
149 dwc3_qcom_vbus_overrride_enable(qcom, !event);
150 qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
152 return NOTIFY_DONE;
155 static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
157 struct device *dev = qcom->dev;
158 struct extcon_dev *host_edev;
159 int ret;
161 if (!of_property_read_bool(dev->of_node, "extcon"))
162 return 0;
164 qcom->edev = extcon_get_edev_by_phandle(dev, 0);
165 if (IS_ERR(qcom->edev))
166 return PTR_ERR(qcom->edev);
168 qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier;
170 qcom->host_edev = extcon_get_edev_by_phandle(dev, 1);
171 if (IS_ERR(qcom->host_edev))
172 qcom->host_edev = NULL;
174 ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB,
175 &qcom->vbus_nb);
176 if (ret < 0) {
177 dev_err(dev, "VBUS notifier register failed\n");
178 return ret;
181 if (qcom->host_edev)
182 host_edev = qcom->host_edev;
183 else
184 host_edev = qcom->edev;
186 qcom->host_nb.notifier_call = dwc3_qcom_host_notifier;
187 ret = devm_extcon_register_notifier(dev, host_edev, EXTCON_USB_HOST,
188 &qcom->host_nb);
189 if (ret < 0) {
190 dev_err(dev, "Host notifier register failed\n");
191 return ret;
194 /* Update initial VBUS override based on extcon state */
195 if (extcon_get_state(qcom->edev, EXTCON_USB) ||
196 !extcon_get_state(host_edev, EXTCON_USB_HOST))
197 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev);
198 else
199 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev);
201 return 0;
204 static int dwc3_qcom_interconnect_enable(struct dwc3_qcom *qcom)
206 int ret;
208 ret = icc_enable(qcom->icc_path_ddr);
209 if (ret)
210 return ret;
212 ret = icc_enable(qcom->icc_path_apps);
213 if (ret)
214 icc_disable(qcom->icc_path_ddr);
216 return ret;
219 static int dwc3_qcom_interconnect_disable(struct dwc3_qcom *qcom)
221 int ret;
223 ret = icc_disable(qcom->icc_path_ddr);
224 if (ret)
225 return ret;
227 ret = icc_disable(qcom->icc_path_apps);
228 if (ret)
229 icc_enable(qcom->icc_path_ddr);
231 return ret;
235 * dwc3_qcom_interconnect_init() - Get interconnect path handles
236 * and set bandwidhth.
237 * @qcom: Pointer to the concerned usb core.
240 static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
242 struct device *dev = qcom->dev;
243 int ret;
245 qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr");
246 if (IS_ERR(qcom->icc_path_ddr)) {
247 dev_err(dev, "failed to get usb-ddr path: %ld\n",
248 PTR_ERR(qcom->icc_path_ddr));
249 return PTR_ERR(qcom->icc_path_ddr);
252 qcom->icc_path_apps = of_icc_get(dev, "apps-usb");
253 if (IS_ERR(qcom->icc_path_apps)) {
254 dev_err(dev, "failed to get apps-usb path: %ld\n",
255 PTR_ERR(qcom->icc_path_apps));
256 return PTR_ERR(qcom->icc_path_apps);
259 if (usb_get_maximum_speed(&qcom->dwc3->dev) >= USB_SPEED_SUPER ||
260 usb_get_maximum_speed(&qcom->dwc3->dev) == USB_SPEED_UNKNOWN)
261 ret = icc_set_bw(qcom->icc_path_ddr,
262 USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
263 else
264 ret = icc_set_bw(qcom->icc_path_ddr,
265 USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW);
267 if (ret) {
268 dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret);
269 return ret;
272 ret = icc_set_bw(qcom->icc_path_apps,
273 APPS_USB_AVG_BW, APPS_USB_PEAK_BW);
274 if (ret) {
275 dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret);
276 return ret;
279 return 0;
283 * dwc3_qcom_interconnect_exit() - Release interconnect path handles
284 * @qcom: Pointer to the concerned usb core.
286 * This function is used to release interconnect path handle.
288 static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
290 icc_put(qcom->icc_path_ddr);
291 icc_put(qcom->icc_path_apps);
294 static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
296 if (qcom->hs_phy_irq) {
297 disable_irq_wake(qcom->hs_phy_irq);
298 disable_irq_nosync(qcom->hs_phy_irq);
301 if (qcom->dp_hs_phy_irq) {
302 disable_irq_wake(qcom->dp_hs_phy_irq);
303 disable_irq_nosync(qcom->dp_hs_phy_irq);
306 if (qcom->dm_hs_phy_irq) {
307 disable_irq_wake(qcom->dm_hs_phy_irq);
308 disable_irq_nosync(qcom->dm_hs_phy_irq);
311 if (qcom->ss_phy_irq) {
312 disable_irq_wake(qcom->ss_phy_irq);
313 disable_irq_nosync(qcom->ss_phy_irq);
317 static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
319 if (qcom->hs_phy_irq) {
320 enable_irq(qcom->hs_phy_irq);
321 enable_irq_wake(qcom->hs_phy_irq);
324 if (qcom->dp_hs_phy_irq) {
325 enable_irq(qcom->dp_hs_phy_irq);
326 enable_irq_wake(qcom->dp_hs_phy_irq);
329 if (qcom->dm_hs_phy_irq) {
330 enable_irq(qcom->dm_hs_phy_irq);
331 enable_irq_wake(qcom->dm_hs_phy_irq);
334 if (qcom->ss_phy_irq) {
335 enable_irq(qcom->ss_phy_irq);
336 enable_irq_wake(qcom->ss_phy_irq);
340 static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
342 u32 val;
343 int i, ret;
345 if (qcom->is_suspended)
346 return 0;
348 val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG);
349 if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
350 dev_err(qcom->dev, "HS-PHY not in L2\n");
352 for (i = qcom->num_clocks - 1; i >= 0; i--)
353 clk_disable_unprepare(qcom->clks[i]);
355 ret = dwc3_qcom_interconnect_disable(qcom);
356 if (ret)
357 dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
359 qcom->is_suspended = true;
360 dwc3_qcom_enable_interrupts(qcom);
362 return 0;
365 static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
367 int ret;
368 int i;
370 if (!qcom->is_suspended)
371 return 0;
373 dwc3_qcom_disable_interrupts(qcom);
375 for (i = 0; i < qcom->num_clocks; i++) {
376 ret = clk_prepare_enable(qcom->clks[i]);
377 if (ret < 0) {
378 while (--i >= 0)
379 clk_disable_unprepare(qcom->clks[i]);
380 return ret;
384 ret = dwc3_qcom_interconnect_enable(qcom);
385 if (ret)
386 dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret);
388 /* Clear existing events from PHY related to L2 in/out */
389 dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG,
390 PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
392 qcom->is_suspended = false;
394 return 0;
397 static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
399 struct dwc3_qcom *qcom = data;
400 struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
402 /* If pm_suspended then let pm_resume take care of resuming h/w */
403 if (qcom->pm_suspended)
404 return IRQ_HANDLED;
406 if (dwc->xhci)
407 pm_runtime_resume(&dwc->xhci->dev);
409 return IRQ_HANDLED;
412 static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom)
414 /* Configure dwc3 to use UTMI clock as PIPE clock not present */
415 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
416 PIPE_UTMI_CLK_DIS);
418 usleep_range(100, 1000);
420 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
421 PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
423 usleep_range(100, 1000);
425 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
426 PIPE_UTMI_CLK_DIS);
429 static int dwc3_qcom_get_irq(struct platform_device *pdev,
430 const char *name, int num)
432 struct device_node *np = pdev->dev.of_node;
433 int ret;
435 if (np)
436 ret = platform_get_irq_byname(pdev, name);
437 else
438 ret = platform_get_irq(pdev, num);
440 return ret;
443 static int dwc3_qcom_setup_irq(struct platform_device *pdev)
445 struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
446 const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata;
447 int irq;
448 int ret;
450 irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq",
451 pdata ? pdata->hs_phy_irq_index : -1);
452 if (irq > 0) {
453 /* Keep wakeup interrupts disabled until suspend */
454 irq_set_status_flags(irq, IRQ_NOAUTOEN);
455 ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
456 qcom_dwc3_resume_irq,
457 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
458 "qcom_dwc3 HS", qcom);
459 if (ret) {
460 dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret);
461 return ret;
463 qcom->hs_phy_irq = irq;
466 irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq",
467 pdata ? pdata->dp_hs_phy_irq_index : -1);
468 if (irq > 0) {
469 irq_set_status_flags(irq, IRQ_NOAUTOEN);
470 ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
471 qcom_dwc3_resume_irq,
472 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
473 "qcom_dwc3 DP_HS", qcom);
474 if (ret) {
475 dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret);
476 return ret;
478 qcom->dp_hs_phy_irq = irq;
481 irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq",
482 pdata ? pdata->dm_hs_phy_irq_index : -1);
483 if (irq > 0) {
484 irq_set_status_flags(irq, IRQ_NOAUTOEN);
485 ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
486 qcom_dwc3_resume_irq,
487 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
488 "qcom_dwc3 DM_HS", qcom);
489 if (ret) {
490 dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret);
491 return ret;
493 qcom->dm_hs_phy_irq = irq;
496 irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq",
497 pdata ? pdata->ss_phy_irq_index : -1);
498 if (irq > 0) {
499 irq_set_status_flags(irq, IRQ_NOAUTOEN);
500 ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
501 qcom_dwc3_resume_irq,
502 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
503 "qcom_dwc3 SS", qcom);
504 if (ret) {
505 dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret);
506 return ret;
508 qcom->ss_phy_irq = irq;
511 return 0;
514 static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count)
516 struct device *dev = qcom->dev;
517 struct device_node *np = dev->of_node;
518 int i;
520 if (!np || !count)
521 return 0;
523 if (count < 0)
524 return count;
526 qcom->num_clocks = count;
528 qcom->clks = devm_kcalloc(dev, qcom->num_clocks,
529 sizeof(struct clk *), GFP_KERNEL);
530 if (!qcom->clks)
531 return -ENOMEM;
533 for (i = 0; i < qcom->num_clocks; i++) {
534 struct clk *clk;
535 int ret;
537 clk = of_clk_get(np, i);
538 if (IS_ERR(clk)) {
539 while (--i >= 0)
540 clk_put(qcom->clks[i]);
541 return PTR_ERR(clk);
544 ret = clk_prepare_enable(clk);
545 if (ret < 0) {
546 while (--i >= 0) {
547 clk_disable_unprepare(qcom->clks[i]);
548 clk_put(qcom->clks[i]);
550 clk_put(clk);
552 return ret;
555 qcom->clks[i] = clk;
558 return 0;
561 static const struct property_entry dwc3_qcom_acpi_properties[] = {
562 PROPERTY_ENTRY_STRING("dr_mode", "host"),
566 static int dwc3_qcom_acpi_register_core(struct platform_device *pdev)
568 struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
569 struct device *dev = &pdev->dev;
570 struct resource *res, *child_res = NULL;
571 int irq;
572 int ret;
574 qcom->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
575 if (!qcom->dwc3)
576 return -ENOMEM;
578 qcom->dwc3->dev.parent = dev;
579 qcom->dwc3->dev.type = dev->type;
580 qcom->dwc3->dev.dma_mask = dev->dma_mask;
581 qcom->dwc3->dev.dma_parms = dev->dma_parms;
582 qcom->dwc3->dev.coherent_dma_mask = dev->coherent_dma_mask;
584 child_res = kcalloc(2, sizeof(*child_res), GFP_KERNEL);
585 if (!child_res)
586 return -ENOMEM;
588 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
589 if (!res) {
590 dev_err(&pdev->dev, "failed to get memory resource\n");
591 ret = -ENODEV;
592 goto out;
595 child_res[0].flags = res->flags;
596 child_res[0].start = res->start;
597 child_res[0].end = child_res[0].start +
598 qcom->acpi_pdata->dwc3_core_base_size;
600 irq = platform_get_irq(pdev, 0);
601 child_res[1].flags = IORESOURCE_IRQ;
602 child_res[1].start = child_res[1].end = irq;
604 ret = platform_device_add_resources(qcom->dwc3, child_res, 2);
605 if (ret) {
606 dev_err(&pdev->dev, "failed to add resources\n");
607 goto out;
610 ret = platform_device_add_properties(qcom->dwc3,
611 dwc3_qcom_acpi_properties);
612 if (ret < 0) {
613 dev_err(&pdev->dev, "failed to add properties\n");
614 goto out;
617 ret = platform_device_add(qcom->dwc3);
618 if (ret)
619 dev_err(&pdev->dev, "failed to add device\n");
621 out:
622 kfree(child_res);
623 return ret;
626 static int dwc3_qcom_of_register_core(struct platform_device *pdev)
628 struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
629 struct device_node *np = pdev->dev.of_node, *dwc3_np;
630 struct device *dev = &pdev->dev;
631 int ret;
633 dwc3_np = of_get_child_by_name(np, "dwc3");
634 if (!dwc3_np) {
635 dev_err(dev, "failed to find dwc3 core child\n");
636 return -ENODEV;
639 ret = of_platform_populate(np, NULL, NULL, dev);
640 if (ret) {
641 dev_err(dev, "failed to register dwc3 core - %d\n", ret);
642 return ret;
645 qcom->dwc3 = of_find_device_by_node(dwc3_np);
646 if (!qcom->dwc3) {
647 dev_err(dev, "failed to get dwc3 platform device\n");
648 return -ENODEV;
651 return 0;
654 static int dwc3_qcom_probe(struct platform_device *pdev)
656 struct device_node *np = pdev->dev.of_node;
657 struct device *dev = &pdev->dev;
658 struct dwc3_qcom *qcom;
659 struct resource *res, *parent_res = NULL;
660 int ret, i;
661 bool ignore_pipe_clk;
663 qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
664 if (!qcom)
665 return -ENOMEM;
667 platform_set_drvdata(pdev, qcom);
668 qcom->dev = &pdev->dev;
670 if (has_acpi_companion(dev)) {
671 qcom->acpi_pdata = acpi_device_get_match_data(dev);
672 if (!qcom->acpi_pdata) {
673 dev_err(&pdev->dev, "no supporting ACPI device data\n");
674 return -EINVAL;
678 qcom->resets = devm_reset_control_array_get_optional_exclusive(dev);
679 if (IS_ERR(qcom->resets)) {
680 ret = PTR_ERR(qcom->resets);
681 dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret);
682 return ret;
685 ret = reset_control_assert(qcom->resets);
686 if (ret) {
687 dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret);
688 return ret;
691 usleep_range(10, 1000);
693 ret = reset_control_deassert(qcom->resets);
694 if (ret) {
695 dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret);
696 goto reset_assert;
699 ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
700 if (ret) {
701 dev_err(dev, "failed to get clocks\n");
702 goto reset_assert;
705 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
707 if (np) {
708 parent_res = res;
709 } else {
710 parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL);
711 if (!parent_res)
712 return -ENOMEM;
714 parent_res->start = res->start +
715 qcom->acpi_pdata->qscratch_base_offset;
716 parent_res->end = parent_res->start +
717 qcom->acpi_pdata->qscratch_base_size;
720 qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
721 if (IS_ERR(qcom->qscratch_base)) {
722 dev_err(dev, "failed to map qscratch, err=%d\n", ret);
723 ret = PTR_ERR(qcom->qscratch_base);
724 goto clk_disable;
727 ret = dwc3_qcom_setup_irq(pdev);
728 if (ret) {
729 dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
730 goto clk_disable;
734 * Disable pipe_clk requirement if specified. Used when dwc3
735 * operates without SSPHY and only HS/FS/LS modes are supported.
737 ignore_pipe_clk = device_property_read_bool(dev,
738 "qcom,select-utmi-as-pipe-clk");
739 if (ignore_pipe_clk)
740 dwc3_qcom_select_utmi_clk(qcom);
742 if (np)
743 ret = dwc3_qcom_of_register_core(pdev);
744 else
745 ret = dwc3_qcom_acpi_register_core(pdev);
747 if (ret) {
748 dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
749 goto depopulate;
752 ret = dwc3_qcom_interconnect_init(qcom);
753 if (ret)
754 goto depopulate;
756 qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
758 /* enable vbus override for device mode */
759 if (qcom->mode == USB_DR_MODE_PERIPHERAL)
760 dwc3_qcom_vbus_overrride_enable(qcom, true);
762 /* register extcon to override sw_vbus on Vbus change later */
763 ret = dwc3_qcom_register_extcon(qcom);
764 if (ret)
765 goto interconnect_exit;
767 device_init_wakeup(&pdev->dev, 1);
768 qcom->is_suspended = false;
769 pm_runtime_set_active(dev);
770 pm_runtime_enable(dev);
771 pm_runtime_forbid(dev);
773 return 0;
775 interconnect_exit:
776 dwc3_qcom_interconnect_exit(qcom);
777 depopulate:
778 if (np)
779 of_platform_depopulate(&pdev->dev);
780 else
781 platform_device_put(pdev);
782 clk_disable:
783 for (i = qcom->num_clocks - 1; i >= 0; i--) {
784 clk_disable_unprepare(qcom->clks[i]);
785 clk_put(qcom->clks[i]);
787 reset_assert:
788 reset_control_assert(qcom->resets);
790 return ret;
793 static int dwc3_qcom_remove(struct platform_device *pdev)
795 struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
796 struct device *dev = &pdev->dev;
797 int i;
799 of_platform_depopulate(dev);
801 for (i = qcom->num_clocks - 1; i >= 0; i--) {
802 clk_disable_unprepare(qcom->clks[i]);
803 clk_put(qcom->clks[i]);
805 qcom->num_clocks = 0;
807 dwc3_qcom_interconnect_exit(qcom);
808 reset_control_assert(qcom->resets);
810 pm_runtime_allow(dev);
811 pm_runtime_disable(dev);
813 return 0;
816 static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
818 struct dwc3_qcom *qcom = dev_get_drvdata(dev);
819 int ret = 0;
821 ret = dwc3_qcom_suspend(qcom);
822 if (!ret)
823 qcom->pm_suspended = true;
825 return ret;
828 static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
830 struct dwc3_qcom *qcom = dev_get_drvdata(dev);
831 int ret;
833 ret = dwc3_qcom_resume(qcom);
834 if (!ret)
835 qcom->pm_suspended = false;
837 return ret;
840 static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
842 struct dwc3_qcom *qcom = dev_get_drvdata(dev);
844 return dwc3_qcom_suspend(qcom);
847 static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
849 struct dwc3_qcom *qcom = dev_get_drvdata(dev);
851 return dwc3_qcom_resume(qcom);
854 static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
855 SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume)
856 SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume,
857 NULL)
860 static const struct of_device_id dwc3_qcom_of_match[] = {
861 { .compatible = "qcom,dwc3" },
862 { .compatible = "qcom,msm8996-dwc3" },
863 { .compatible = "qcom,msm8998-dwc3" },
864 { .compatible = "qcom,sdm845-dwc3" },
867 MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
869 #ifdef CONFIG_ACPI
870 static const struct dwc3_acpi_pdata sdm845_acpi_pdata = {
871 .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET,
872 .qscratch_base_size = SDM845_QSCRATCH_SIZE,
873 .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE,
874 .hs_phy_irq_index = 1,
875 .dp_hs_phy_irq_index = 4,
876 .dm_hs_phy_irq_index = 3,
877 .ss_phy_irq_index = 2
880 static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
881 { "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
882 { },
884 MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
885 #endif
887 static struct platform_driver dwc3_qcom_driver = {
888 .probe = dwc3_qcom_probe,
889 .remove = dwc3_qcom_remove,
890 .driver = {
891 .name = "dwc3-qcom",
892 .pm = &dwc3_qcom_dev_pm_ops,
893 .of_match_table = dwc3_qcom_of_match,
894 .acpi_match_table = ACPI_PTR(dwc3_qcom_acpi_match),
898 module_platform_driver(dwc3_qcom_driver);
900 MODULE_LICENSE("GPL v2");
901 MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver");