aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2018-01-28 00:55:30 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2018-01-28 00:55:29 -0800
commit65ee504d6e283e164ef1a8825baa3eaf77cc72e9 (patch)
treef35845e0402020f4338196f077b64fb285960f78
parent4823f734cd1dea37e4ce7a3164c9ef77a6da2ce7 (diff)
parent589759f262e8f7515b9eaa9fc99c2f433c85bcf7 (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.c15
-rw-r--r--drivers/usb/dwc3/io.h24
-rw-r--r--drivers/usb/dwc3/trace.h5
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)