From 070cae6f80585da99046286bcd20cec4be177b63 Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 23 Oct 2018 16:31:23 +0800 Subject: [PATCH] usb: dwc3: add dis-u1u2-quirk to reject enter U1 and U2 The DWC3 with Innosilicon USB 3.0 PHY on Rockchip platforms (e.g. rk3328, rk1808) has problem to exit to U0 state from U1 or U2 state when DWC3 work as peripheral mode. This patch adds a quirk to reject transition to U1 and U2 state to workaround this issue. Change-Id: Ib5a7a603193df23e4d274681bad155d005238349 Signed-off-by: William Wu --- drivers/usb/dwc3/core.c | 2 ++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/ep0.c | 11 ++++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d6899567a0fa..79b789444fee 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1275,6 +1275,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,dis_u3_susphy_quirk"); dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, "snps,dis_u2_susphy_quirk"); + dwc->dis_u1u2_quirk = device_property_read_bool(dev, + "snps,dis-u1u2-quirk"); dwc->dis_enblslpm_quirk = device_property_read_bool(dev, "snps,dis_enblslpm_quirk"); dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9a023769cba1..232ccd02a775 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -981,6 +981,7 @@ struct dwc3_scratchpad_array { * @rx_detect_poll_quirk: set if we enable rx_detect to polling lfps quirk * @dis_u3_susphy_quirk: set if we disable usb3 suspend phy * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy + * @dis_u1u2_quirk: set if we reject transition to U1 or U2 state * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG, * disabling the suspend signal to the PHY. * @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3 @@ -1160,6 +1161,7 @@ struct dwc3 { unsigned rx_detect_poll_quirk:1; unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; + unsigned dis_u1u2_quirk:1; unsigned dis_enblslpm_quirk:1; unsigned dis_rxdet_inp3_quirk:1; unsigned dis_u2_freeclk_exists_quirk:1; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 8efde178eef4..26b0aa3fa778 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -381,7 +381,7 @@ static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state, return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (set) + if (set && !dwc->dis_u1u2_quirk) reg |= DWC3_DCTL_INITU1ENA; else reg &= ~DWC3_DCTL_INITU1ENA; @@ -403,7 +403,7 @@ static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state, return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (set) + if (set && !dwc->dis_u1u2_quirk) reg |= DWC3_DCTL_INITU2ENA; else reg &= ~DWC3_DCTL_INITU2ENA; @@ -626,7 +626,12 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); + if (dwc->dis_u1u2_quirk) + reg &= ~(DWC3_DCTL_ACCEPTU1ENA | + DWC3_DCTL_ACCEPTU2ENA); + else + reg |= (DWC3_DCTL_ACCEPTU1ENA | + DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); } break;