diff options
Diffstat (limited to 'drivers/usb/dwc3/core.c')
-rw-r--r-- | drivers/usb/dwc3/core.c | 110 |
1 files changed, 85 insertions, 25 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2bbab3d86fff..ff5773c66b84 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -117,6 +117,33 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * dwc3_soft_reset - Issue soft reset | ||
121 | * @dwc: Pointer to our controller context structure | ||
122 | */ | ||
123 | static int dwc3_soft_reset(struct dwc3 *dwc) | ||
124 | { | ||
125 | unsigned long timeout; | ||
126 | u32 reg; | ||
127 | |||
128 | timeout = jiffies + msecs_to_jiffies(500); | ||
129 | dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); | ||
130 | do { | ||
131 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | ||
132 | if (!(reg & DWC3_DCTL_CSFTRST)) | ||
133 | break; | ||
134 | |||
135 | if (time_after(jiffies, timeout)) { | ||
136 | dev_err(dwc->dev, "Reset Timed Out\n"); | ||
137 | return -ETIMEDOUT; | ||
138 | } | ||
139 | |||
140 | cpu_relax(); | ||
141 | } while (true); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /** | ||
120 | * dwc3_free_one_event_buffer - Frees one event buffer | 147 | * dwc3_free_one_event_buffer - Frees one event buffer |
121 | * @dwc: Pointer to our controller context structure | 148 | * @dwc: Pointer to our controller context structure |
122 | * @evt: Pointer to event buffer to be freed | 149 | * @evt: Pointer to event buffer to be freed |
@@ -367,10 +394,15 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) | |||
367 | /** | 394 | /** |
368 | * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core | 395 | * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core |
369 | * @dwc: Pointer to our controller context structure | 396 | * @dwc: Pointer to our controller context structure |
397 | * | ||
398 | * Returns 0 on success. The USB PHY interfaces are configured but not | ||
399 | * initialized. The PHY interfaces and the PHYs get initialized together with | ||
400 | * the core in dwc3_core_init. | ||
370 | */ | 401 | */ |
371 | static void dwc3_phy_setup(struct dwc3 *dwc) | 402 | static int dwc3_phy_setup(struct dwc3 *dwc) |
372 | { | 403 | { |
373 | u32 reg; | 404 | u32 reg; |
405 | int ret; | ||
374 | 406 | ||
375 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | 407 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); |
376 | 408 | ||
@@ -409,10 +441,43 @@ static void dwc3_phy_setup(struct dwc3 *dwc) | |||
409 | 441 | ||
410 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | 442 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); |
411 | 443 | ||
412 | mdelay(100); | ||
413 | |||
414 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | 444 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); |
415 | 445 | ||
446 | /* Select the HS PHY interface */ | ||
447 | switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { | ||
448 | case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: | ||
449 | if (dwc->hsphy_interface && | ||
450 | !strncmp(dwc->hsphy_interface, "utmi", 4)) { | ||
451 | reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; | ||
452 | break; | ||
453 | } else if (dwc->hsphy_interface && | ||
454 | !strncmp(dwc->hsphy_interface, "ulpi", 4)) { | ||
455 | reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; | ||
456 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
457 | } else { | ||
458 | dev_warn(dwc->dev, "HSPHY Interface not defined\n"); | ||
459 | |||
460 | /* Relying on default value. */ | ||
461 | if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) | ||
462 | break; | ||
463 | } | ||
464 | /* FALLTHROUGH */ | ||
465 | case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: | ||
466 | /* Making sure the interface and PHY are operational */ | ||
467 | ret = dwc3_soft_reset(dwc); | ||
468 | if (ret) | ||
469 | return ret; | ||
470 | |||
471 | udelay(1); | ||
472 | |||
473 | ret = dwc3_ulpi_init(dwc); | ||
474 | if (ret) | ||
475 | return ret; | ||
476 | /* FALLTHROUGH */ | ||
477 | default: | ||
478 | break; | ||
479 | } | ||
480 | |||
416 | /* | 481 | /* |
417 | * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to | 482 | * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to |
418 | * '0' during coreConsultant configuration. So default value will | 483 | * '0' during coreConsultant configuration. So default value will |
@@ -427,7 +492,7 @@ static void dwc3_phy_setup(struct dwc3 *dwc) | |||
427 | 492 | ||
428 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | 493 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); |
429 | 494 | ||
430 | mdelay(100); | 495 | return 0; |
431 | } | 496 | } |
432 | 497 | ||
433 | /** | 498 | /** |
@@ -438,7 +503,6 @@ static void dwc3_phy_setup(struct dwc3 *dwc) | |||
438 | */ | 503 | */ |
439 | static int dwc3_core_init(struct dwc3 *dwc) | 504 | static int dwc3_core_init(struct dwc3 *dwc) |
440 | { | 505 | { |
441 | unsigned long timeout; | ||
442 | u32 hwparams4 = dwc->hwparams.hwparams4; | 506 | u32 hwparams4 = dwc->hwparams.hwparams4; |
443 | u32 reg; | 507 | u32 reg; |
444 | int ret; | 508 | int ret; |
@@ -466,21 +530,9 @@ static int dwc3_core_init(struct dwc3 *dwc) | |||
466 | } | 530 | } |
467 | 531 | ||
468 | /* issue device SoftReset too */ | 532 | /* issue device SoftReset too */ |
469 | timeout = jiffies + msecs_to_jiffies(500); | 533 | ret = dwc3_soft_reset(dwc); |
470 | dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); | 534 | if (ret) |
471 | do { | 535 | goto err0; |
472 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | ||
473 | if (!(reg & DWC3_DCTL_CSFTRST)) | ||
474 | break; | ||
475 | |||
476 | if (time_after(jiffies, timeout)) { | ||
477 | dev_err(dwc->dev, "Reset Timed Out\n"); | ||
478 | ret = -ETIMEDOUT; | ||
479 | goto err0; | ||
480 | } | ||
481 | |||
482 | cpu_relax(); | ||
483 | } while (true); | ||
484 | 536 | ||
485 | ret = dwc3_core_soft_reset(dwc); | 537 | ret = dwc3_core_soft_reset(dwc); |
486 | if (ret) | 538 | if (ret) |
@@ -555,8 +607,6 @@ static int dwc3_core_init(struct dwc3 *dwc) | |||
555 | 607 | ||
556 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | 608 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); |
557 | 609 | ||
558 | dwc3_phy_setup(dwc); | ||
559 | |||
560 | ret = dwc3_alloc_scratch_buffers(dwc); | 610 | ret = dwc3_alloc_scratch_buffers(dwc); |
561 | if (ret) | 611 | if (ret) |
562 | goto err1; | 612 | goto err1; |
@@ -836,6 +886,8 @@ static int dwc3_probe(struct platform_device *pdev) | |||
836 | "snps,tx_de_emphasis_quirk"); | 886 | "snps,tx_de_emphasis_quirk"); |
837 | of_property_read_u8(node, "snps,tx_de_emphasis", | 887 | of_property_read_u8(node, "snps,tx_de_emphasis", |
838 | &tx_de_emphasis); | 888 | &tx_de_emphasis); |
889 | of_property_read_string(node, "snps,hsphy_interface", | ||
890 | &dwc->hsphy_interface); | ||
839 | } else if (pdata) { | 891 | } else if (pdata) { |
840 | dwc->maximum_speed = pdata->maximum_speed; | 892 | dwc->maximum_speed = pdata->maximum_speed; |
841 | dwc->has_lpm_erratum = pdata->has_lpm_erratum; | 893 | dwc->has_lpm_erratum = pdata->has_lpm_erratum; |
@@ -863,6 +915,8 @@ static int dwc3_probe(struct platform_device *pdev) | |||
863 | dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; | 915 | dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; |
864 | if (pdata->tx_de_emphasis) | 916 | if (pdata->tx_de_emphasis) |
865 | tx_de_emphasis = pdata->tx_de_emphasis; | 917 | tx_de_emphasis = pdata->tx_de_emphasis; |
918 | |||
919 | dwc->hsphy_interface = pdata->hsphy_interface; | ||
866 | } | 920 | } |
867 | 921 | ||
868 | /* default to superspeed if no maximum_speed passed */ | 922 | /* default to superspeed if no maximum_speed passed */ |
@@ -875,12 +929,18 @@ static int dwc3_probe(struct platform_device *pdev) | |||
875 | dwc->hird_threshold = hird_threshold | 929 | dwc->hird_threshold = hird_threshold |
876 | | (dwc->is_utmi_l1_suspend << 4); | 930 | | (dwc->is_utmi_l1_suspend << 4); |
877 | 931 | ||
932 | platform_set_drvdata(pdev, dwc); | ||
933 | dwc3_cache_hwparams(dwc); | ||
934 | |||
935 | ret = dwc3_phy_setup(dwc); | ||
936 | if (ret) | ||
937 | goto err0; | ||
938 | |||
878 | ret = dwc3_core_get_phy(dwc); | 939 | ret = dwc3_core_get_phy(dwc); |
879 | if (ret) | 940 | if (ret) |
880 | goto err0; | 941 | goto err0; |
881 | 942 | ||
882 | spin_lock_init(&dwc->lock); | 943 | spin_lock_init(&dwc->lock); |
883 | platform_set_drvdata(pdev, dwc); | ||
884 | 944 | ||
885 | if (!dev->dma_mask) { | 945 | if (!dev->dma_mask) { |
886 | dev->dma_mask = dev->parent->dma_mask; | 946 | dev->dma_mask = dev->parent->dma_mask; |
@@ -892,8 +952,6 @@ static int dwc3_probe(struct platform_device *pdev) | |||
892 | pm_runtime_get_sync(dev); | 952 | pm_runtime_get_sync(dev); |
893 | pm_runtime_forbid(dev); | 953 | pm_runtime_forbid(dev); |
894 | 954 | ||
895 | dwc3_cache_hwparams(dwc); | ||
896 | |||
897 | ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); | 955 | ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); |
898 | if (ret) { | 956 | if (ret) { |
899 | dev_err(dwc->dev, "failed to allocate event buffers\n"); | 957 | dev_err(dwc->dev, "failed to allocate event buffers\n"); |
@@ -964,6 +1022,7 @@ err2: | |||
964 | 1022 | ||
965 | err1: | 1023 | err1: |
966 | dwc3_free_event_buffers(dwc); | 1024 | dwc3_free_event_buffers(dwc); |
1025 | dwc3_ulpi_exit(dwc); | ||
967 | 1026 | ||
968 | err0: | 1027 | err0: |
969 | /* | 1028 | /* |
@@ -999,6 +1058,7 @@ static int dwc3_remove(struct platform_device *pdev) | |||
999 | phy_power_off(dwc->usb3_generic_phy); | 1058 | phy_power_off(dwc->usb3_generic_phy); |
1000 | 1059 | ||
1001 | dwc3_core_exit(dwc); | 1060 | dwc3_core_exit(dwc); |
1061 | dwc3_ulpi_exit(dwc); | ||
1002 | 1062 | ||
1003 | pm_runtime_put_sync(&pdev->dev); | 1063 | pm_runtime_put_sync(&pdev->dev); |
1004 | pm_runtime_disable(&pdev->dev); | 1064 | pm_runtime_disable(&pdev->dev); |