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/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/of_platform.h> 17 #include <linux/platform_device.h> 18 #include <linux/phy/phy.h> 19 #include <linux/usb/of.h> 20 #include <linux/reset.h> 21 #include <linux/iopoll.h> 22 23 #include "core.h" 24 25 /* USB QSCRATCH Hardware registers */ 26 #define QSCRATCH_HS_PHY_CTRL 0x10 27 #define UTMI_OTG_VBUS_VALID BIT(20) 28 #define SW_SESSVLD_SEL BIT(28) 29 30 #define QSCRATCH_SS_PHY_CTRL 0x30 31 #define LANE0_PWR_PRESENT BIT(24) 32 33 #define QSCRATCH_GENERAL_CFG 0x08 34 #define PIPE_UTMI_CLK_SEL BIT(0) 35 #define PIPE3_PHYSTATUS_SW BIT(3) 36 #define PIPE_UTMI_CLK_DIS BIT(8) 37 38 #define PWR_EVNT_IRQ_STAT_REG 0x58 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 struct dwc3_acpi_pdata { 47 u32 qscratch_base_offset; 48 u32 qscratch_base_size; 49 u32 dwc3_core_base_size; 50 int hs_phy_irq_index; 51 int dp_hs_phy_irq_index; 52 int dm_hs_phy_irq_index; 53 int ss_phy_irq_index; 54 }; 55 56 struct dwc3_qcom { 57 struct device *dev; 58 void __iomem *qscratch_base; 59 struct platform_device *dwc3; 60 struct clk **clks; 61 int num_clocks; 62 struct reset_control *resets; 63 64 int hs_phy_irq; 65 int dp_hs_phy_irq; 66 int dm_hs_phy_irq; 67 int ss_phy_irq; 68 69 struct extcon_dev *edev; 70 struct extcon_dev *host_edev; 71 struct notifier_block vbus_nb; 72 struct notifier_block host_nb; 73 74 const struct dwc3_acpi_pdata *acpi_pdata; 75 76 enum usb_dr_mode mode; 77 bool is_suspended; 78 bool pm_suspended; 79 }; 80 81 static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) 82 { 83 u32 reg; 84 85 reg = readl(base + offset); 86 reg |= val; 87 writel(reg, base + offset); 88 89 /* ensure that above write is through */ 90 readl(base + offset); 91 } 92 93 static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val) 94 { 95 u32 reg; 96 97 reg = readl(base + offset); 98 reg &= ~val; 99 writel(reg, base + offset); 100 101 /* ensure that above write is through */ 102 readl(base + offset); 103 } 104 105 static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable) 106 { 107 if (enable) { 108 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, 109 LANE0_PWR_PRESENT); 110 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, 111 UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); 112 } else { 113 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, 114 LANE0_PWR_PRESENT); 115 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, 116 UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); 117 } 118 } 119 120 static int dwc3_qcom_vbus_notifier(struct notifier_block *nb, 121 unsigned long event, void *ptr) 122 { 123 struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb); 124 125 /* enable vbus override for device mode */ 126 dwc3_qcom_vbus_overrride_enable(qcom, event); 127 qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST; 128 129 return NOTIFY_DONE; 130 } 131 132 static int dwc3_qcom_host_notifier(struct notifier_block *nb, 133 unsigned long event, void *ptr) 134 { 135 struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb); 136 137 /* disable vbus override in host mode */ 138 dwc3_qcom_vbus_overrride_enable(qcom, !event); 139 qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL; 140 141 return NOTIFY_DONE; 142 } 143 144 static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom) 145 { 146 struct device *dev = qcom->dev; 147 struct extcon_dev *host_edev; 148 int ret; 149 150 if (!of_property_read_bool(dev->of_node, "extcon")) 151 return 0; 152 153 qcom->edev = extcon_get_edev_by_phandle(dev, 0); 154 if (IS_ERR(qcom->edev)) 155 return PTR_ERR(qcom->edev); 156 157 qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier; 158 159 qcom->host_edev = extcon_get_edev_by_phandle(dev, 1); 160 if (IS_ERR(qcom->host_edev)) 161 qcom->host_edev = NULL; 162 163 ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB, 164 &qcom->vbus_nb); 165 if (ret < 0) { 166 dev_err(dev, "VBUS notifier register failed\n"); 167 return ret; 168 } 169 170 if (qcom->host_edev) 171 host_edev = qcom->host_edev; 172 else 173 host_edev = qcom->edev; 174 175 qcom->host_nb.notifier_call = dwc3_qcom_host_notifier; 176 ret = devm_extcon_register_notifier(dev, host_edev, EXTCON_USB_HOST, 177 &qcom->host_nb); 178 if (ret < 0) { 179 dev_err(dev, "Host notifier register failed\n"); 180 return ret; 181 } 182 183 /* Update initial VBUS override based on extcon state */ 184 if (extcon_get_state(qcom->edev, EXTCON_USB) || 185 !extcon_get_state(host_edev, EXTCON_USB_HOST)) 186 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev); 187 else 188 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev); 189 190 return 0; 191 } 192 193 static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) 194 { 195 if (qcom->hs_phy_irq) { 196 disable_irq_wake(qcom->hs_phy_irq); 197 disable_irq_nosync(qcom->hs_phy_irq); 198 } 199 200 if (qcom->dp_hs_phy_irq) { 201 disable_irq_wake(qcom->dp_hs_phy_irq); 202 disable_irq_nosync(qcom->dp_hs_phy_irq); 203 } 204 205 if (qcom->dm_hs_phy_irq) { 206 disable_irq_wake(qcom->dm_hs_phy_irq); 207 disable_irq_nosync(qcom->dm_hs_phy_irq); 208 } 209 210 if (qcom->ss_phy_irq) { 211 disable_irq_wake(qcom->ss_phy_irq); 212 disable_irq_nosync(qcom->ss_phy_irq); 213 } 214 } 215 216 static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) 217 { 218 if (qcom->hs_phy_irq) { 219 enable_irq(qcom->hs_phy_irq); 220 enable_irq_wake(qcom->hs_phy_irq); 221 } 222 223 if (qcom->dp_hs_phy_irq) { 224 enable_irq(qcom->dp_hs_phy_irq); 225 enable_irq_wake(qcom->dp_hs_phy_irq); 226 } 227 228 if (qcom->dm_hs_phy_irq) { 229 enable_irq(qcom->dm_hs_phy_irq); 230 enable_irq_wake(qcom->dm_hs_phy_irq); 231 } 232 233 if (qcom->ss_phy_irq) { 234 enable_irq(qcom->ss_phy_irq); 235 enable_irq_wake(qcom->ss_phy_irq); 236 } 237 } 238 239 static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) 240 { 241 u32 val; 242 int i; 243 244 if (qcom->is_suspended) 245 return 0; 246 247 val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG); 248 if (!(val & PWR_EVNT_LPM_IN_L2_MASK)) 249 dev_err(qcom->dev, "HS-PHY not in L2\n"); 250 251 for (i = qcom->num_clocks - 1; i >= 0; i--) 252 clk_disable_unprepare(qcom->clks[i]); 253 254 qcom->is_suspended = true; 255 dwc3_qcom_enable_interrupts(qcom); 256 257 return 0; 258 } 259 260 static int dwc3_qcom_resume(struct dwc3_qcom *qcom) 261 { 262 int ret; 263 int i; 264 265 if (!qcom->is_suspended) 266 return 0; 267 268 dwc3_qcom_disable_interrupts(qcom); 269 270 for (i = 0; i < qcom->num_clocks; i++) { 271 ret = clk_prepare_enable(qcom->clks[i]); 272 if (ret < 0) { 273 while (--i >= 0) 274 clk_disable_unprepare(qcom->clks[i]); 275 return ret; 276 } 277 } 278 279 /* Clear existing events from PHY related to L2 in/out */ 280 dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG, 281 PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK); 282 283 qcom->is_suspended = false; 284 285 return 0; 286 } 287 288 static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) 289 { 290 struct dwc3_qcom *qcom = data; 291 struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); 292 293 /* If pm_suspended then let pm_resume take care of resuming h/w */ 294 if (qcom->pm_suspended) 295 return IRQ_HANDLED; 296 297 if (dwc->xhci) 298 pm_runtime_resume(&dwc->xhci->dev); 299 300 return IRQ_HANDLED; 301 } 302 303 static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) 304 { 305 /* Configure dwc3 to use UTMI clock as PIPE clock not present */ 306 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, 307 PIPE_UTMI_CLK_DIS); 308 309 usleep_range(100, 1000); 310 311 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, 312 PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW); 313 314 usleep_range(100, 1000); 315 316 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, 317 PIPE_UTMI_CLK_DIS); 318 } 319 320 static int dwc3_qcom_get_irq(struct platform_device *pdev, 321 const char *name, int num) 322 { 323 struct device_node *np = pdev->dev.of_node; 324 int ret; 325 326 if (np) 327 ret = platform_get_irq_byname(pdev, name); 328 else 329 ret = platform_get_irq(pdev, num); 330 331 return ret; 332 } 333 334 static int dwc3_qcom_setup_irq(struct platform_device *pdev) 335 { 336 struct dwc3_qcom *qcom = platform_get_drvdata(pdev); 337 const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; 338 int irq, ret; 339 irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", 340 pdata ? pdata->hs_phy_irq_index : -1); 341 if (irq > 0) { 342 /* Keep wakeup interrupts disabled until suspend */ 343 irq_set_status_flags(irq, IRQ_NOAUTOEN); 344 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, 345 qcom_dwc3_resume_irq, 346 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 347 "qcom_dwc3 HS", qcom); 348 if (ret) { 349 dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); 350 return ret; 351 } 352 qcom->hs_phy_irq = irq; 353 } 354 355 irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq", 356 pdata ? pdata->dp_hs_phy_irq_index : -1); 357 if (irq > 0) { 358 irq_set_status_flags(irq, IRQ_NOAUTOEN); 359 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, 360 qcom_dwc3_resume_irq, 361 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 362 "qcom_dwc3 DP_HS", qcom); 363 if (ret) { 364 dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); 365 return ret; 366 } 367 qcom->dp_hs_phy_irq = irq; 368 } 369 370 irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq", 371 pdata ? pdata->dm_hs_phy_irq_index : -1); 372 if (irq > 0) { 373 irq_set_status_flags(irq, IRQ_NOAUTOEN); 374 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, 375 qcom_dwc3_resume_irq, 376 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 377 "qcom_dwc3 DM_HS", qcom); 378 if (ret) { 379 dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); 380 return ret; 381 } 382 qcom->dm_hs_phy_irq = irq; 383 } 384 385 irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq", 386 pdata ? pdata->ss_phy_irq_index : -1); 387 if (irq > 0) { 388 irq_set_status_flags(irq, IRQ_NOAUTOEN); 389 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, 390 qcom_dwc3_resume_irq, 391 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 392 "qcom_dwc3 SS", qcom); 393 if (ret) { 394 dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); 395 return ret; 396 } 397 qcom->ss_phy_irq = irq; 398 } 399 400 return 0; 401 } 402 403 static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count) 404 { 405 struct device *dev = qcom->dev; 406 struct device_node *np = dev->of_node; 407 int i; 408 409 if (!np || !count) 410 return 0; 411 412 if (count < 0) 413 return count; 414 415 qcom->num_clocks = count; 416 417 qcom->clks = devm_kcalloc(dev, qcom->num_clocks, 418 sizeof(struct clk *), GFP_KERNEL); 419 if (!qcom->clks) 420 return -ENOMEM; 421 422 for (i = 0; i < qcom->num_clocks; i++) { 423 struct clk *clk; 424 int ret; 425 426 clk = of_clk_get(np, i); 427 if (IS_ERR(clk)) { 428 while (--i >= 0) 429 clk_put(qcom->clks[i]); 430 return PTR_ERR(clk); 431 } 432 433 ret = clk_prepare_enable(clk); 434 if (ret < 0) { 435 while (--i >= 0) { 436 clk_disable_unprepare(qcom->clks[i]); 437 clk_put(qcom->clks[i]); 438 } 439 clk_put(clk); 440 441 return ret; 442 } 443 444 qcom->clks[i] = clk; 445 } 446 447 return 0; 448 } 449 450 static const struct property_entry dwc3_qcom_acpi_properties[] = { 451 PROPERTY_ENTRY_STRING("dr_mode", "host"), 452 {} 453 }; 454 455 static int dwc3_qcom_acpi_register_core(struct platform_device *pdev) 456 { 457 struct dwc3_qcom *qcom = platform_get_drvdata(pdev); 458 struct device *dev = &pdev->dev; 459 struct resource *res, *child_res = NULL; 460 int irq; 461 int ret; 462 463 qcom->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); 464 if (!qcom->dwc3) 465 return -ENOMEM; 466 467 qcom->dwc3->dev.parent = dev; 468 qcom->dwc3->dev.type = dev->type; 469 qcom->dwc3->dev.dma_mask = dev->dma_mask; 470 qcom->dwc3->dev.dma_parms = dev->dma_parms; 471 qcom->dwc3->dev.coherent_dma_mask = dev->coherent_dma_mask; 472 473 child_res = kcalloc(2, sizeof(*child_res), GFP_KERNEL); 474 if (!child_res) 475 return -ENOMEM; 476 477 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 478 if (!res) { 479 dev_err(&pdev->dev, "failed to get memory resource\n"); 480 ret = -ENODEV; 481 goto out; 482 } 483 484 child_res[0].flags = res->flags; 485 child_res[0].start = res->start; 486 child_res[0].end = child_res[0].start + 487 qcom->acpi_pdata->dwc3_core_base_size; 488 489 irq = platform_get_irq(pdev, 0); 490 child_res[1].flags = IORESOURCE_IRQ; 491 child_res[1].start = child_res[1].end = irq; 492 493 ret = platform_device_add_resources(qcom->dwc3, child_res, 2); 494 if (ret) { 495 dev_err(&pdev->dev, "failed to add resources\n"); 496 goto out; 497 } 498 499 ret = platform_device_add_properties(qcom->dwc3, 500 dwc3_qcom_acpi_properties); 501 if (ret < 0) { 502 dev_err(&pdev->dev, "failed to add properties\n"); 503 goto out; 504 } 505 506 ret = platform_device_add(qcom->dwc3); 507 if (ret) 508 dev_err(&pdev->dev, "failed to add device\n"); 509 510 out: 511 kfree(child_res); 512 return ret; 513 } 514 515 static int dwc3_qcom_of_register_core(struct platform_device *pdev) 516 { 517 struct dwc3_qcom *qcom = platform_get_drvdata(pdev); 518 struct device_node *np = pdev->dev.of_node, *dwc3_np; 519 struct device *dev = &pdev->dev; 520 int ret; 521 522 dwc3_np = of_get_child_by_name(np, "dwc3"); 523 if (!dwc3_np) { 524 dev_err(dev, "failed to find dwc3 core child\n"); 525 return -ENODEV; 526 } 527 528 ret = of_platform_populate(np, NULL, NULL, dev); 529 if (ret) { 530 dev_err(dev, "failed to register dwc3 core - %d\n", ret); 531 return ret; 532 } 533 534 qcom->dwc3 = of_find_device_by_node(dwc3_np); 535 if (!qcom->dwc3) { 536 dev_err(dev, "failed to get dwc3 platform device\n"); 537 return -ENODEV; 538 } 539 540 return 0; 541 } 542 543 static int dwc3_qcom_probe(struct platform_device *pdev) 544 { 545 struct device_node *np = pdev->dev.of_node; 546 struct device *dev = &pdev->dev; 547 struct dwc3_qcom *qcom; 548 struct resource *res, *parent_res = NULL; 549 int ret, i; 550 bool ignore_pipe_clk; 551 552 qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); 553 if (!qcom) 554 return -ENOMEM; 555 556 platform_set_drvdata(pdev, qcom); 557 qcom->dev = &pdev->dev; 558 559 if (has_acpi_companion(dev)) { 560 qcom->acpi_pdata = acpi_device_get_match_data(dev); 561 if (!qcom->acpi_pdata) { 562 dev_err(&pdev->dev, "no supporting ACPI device data\n"); 563 return -EINVAL; 564 } 565 } 566 567 qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); 568 if (IS_ERR(qcom->resets)) { 569 ret = PTR_ERR(qcom->resets); 570 dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret); 571 return ret; 572 } 573 574 ret = reset_control_assert(qcom->resets); 575 if (ret) { 576 dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret); 577 return ret; 578 } 579 580 usleep_range(10, 1000); 581 582 ret = reset_control_deassert(qcom->resets); 583 if (ret) { 584 dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); 585 goto reset_assert; 586 } 587 588 ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np)); 589 if (ret) { 590 dev_err(dev, "failed to get clocks\n"); 591 goto reset_assert; 592 } 593 594 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 595 596 if (np) { 597 parent_res = res; 598 } else { 599 parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL); 600 if (!parent_res) 601 return -ENOMEM; 602 603 parent_res->start = res->start + 604 qcom->acpi_pdata->qscratch_base_offset; 605 parent_res->end = parent_res->start + 606 qcom->acpi_pdata->qscratch_base_size; 607 } 608 609 qcom->qscratch_base = devm_ioremap_resource(dev, parent_res); 610 if (IS_ERR(qcom->qscratch_base)) { 611 dev_err(dev, "failed to map qscratch, err=%d\n", ret); 612 ret = PTR_ERR(qcom->qscratch_base); 613 goto clk_disable; 614 } 615 616 ret = dwc3_qcom_setup_irq(pdev); 617 if (ret) { 618 dev_err(dev, "failed to setup IRQs, err=%d\n", ret); 619 goto clk_disable; 620 } 621 622 /* 623 * Disable pipe_clk requirement if specified. Used when dwc3 624 * operates without SSPHY and only HS/FS/LS modes are supported. 625 */ 626 ignore_pipe_clk = device_property_read_bool(dev, 627 "qcom,select-utmi-as-pipe-clk"); 628 if (ignore_pipe_clk) 629 dwc3_qcom_select_utmi_clk(qcom); 630 631 if (np) 632 ret = dwc3_qcom_of_register_core(pdev); 633 else 634 ret = dwc3_qcom_acpi_register_core(pdev); 635 636 if (ret) { 637 dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret); 638 goto depopulate; 639 } 640 641 qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); 642 643 /* enable vbus override for device mode */ 644 if (qcom->mode == USB_DR_MODE_PERIPHERAL) 645 dwc3_qcom_vbus_overrride_enable(qcom, true); 646 647 /* register extcon to override sw_vbus on Vbus change later */ 648 ret = dwc3_qcom_register_extcon(qcom); 649 if (ret) 650 goto depopulate; 651 652 device_init_wakeup(&pdev->dev, 1); 653 qcom->is_suspended = false; 654 pm_runtime_set_active(dev); 655 pm_runtime_enable(dev); 656 pm_runtime_forbid(dev); 657 658 return 0; 659 660 depopulate: 661 if (np) 662 of_platform_depopulate(&pdev->dev); 663 else 664 platform_device_put(pdev); 665 clk_disable: 666 for (i = qcom->num_clocks - 1; i >= 0; i--) { 667 clk_disable_unprepare(qcom->clks[i]); 668 clk_put(qcom->clks[i]); 669 } 670 reset_assert: 671 reset_control_assert(qcom->resets); 672 673 return ret; 674 } 675 676 static int dwc3_qcom_remove(struct platform_device *pdev) 677 { 678 struct dwc3_qcom *qcom = platform_get_drvdata(pdev); 679 struct device *dev = &pdev->dev; 680 int i; 681 682 of_platform_depopulate(dev); 683 684 for (i = qcom->num_clocks - 1; i >= 0; i--) { 685 clk_disable_unprepare(qcom->clks[i]); 686 clk_put(qcom->clks[i]); 687 } 688 qcom->num_clocks = 0; 689 690 reset_control_assert(qcom->resets); 691 692 pm_runtime_allow(dev); 693 pm_runtime_disable(dev); 694 695 return 0; 696 } 697 698 static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev) 699 { 700 struct dwc3_qcom *qcom = dev_get_drvdata(dev); 701 int ret = 0; 702 703 ret = dwc3_qcom_suspend(qcom); 704 if (!ret) 705 qcom->pm_suspended = true; 706 707 return ret; 708 } 709 710 static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev) 711 { 712 struct dwc3_qcom *qcom = dev_get_drvdata(dev); 713 int ret; 714 715 ret = dwc3_qcom_resume(qcom); 716 if (!ret) 717 qcom->pm_suspended = false; 718 719 return ret; 720 } 721 722 static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev) 723 { 724 struct dwc3_qcom *qcom = dev_get_drvdata(dev); 725 726 return dwc3_qcom_suspend(qcom); 727 } 728 729 static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev) 730 { 731 struct dwc3_qcom *qcom = dev_get_drvdata(dev); 732 733 return dwc3_qcom_resume(qcom); 734 } 735 736 static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { 737 SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume) 738 SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume, 739 NULL) 740 }; 741 742 static const struct of_device_id dwc3_qcom_of_match[] = { 743 { .compatible = "qcom,dwc3" }, 744 { .compatible = "qcom,msm8996-dwc3" }, 745 { .compatible = "qcom,msm8998-dwc3" }, 746 { .compatible = "qcom,sdm845-dwc3" }, 747 { } 748 }; 749 MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match); 750 751 #ifdef CONFIG_ACPI 752 static const struct dwc3_acpi_pdata sdm845_acpi_pdata = { 753 .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET, 754 .qscratch_base_size = SDM845_QSCRATCH_SIZE, 755 .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE, 756 .hs_phy_irq_index = 1, 757 .dp_hs_phy_irq_index = 4, 758 .dm_hs_phy_irq_index = 3, 759 .ss_phy_irq_index = 2 760 }; 761 762 static const struct acpi_device_id dwc3_qcom_acpi_match[] = { 763 { "QCOM2430", (unsigned long)&sdm845_acpi_pdata }, 764 { }, 765 }; 766 MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match); 767 #endif 768 769 static struct platform_driver dwc3_qcom_driver = { 770 .probe = dwc3_qcom_probe, 771 .remove = dwc3_qcom_remove, 772 .driver = { 773 .name = "dwc3-qcom", 774 .pm = &dwc3_qcom_dev_pm_ops, 775 .of_match_table = dwc3_qcom_of_match, 776 .acpi_match_table = ACPI_PTR(dwc3_qcom_acpi_match), 777 }, 778 }; 779 780 module_platform_driver(dwc3_qcom_driver); 781 782 MODULE_LICENSE("GPL v2"); 783 MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver"); 784