diff options
author | Linux Build Service Account <lnxbuild@quicinc.com> | 2018-01-28 00:55:30 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-01-28 00:55:29 -0800 |
commit | 65ee504d6e283e164ef1a8825baa3eaf77cc72e9 (patch) | |
tree | f35845e0402020f4338196f077b64fb285960f78 | |
parent | 4823f734cd1dea37e4ce7a3164c9ef77a6da2ce7 (diff) | |
parent | 589759f262e8f7515b9eaa9fc99c2f433c85bcf7 (diff) |
Merge "usb: dwc3: ep0: NAK L1 initiated between SETUP and STATUS stage"LE.UM.2.3.2-13400-SDX24
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 15 | ||||
-rw-r--r-- | drivers/usb/dwc3/io.h | 24 | ||||
-rw-r--r-- | drivers/usb/dwc3/trace.h | 5 |
3 files changed, 44 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index cbce880b433d..986c97c64c18 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -816,6 +816,16 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, if (!dwc->gadget_driver) goto out; + /* + * Workaround for SNPS STAR: 9001046257 which affects dwc3 core + * 3.10a or earlier. LPM Not rejected during control transfer. Device + * is programmed to reject LPM when SETUP packet is received and + * ACK LPM after completing STATUS stage. + */ + if (dwc->has_lpm_erratum && dwc->revision <= DWC3_REVISION_310A) + dwc3_masked_write_readback(dwc->regs, DWC3_DCTL, + DWC3_DCTL_LPM_ERRATA_MASK, DWC3_DCTL_LPM_ERRATA(0)); + trace_dwc3_ctrl_req(ctrl); len = le16_to_cpu(ctrl->wLength); @@ -990,6 +1000,11 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc, dbg_print(dep->number, "DONE", status, "STATUS"); dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); + + if (dwc->has_lpm_erratum && dwc->revision <= DWC3_REVISION_310A) + dwc3_masked_write_readback(dwc->regs, DWC3_DCTL, + DWC3_DCTL_LPM_ERRATA_MASK, + DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold)); } static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index a06f9a8fecc7..4911253de95a 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -64,4 +64,28 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) base - DWC3_GLOBALS_REGS_START + offset, value); } +static inline void dwc3_masked_write_readback(void __iomem *base, + u32 offset, const u32 mask, u32 value) +{ + u32 write_val, tmp; + + tmp = readl_relaxed(base + offset - DWC3_GLOBALS_REGS_START); + tmp &= ~mask; /* retain other bits */ + write_val = tmp | value; + + writel_relaxed(write_val, base + offset - DWC3_GLOBALS_REGS_START); + + /* Read back to see if value was written */ + tmp = readl_relaxed(base + offset); + + dwc3_trace(trace_dwc3_masked_write_readback, + "addr %p readback val %08x", + base - DWC3_GLOBALS_REGS_START + offset, tmp); + + tmp &= mask; /* clear other bits */ + if (tmp != value) + pr_err("%s: write: %x to %x FAILED\n", + __func__, value, offset); +} + #endif /* __DRIVERS_USB_DWC3_IO_H */ diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index d24cefd191b5..88f5fb81076a 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -47,6 +47,11 @@ DEFINE_EVENT(dwc3_log_msg, dwc3_writel, TP_ARGS(vaf) ); +DEFINE_EVENT(dwc3_log_msg, dwc3_masked_write_readback, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, TP_PROTO(struct va_format *vaf), TP_ARGS(vaf) |