From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chin Liang See Date: Tue, 5 Jan 2016 13:00:04 +0800 Subject: [U-Boot] [PATCH] usb: dwc2: Enhance interrupt handling for CONTROL transaction Message-ID: <1451970004-2344-1-git-send-email-clsee@altera.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Per DesignWare USB OTG databook, driver should retry up to 3 times when transaction error (hcint.xacterr) happen. But the 3 times doesn't count when the response is nack (hcint.nak) or frame overrun (hcint.frmoverun) This patch solved the enumeration error as spotted at socfpga cyclone5_socdk when plugging in certain pendrive. Signed-off-by: Chin Liang See Cc: Marek Vasut Cc: Dinh Nguyen Cc: Dinh Nguyen Cc: Pavel Machek Cc: Oleksandr Tymoshenko Cc: Stephen Warren Cc: Alexander Stein Cc: Peter Griffin --- drivers/usb/host/dwc2.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 541c0f9..f00cd1b 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -786,15 +786,12 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, uint32_t xfer_len; uint32_t num_packets; int stop_transfer = 0; + int error_retry_count = 0; debug("%s: msg: pipe %lx pid %d in %d len %d\n", __func__, pipe, *pid, in, len); do { - /* Initialize channel */ - dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in, - eptype, max); - xfer_len = len - done; if (xfer_len > CONFIG_DWC2_MAX_TRANSFER_SIZE) xfer_len = CONFIG_DWC2_MAX_TRANSFER_SIZE - max + 1; @@ -818,6 +815,14 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, debug("%s: chunk: pid %d xfer_len %u pkts %u\n", __func__, *pid, xfer_len, num_packets); + /* per DW spec, we can retry up to 3 times */ + error_retry_count = 3; + +error_retry: + /* Initialize channel */ + dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in, + eptype, max); + writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) | (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) | (*pid << DWC2_HCTSIZ_PID_OFFSET), @@ -841,8 +846,14 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, DWC2_HCCHAR_CHEN); ret = wait_for_chhltd(regs, &sub, pid, ignore_ack); - if (ret) - break; + if (ret) { + if (ret == -EINVAL) + error_retry_count--; + if (error_retry_count) + goto error_retry; + else + break; + } if (in) { xfer_len -= sub; -- 1.9.2.468.g3f0c02a