From patchwork Sun Jan 17 03:09:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Stefan_Br=C3=BCns?= X-Patchwork-Id: 569203 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id D78C314032F for ; Sun, 17 Jan 2016 14:10:17 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4D401A77B1; Sun, 17 Jan 2016 04:10:14 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qIt4FaTz-HRK; Sun, 17 Jan 2016 04:10:14 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6F6AEA7803; Sun, 17 Jan 2016 04:10:09 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 644CAA7553 for ; Sun, 17 Jan 2016 04:10:05 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HHx2bUJ3WsDb for ; Sun, 17 Jan 2016 04:10:05 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mx-out-2.rwth-aachen.de (mx-out-2.rwth-aachen.de [134.130.5.187]) by theia.denx.de (Postfix) with ESMTPS id 253A7A748A for ; Sun, 17 Jan 2016 04:10:04 +0100 (CET) X-IronPort-AV: E=Sophos;i="5.22,306,1449529200"; d="scan'208";a="420879770" Received: from rwthex-w2-a.rwth-ad.de ([134.130.26.158]) by mx-2.rz.rwth-aachen.de with ESMTP; 17 Jan 2016 04:10:04 +0100 Received: from pebbles.fritz.box (78.48.240.167) by rwthex-w2-a.rwth-ad.de (2002:8682:1a9e::8682:1a9e) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Sun, 17 Jan 2016 04:10:01 +0100 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= To: Date: Sun, 17 Jan 2016 04:09:53 +0100 Message-ID: <1453000196-4752-4-git-send-email-stefan.bruens@rwth-aachen.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1453000196-4752-1-git-send-email-stefan.bruens@rwth-aachen.de> References: <1453000196-4752-1-git-send-email-stefan.bruens@rwth-aachen.de> MIME-Version: 1.0 X-ClientProxiedBy: rwthex-s2-b.rwth-ad.de (2002:8682:1a9b::8682:1a9b) To rwthex-w2-a.rwth-ad.de (2002:8682:1a9e::8682:1a9e) Cc: Marek Vasut Subject: [U-Boot] [PATCH 3/6] usb: dwc2: split transfer core from outer loop X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Split the movement of data between CPU and Host Controller from the status handling and tracking of transfer progress. This will also simplify adding of SPLIT transaction support. Signed-off-by: Stefan BrĂ¼ns --- drivers/usb/host/dwc2.c | 112 +++++++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index ad097cb..0e710d9 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -426,9 +426,6 @@ static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num, if (dev->speed == USB_SPEED_LOW) hcchar |= DWC2_HCCHAR_LSPDDEV; - /* Clear old interrupt conditions for this host channel. */ - writel(0x3fff, &hc_regs->hcint); - /* * Program the HCCHARn register with the endpoint characteristics * for the current transfer. @@ -729,9 +726,8 @@ static int dwc_otg_submit_rh_msg(struct dwc2_priv *priv, struct usb_device *dev, return stat; } -int wait_for_chhltd(struct dwc2_core_regs *regs, uint32_t *sub, int *toggle) +int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, int *toggle) { - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[DWC2_HC_CHANNEL]; int ret; uint32_t hcint, hctsiz; @@ -765,6 +761,58 @@ static int dwc2_eptype[] = { DWC2_HCCHAR_EPTYPE_BULK, }; +static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer, + int *pid, int in, void *buffer, int num_packets, + int xfer_len, int *actual_len) +{ + int ret = 0; + uint32_t sub; + + debug("%s: chunk: pid %d xfer_len %u pkts %u\n", __func__, + *pid, xfer_len, num_packets); + + writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) | + (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) | + (*pid << DWC2_HCTSIZ_PID_OFFSET), + &hc_regs->hctsiz); + + if (!in && xfer_len) { + memcpy(aligned_buffer, buffer, xfer_len); + + flush_dcache_range((unsigned long)aligned_buffer, + (unsigned long)aligned_buffer + + roundup(xfer_len, ARCH_DMA_MINALIGN)); + } + + writel(phys_to_bus((unsigned long)aligned_buffer), &hc_regs->hcdma); + + /* Clear old interrupt conditions for this host channel. */ + writel(0x3fff, &hc_regs->hcint); + + /* Set host channel enable after all other setup is complete. */ + clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK | + DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS, + (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | + DWC2_HCCHAR_CHEN); + + ret = wait_for_chhltd(hc_regs, &sub, pid); + if (ret < 0) + return ret; + + if (in) { + xfer_len -= sub; + + invalidate_dcache_range((unsigned long)aligned_buffer, + (unsigned long)aligned_buffer + + roundup(xfer_len, ARCH_DMA_MINALIGN)); + + memcpy(buffer, aligned_buffer, xfer_len); + } + *actual_len = xfer_len; + + return ret; +} + int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, unsigned long pipe, int *pid, int in, void *buffer, int len) { @@ -776,7 +824,6 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, int eptype = dwc2_eptype[usb_pipetype(pipe)]; int done = 0; int ret = 0; - uint32_t sub; uint32_t xfer_len; uint32_t num_packets; int stop_transfer = 0; @@ -795,11 +842,12 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, num_packets = max_xfer_len / max; max_xfer_len = num_packets * max; - do { - /* Initialize channel */ - dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in, - eptype, max); + /* Initialize channel */ + dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in, + eptype, max); + do { + int actual_len = 0; xfer_len = len - done; if (xfer_len > max_xfer_len) @@ -809,49 +857,17 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, else num_packets = 1; - debug("%s: chunk: pid %d xfer_len %u pkts %u\n", __func__, - *pid, xfer_len, num_packets); + ret = transfer_chunk(hc_regs, priv->aligned_buffer, pid, + in, (char *)buffer + done, num_packets, + xfer_len, &actual_len); - writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) | - (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) | - (*pid << DWC2_HCTSIZ_PID_OFFSET), - &hc_regs->hctsiz); - - if (!in && xfer_len) { - memcpy(priv->aligned_buffer, (char *)buffer + done, - xfer_len); - - flush_dcache_range((unsigned long)priv->aligned_buffer, - (unsigned long)((void *)priv->aligned_buffer + - roundup(xfer_len, ARCH_DMA_MINALIGN))); - } - - writel(phys_to_bus((unsigned long)priv->aligned_buffer), - &hc_regs->hcdma); - - /* Set host channel enable after all other setup is complete. */ - clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK | - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS, - (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | - DWC2_HCCHAR_CHEN); - - ret = wait_for_chhltd(regs, &sub, pid); if (ret) break; - if (in) { - xfer_len -= sub; - - invalidate_dcache_range((unsigned long)priv->aligned_buffer, - (unsigned long)((void *)priv->aligned_buffer + - roundup(xfer_len, ARCH_DMA_MINALIGN))); - - memcpy(buffer + done, priv->aligned_buffer, xfer_len); - if (sub) - stop_transfer = 1; - } + if (actual_len < xfer_len) + stop_transfer = 1; - done += xfer_len; + done += actual_len; } while ((done < len) && !stop_transfer);