summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/core.c')
-rw-r--r--drivers/usb/dwc3/core.c45
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)
};