diff options
Diffstat (limited to 'drivers/usb/dwc3/core.c')
-rw-r--r-- | drivers/usb/dwc3/core.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 38679e7d72a8..76bc1bd2a71d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -119,6 +119,7 @@ static void __dwc3_set_mode(struct work_struct *work) struct dwc3_platform_data *dwc3_pdata; unsigned long flags; int ret; + u32 reg; pm_runtime_get_sync(dwc->dev); @@ -166,6 +167,11 @@ static void __dwc3_set_mode(struct work_struct *work) otg_set_vbus(dwc->usb2_phy->otg, true); phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); + if (dwc->dis_split_quirk) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg |= DWC3_GUCTL3_SPLITDISABLE; + dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + } } break; case DWC3_GCTL_PRTCAP_DEVICE: @@ -316,7 +322,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) dwc3_pdata = (struct dwc3_platform_data *)dev_get_platdata(dwc->dev); if (dwc3_pdata && dwc3_pdata->quirks & DWC3_SOFT_ITP_SYNC) { u32 ref_clk_hz, ref_clk_period_integer; - unsigned long long temp; + u64 temp; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_SOFITPSYNC; @@ -343,10 +349,10 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) } /* nano seconds the period of ref_clk */ - ref_clk_period_integer = DIV_ROUND_DOWN_ULL(1000000000, ref_clk_hz); - temp = 125000ULL * 1000000000ULL; - temp = DIV_ROUND_DOWN_ULL(temp, ref_clk_hz); - temp = DIV_ROUND_DOWN_ULL(temp, ref_clk_period_integer); + ref_clk_period_integer = 1000000000 / ref_clk_hz; + temp = 125000L * 1000000000L; + temp = temp / ref_clk_hz; + temp = temp / ref_clk_period_integer; temp = temp - 125000; temp = temp << GFLADJ_REFCLK_FLADJ_SHIFT; reg &= ~GFLADJ_REFCLK_FLADJ_MASK; @@ -1487,6 +1493,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->host_vbus_glitches = device_property_read_bool(dev, "snps,host-vbus-glitches"); + dwc->dis_split_quirk = device_property_read_bool(dev, + "snps,dis-split-quirk"); dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; @@ -1691,6 +1699,17 @@ static int dwc3_probe(struct platform_device *pdev) err5: dwc3_event_buffers_cleanup(dwc); + + usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); + phy_exit(dwc->usb2_generic_phy); + phy_exit(dwc->usb3_generic_phy); + + usb_phy_set_suspend(dwc->usb2_phy, 1); + usb_phy_set_suspend(dwc->usb3_phy, 1); + phy_power_off(dwc->usb2_generic_phy); + phy_power_off(dwc->usb3_generic_phy); + dwc3_ulpi_exit(dwc); err4: @@ -2024,10 +2043,26 @@ static int dwc3_resume(struct device *dev) return 0; } + +static void dwc3_complete(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + u32 reg; + + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && + dwc->dis_split_quirk) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg |= DWC3_GUCTL3_SPLITDISABLE; + dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + } +} +#else +#define dwc3_complete NULL #endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops dwc3_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) + .complete = dwc3_complete, SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, dwc3_runtime_idle) }; |