1197ba5f4SPaul Zimmerman /* 2197ba5f4SPaul Zimmerman * hcd.c - DesignWare HS OTG Controller host-mode routines 3197ba5f4SPaul Zimmerman * 4197ba5f4SPaul Zimmerman * Copyright (C) 2004-2013 Synopsys, Inc. 5197ba5f4SPaul Zimmerman * 6197ba5f4SPaul Zimmerman * Redistribution and use in source and binary forms, with or without 7197ba5f4SPaul Zimmerman * modification, are permitted provided that the following conditions 8197ba5f4SPaul Zimmerman * are met: 9197ba5f4SPaul Zimmerman * 1. Redistributions of source code must retain the above copyright 10197ba5f4SPaul Zimmerman * notice, this list of conditions, and the following disclaimer, 11197ba5f4SPaul Zimmerman * without modification. 12197ba5f4SPaul Zimmerman * 2. Redistributions in binary form must reproduce the above copyright 13197ba5f4SPaul Zimmerman * notice, this list of conditions and the following disclaimer in the 14197ba5f4SPaul Zimmerman * documentation and/or other materials provided with the distribution. 15197ba5f4SPaul Zimmerman * 3. The names of the above-listed copyright holders may not be used 16197ba5f4SPaul Zimmerman * to endorse or promote products derived from this software without 17197ba5f4SPaul Zimmerman * specific prior written permission. 18197ba5f4SPaul Zimmerman * 19197ba5f4SPaul Zimmerman * ALTERNATIVELY, this software may be distributed under the terms of the 20197ba5f4SPaul Zimmerman * GNU General Public License ("GPL") as published by the Free Software 21197ba5f4SPaul Zimmerman * Foundation; either version 2 of the License, or (at your option) any 22197ba5f4SPaul Zimmerman * later version. 23197ba5f4SPaul Zimmerman * 24197ba5f4SPaul Zimmerman * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25197ba5f4SPaul Zimmerman * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 26197ba5f4SPaul Zimmerman * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27197ba5f4SPaul Zimmerman * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 28197ba5f4SPaul Zimmerman * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29197ba5f4SPaul Zimmerman * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30197ba5f4SPaul Zimmerman * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31197ba5f4SPaul Zimmerman * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32197ba5f4SPaul Zimmerman * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33197ba5f4SPaul Zimmerman * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34197ba5f4SPaul Zimmerman * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35197ba5f4SPaul Zimmerman */ 36197ba5f4SPaul Zimmerman 37197ba5f4SPaul Zimmerman /* 38197ba5f4SPaul Zimmerman * This file contains the core HCD code, and implements the Linux hc_driver 39197ba5f4SPaul Zimmerman * API 40197ba5f4SPaul Zimmerman */ 41197ba5f4SPaul Zimmerman #include <linux/kernel.h> 42197ba5f4SPaul Zimmerman #include <linux/module.h> 43197ba5f4SPaul Zimmerman #include <linux/spinlock.h> 44197ba5f4SPaul Zimmerman #include <linux/interrupt.h> 45197ba5f4SPaul Zimmerman #include <linux/dma-mapping.h> 46197ba5f4SPaul Zimmerman #include <linux/delay.h> 47197ba5f4SPaul Zimmerman #include <linux/io.h> 48197ba5f4SPaul Zimmerman #include <linux/slab.h> 49197ba5f4SPaul Zimmerman #include <linux/usb.h> 50197ba5f4SPaul Zimmerman 51197ba5f4SPaul Zimmerman #include <linux/usb/hcd.h> 52197ba5f4SPaul Zimmerman #include <linux/usb/ch11.h> 53197ba5f4SPaul Zimmerman 54197ba5f4SPaul Zimmerman #include "core.h" 55197ba5f4SPaul Zimmerman #include "hcd.h" 56197ba5f4SPaul Zimmerman 57b02038faSJohn Youn /* 58b02038faSJohn Youn * ========================================================================= 59b02038faSJohn Youn * Host Core Layer Functions 60b02038faSJohn Youn * ========================================================================= 61b02038faSJohn Youn */ 62b02038faSJohn Youn 63b02038faSJohn Youn /** 64b02038faSJohn Youn * dwc2_enable_common_interrupts() - Initializes the commmon interrupts, 65b02038faSJohn Youn * used in both device and host modes 66b02038faSJohn Youn * 67b02038faSJohn Youn * @hsotg: Programming view of the DWC_otg controller 68b02038faSJohn Youn */ 69b02038faSJohn Youn static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) 70b02038faSJohn Youn { 71b02038faSJohn Youn u32 intmsk; 72b02038faSJohn Youn 73b02038faSJohn Youn /* Clear any pending OTG Interrupts */ 74b02038faSJohn Youn dwc2_writel(0xffffffff, hsotg->regs + GOTGINT); 75b02038faSJohn Youn 76b02038faSJohn Youn /* Clear any pending interrupts */ 77b02038faSJohn Youn dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); 78b02038faSJohn Youn 79b02038faSJohn Youn /* Enable the interrupts in the GINTMSK */ 80b02038faSJohn Youn intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; 81b02038faSJohn Youn 82*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) 83b02038faSJohn Youn intmsk |= GINTSTS_RXFLVL; 84bea8e86cSJohn Youn if (hsotg->params.external_id_pin_ctl <= 0) 85b02038faSJohn Youn intmsk |= GINTSTS_CONIDSTSCHNG; 86b02038faSJohn Youn 87b02038faSJohn Youn intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP | 88b02038faSJohn Youn GINTSTS_SESSREQINT; 89b02038faSJohn Youn 90b02038faSJohn Youn dwc2_writel(intmsk, hsotg->regs + GINTMSK); 91b02038faSJohn Youn } 92b02038faSJohn Youn 93b02038faSJohn Youn /* 94b02038faSJohn Youn * Initializes the FSLSPClkSel field of the HCFG register depending on the 95b02038faSJohn Youn * PHY type 96b02038faSJohn Youn */ 97b02038faSJohn Youn static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) 98b02038faSJohn Youn { 99b02038faSJohn Youn u32 hcfg, val; 100b02038faSJohn Youn 101b02038faSJohn Youn if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && 102b02038faSJohn Youn hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && 103bea8e86cSJohn Youn hsotg->params.ulpi_fs_ls > 0) || 104bea8e86cSJohn Youn hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { 105b02038faSJohn Youn /* Full speed PHY */ 106b02038faSJohn Youn val = HCFG_FSLSPCLKSEL_48_MHZ; 107b02038faSJohn Youn } else { 108b02038faSJohn Youn /* High speed PHY running at full speed or high speed */ 109b02038faSJohn Youn val = HCFG_FSLSPCLKSEL_30_60_MHZ; 110b02038faSJohn Youn } 111b02038faSJohn Youn 112b02038faSJohn Youn dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val); 113b02038faSJohn Youn hcfg = dwc2_readl(hsotg->regs + HCFG); 114b02038faSJohn Youn hcfg &= ~HCFG_FSLSPCLKSEL_MASK; 115b02038faSJohn Youn hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT; 116b02038faSJohn Youn dwc2_writel(hcfg, hsotg->regs + HCFG); 117b02038faSJohn Youn } 118b02038faSJohn Youn 119b02038faSJohn Youn static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) 120b02038faSJohn Youn { 121b02038faSJohn Youn u32 usbcfg, i2cctl; 122b02038faSJohn Youn int retval = 0; 123b02038faSJohn Youn 124b02038faSJohn Youn /* 125b02038faSJohn Youn * core_init() is now called on every switch so only call the 126b02038faSJohn Youn * following for the first time through 127b02038faSJohn Youn */ 128b02038faSJohn Youn if (select_phy) { 129b02038faSJohn Youn dev_dbg(hsotg->dev, "FS PHY selected\n"); 130b02038faSJohn Youn 131b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 132b02038faSJohn Youn if (!(usbcfg & GUSBCFG_PHYSEL)) { 133b02038faSJohn Youn usbcfg |= GUSBCFG_PHYSEL; 134b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 135b02038faSJohn Youn 136b02038faSJohn Youn /* Reset after a PHY select */ 137b02038faSJohn Youn retval = dwc2_core_reset_and_force_dr_mode(hsotg); 138b02038faSJohn Youn 139b02038faSJohn Youn if (retval) { 140b02038faSJohn Youn dev_err(hsotg->dev, 141b02038faSJohn Youn "%s: Reset failed, aborting", __func__); 142b02038faSJohn Youn return retval; 143b02038faSJohn Youn } 144b02038faSJohn Youn } 145b02038faSJohn Youn } 146b02038faSJohn Youn 147b02038faSJohn Youn /* 148b02038faSJohn Youn * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also 149b02038faSJohn Youn * do this on HNP Dev/Host mode switches (done in dev_init and 150b02038faSJohn Youn * host_init). 151b02038faSJohn Youn */ 152b02038faSJohn Youn if (dwc2_is_host_mode(hsotg)) 153b02038faSJohn Youn dwc2_init_fs_ls_pclk_sel(hsotg); 154b02038faSJohn Youn 155bea8e86cSJohn Youn if (hsotg->params.i2c_enable > 0) { 156b02038faSJohn Youn dev_dbg(hsotg->dev, "FS PHY enabling I2C\n"); 157b02038faSJohn Youn 158b02038faSJohn Youn /* Program GUSBCFG.OtgUtmiFsSel to I2C */ 159b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 160b02038faSJohn Youn usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL; 161b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 162b02038faSJohn Youn 163b02038faSJohn Youn /* Program GI2CCTL.I2CEn */ 164b02038faSJohn Youn i2cctl = dwc2_readl(hsotg->regs + GI2CCTL); 165b02038faSJohn Youn i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK; 166b02038faSJohn Youn i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT; 167b02038faSJohn Youn i2cctl &= ~GI2CCTL_I2CEN; 168b02038faSJohn Youn dwc2_writel(i2cctl, hsotg->regs + GI2CCTL); 169b02038faSJohn Youn i2cctl |= GI2CCTL_I2CEN; 170b02038faSJohn Youn dwc2_writel(i2cctl, hsotg->regs + GI2CCTL); 171b02038faSJohn Youn } 172b02038faSJohn Youn 173b02038faSJohn Youn return retval; 174b02038faSJohn Youn } 175b02038faSJohn Youn 176b02038faSJohn Youn static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) 177b02038faSJohn Youn { 178b02038faSJohn Youn u32 usbcfg, usbcfg_old; 179b02038faSJohn Youn int retval = 0; 180b02038faSJohn Youn 181b02038faSJohn Youn if (!select_phy) 182b02038faSJohn Youn return 0; 183b02038faSJohn Youn 184b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 185b02038faSJohn Youn usbcfg_old = usbcfg; 186b02038faSJohn Youn 187b02038faSJohn Youn /* 188b02038faSJohn Youn * HS PHY parameters. These parameters are preserved during soft reset 189b02038faSJohn Youn * so only program the first time. Do a soft reset immediately after 190b02038faSJohn Youn * setting phyif. 191b02038faSJohn Youn */ 192bea8e86cSJohn Youn switch (hsotg->params.phy_type) { 193b02038faSJohn Youn case DWC2_PHY_TYPE_PARAM_ULPI: 194b02038faSJohn Youn /* ULPI interface */ 195b02038faSJohn Youn dev_dbg(hsotg->dev, "HS ULPI PHY selected\n"); 196b02038faSJohn Youn usbcfg |= GUSBCFG_ULPI_UTMI_SEL; 197b02038faSJohn Youn usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); 198bea8e86cSJohn Youn if (hsotg->params.phy_ulpi_ddr > 0) 199b02038faSJohn Youn usbcfg |= GUSBCFG_DDRSEL; 200b02038faSJohn Youn break; 201b02038faSJohn Youn case DWC2_PHY_TYPE_PARAM_UTMI: 202b02038faSJohn Youn /* UTMI+ interface */ 203b02038faSJohn Youn dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n"); 204b02038faSJohn Youn usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); 205bea8e86cSJohn Youn if (hsotg->params.phy_utmi_width == 16) 206b02038faSJohn Youn usbcfg |= GUSBCFG_PHYIF16; 207b02038faSJohn Youn break; 208b02038faSJohn Youn default: 209b02038faSJohn Youn dev_err(hsotg->dev, "FS PHY selected at HS!\n"); 210b02038faSJohn Youn break; 211b02038faSJohn Youn } 212b02038faSJohn Youn 213b02038faSJohn Youn if (usbcfg != usbcfg_old) { 214b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 215b02038faSJohn Youn 216b02038faSJohn Youn /* Reset after setting the PHY parameters */ 217b02038faSJohn Youn retval = dwc2_core_reset_and_force_dr_mode(hsotg); 218b02038faSJohn Youn if (retval) { 219b02038faSJohn Youn dev_err(hsotg->dev, 220b02038faSJohn Youn "%s: Reset failed, aborting", __func__); 221b02038faSJohn Youn return retval; 222b02038faSJohn Youn } 223b02038faSJohn Youn } 224b02038faSJohn Youn 225b02038faSJohn Youn return retval; 226b02038faSJohn Youn } 227b02038faSJohn Youn 228b02038faSJohn Youn static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) 229b02038faSJohn Youn { 230b02038faSJohn Youn u32 usbcfg; 231b02038faSJohn Youn int retval = 0; 232b02038faSJohn Youn 233bea8e86cSJohn Youn if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL && 234bea8e86cSJohn Youn hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { 235b02038faSJohn Youn /* If FS mode with FS PHY */ 236b02038faSJohn Youn retval = dwc2_fs_phy_init(hsotg, select_phy); 237b02038faSJohn Youn if (retval) 238b02038faSJohn Youn return retval; 239b02038faSJohn Youn } else { 240b02038faSJohn Youn /* High speed PHY */ 241b02038faSJohn Youn retval = dwc2_hs_phy_init(hsotg, select_phy); 242b02038faSJohn Youn if (retval) 243b02038faSJohn Youn return retval; 244b02038faSJohn Youn } 245b02038faSJohn Youn 246b02038faSJohn Youn if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && 247b02038faSJohn Youn hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && 248bea8e86cSJohn Youn hsotg->params.ulpi_fs_ls > 0) { 249b02038faSJohn Youn dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); 250b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 251b02038faSJohn Youn usbcfg |= GUSBCFG_ULPI_FS_LS; 252b02038faSJohn Youn usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M; 253b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 254b02038faSJohn Youn } else { 255b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 256b02038faSJohn Youn usbcfg &= ~GUSBCFG_ULPI_FS_LS; 257b02038faSJohn Youn usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M; 258b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 259b02038faSJohn Youn } 260b02038faSJohn Youn 261b02038faSJohn Youn return retval; 262b02038faSJohn Youn } 263b02038faSJohn Youn 264b02038faSJohn Youn static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) 265b02038faSJohn Youn { 266b02038faSJohn Youn u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); 267b02038faSJohn Youn 268b02038faSJohn Youn switch (hsotg->hw_params.arch) { 269b02038faSJohn Youn case GHWCFG2_EXT_DMA_ARCH: 270b02038faSJohn Youn dev_err(hsotg->dev, "External DMA Mode not supported\n"); 271b02038faSJohn Youn return -EINVAL; 272b02038faSJohn Youn 273b02038faSJohn Youn case GHWCFG2_INT_DMA_ARCH: 274b02038faSJohn Youn dev_dbg(hsotg->dev, "Internal DMA Mode\n"); 275bea8e86cSJohn Youn if (hsotg->params.ahbcfg != -1) { 276b02038faSJohn Youn ahbcfg &= GAHBCFG_CTRL_MASK; 277bea8e86cSJohn Youn ahbcfg |= hsotg->params.ahbcfg & 278b02038faSJohn Youn ~GAHBCFG_CTRL_MASK; 279b02038faSJohn Youn } 280b02038faSJohn Youn break; 281b02038faSJohn Youn 282b02038faSJohn Youn case GHWCFG2_SLAVE_ONLY_ARCH: 283b02038faSJohn Youn default: 284b02038faSJohn Youn dev_dbg(hsotg->dev, "Slave Only Mode\n"); 285b02038faSJohn Youn break; 286b02038faSJohn Youn } 287b02038faSJohn Youn 288*e7839f99SJohn Youn dev_dbg(hsotg->dev, "host_dma:%d dma_desc_enable:%d\n", 289*e7839f99SJohn Youn hsotg->params.host_dma, 290bea8e86cSJohn Youn hsotg->params.dma_desc_enable); 291b02038faSJohn Youn 292*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 293bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable > 0) 294b02038faSJohn Youn dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n"); 295b02038faSJohn Youn else 296b02038faSJohn Youn dev_dbg(hsotg->dev, "Using Buffer DMA mode\n"); 297b02038faSJohn Youn } else { 298b02038faSJohn Youn dev_dbg(hsotg->dev, "Using Slave mode\n"); 299bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 0; 300b02038faSJohn Youn } 301b02038faSJohn Youn 302*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) 303b02038faSJohn Youn ahbcfg |= GAHBCFG_DMA_EN; 304b02038faSJohn Youn 305b02038faSJohn Youn dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); 306b02038faSJohn Youn 307b02038faSJohn Youn return 0; 308b02038faSJohn Youn } 309b02038faSJohn Youn 310b02038faSJohn Youn static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) 311b02038faSJohn Youn { 312b02038faSJohn Youn u32 usbcfg; 313b02038faSJohn Youn 314b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 315b02038faSJohn Youn usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP); 316b02038faSJohn Youn 317b02038faSJohn Youn switch (hsotg->hw_params.op_mode) { 318b02038faSJohn Youn case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: 319bea8e86cSJohn Youn if (hsotg->params.otg_cap == 320b02038faSJohn Youn DWC2_CAP_PARAM_HNP_SRP_CAPABLE) 321b02038faSJohn Youn usbcfg |= GUSBCFG_HNPCAP; 322bea8e86cSJohn Youn if (hsotg->params.otg_cap != 323b02038faSJohn Youn DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) 324b02038faSJohn Youn usbcfg |= GUSBCFG_SRPCAP; 325b02038faSJohn Youn break; 326b02038faSJohn Youn 327b02038faSJohn Youn case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: 328b02038faSJohn Youn case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: 329b02038faSJohn Youn case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: 330bea8e86cSJohn Youn if (hsotg->params.otg_cap != 331b02038faSJohn Youn DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) 332b02038faSJohn Youn usbcfg |= GUSBCFG_SRPCAP; 333b02038faSJohn Youn break; 334b02038faSJohn Youn 335b02038faSJohn Youn case GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE: 336b02038faSJohn Youn case GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE: 337b02038faSJohn Youn case GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST: 338b02038faSJohn Youn default: 339b02038faSJohn Youn break; 340b02038faSJohn Youn } 341b02038faSJohn Youn 342b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 343b02038faSJohn Youn } 344b02038faSJohn Youn 345b02038faSJohn Youn /** 346b02038faSJohn Youn * dwc2_enable_host_interrupts() - Enables the Host mode interrupts 347b02038faSJohn Youn * 348b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 349b02038faSJohn Youn */ 350b02038faSJohn Youn static void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg) 351b02038faSJohn Youn { 352b02038faSJohn Youn u32 intmsk; 353b02038faSJohn Youn 354b02038faSJohn Youn dev_dbg(hsotg->dev, "%s()\n", __func__); 355b02038faSJohn Youn 356b02038faSJohn Youn /* Disable all interrupts */ 357b02038faSJohn Youn dwc2_writel(0, hsotg->regs + GINTMSK); 358b02038faSJohn Youn dwc2_writel(0, hsotg->regs + HAINTMSK); 359b02038faSJohn Youn 360b02038faSJohn Youn /* Enable the common interrupts */ 361b02038faSJohn Youn dwc2_enable_common_interrupts(hsotg); 362b02038faSJohn Youn 363b02038faSJohn Youn /* Enable host mode interrupts without disturbing common interrupts */ 364b02038faSJohn Youn intmsk = dwc2_readl(hsotg->regs + GINTMSK); 365b02038faSJohn Youn intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT; 366b02038faSJohn Youn dwc2_writel(intmsk, hsotg->regs + GINTMSK); 367b02038faSJohn Youn } 368b02038faSJohn Youn 369b02038faSJohn Youn /** 370b02038faSJohn Youn * dwc2_disable_host_interrupts() - Disables the Host Mode interrupts 371b02038faSJohn Youn * 372b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 373b02038faSJohn Youn */ 374b02038faSJohn Youn static void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg) 375b02038faSJohn Youn { 376b02038faSJohn Youn u32 intmsk = dwc2_readl(hsotg->regs + GINTMSK); 377b02038faSJohn Youn 378b02038faSJohn Youn /* Disable host mode interrupts without disturbing common interrupts */ 379b02038faSJohn Youn intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT | 380b02038faSJohn Youn GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT); 381b02038faSJohn Youn dwc2_writel(intmsk, hsotg->regs + GINTMSK); 382b02038faSJohn Youn } 383b02038faSJohn Youn 384b02038faSJohn Youn /* 385b02038faSJohn Youn * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size 386b02038faSJohn Youn * For system that have a total fifo depth that is smaller than the default 387b02038faSJohn Youn * RX + TX fifo size. 388b02038faSJohn Youn * 389b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 390b02038faSJohn Youn */ 391b02038faSJohn Youn static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) 392b02038faSJohn Youn { 393bea8e86cSJohn Youn struct dwc2_core_params *params = &hsotg->params; 394b02038faSJohn Youn struct dwc2_hw_params *hw = &hsotg->hw_params; 395b02038faSJohn Youn u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size; 396b02038faSJohn Youn 397b02038faSJohn Youn total_fifo_size = hw->total_fifo_size; 398b02038faSJohn Youn rxfsiz = params->host_rx_fifo_size; 399b02038faSJohn Youn nptxfsiz = params->host_nperio_tx_fifo_size; 400b02038faSJohn Youn ptxfsiz = params->host_perio_tx_fifo_size; 401b02038faSJohn Youn 402b02038faSJohn Youn /* 403b02038faSJohn Youn * Will use Method 2 defined in the DWC2 spec: minimum FIFO depth 404b02038faSJohn Youn * allocation with support for high bandwidth endpoints. Synopsys 405b02038faSJohn Youn * defines MPS(Max Packet size) for a periodic EP=1024, and for 406b02038faSJohn Youn * non-periodic as 512. 407b02038faSJohn Youn */ 408b02038faSJohn Youn if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) { 409b02038faSJohn Youn /* 410b02038faSJohn Youn * For Buffer DMA mode/Scatter Gather DMA mode 411b02038faSJohn Youn * 2 * ((Largest Packet size / 4) + 1 + 1) + n 412b02038faSJohn Youn * with n = number of host channel. 413b02038faSJohn Youn * 2 * ((1024/4) + 2) = 516 414b02038faSJohn Youn */ 415b02038faSJohn Youn rxfsiz = 516 + hw->host_channels; 416b02038faSJohn Youn 417b02038faSJohn Youn /* 418b02038faSJohn Youn * min non-periodic tx fifo depth 419b02038faSJohn Youn * 2 * (largest non-periodic USB packet used / 4) 420b02038faSJohn Youn * 2 * (512/4) = 256 421b02038faSJohn Youn */ 422b02038faSJohn Youn nptxfsiz = 256; 423b02038faSJohn Youn 424b02038faSJohn Youn /* 425b02038faSJohn Youn * min periodic tx fifo depth 426b02038faSJohn Youn * (largest packet size*MC)/4 427b02038faSJohn Youn * (1024 * 3)/4 = 768 428b02038faSJohn Youn */ 429b02038faSJohn Youn ptxfsiz = 768; 430b02038faSJohn Youn 431b02038faSJohn Youn params->host_rx_fifo_size = rxfsiz; 432b02038faSJohn Youn params->host_nperio_tx_fifo_size = nptxfsiz; 433b02038faSJohn Youn params->host_perio_tx_fifo_size = ptxfsiz; 434b02038faSJohn Youn } 435b02038faSJohn Youn 436b02038faSJohn Youn /* 437b02038faSJohn Youn * If the summation of RX, NPTX and PTX fifo sizes is still 438b02038faSJohn Youn * bigger than the total_fifo_size, then we have a problem. 439b02038faSJohn Youn * 440b02038faSJohn Youn * We won't be able to allocate as many endpoints. Right now, 441b02038faSJohn Youn * we're just printing an error message, but ideally this FIFO 442b02038faSJohn Youn * allocation algorithm would be improved in the future. 443b02038faSJohn Youn * 444b02038faSJohn Youn * FIXME improve this FIFO allocation algorithm. 445b02038faSJohn Youn */ 446b02038faSJohn Youn if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz))) 447b02038faSJohn Youn dev_err(hsotg->dev, "invalid fifo sizes\n"); 448b02038faSJohn Youn } 449b02038faSJohn Youn 450b02038faSJohn Youn static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) 451b02038faSJohn Youn { 452bea8e86cSJohn Youn struct dwc2_core_params *params = &hsotg->params; 453b02038faSJohn Youn u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz; 454b02038faSJohn Youn 455b02038faSJohn Youn if (!params->enable_dynamic_fifo) 456b02038faSJohn Youn return; 457b02038faSJohn Youn 458b02038faSJohn Youn dwc2_calculate_dynamic_fifo(hsotg); 459b02038faSJohn Youn 460b02038faSJohn Youn /* Rx FIFO */ 461b02038faSJohn Youn grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); 462b02038faSJohn Youn dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz); 463b02038faSJohn Youn grxfsiz &= ~GRXFSIZ_DEPTH_MASK; 464b02038faSJohn Youn grxfsiz |= params->host_rx_fifo_size << 465b02038faSJohn Youn GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK; 466b02038faSJohn Youn dwc2_writel(grxfsiz, hsotg->regs + GRXFSIZ); 467b02038faSJohn Youn dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", 468b02038faSJohn Youn dwc2_readl(hsotg->regs + GRXFSIZ)); 469b02038faSJohn Youn 470b02038faSJohn Youn /* Non-periodic Tx FIFO */ 471b02038faSJohn Youn dev_dbg(hsotg->dev, "initial gnptxfsiz=%08x\n", 472b02038faSJohn Youn dwc2_readl(hsotg->regs + GNPTXFSIZ)); 473b02038faSJohn Youn nptxfsiz = params->host_nperio_tx_fifo_size << 474b02038faSJohn Youn FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; 475b02038faSJohn Youn nptxfsiz |= params->host_rx_fifo_size << 476b02038faSJohn Youn FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; 477b02038faSJohn Youn dwc2_writel(nptxfsiz, hsotg->regs + GNPTXFSIZ); 478b02038faSJohn Youn dev_dbg(hsotg->dev, "new gnptxfsiz=%08x\n", 479b02038faSJohn Youn dwc2_readl(hsotg->regs + GNPTXFSIZ)); 480b02038faSJohn Youn 481b02038faSJohn Youn /* Periodic Tx FIFO */ 482b02038faSJohn Youn dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n", 483b02038faSJohn Youn dwc2_readl(hsotg->regs + HPTXFSIZ)); 484b02038faSJohn Youn hptxfsiz = params->host_perio_tx_fifo_size << 485b02038faSJohn Youn FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; 486b02038faSJohn Youn hptxfsiz |= (params->host_rx_fifo_size + 487b02038faSJohn Youn params->host_nperio_tx_fifo_size) << 488b02038faSJohn Youn FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; 489b02038faSJohn Youn dwc2_writel(hptxfsiz, hsotg->regs + HPTXFSIZ); 490b02038faSJohn Youn dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n", 491b02038faSJohn Youn dwc2_readl(hsotg->regs + HPTXFSIZ)); 492b02038faSJohn Youn 493bea8e86cSJohn Youn if (hsotg->params.en_multiple_tx_fifo > 0 && 494b02038faSJohn Youn hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) { 495b02038faSJohn Youn /* 496b02038faSJohn Youn * Global DFIFOCFG calculation for Host mode - 497b02038faSJohn Youn * include RxFIFO, NPTXFIFO and HPTXFIFO 498b02038faSJohn Youn */ 499b02038faSJohn Youn dfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG); 500b02038faSJohn Youn dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK; 501b02038faSJohn Youn dfifocfg |= (params->host_rx_fifo_size + 502b02038faSJohn Youn params->host_nperio_tx_fifo_size + 503b02038faSJohn Youn params->host_perio_tx_fifo_size) << 504b02038faSJohn Youn GDFIFOCFG_EPINFOBASE_SHIFT & 505b02038faSJohn Youn GDFIFOCFG_EPINFOBASE_MASK; 506b02038faSJohn Youn dwc2_writel(dfifocfg, hsotg->regs + GDFIFOCFG); 507b02038faSJohn Youn } 508b02038faSJohn Youn } 509b02038faSJohn Youn 510b02038faSJohn Youn /** 511b02038faSJohn Youn * dwc2_calc_frame_interval() - Calculates the correct frame Interval value for 512b02038faSJohn Youn * the HFIR register according to PHY type and speed 513b02038faSJohn Youn * 514b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 515b02038faSJohn Youn * 516b02038faSJohn Youn * NOTE: The caller can modify the value of the HFIR register only after the 517b02038faSJohn Youn * Port Enable bit of the Host Port Control and Status register (HPRT.EnaPort) 518b02038faSJohn Youn * has been set 519b02038faSJohn Youn */ 520b02038faSJohn Youn u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) 521b02038faSJohn Youn { 522b02038faSJohn Youn u32 usbcfg; 523b02038faSJohn Youn u32 hprt0; 524b02038faSJohn Youn int clock = 60; /* default value */ 525b02038faSJohn Youn 526b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 527b02038faSJohn Youn hprt0 = dwc2_readl(hsotg->regs + HPRT0); 528b02038faSJohn Youn 529b02038faSJohn Youn if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) && 530b02038faSJohn Youn !(usbcfg & GUSBCFG_PHYIF16)) 531b02038faSJohn Youn clock = 60; 532b02038faSJohn Youn if ((usbcfg & GUSBCFG_PHYSEL) && hsotg->hw_params.fs_phy_type == 533b02038faSJohn Youn GHWCFG2_FS_PHY_TYPE_SHARED_ULPI) 534b02038faSJohn Youn clock = 48; 535b02038faSJohn Youn if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) && 536b02038faSJohn Youn !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16)) 537b02038faSJohn Youn clock = 30; 538b02038faSJohn Youn if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) && 539b02038faSJohn Youn !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && !(usbcfg & GUSBCFG_PHYIF16)) 540b02038faSJohn Youn clock = 60; 541b02038faSJohn Youn if ((usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) && 542b02038faSJohn Youn !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16)) 543b02038faSJohn Youn clock = 48; 544b02038faSJohn Youn if ((usbcfg & GUSBCFG_PHYSEL) && !(usbcfg & GUSBCFG_PHYIF16) && 545b02038faSJohn Youn hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI) 546b02038faSJohn Youn clock = 48; 547b02038faSJohn Youn if ((usbcfg & GUSBCFG_PHYSEL) && 548b02038faSJohn Youn hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) 549b02038faSJohn Youn clock = 48; 550b02038faSJohn Youn 551b02038faSJohn Youn if ((hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT == HPRT0_SPD_HIGH_SPEED) 552b02038faSJohn Youn /* High speed case */ 553b02038faSJohn Youn return 125 * clock - 1; 554b02038faSJohn Youn 555b02038faSJohn Youn /* FS/LS case */ 556b02038faSJohn Youn return 1000 * clock - 1; 557b02038faSJohn Youn } 558b02038faSJohn Youn 559b02038faSJohn Youn /** 560b02038faSJohn Youn * dwc2_read_packet() - Reads a packet from the Rx FIFO into the destination 561b02038faSJohn Youn * buffer 562b02038faSJohn Youn * 563b02038faSJohn Youn * @core_if: Programming view of DWC_otg controller 564b02038faSJohn Youn * @dest: Destination buffer for the packet 565b02038faSJohn Youn * @bytes: Number of bytes to copy to the destination 566b02038faSJohn Youn */ 567b02038faSJohn Youn void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes) 568b02038faSJohn Youn { 569b02038faSJohn Youn u32 __iomem *fifo = hsotg->regs + HCFIFO(0); 570b02038faSJohn Youn u32 *data_buf = (u32 *)dest; 571b02038faSJohn Youn int word_count = (bytes + 3) / 4; 572b02038faSJohn Youn int i; 573b02038faSJohn Youn 574b02038faSJohn Youn /* 575b02038faSJohn Youn * Todo: Account for the case where dest is not dword aligned. This 576b02038faSJohn Youn * requires reading data from the FIFO into a u32 temp buffer, then 577b02038faSJohn Youn * moving it into the data buffer. 578b02038faSJohn Youn */ 579b02038faSJohn Youn 580b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes); 581b02038faSJohn Youn 582b02038faSJohn Youn for (i = 0; i < word_count; i++, data_buf++) 583b02038faSJohn Youn *data_buf = dwc2_readl(fifo); 584b02038faSJohn Youn } 585b02038faSJohn Youn 586197ba5f4SPaul Zimmerman /** 587197ba5f4SPaul Zimmerman * dwc2_dump_channel_info() - Prints the state of a host channel 588197ba5f4SPaul Zimmerman * 589197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 590197ba5f4SPaul Zimmerman * @chan: Pointer to the channel to dump 591197ba5f4SPaul Zimmerman * 592197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 593197ba5f4SPaul Zimmerman * 594197ba5f4SPaul Zimmerman * NOTE: This function will be removed once the peripheral controller code 595197ba5f4SPaul Zimmerman * is integrated and the driver is stable 596197ba5f4SPaul Zimmerman */ 597197ba5f4SPaul Zimmerman static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, 598197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan) 599197ba5f4SPaul Zimmerman { 600197ba5f4SPaul Zimmerman #ifdef VERBOSE_DEBUG 601bea8e86cSJohn Youn int num_channels = hsotg->params.host_channels; 602197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 603197ba5f4SPaul Zimmerman u32 hcchar; 604197ba5f4SPaul Zimmerman u32 hcsplt; 605197ba5f4SPaul Zimmerman u32 hctsiz; 606197ba5f4SPaul Zimmerman u32 hc_dma; 607197ba5f4SPaul Zimmerman int i; 608197ba5f4SPaul Zimmerman 609b02038faSJohn Youn if (!chan) 610197ba5f4SPaul Zimmerman return; 611197ba5f4SPaul Zimmerman 61295c8bc36SAntti Seppälä hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 61395c8bc36SAntti Seppälä hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num)); 61495c8bc36SAntti Seppälä hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chan->hc_num)); 61595c8bc36SAntti Seppälä hc_dma = dwc2_readl(hsotg->regs + HCDMA(chan->hc_num)); 616197ba5f4SPaul Zimmerman 617197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " Assigned to channel %p:\n", chan); 618197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hcchar 0x%08x, hcsplt 0x%08x\n", 619197ba5f4SPaul Zimmerman hcchar, hcsplt); 620197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hctsiz 0x%08x, hc_dma 0x%08x\n", 621197ba5f4SPaul Zimmerman hctsiz, hc_dma); 622197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " dev_addr: %d, ep_num: %d, ep_is_in: %d\n", 623197ba5f4SPaul Zimmerman chan->dev_addr, chan->ep_num, chan->ep_is_in); 624197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " ep_type: %d\n", chan->ep_type); 625197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " max_packet: %d\n", chan->max_packet); 626197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " data_pid_start: %d\n", chan->data_pid_start); 627197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_started: %d\n", chan->xfer_started); 628197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " halt_status: %d\n", chan->halt_status); 629197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_buf: %p\n", chan->xfer_buf); 630197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_dma: %08lx\n", 631197ba5f4SPaul Zimmerman (unsigned long)chan->xfer_dma); 632197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_len: %d\n", chan->xfer_len); 633197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " qh: %p\n", chan->qh); 634197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " NP inactive sched:\n"); 635197ba5f4SPaul Zimmerman list_for_each_entry(qh, &hsotg->non_periodic_sched_inactive, 636197ba5f4SPaul Zimmerman qh_list_entry) 637197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " %p\n", qh); 638197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " NP active sched:\n"); 639197ba5f4SPaul Zimmerman list_for_each_entry(qh, &hsotg->non_periodic_sched_active, 640197ba5f4SPaul Zimmerman qh_list_entry) 641197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " %p\n", qh); 642197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " Channels:\n"); 643197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 644197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i]; 645197ba5f4SPaul Zimmerman 646197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " %2d: %p\n", i, chan); 647197ba5f4SPaul Zimmerman } 648197ba5f4SPaul Zimmerman #endif /* VERBOSE_DEBUG */ 649197ba5f4SPaul Zimmerman } 650197ba5f4SPaul Zimmerman 651197ba5f4SPaul Zimmerman /* 652b02038faSJohn Youn * ========================================================================= 653b02038faSJohn Youn * Low Level Host Channel Access Functions 654b02038faSJohn Youn * ========================================================================= 655b02038faSJohn Youn */ 656b02038faSJohn Youn 657b02038faSJohn Youn static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg, 658b02038faSJohn Youn struct dwc2_host_chan *chan) 659b02038faSJohn Youn { 660b02038faSJohn Youn u32 hcintmsk = HCINTMSK_CHHLTD; 661b02038faSJohn Youn 662b02038faSJohn Youn switch (chan->ep_type) { 663b02038faSJohn Youn case USB_ENDPOINT_XFER_CONTROL: 664b02038faSJohn Youn case USB_ENDPOINT_XFER_BULK: 665b02038faSJohn Youn dev_vdbg(hsotg->dev, "control/bulk\n"); 666b02038faSJohn Youn hcintmsk |= HCINTMSK_XFERCOMPL; 667b02038faSJohn Youn hcintmsk |= HCINTMSK_STALL; 668b02038faSJohn Youn hcintmsk |= HCINTMSK_XACTERR; 669b02038faSJohn Youn hcintmsk |= HCINTMSK_DATATGLERR; 670b02038faSJohn Youn if (chan->ep_is_in) { 671b02038faSJohn Youn hcintmsk |= HCINTMSK_BBLERR; 672b02038faSJohn Youn } else { 673b02038faSJohn Youn hcintmsk |= HCINTMSK_NAK; 674b02038faSJohn Youn hcintmsk |= HCINTMSK_NYET; 675b02038faSJohn Youn if (chan->do_ping) 676b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 677b02038faSJohn Youn } 678b02038faSJohn Youn 679b02038faSJohn Youn if (chan->do_split) { 680b02038faSJohn Youn hcintmsk |= HCINTMSK_NAK; 681b02038faSJohn Youn if (chan->complete_split) 682b02038faSJohn Youn hcintmsk |= HCINTMSK_NYET; 683b02038faSJohn Youn else 684b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 685b02038faSJohn Youn } 686b02038faSJohn Youn 687b02038faSJohn Youn if (chan->error_state) 688b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 689b02038faSJohn Youn break; 690b02038faSJohn Youn 691b02038faSJohn Youn case USB_ENDPOINT_XFER_INT: 692b02038faSJohn Youn if (dbg_perio()) 693b02038faSJohn Youn dev_vdbg(hsotg->dev, "intr\n"); 694b02038faSJohn Youn hcintmsk |= HCINTMSK_XFERCOMPL; 695b02038faSJohn Youn hcintmsk |= HCINTMSK_NAK; 696b02038faSJohn Youn hcintmsk |= HCINTMSK_STALL; 697b02038faSJohn Youn hcintmsk |= HCINTMSK_XACTERR; 698b02038faSJohn Youn hcintmsk |= HCINTMSK_DATATGLERR; 699b02038faSJohn Youn hcintmsk |= HCINTMSK_FRMOVRUN; 700b02038faSJohn Youn 701b02038faSJohn Youn if (chan->ep_is_in) 702b02038faSJohn Youn hcintmsk |= HCINTMSK_BBLERR; 703b02038faSJohn Youn if (chan->error_state) 704b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 705b02038faSJohn Youn if (chan->do_split) { 706b02038faSJohn Youn if (chan->complete_split) 707b02038faSJohn Youn hcintmsk |= HCINTMSK_NYET; 708b02038faSJohn Youn else 709b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 710b02038faSJohn Youn } 711b02038faSJohn Youn break; 712b02038faSJohn Youn 713b02038faSJohn Youn case USB_ENDPOINT_XFER_ISOC: 714b02038faSJohn Youn if (dbg_perio()) 715b02038faSJohn Youn dev_vdbg(hsotg->dev, "isoc\n"); 716b02038faSJohn Youn hcintmsk |= HCINTMSK_XFERCOMPL; 717b02038faSJohn Youn hcintmsk |= HCINTMSK_FRMOVRUN; 718b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 719b02038faSJohn Youn 720b02038faSJohn Youn if (chan->ep_is_in) { 721b02038faSJohn Youn hcintmsk |= HCINTMSK_XACTERR; 722b02038faSJohn Youn hcintmsk |= HCINTMSK_BBLERR; 723b02038faSJohn Youn } 724b02038faSJohn Youn break; 725b02038faSJohn Youn default: 726b02038faSJohn Youn dev_err(hsotg->dev, "## Unknown EP type ##\n"); 727b02038faSJohn Youn break; 728b02038faSJohn Youn } 729b02038faSJohn Youn 730b02038faSJohn Youn dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); 731b02038faSJohn Youn if (dbg_hc(chan)) 732b02038faSJohn Youn dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); 733b02038faSJohn Youn } 734b02038faSJohn Youn 735b02038faSJohn Youn static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, 736b02038faSJohn Youn struct dwc2_host_chan *chan) 737b02038faSJohn Youn { 738b02038faSJohn Youn u32 hcintmsk = HCINTMSK_CHHLTD; 739b02038faSJohn Youn 740b02038faSJohn Youn /* 741b02038faSJohn Youn * For Descriptor DMA mode core halts the channel on AHB error. 742b02038faSJohn Youn * Interrupt is not required. 743b02038faSJohn Youn */ 744bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable <= 0) { 745b02038faSJohn Youn if (dbg_hc(chan)) 746b02038faSJohn Youn dev_vdbg(hsotg->dev, "desc DMA disabled\n"); 747b02038faSJohn Youn hcintmsk |= HCINTMSK_AHBERR; 748b02038faSJohn Youn } else { 749b02038faSJohn Youn if (dbg_hc(chan)) 750b02038faSJohn Youn dev_vdbg(hsotg->dev, "desc DMA enabled\n"); 751b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) 752b02038faSJohn Youn hcintmsk |= HCINTMSK_XFERCOMPL; 753b02038faSJohn Youn } 754b02038faSJohn Youn 755b02038faSJohn Youn if (chan->error_state && !chan->do_split && 756b02038faSJohn Youn chan->ep_type != USB_ENDPOINT_XFER_ISOC) { 757b02038faSJohn Youn if (dbg_hc(chan)) 758b02038faSJohn Youn dev_vdbg(hsotg->dev, "setting ACK\n"); 759b02038faSJohn Youn hcintmsk |= HCINTMSK_ACK; 760b02038faSJohn Youn if (chan->ep_is_in) { 761b02038faSJohn Youn hcintmsk |= HCINTMSK_DATATGLERR; 762b02038faSJohn Youn if (chan->ep_type != USB_ENDPOINT_XFER_INT) 763b02038faSJohn Youn hcintmsk |= HCINTMSK_NAK; 764b02038faSJohn Youn } 765b02038faSJohn Youn } 766b02038faSJohn Youn 767b02038faSJohn Youn dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); 768b02038faSJohn Youn if (dbg_hc(chan)) 769b02038faSJohn Youn dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); 770b02038faSJohn Youn } 771b02038faSJohn Youn 772b02038faSJohn Youn static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, 773b02038faSJohn Youn struct dwc2_host_chan *chan) 774b02038faSJohn Youn { 775b02038faSJohn Youn u32 intmsk; 776b02038faSJohn Youn 777*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 778b02038faSJohn Youn if (dbg_hc(chan)) 779b02038faSJohn Youn dev_vdbg(hsotg->dev, "DMA enabled\n"); 780b02038faSJohn Youn dwc2_hc_enable_dma_ints(hsotg, chan); 781b02038faSJohn Youn } else { 782b02038faSJohn Youn if (dbg_hc(chan)) 783b02038faSJohn Youn dev_vdbg(hsotg->dev, "DMA disabled\n"); 784b02038faSJohn Youn dwc2_hc_enable_slave_ints(hsotg, chan); 785b02038faSJohn Youn } 786b02038faSJohn Youn 787b02038faSJohn Youn /* Enable the top level host channel interrupt */ 788b02038faSJohn Youn intmsk = dwc2_readl(hsotg->regs + HAINTMSK); 789b02038faSJohn Youn intmsk |= 1 << chan->hc_num; 790b02038faSJohn Youn dwc2_writel(intmsk, hsotg->regs + HAINTMSK); 791b02038faSJohn Youn if (dbg_hc(chan)) 792b02038faSJohn Youn dev_vdbg(hsotg->dev, "set HAINTMSK to %08x\n", intmsk); 793b02038faSJohn Youn 794b02038faSJohn Youn /* Make sure host channel interrupts are enabled */ 795b02038faSJohn Youn intmsk = dwc2_readl(hsotg->regs + GINTMSK); 796b02038faSJohn Youn intmsk |= GINTSTS_HCHINT; 797b02038faSJohn Youn dwc2_writel(intmsk, hsotg->regs + GINTMSK); 798b02038faSJohn Youn if (dbg_hc(chan)) 799b02038faSJohn Youn dev_vdbg(hsotg->dev, "set GINTMSK to %08x\n", intmsk); 800b02038faSJohn Youn } 801b02038faSJohn Youn 802b02038faSJohn Youn /** 803b02038faSJohn Youn * dwc2_hc_init() - Prepares a host channel for transferring packets to/from 804b02038faSJohn Youn * a specific endpoint 805b02038faSJohn Youn * 806b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 807b02038faSJohn Youn * @chan: Information needed to initialize the host channel 808b02038faSJohn Youn * 809b02038faSJohn Youn * The HCCHARn register is set up with the characteristics specified in chan. 810b02038faSJohn Youn * Host channel interrupts that may need to be serviced while this transfer is 811b02038faSJohn Youn * in progress are enabled. 812b02038faSJohn Youn */ 813b02038faSJohn Youn static void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) 814b02038faSJohn Youn { 815b02038faSJohn Youn u8 hc_num = chan->hc_num; 816b02038faSJohn Youn u32 hcintmsk; 817b02038faSJohn Youn u32 hcchar; 818b02038faSJohn Youn u32 hcsplt = 0; 819b02038faSJohn Youn 820b02038faSJohn Youn if (dbg_hc(chan)) 821b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s()\n", __func__); 822b02038faSJohn Youn 823b02038faSJohn Youn /* Clear old interrupt conditions for this host channel */ 824b02038faSJohn Youn hcintmsk = 0xffffffff; 825b02038faSJohn Youn hcintmsk &= ~HCINTMSK_RESERVED14_31; 826b02038faSJohn Youn dwc2_writel(hcintmsk, hsotg->regs + HCINT(hc_num)); 827b02038faSJohn Youn 828b02038faSJohn Youn /* Enable channel interrupts required for this transfer */ 829b02038faSJohn Youn dwc2_hc_enable_ints(hsotg, chan); 830b02038faSJohn Youn 831b02038faSJohn Youn /* 832b02038faSJohn Youn * Program the HCCHARn register with the endpoint characteristics for 833b02038faSJohn Youn * the current transfer 834b02038faSJohn Youn */ 835b02038faSJohn Youn hcchar = chan->dev_addr << HCCHAR_DEVADDR_SHIFT & HCCHAR_DEVADDR_MASK; 836b02038faSJohn Youn hcchar |= chan->ep_num << HCCHAR_EPNUM_SHIFT & HCCHAR_EPNUM_MASK; 837b02038faSJohn Youn if (chan->ep_is_in) 838b02038faSJohn Youn hcchar |= HCCHAR_EPDIR; 839b02038faSJohn Youn if (chan->speed == USB_SPEED_LOW) 840b02038faSJohn Youn hcchar |= HCCHAR_LSPDDEV; 841b02038faSJohn Youn hcchar |= chan->ep_type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK; 842b02038faSJohn Youn hcchar |= chan->max_packet << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK; 843b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(hc_num)); 844b02038faSJohn Youn if (dbg_hc(chan)) { 845b02038faSJohn Youn dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n", 846b02038faSJohn Youn hc_num, hcchar); 847b02038faSJohn Youn 848b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", 849b02038faSJohn Youn __func__, hc_num); 850b02038faSJohn Youn dev_vdbg(hsotg->dev, " Dev Addr: %d\n", 851b02038faSJohn Youn chan->dev_addr); 852b02038faSJohn Youn dev_vdbg(hsotg->dev, " Ep Num: %d\n", 853b02038faSJohn Youn chan->ep_num); 854b02038faSJohn Youn dev_vdbg(hsotg->dev, " Is In: %d\n", 855b02038faSJohn Youn chan->ep_is_in); 856b02038faSJohn Youn dev_vdbg(hsotg->dev, " Is Low Speed: %d\n", 857b02038faSJohn Youn chan->speed == USB_SPEED_LOW); 858b02038faSJohn Youn dev_vdbg(hsotg->dev, " Ep Type: %d\n", 859b02038faSJohn Youn chan->ep_type); 860b02038faSJohn Youn dev_vdbg(hsotg->dev, " Max Pkt: %d\n", 861b02038faSJohn Youn chan->max_packet); 862b02038faSJohn Youn } 863b02038faSJohn Youn 864b02038faSJohn Youn /* Program the HCSPLT register for SPLITs */ 865b02038faSJohn Youn if (chan->do_split) { 866b02038faSJohn Youn if (dbg_hc(chan)) 867b02038faSJohn Youn dev_vdbg(hsotg->dev, 868b02038faSJohn Youn "Programming HC %d with split --> %s\n", 869b02038faSJohn Youn hc_num, 870b02038faSJohn Youn chan->complete_split ? "CSPLIT" : "SSPLIT"); 871b02038faSJohn Youn if (chan->complete_split) 872b02038faSJohn Youn hcsplt |= HCSPLT_COMPSPLT; 873b02038faSJohn Youn hcsplt |= chan->xact_pos << HCSPLT_XACTPOS_SHIFT & 874b02038faSJohn Youn HCSPLT_XACTPOS_MASK; 875b02038faSJohn Youn hcsplt |= chan->hub_addr << HCSPLT_HUBADDR_SHIFT & 876b02038faSJohn Youn HCSPLT_HUBADDR_MASK; 877b02038faSJohn Youn hcsplt |= chan->hub_port << HCSPLT_PRTADDR_SHIFT & 878b02038faSJohn Youn HCSPLT_PRTADDR_MASK; 879b02038faSJohn Youn if (dbg_hc(chan)) { 880b02038faSJohn Youn dev_vdbg(hsotg->dev, " comp split %d\n", 881b02038faSJohn Youn chan->complete_split); 882b02038faSJohn Youn dev_vdbg(hsotg->dev, " xact pos %d\n", 883b02038faSJohn Youn chan->xact_pos); 884b02038faSJohn Youn dev_vdbg(hsotg->dev, " hub addr %d\n", 885b02038faSJohn Youn chan->hub_addr); 886b02038faSJohn Youn dev_vdbg(hsotg->dev, " hub port %d\n", 887b02038faSJohn Youn chan->hub_port); 888b02038faSJohn Youn dev_vdbg(hsotg->dev, " is_in %d\n", 889b02038faSJohn Youn chan->ep_is_in); 890b02038faSJohn Youn dev_vdbg(hsotg->dev, " Max Pkt %d\n", 891b02038faSJohn Youn chan->max_packet); 892b02038faSJohn Youn dev_vdbg(hsotg->dev, " xferlen %d\n", 893b02038faSJohn Youn chan->xfer_len); 894b02038faSJohn Youn } 895b02038faSJohn Youn } 896b02038faSJohn Youn 897b02038faSJohn Youn dwc2_writel(hcsplt, hsotg->regs + HCSPLT(hc_num)); 898b02038faSJohn Youn } 899b02038faSJohn Youn 900b02038faSJohn Youn /** 901b02038faSJohn Youn * dwc2_hc_halt() - Attempts to halt a host channel 902b02038faSJohn Youn * 903b02038faSJohn Youn * @hsotg: Controller register interface 904b02038faSJohn Youn * @chan: Host channel to halt 905b02038faSJohn Youn * @halt_status: Reason for halting the channel 906b02038faSJohn Youn * 907b02038faSJohn Youn * This function should only be called in Slave mode or to abort a transfer in 908b02038faSJohn Youn * either Slave mode or DMA mode. Under normal circumstances in DMA mode, the 909b02038faSJohn Youn * controller halts the channel when the transfer is complete or a condition 910b02038faSJohn Youn * occurs that requires application intervention. 911b02038faSJohn Youn * 912b02038faSJohn Youn * In slave mode, checks for a free request queue entry, then sets the Channel 913b02038faSJohn Youn * Enable and Channel Disable bits of the Host Channel Characteristics 914b02038faSJohn Youn * register of the specified channel to intiate the halt. If there is no free 915b02038faSJohn Youn * request queue entry, sets only the Channel Disable bit of the HCCHARn 916b02038faSJohn Youn * register to flush requests for this channel. In the latter case, sets a 917b02038faSJohn Youn * flag to indicate that the host channel needs to be halted when a request 918b02038faSJohn Youn * queue slot is open. 919b02038faSJohn Youn * 920b02038faSJohn Youn * In DMA mode, always sets the Channel Enable and Channel Disable bits of the 921b02038faSJohn Youn * HCCHARn register. The controller ensures there is space in the request 922b02038faSJohn Youn * queue before submitting the halt request. 923b02038faSJohn Youn * 924b02038faSJohn Youn * Some time may elapse before the core flushes any posted requests for this 925b02038faSJohn Youn * host channel and halts. The Channel Halted interrupt handler completes the 926b02038faSJohn Youn * deactivation of the host channel. 927b02038faSJohn Youn */ 928b02038faSJohn Youn void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, 929b02038faSJohn Youn enum dwc2_halt_status halt_status) 930b02038faSJohn Youn { 931b02038faSJohn Youn u32 nptxsts, hptxsts, hcchar; 932b02038faSJohn Youn 933b02038faSJohn Youn if (dbg_hc(chan)) 934b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s()\n", __func__); 935b02038faSJohn Youn if (halt_status == DWC2_HC_XFER_NO_HALT_STATUS) 936b02038faSJohn Youn dev_err(hsotg->dev, "!!! halt_status = %d !!!\n", halt_status); 937b02038faSJohn Youn 938b02038faSJohn Youn if (halt_status == DWC2_HC_XFER_URB_DEQUEUE || 939b02038faSJohn Youn halt_status == DWC2_HC_XFER_AHB_ERR) { 940b02038faSJohn Youn /* 941b02038faSJohn Youn * Disable all channel interrupts except Ch Halted. The QTD 942b02038faSJohn Youn * and QH state associated with this transfer has been cleared 943b02038faSJohn Youn * (in the case of URB_DEQUEUE), so the channel needs to be 944b02038faSJohn Youn * shut down carefully to prevent crashes. 945b02038faSJohn Youn */ 946b02038faSJohn Youn u32 hcintmsk = HCINTMSK_CHHLTD; 947b02038faSJohn Youn 948b02038faSJohn Youn dev_vdbg(hsotg->dev, "dequeue/error\n"); 949b02038faSJohn Youn dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num)); 950b02038faSJohn Youn 951b02038faSJohn Youn /* 952b02038faSJohn Youn * Make sure no other interrupts besides halt are currently 953b02038faSJohn Youn * pending. Handling another interrupt could cause a crash due 954b02038faSJohn Youn * to the QTD and QH state. 955b02038faSJohn Youn */ 956b02038faSJohn Youn dwc2_writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num)); 957b02038faSJohn Youn 958b02038faSJohn Youn /* 959b02038faSJohn Youn * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR 960b02038faSJohn Youn * even if the channel was already halted for some other 961b02038faSJohn Youn * reason 962b02038faSJohn Youn */ 963b02038faSJohn Youn chan->halt_status = halt_status; 964b02038faSJohn Youn 965b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 966b02038faSJohn Youn if (!(hcchar & HCCHAR_CHENA)) { 967b02038faSJohn Youn /* 968b02038faSJohn Youn * The channel is either already halted or it hasn't 969b02038faSJohn Youn * started yet. In DMA mode, the transfer may halt if 970b02038faSJohn Youn * it finishes normally or a condition occurs that 971b02038faSJohn Youn * requires driver intervention. Don't want to halt 972b02038faSJohn Youn * the channel again. In either Slave or DMA mode, 973b02038faSJohn Youn * it's possible that the transfer has been assigned 974b02038faSJohn Youn * to a channel, but not started yet when an URB is 975b02038faSJohn Youn * dequeued. Don't want to halt a channel that hasn't 976b02038faSJohn Youn * started yet. 977b02038faSJohn Youn */ 978b02038faSJohn Youn return; 979b02038faSJohn Youn } 980b02038faSJohn Youn } 981b02038faSJohn Youn if (chan->halt_pending) { 982b02038faSJohn Youn /* 983b02038faSJohn Youn * A halt has already been issued for this channel. This might 984b02038faSJohn Youn * happen when a transfer is aborted by a higher level in 985b02038faSJohn Youn * the stack. 986b02038faSJohn Youn */ 987b02038faSJohn Youn dev_vdbg(hsotg->dev, 988b02038faSJohn Youn "*** %s: Channel %d, chan->halt_pending already set ***\n", 989b02038faSJohn Youn __func__, chan->hc_num); 990b02038faSJohn Youn return; 991b02038faSJohn Youn } 992b02038faSJohn Youn 993b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 994b02038faSJohn Youn 995b02038faSJohn Youn /* No need to set the bit in DDMA for disabling the channel */ 996b02038faSJohn Youn /* TODO check it everywhere channel is disabled */ 997bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable <= 0) { 998b02038faSJohn Youn if (dbg_hc(chan)) 999b02038faSJohn Youn dev_vdbg(hsotg->dev, "desc DMA disabled\n"); 1000b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1001b02038faSJohn Youn } else { 1002b02038faSJohn Youn if (dbg_hc(chan)) 1003b02038faSJohn Youn dev_dbg(hsotg->dev, "desc DMA enabled\n"); 1004b02038faSJohn Youn } 1005b02038faSJohn Youn hcchar |= HCCHAR_CHDIS; 1006b02038faSJohn Youn 1007*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) { 1008b02038faSJohn Youn if (dbg_hc(chan)) 1009b02038faSJohn Youn dev_vdbg(hsotg->dev, "DMA not enabled\n"); 1010b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1011b02038faSJohn Youn 1012b02038faSJohn Youn /* Check for space in the request queue to issue the halt */ 1013b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL || 1014b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_BULK) { 1015b02038faSJohn Youn dev_vdbg(hsotg->dev, "control/bulk\n"); 1016b02038faSJohn Youn nptxsts = dwc2_readl(hsotg->regs + GNPTXSTS); 1017b02038faSJohn Youn if ((nptxsts & TXSTS_QSPCAVAIL_MASK) == 0) { 1018b02038faSJohn Youn dev_vdbg(hsotg->dev, "Disabling channel\n"); 1019b02038faSJohn Youn hcchar &= ~HCCHAR_CHENA; 1020b02038faSJohn Youn } 1021b02038faSJohn Youn } else { 1022b02038faSJohn Youn if (dbg_perio()) 1023b02038faSJohn Youn dev_vdbg(hsotg->dev, "isoc/intr\n"); 1024b02038faSJohn Youn hptxsts = dwc2_readl(hsotg->regs + HPTXSTS); 1025b02038faSJohn Youn if ((hptxsts & TXSTS_QSPCAVAIL_MASK) == 0 || 1026b02038faSJohn Youn hsotg->queuing_high_bandwidth) { 1027b02038faSJohn Youn if (dbg_perio()) 1028b02038faSJohn Youn dev_vdbg(hsotg->dev, "Disabling channel\n"); 1029b02038faSJohn Youn hcchar &= ~HCCHAR_CHENA; 1030b02038faSJohn Youn } 1031b02038faSJohn Youn } 1032b02038faSJohn Youn } else { 1033b02038faSJohn Youn if (dbg_hc(chan)) 1034b02038faSJohn Youn dev_vdbg(hsotg->dev, "DMA enabled\n"); 1035b02038faSJohn Youn } 1036b02038faSJohn Youn 1037b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); 1038b02038faSJohn Youn chan->halt_status = halt_status; 1039b02038faSJohn Youn 1040b02038faSJohn Youn if (hcchar & HCCHAR_CHENA) { 1041b02038faSJohn Youn if (dbg_hc(chan)) 1042b02038faSJohn Youn dev_vdbg(hsotg->dev, "Channel enabled\n"); 1043b02038faSJohn Youn chan->halt_pending = 1; 1044b02038faSJohn Youn chan->halt_on_queue = 0; 1045b02038faSJohn Youn } else { 1046b02038faSJohn Youn if (dbg_hc(chan)) 1047b02038faSJohn Youn dev_vdbg(hsotg->dev, "Channel disabled\n"); 1048b02038faSJohn Youn chan->halt_on_queue = 1; 1049b02038faSJohn Youn } 1050b02038faSJohn Youn 1051b02038faSJohn Youn if (dbg_hc(chan)) { 1052b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, 1053b02038faSJohn Youn chan->hc_num); 1054b02038faSJohn Youn dev_vdbg(hsotg->dev, " hcchar: 0x%08x\n", 1055b02038faSJohn Youn hcchar); 1056b02038faSJohn Youn dev_vdbg(hsotg->dev, " halt_pending: %d\n", 1057b02038faSJohn Youn chan->halt_pending); 1058b02038faSJohn Youn dev_vdbg(hsotg->dev, " halt_on_queue: %d\n", 1059b02038faSJohn Youn chan->halt_on_queue); 1060b02038faSJohn Youn dev_vdbg(hsotg->dev, " halt_status: %d\n", 1061b02038faSJohn Youn chan->halt_status); 1062b02038faSJohn Youn } 1063b02038faSJohn Youn } 1064b02038faSJohn Youn 1065b02038faSJohn Youn /** 1066b02038faSJohn Youn * dwc2_hc_cleanup() - Clears the transfer state for a host channel 1067b02038faSJohn Youn * 1068b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1069b02038faSJohn Youn * @chan: Identifies the host channel to clean up 1070b02038faSJohn Youn * 1071b02038faSJohn Youn * This function is normally called after a transfer is done and the host 1072b02038faSJohn Youn * channel is being released 1073b02038faSJohn Youn */ 1074b02038faSJohn Youn void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) 1075b02038faSJohn Youn { 1076b02038faSJohn Youn u32 hcintmsk; 1077b02038faSJohn Youn 1078b02038faSJohn Youn chan->xfer_started = 0; 1079b02038faSJohn Youn 1080b02038faSJohn Youn list_del_init(&chan->split_order_list_entry); 1081b02038faSJohn Youn 1082b02038faSJohn Youn /* 1083b02038faSJohn Youn * Clear channel interrupt enables and any unhandled channel interrupt 1084b02038faSJohn Youn * conditions 1085b02038faSJohn Youn */ 1086b02038faSJohn Youn dwc2_writel(0, hsotg->regs + HCINTMSK(chan->hc_num)); 1087b02038faSJohn Youn hcintmsk = 0xffffffff; 1088b02038faSJohn Youn hcintmsk &= ~HCINTMSK_RESERVED14_31; 1089b02038faSJohn Youn dwc2_writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num)); 1090b02038faSJohn Youn } 1091b02038faSJohn Youn 1092b02038faSJohn Youn /** 1093b02038faSJohn Youn * dwc2_hc_set_even_odd_frame() - Sets the channel property that indicates in 1094b02038faSJohn Youn * which frame a periodic transfer should occur 1095b02038faSJohn Youn * 1096b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1097b02038faSJohn Youn * @chan: Identifies the host channel to set up and its properties 1098b02038faSJohn Youn * @hcchar: Current value of the HCCHAR register for the specified host channel 1099b02038faSJohn Youn * 1100b02038faSJohn Youn * This function has no effect on non-periodic transfers 1101b02038faSJohn Youn */ 1102b02038faSJohn Youn static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg, 1103b02038faSJohn Youn struct dwc2_host_chan *chan, u32 *hcchar) 1104b02038faSJohn Youn { 1105b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1106b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_ISOC) { 1107b02038faSJohn Youn int host_speed; 1108b02038faSJohn Youn int xfer_ns; 1109b02038faSJohn Youn int xfer_us; 1110b02038faSJohn Youn int bytes_in_fifo; 1111b02038faSJohn Youn u16 fifo_space; 1112b02038faSJohn Youn u16 frame_number; 1113b02038faSJohn Youn u16 wire_frame; 1114b02038faSJohn Youn 1115b02038faSJohn Youn /* 1116b02038faSJohn Youn * Try to figure out if we're an even or odd frame. If we set 1117b02038faSJohn Youn * even and the current frame number is even the the transfer 1118b02038faSJohn Youn * will happen immediately. Similar if both are odd. If one is 1119b02038faSJohn Youn * even and the other is odd then the transfer will happen when 1120b02038faSJohn Youn * the frame number ticks. 1121b02038faSJohn Youn * 1122b02038faSJohn Youn * There's a bit of a balancing act to get this right. 1123b02038faSJohn Youn * Sometimes we may want to send data in the current frame (AK 1124b02038faSJohn Youn * right away). We might want to do this if the frame number 1125b02038faSJohn Youn * _just_ ticked, but we might also want to do this in order 1126b02038faSJohn Youn * to continue a split transaction that happened late in a 1127b02038faSJohn Youn * microframe (so we didn't know to queue the next transfer 1128b02038faSJohn Youn * until the frame number had ticked). The problem is that we 1129b02038faSJohn Youn * need a lot of knowledge to know if there's actually still 1130b02038faSJohn Youn * time to send things or if it would be better to wait until 1131b02038faSJohn Youn * the next frame. 1132b02038faSJohn Youn * 1133b02038faSJohn Youn * We can look at how much time is left in the current frame 1134b02038faSJohn Youn * and make a guess about whether we'll have time to transfer. 1135b02038faSJohn Youn * We'll do that. 1136b02038faSJohn Youn */ 1137b02038faSJohn Youn 1138b02038faSJohn Youn /* Get speed host is running at */ 1139b02038faSJohn Youn host_speed = (chan->speed != USB_SPEED_HIGH && 1140b02038faSJohn Youn !chan->do_split) ? chan->speed : USB_SPEED_HIGH; 1141b02038faSJohn Youn 1142b02038faSJohn Youn /* See how many bytes are in the periodic FIFO right now */ 1143b02038faSJohn Youn fifo_space = (dwc2_readl(hsotg->regs + HPTXSTS) & 1144b02038faSJohn Youn TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT; 1145b02038faSJohn Youn bytes_in_fifo = sizeof(u32) * 1146bea8e86cSJohn Youn (hsotg->params.host_perio_tx_fifo_size - 1147b02038faSJohn Youn fifo_space); 1148b02038faSJohn Youn 1149b02038faSJohn Youn /* 1150b02038faSJohn Youn * Roughly estimate bus time for everything in the periodic 1151b02038faSJohn Youn * queue + our new transfer. This is "rough" because we're 1152b02038faSJohn Youn * using a function that makes takes into account IN/OUT 1153b02038faSJohn Youn * and INT/ISO and we're just slamming in one value for all 1154b02038faSJohn Youn * transfers. This should be an over-estimate and that should 1155b02038faSJohn Youn * be OK, but we can probably tighten it. 1156b02038faSJohn Youn */ 1157b02038faSJohn Youn xfer_ns = usb_calc_bus_time(host_speed, false, false, 1158b02038faSJohn Youn chan->xfer_len + bytes_in_fifo); 1159b02038faSJohn Youn xfer_us = NS_TO_US(xfer_ns); 1160b02038faSJohn Youn 1161b02038faSJohn Youn /* See what frame number we'll be at by the time we finish */ 1162b02038faSJohn Youn frame_number = dwc2_hcd_get_future_frame_number(hsotg, xfer_us); 1163b02038faSJohn Youn 1164b02038faSJohn Youn /* This is when we were scheduled to be on the wire */ 1165b02038faSJohn Youn wire_frame = dwc2_frame_num_inc(chan->qh->next_active_frame, 1); 1166b02038faSJohn Youn 1167b02038faSJohn Youn /* 1168b02038faSJohn Youn * If we'd finish _after_ the frame we're scheduled in then 1169b02038faSJohn Youn * it's hopeless. Just schedule right away and hope for the 1170b02038faSJohn Youn * best. Note that it _might_ be wise to call back into the 1171b02038faSJohn Youn * scheduler to pick a better frame, but this is better than 1172b02038faSJohn Youn * nothing. 1173b02038faSJohn Youn */ 1174b02038faSJohn Youn if (dwc2_frame_num_gt(frame_number, wire_frame)) { 1175b02038faSJohn Youn dwc2_sch_vdbg(hsotg, 1176b02038faSJohn Youn "QH=%p EO MISS fr=%04x=>%04x (%+d)\n", 1177b02038faSJohn Youn chan->qh, wire_frame, frame_number, 1178b02038faSJohn Youn dwc2_frame_num_dec(frame_number, 1179b02038faSJohn Youn wire_frame)); 1180b02038faSJohn Youn wire_frame = frame_number; 1181b02038faSJohn Youn 1182b02038faSJohn Youn /* 1183b02038faSJohn Youn * We picked a different frame number; communicate this 1184b02038faSJohn Youn * back to the scheduler so it doesn't try to schedule 1185b02038faSJohn Youn * another in the same frame. 1186b02038faSJohn Youn * 1187b02038faSJohn Youn * Remember that next_active_frame is 1 before the wire 1188b02038faSJohn Youn * frame. 1189b02038faSJohn Youn */ 1190b02038faSJohn Youn chan->qh->next_active_frame = 1191b02038faSJohn Youn dwc2_frame_num_dec(frame_number, 1); 1192b02038faSJohn Youn } 1193b02038faSJohn Youn 1194b02038faSJohn Youn if (wire_frame & 1) 1195b02038faSJohn Youn *hcchar |= HCCHAR_ODDFRM; 1196b02038faSJohn Youn else 1197b02038faSJohn Youn *hcchar &= ~HCCHAR_ODDFRM; 1198b02038faSJohn Youn } 1199b02038faSJohn Youn } 1200b02038faSJohn Youn 1201b02038faSJohn Youn static void dwc2_set_pid_isoc(struct dwc2_host_chan *chan) 1202b02038faSJohn Youn { 1203b02038faSJohn Youn /* Set up the initial PID for the transfer */ 1204b02038faSJohn Youn if (chan->speed == USB_SPEED_HIGH) { 1205b02038faSJohn Youn if (chan->ep_is_in) { 1206b02038faSJohn Youn if (chan->multi_count == 1) 1207b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_DATA0; 1208b02038faSJohn Youn else if (chan->multi_count == 2) 1209b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_DATA1; 1210b02038faSJohn Youn else 1211b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_DATA2; 1212b02038faSJohn Youn } else { 1213b02038faSJohn Youn if (chan->multi_count == 1) 1214b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_DATA0; 1215b02038faSJohn Youn else 1216b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_MDATA; 1217b02038faSJohn Youn } 1218b02038faSJohn Youn } else { 1219b02038faSJohn Youn chan->data_pid_start = DWC2_HC_PID_DATA0; 1220b02038faSJohn Youn } 1221b02038faSJohn Youn } 1222b02038faSJohn Youn 1223b02038faSJohn Youn /** 1224b02038faSJohn Youn * dwc2_hc_write_packet() - Writes a packet into the Tx FIFO associated with 1225b02038faSJohn Youn * the Host Channel 1226b02038faSJohn Youn * 1227b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1228b02038faSJohn Youn * @chan: Information needed to initialize the host channel 1229b02038faSJohn Youn * 1230b02038faSJohn Youn * This function should only be called in Slave mode. For a channel associated 1231b02038faSJohn Youn * with a non-periodic EP, the non-periodic Tx FIFO is written. For a channel 1232b02038faSJohn Youn * associated with a periodic EP, the periodic Tx FIFO is written. 1233b02038faSJohn Youn * 1234b02038faSJohn Youn * Upon return the xfer_buf and xfer_count fields in chan are incremented by 1235b02038faSJohn Youn * the number of bytes written to the Tx FIFO. 1236b02038faSJohn Youn */ 1237b02038faSJohn Youn static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, 1238b02038faSJohn Youn struct dwc2_host_chan *chan) 1239b02038faSJohn Youn { 1240b02038faSJohn Youn u32 i; 1241b02038faSJohn Youn u32 remaining_count; 1242b02038faSJohn Youn u32 byte_count; 1243b02038faSJohn Youn u32 dword_count; 1244b02038faSJohn Youn u32 __iomem *data_fifo; 1245b02038faSJohn Youn u32 *data_buf = (u32 *)chan->xfer_buf; 1246b02038faSJohn Youn 1247b02038faSJohn Youn if (dbg_hc(chan)) 1248b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s()\n", __func__); 1249b02038faSJohn Youn 1250b02038faSJohn Youn data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num)); 1251b02038faSJohn Youn 1252b02038faSJohn Youn remaining_count = chan->xfer_len - chan->xfer_count; 1253b02038faSJohn Youn if (remaining_count > chan->max_packet) 1254b02038faSJohn Youn byte_count = chan->max_packet; 1255b02038faSJohn Youn else 1256b02038faSJohn Youn byte_count = remaining_count; 1257b02038faSJohn Youn 1258b02038faSJohn Youn dword_count = (byte_count + 3) / 4; 1259b02038faSJohn Youn 1260b02038faSJohn Youn if (((unsigned long)data_buf & 0x3) == 0) { 1261b02038faSJohn Youn /* xfer_buf is DWORD aligned */ 1262b02038faSJohn Youn for (i = 0; i < dword_count; i++, data_buf++) 1263b02038faSJohn Youn dwc2_writel(*data_buf, data_fifo); 1264b02038faSJohn Youn } else { 1265b02038faSJohn Youn /* xfer_buf is not DWORD aligned */ 1266b02038faSJohn Youn for (i = 0; i < dword_count; i++, data_buf++) { 1267b02038faSJohn Youn u32 data = data_buf[0] | data_buf[1] << 8 | 1268b02038faSJohn Youn data_buf[2] << 16 | data_buf[3] << 24; 1269b02038faSJohn Youn dwc2_writel(data, data_fifo); 1270b02038faSJohn Youn } 1271b02038faSJohn Youn } 1272b02038faSJohn Youn 1273b02038faSJohn Youn chan->xfer_count += byte_count; 1274b02038faSJohn Youn chan->xfer_buf += byte_count; 1275b02038faSJohn Youn } 1276b02038faSJohn Youn 1277b02038faSJohn Youn /** 1278b02038faSJohn Youn * dwc2_hc_do_ping() - Starts a PING transfer 1279b02038faSJohn Youn * 1280b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1281b02038faSJohn Youn * @chan: Information needed to initialize the host channel 1282b02038faSJohn Youn * 1283b02038faSJohn Youn * This function should only be called in Slave mode. The Do Ping bit is set in 1284b02038faSJohn Youn * the HCTSIZ register, then the channel is enabled. 1285b02038faSJohn Youn */ 1286b02038faSJohn Youn static void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, 1287b02038faSJohn Youn struct dwc2_host_chan *chan) 1288b02038faSJohn Youn { 1289b02038faSJohn Youn u32 hcchar; 1290b02038faSJohn Youn u32 hctsiz; 1291b02038faSJohn Youn 1292b02038faSJohn Youn if (dbg_hc(chan)) 1293b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, 1294b02038faSJohn Youn chan->hc_num); 1295b02038faSJohn Youn 1296b02038faSJohn Youn hctsiz = TSIZ_DOPNG; 1297b02038faSJohn Youn hctsiz |= 1 << TSIZ_PKTCNT_SHIFT; 1298b02038faSJohn Youn dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); 1299b02038faSJohn Youn 1300b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 1301b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1302b02038faSJohn Youn hcchar &= ~HCCHAR_CHDIS; 1303b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); 1304b02038faSJohn Youn } 1305b02038faSJohn Youn 1306b02038faSJohn Youn /** 1307b02038faSJohn Youn * dwc2_hc_start_transfer() - Does the setup for a data transfer for a host 1308b02038faSJohn Youn * channel and starts the transfer 1309b02038faSJohn Youn * 1310b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1311b02038faSJohn Youn * @chan: Information needed to initialize the host channel. The xfer_len value 1312b02038faSJohn Youn * may be reduced to accommodate the max widths of the XferSize and 1313b02038faSJohn Youn * PktCnt fields in the HCTSIZn register. The multi_count value may be 1314b02038faSJohn Youn * changed to reflect the final xfer_len value. 1315b02038faSJohn Youn * 1316b02038faSJohn Youn * This function may be called in either Slave mode or DMA mode. In Slave mode, 1317b02038faSJohn Youn * the caller must ensure that there is sufficient space in the request queue 1318b02038faSJohn Youn * and Tx Data FIFO. 1319b02038faSJohn Youn * 1320b02038faSJohn Youn * For an OUT transfer in Slave mode, it loads a data packet into the 1321b02038faSJohn Youn * appropriate FIFO. If necessary, additional data packets are loaded in the 1322b02038faSJohn Youn * Host ISR. 1323b02038faSJohn Youn * 1324b02038faSJohn Youn * For an IN transfer in Slave mode, a data packet is requested. The data 1325b02038faSJohn Youn * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, 1326b02038faSJohn Youn * additional data packets are requested in the Host ISR. 1327b02038faSJohn Youn * 1328b02038faSJohn Youn * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ 1329b02038faSJohn Youn * register along with a packet count of 1 and the channel is enabled. This 1330b02038faSJohn Youn * causes a single PING transaction to occur. Other fields in HCTSIZ are 1331b02038faSJohn Youn * simply set to 0 since no data transfer occurs in this case. 1332b02038faSJohn Youn * 1333b02038faSJohn Youn * For a PING transfer in DMA mode, the HCTSIZ register is initialized with 1334b02038faSJohn Youn * all the information required to perform the subsequent data transfer. In 1335b02038faSJohn Youn * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the 1336b02038faSJohn Youn * controller performs the entire PING protocol, then starts the data 1337b02038faSJohn Youn * transfer. 1338b02038faSJohn Youn */ 1339b02038faSJohn Youn static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, 1340b02038faSJohn Youn struct dwc2_host_chan *chan) 1341b02038faSJohn Youn { 1342bea8e86cSJohn Youn u32 max_hc_xfer_size = hsotg->params.max_transfer_size; 1343bea8e86cSJohn Youn u16 max_hc_pkt_count = hsotg->params.max_packet_count; 1344b02038faSJohn Youn u32 hcchar; 1345b02038faSJohn Youn u32 hctsiz = 0; 1346b02038faSJohn Youn u16 num_packets; 1347b02038faSJohn Youn u32 ec_mc; 1348b02038faSJohn Youn 1349b02038faSJohn Youn if (dbg_hc(chan)) 1350b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s()\n", __func__); 1351b02038faSJohn Youn 1352b02038faSJohn Youn if (chan->do_ping) { 1353*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) { 1354b02038faSJohn Youn if (dbg_hc(chan)) 1355b02038faSJohn Youn dev_vdbg(hsotg->dev, "ping, no DMA\n"); 1356b02038faSJohn Youn dwc2_hc_do_ping(hsotg, chan); 1357b02038faSJohn Youn chan->xfer_started = 1; 1358b02038faSJohn Youn return; 1359b02038faSJohn Youn } 1360b02038faSJohn Youn 1361b02038faSJohn Youn if (dbg_hc(chan)) 1362b02038faSJohn Youn dev_vdbg(hsotg->dev, "ping, DMA\n"); 1363b02038faSJohn Youn 1364b02038faSJohn Youn hctsiz |= TSIZ_DOPNG; 1365b02038faSJohn Youn } 1366b02038faSJohn Youn 1367b02038faSJohn Youn if (chan->do_split) { 1368b02038faSJohn Youn if (dbg_hc(chan)) 1369b02038faSJohn Youn dev_vdbg(hsotg->dev, "split\n"); 1370b02038faSJohn Youn num_packets = 1; 1371b02038faSJohn Youn 1372b02038faSJohn Youn if (chan->complete_split && !chan->ep_is_in) 1373b02038faSJohn Youn /* 1374b02038faSJohn Youn * For CSPLIT OUT Transfer, set the size to 0 so the 1375b02038faSJohn Youn * core doesn't expect any data written to the FIFO 1376b02038faSJohn Youn */ 1377b02038faSJohn Youn chan->xfer_len = 0; 1378b02038faSJohn Youn else if (chan->ep_is_in || chan->xfer_len > chan->max_packet) 1379b02038faSJohn Youn chan->xfer_len = chan->max_packet; 1380b02038faSJohn Youn else if (!chan->ep_is_in && chan->xfer_len > 188) 1381b02038faSJohn Youn chan->xfer_len = 188; 1382b02038faSJohn Youn 1383b02038faSJohn Youn hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT & 1384b02038faSJohn Youn TSIZ_XFERSIZE_MASK; 1385b02038faSJohn Youn 1386b02038faSJohn Youn /* For split set ec_mc for immediate retries */ 1387b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1388b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_ISOC) 1389b02038faSJohn Youn ec_mc = 3; 1390b02038faSJohn Youn else 1391b02038faSJohn Youn ec_mc = 1; 1392b02038faSJohn Youn } else { 1393b02038faSJohn Youn if (dbg_hc(chan)) 1394b02038faSJohn Youn dev_vdbg(hsotg->dev, "no split\n"); 1395b02038faSJohn Youn /* 1396b02038faSJohn Youn * Ensure that the transfer length and packet count will fit 1397b02038faSJohn Youn * in the widths allocated for them in the HCTSIZn register 1398b02038faSJohn Youn */ 1399b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1400b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_ISOC) { 1401b02038faSJohn Youn /* 1402b02038faSJohn Youn * Make sure the transfer size is no larger than one 1403b02038faSJohn Youn * (micro)frame's worth of data. (A check was done 1404b02038faSJohn Youn * when the periodic transfer was accepted to ensure 1405b02038faSJohn Youn * that a (micro)frame's worth of data can be 1406b02038faSJohn Youn * programmed into a channel.) 1407b02038faSJohn Youn */ 1408b02038faSJohn Youn u32 max_periodic_len = 1409b02038faSJohn Youn chan->multi_count * chan->max_packet; 1410b02038faSJohn Youn 1411b02038faSJohn Youn if (chan->xfer_len > max_periodic_len) 1412b02038faSJohn Youn chan->xfer_len = max_periodic_len; 1413b02038faSJohn Youn } else if (chan->xfer_len > max_hc_xfer_size) { 1414b02038faSJohn Youn /* 1415b02038faSJohn Youn * Make sure that xfer_len is a multiple of max packet 1416b02038faSJohn Youn * size 1417b02038faSJohn Youn */ 1418b02038faSJohn Youn chan->xfer_len = 1419b02038faSJohn Youn max_hc_xfer_size - chan->max_packet + 1; 1420b02038faSJohn Youn } 1421b02038faSJohn Youn 1422b02038faSJohn Youn if (chan->xfer_len > 0) { 1423b02038faSJohn Youn num_packets = (chan->xfer_len + chan->max_packet - 1) / 1424b02038faSJohn Youn chan->max_packet; 1425b02038faSJohn Youn if (num_packets > max_hc_pkt_count) { 1426b02038faSJohn Youn num_packets = max_hc_pkt_count; 1427b02038faSJohn Youn chan->xfer_len = num_packets * chan->max_packet; 1428b02038faSJohn Youn } 1429b02038faSJohn Youn } else { 1430b02038faSJohn Youn /* Need 1 packet for transfer length of 0 */ 1431b02038faSJohn Youn num_packets = 1; 1432b02038faSJohn Youn } 1433b02038faSJohn Youn 1434b02038faSJohn Youn if (chan->ep_is_in) 1435b02038faSJohn Youn /* 1436b02038faSJohn Youn * Always program an integral # of max packets for IN 1437b02038faSJohn Youn * transfers 1438b02038faSJohn Youn */ 1439b02038faSJohn Youn chan->xfer_len = num_packets * chan->max_packet; 1440b02038faSJohn Youn 1441b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1442b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_ISOC) 1443b02038faSJohn Youn /* 1444b02038faSJohn Youn * Make sure that the multi_count field matches the 1445b02038faSJohn Youn * actual transfer length 1446b02038faSJohn Youn */ 1447b02038faSJohn Youn chan->multi_count = num_packets; 1448b02038faSJohn Youn 1449b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) 1450b02038faSJohn Youn dwc2_set_pid_isoc(chan); 1451b02038faSJohn Youn 1452b02038faSJohn Youn hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT & 1453b02038faSJohn Youn TSIZ_XFERSIZE_MASK; 1454b02038faSJohn Youn 1455b02038faSJohn Youn /* The ec_mc gets the multi_count for non-split */ 1456b02038faSJohn Youn ec_mc = chan->multi_count; 1457b02038faSJohn Youn } 1458b02038faSJohn Youn 1459b02038faSJohn Youn chan->start_pkt_count = num_packets; 1460b02038faSJohn Youn hctsiz |= num_packets << TSIZ_PKTCNT_SHIFT & TSIZ_PKTCNT_MASK; 1461b02038faSJohn Youn hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT & 1462b02038faSJohn Youn TSIZ_SC_MC_PID_MASK; 1463b02038faSJohn Youn dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); 1464b02038faSJohn Youn if (dbg_hc(chan)) { 1465b02038faSJohn Youn dev_vdbg(hsotg->dev, "Wrote %08x to HCTSIZ(%d)\n", 1466b02038faSJohn Youn hctsiz, chan->hc_num); 1467b02038faSJohn Youn 1468b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, 1469b02038faSJohn Youn chan->hc_num); 1470b02038faSJohn Youn dev_vdbg(hsotg->dev, " Xfer Size: %d\n", 1471b02038faSJohn Youn (hctsiz & TSIZ_XFERSIZE_MASK) >> 1472b02038faSJohn Youn TSIZ_XFERSIZE_SHIFT); 1473b02038faSJohn Youn dev_vdbg(hsotg->dev, " Num Pkts: %d\n", 1474b02038faSJohn Youn (hctsiz & TSIZ_PKTCNT_MASK) >> 1475b02038faSJohn Youn TSIZ_PKTCNT_SHIFT); 1476b02038faSJohn Youn dev_vdbg(hsotg->dev, " Start PID: %d\n", 1477b02038faSJohn Youn (hctsiz & TSIZ_SC_MC_PID_MASK) >> 1478b02038faSJohn Youn TSIZ_SC_MC_PID_SHIFT); 1479b02038faSJohn Youn } 1480b02038faSJohn Youn 1481*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 1482b02038faSJohn Youn dwc2_writel((u32)chan->xfer_dma, 1483b02038faSJohn Youn hsotg->regs + HCDMA(chan->hc_num)); 1484b02038faSJohn Youn if (dbg_hc(chan)) 1485b02038faSJohn Youn dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n", 1486b02038faSJohn Youn (unsigned long)chan->xfer_dma, chan->hc_num); 1487b02038faSJohn Youn } 1488b02038faSJohn Youn 1489b02038faSJohn Youn /* Start the split */ 1490b02038faSJohn Youn if (chan->do_split) { 1491b02038faSJohn Youn u32 hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num)); 1492b02038faSJohn Youn 1493b02038faSJohn Youn hcsplt |= HCSPLT_SPLTENA; 1494b02038faSJohn Youn dwc2_writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num)); 1495b02038faSJohn Youn } 1496b02038faSJohn Youn 1497b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 1498b02038faSJohn Youn hcchar &= ~HCCHAR_MULTICNT_MASK; 1499b02038faSJohn Youn hcchar |= (ec_mc << HCCHAR_MULTICNT_SHIFT) & HCCHAR_MULTICNT_MASK; 1500b02038faSJohn Youn dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar); 1501b02038faSJohn Youn 1502b02038faSJohn Youn if (hcchar & HCCHAR_CHDIS) 1503b02038faSJohn Youn dev_warn(hsotg->dev, 1504b02038faSJohn Youn "%s: chdis set, channel %d, hcchar 0x%08x\n", 1505b02038faSJohn Youn __func__, chan->hc_num, hcchar); 1506b02038faSJohn Youn 1507b02038faSJohn Youn /* Set host channel enable after all other setup is complete */ 1508b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1509b02038faSJohn Youn hcchar &= ~HCCHAR_CHDIS; 1510b02038faSJohn Youn 1511b02038faSJohn Youn if (dbg_hc(chan)) 1512b02038faSJohn Youn dev_vdbg(hsotg->dev, " Multi Cnt: %d\n", 1513b02038faSJohn Youn (hcchar & HCCHAR_MULTICNT_MASK) >> 1514b02038faSJohn Youn HCCHAR_MULTICNT_SHIFT); 1515b02038faSJohn Youn 1516b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); 1517b02038faSJohn Youn if (dbg_hc(chan)) 1518b02038faSJohn Youn dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar, 1519b02038faSJohn Youn chan->hc_num); 1520b02038faSJohn Youn 1521b02038faSJohn Youn chan->xfer_started = 1; 1522b02038faSJohn Youn chan->requests++; 1523b02038faSJohn Youn 1524*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0 && 1525b02038faSJohn Youn !chan->ep_is_in && chan->xfer_len > 0) 1526b02038faSJohn Youn /* Load OUT packet into the appropriate Tx FIFO */ 1527b02038faSJohn Youn dwc2_hc_write_packet(hsotg, chan); 1528b02038faSJohn Youn } 1529b02038faSJohn Youn 1530b02038faSJohn Youn /** 1531b02038faSJohn Youn * dwc2_hc_start_transfer_ddma() - Does the setup for a data transfer for a 1532b02038faSJohn Youn * host channel and starts the transfer in Descriptor DMA mode 1533b02038faSJohn Youn * 1534b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1535b02038faSJohn Youn * @chan: Information needed to initialize the host channel 1536b02038faSJohn Youn * 1537b02038faSJohn Youn * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. 1538b02038faSJohn Youn * Sets PID and NTD values. For periodic transfers initializes SCHED_INFO field 1539b02038faSJohn Youn * with micro-frame bitmap. 1540b02038faSJohn Youn * 1541b02038faSJohn Youn * Initializes HCDMA register with descriptor list address and CTD value then 1542b02038faSJohn Youn * starts the transfer via enabling the channel. 1543b02038faSJohn Youn */ 1544b02038faSJohn Youn void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg, 1545b02038faSJohn Youn struct dwc2_host_chan *chan) 1546b02038faSJohn Youn { 1547b02038faSJohn Youn u32 hcchar; 1548b02038faSJohn Youn u32 hctsiz = 0; 1549b02038faSJohn Youn 1550b02038faSJohn Youn if (chan->do_ping) 1551b02038faSJohn Youn hctsiz |= TSIZ_DOPNG; 1552b02038faSJohn Youn 1553b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) 1554b02038faSJohn Youn dwc2_set_pid_isoc(chan); 1555b02038faSJohn Youn 1556b02038faSJohn Youn /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ 1557b02038faSJohn Youn hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT & 1558b02038faSJohn Youn TSIZ_SC_MC_PID_MASK; 1559b02038faSJohn Youn 1560b02038faSJohn Youn /* 0 - 1 descriptor, 1 - 2 descriptors, etc */ 1561b02038faSJohn Youn hctsiz |= (chan->ntd - 1) << TSIZ_NTD_SHIFT & TSIZ_NTD_MASK; 1562b02038faSJohn Youn 1563b02038faSJohn Youn /* Non-zero only for high-speed interrupt endpoints */ 1564b02038faSJohn Youn hctsiz |= chan->schinfo << TSIZ_SCHINFO_SHIFT & TSIZ_SCHINFO_MASK; 1565b02038faSJohn Youn 1566b02038faSJohn Youn if (dbg_hc(chan)) { 1567b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, 1568b02038faSJohn Youn chan->hc_num); 1569b02038faSJohn Youn dev_vdbg(hsotg->dev, " Start PID: %d\n", 1570b02038faSJohn Youn chan->data_pid_start); 1571b02038faSJohn Youn dev_vdbg(hsotg->dev, " NTD: %d\n", chan->ntd - 1); 1572b02038faSJohn Youn } 1573b02038faSJohn Youn 1574b02038faSJohn Youn dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num)); 1575b02038faSJohn Youn 1576b02038faSJohn Youn dma_sync_single_for_device(hsotg->dev, chan->desc_list_addr, 1577b02038faSJohn Youn chan->desc_list_sz, DMA_TO_DEVICE); 1578b02038faSJohn Youn 1579b02038faSJohn Youn dwc2_writel(chan->desc_list_addr, hsotg->regs + HCDMA(chan->hc_num)); 1580b02038faSJohn Youn 1581b02038faSJohn Youn if (dbg_hc(chan)) 1582b02038faSJohn Youn dev_vdbg(hsotg->dev, "Wrote %pad to HCDMA(%d)\n", 1583b02038faSJohn Youn &chan->desc_list_addr, chan->hc_num); 1584b02038faSJohn Youn 1585b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 1586b02038faSJohn Youn hcchar &= ~HCCHAR_MULTICNT_MASK; 1587b02038faSJohn Youn hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT & 1588b02038faSJohn Youn HCCHAR_MULTICNT_MASK; 1589b02038faSJohn Youn 1590b02038faSJohn Youn if (hcchar & HCCHAR_CHDIS) 1591b02038faSJohn Youn dev_warn(hsotg->dev, 1592b02038faSJohn Youn "%s: chdis set, channel %d, hcchar 0x%08x\n", 1593b02038faSJohn Youn __func__, chan->hc_num, hcchar); 1594b02038faSJohn Youn 1595b02038faSJohn Youn /* Set host channel enable after all other setup is complete */ 1596b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1597b02038faSJohn Youn hcchar &= ~HCCHAR_CHDIS; 1598b02038faSJohn Youn 1599b02038faSJohn Youn if (dbg_hc(chan)) 1600b02038faSJohn Youn dev_vdbg(hsotg->dev, " Multi Cnt: %d\n", 1601b02038faSJohn Youn (hcchar & HCCHAR_MULTICNT_MASK) >> 1602b02038faSJohn Youn HCCHAR_MULTICNT_SHIFT); 1603b02038faSJohn Youn 1604b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); 1605b02038faSJohn Youn if (dbg_hc(chan)) 1606b02038faSJohn Youn dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar, 1607b02038faSJohn Youn chan->hc_num); 1608b02038faSJohn Youn 1609b02038faSJohn Youn chan->xfer_started = 1; 1610b02038faSJohn Youn chan->requests++; 1611b02038faSJohn Youn } 1612b02038faSJohn Youn 1613b02038faSJohn Youn /** 1614b02038faSJohn Youn * dwc2_hc_continue_transfer() - Continues a data transfer that was started by 1615b02038faSJohn Youn * a previous call to dwc2_hc_start_transfer() 1616b02038faSJohn Youn * 1617b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 1618b02038faSJohn Youn * @chan: Information needed to initialize the host channel 1619b02038faSJohn Youn * 1620b02038faSJohn Youn * The caller must ensure there is sufficient space in the request queue and Tx 1621b02038faSJohn Youn * Data FIFO. This function should only be called in Slave mode. In DMA mode, 1622b02038faSJohn Youn * the controller acts autonomously to complete transfers programmed to a host 1623b02038faSJohn Youn * channel. 1624b02038faSJohn Youn * 1625b02038faSJohn Youn * For an OUT transfer, a new data packet is loaded into the appropriate FIFO 1626b02038faSJohn Youn * if there is any data remaining to be queued. For an IN transfer, another 1627b02038faSJohn Youn * data packet is always requested. For the SETUP phase of a control transfer, 1628b02038faSJohn Youn * this function does nothing. 1629b02038faSJohn Youn * 1630b02038faSJohn Youn * Return: 1 if a new request is queued, 0 if no more requests are required 1631b02038faSJohn Youn * for this transfer 1632b02038faSJohn Youn */ 1633b02038faSJohn Youn static int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg, 1634b02038faSJohn Youn struct dwc2_host_chan *chan) 1635b02038faSJohn Youn { 1636b02038faSJohn Youn if (dbg_hc(chan)) 1637b02038faSJohn Youn dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, 1638b02038faSJohn Youn chan->hc_num); 1639b02038faSJohn Youn 1640b02038faSJohn Youn if (chan->do_split) 1641b02038faSJohn Youn /* SPLITs always queue just once per channel */ 1642b02038faSJohn Youn return 0; 1643b02038faSJohn Youn 1644b02038faSJohn Youn if (chan->data_pid_start == DWC2_HC_PID_SETUP) 1645b02038faSJohn Youn /* SETUPs are queued only once since they can't be NAK'd */ 1646b02038faSJohn Youn return 0; 1647b02038faSJohn Youn 1648b02038faSJohn Youn if (chan->ep_is_in) { 1649b02038faSJohn Youn /* 1650b02038faSJohn Youn * Always queue another request for other IN transfers. If 1651b02038faSJohn Youn * back-to-back INs are issued and NAKs are received for both, 1652b02038faSJohn Youn * the driver may still be processing the first NAK when the 1653b02038faSJohn Youn * second NAK is received. When the interrupt handler clears 1654b02038faSJohn Youn * the NAK interrupt for the first NAK, the second NAK will 1655b02038faSJohn Youn * not be seen. So we can't depend on the NAK interrupt 1656b02038faSJohn Youn * handler to requeue a NAK'd request. Instead, IN requests 1657b02038faSJohn Youn * are issued each time this function is called. When the 1658b02038faSJohn Youn * transfer completes, the extra requests for the channel will 1659b02038faSJohn Youn * be flushed. 1660b02038faSJohn Youn */ 1661b02038faSJohn Youn u32 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num)); 1662b02038faSJohn Youn 1663b02038faSJohn Youn dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar); 1664b02038faSJohn Youn hcchar |= HCCHAR_CHENA; 1665b02038faSJohn Youn hcchar &= ~HCCHAR_CHDIS; 1666b02038faSJohn Youn if (dbg_hc(chan)) 1667b02038faSJohn Youn dev_vdbg(hsotg->dev, " IN xfer: hcchar = 0x%08x\n", 1668b02038faSJohn Youn hcchar); 1669b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); 1670b02038faSJohn Youn chan->requests++; 1671b02038faSJohn Youn return 1; 1672b02038faSJohn Youn } 1673b02038faSJohn Youn 1674b02038faSJohn Youn /* OUT transfers */ 1675b02038faSJohn Youn 1676b02038faSJohn Youn if (chan->xfer_count < chan->xfer_len) { 1677b02038faSJohn Youn if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1678b02038faSJohn Youn chan->ep_type == USB_ENDPOINT_XFER_ISOC) { 1679b02038faSJohn Youn u32 hcchar = dwc2_readl(hsotg->regs + 1680b02038faSJohn Youn HCCHAR(chan->hc_num)); 1681b02038faSJohn Youn 1682b02038faSJohn Youn dwc2_hc_set_even_odd_frame(hsotg, chan, 1683b02038faSJohn Youn &hcchar); 1684b02038faSJohn Youn } 1685b02038faSJohn Youn 1686b02038faSJohn Youn /* Load OUT packet into the appropriate Tx FIFO */ 1687b02038faSJohn Youn dwc2_hc_write_packet(hsotg, chan); 1688b02038faSJohn Youn chan->requests++; 1689b02038faSJohn Youn return 1; 1690b02038faSJohn Youn } 1691b02038faSJohn Youn 1692b02038faSJohn Youn return 0; 1693b02038faSJohn Youn } 1694b02038faSJohn Youn 1695b02038faSJohn Youn /* 1696b02038faSJohn Youn * ========================================================================= 1697b02038faSJohn Youn * HCD 1698b02038faSJohn Youn * ========================================================================= 1699b02038faSJohn Youn */ 1700b02038faSJohn Youn 1701b02038faSJohn Youn /* 1702197ba5f4SPaul Zimmerman * Processes all the URBs in a single list of QHs. Completes them with 1703197ba5f4SPaul Zimmerman * -ETIMEDOUT and frees the QTD. 1704197ba5f4SPaul Zimmerman * 1705197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 1706197ba5f4SPaul Zimmerman */ 1707197ba5f4SPaul Zimmerman static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, 1708197ba5f4SPaul Zimmerman struct list_head *qh_list) 1709197ba5f4SPaul Zimmerman { 1710197ba5f4SPaul Zimmerman struct dwc2_qh *qh, *qh_tmp; 1711197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd, *qtd_tmp; 1712197ba5f4SPaul Zimmerman 1713197ba5f4SPaul Zimmerman list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) { 1714197ba5f4SPaul Zimmerman list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, 1715197ba5f4SPaul Zimmerman qtd_list_entry) { 17162e84da6eSGregory Herrero dwc2_host_complete(hsotg, qtd, -ECONNRESET); 1717197ba5f4SPaul Zimmerman dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); 1718197ba5f4SPaul Zimmerman } 1719197ba5f4SPaul Zimmerman } 1720197ba5f4SPaul Zimmerman } 1721197ba5f4SPaul Zimmerman 1722197ba5f4SPaul Zimmerman static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg, 1723197ba5f4SPaul Zimmerman struct list_head *qh_list) 1724197ba5f4SPaul Zimmerman { 1725197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd, *qtd_tmp; 1726197ba5f4SPaul Zimmerman struct dwc2_qh *qh, *qh_tmp; 1727197ba5f4SPaul Zimmerman unsigned long flags; 1728197ba5f4SPaul Zimmerman 1729197ba5f4SPaul Zimmerman if (!qh_list->next) 1730197ba5f4SPaul Zimmerman /* The list hasn't been initialized yet */ 1731197ba5f4SPaul Zimmerman return; 1732197ba5f4SPaul Zimmerman 1733197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 1734197ba5f4SPaul Zimmerman 1735197ba5f4SPaul Zimmerman /* Ensure there are no QTDs or URBs left */ 1736197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, qh_list); 1737197ba5f4SPaul Zimmerman 1738197ba5f4SPaul Zimmerman list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) { 1739197ba5f4SPaul Zimmerman dwc2_hcd_qh_unlink(hsotg, qh); 1740197ba5f4SPaul Zimmerman 1741197ba5f4SPaul Zimmerman /* Free each QTD in the QH's QTD list */ 1742197ba5f4SPaul Zimmerman list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, 1743197ba5f4SPaul Zimmerman qtd_list_entry) 1744197ba5f4SPaul Zimmerman dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); 1745197ba5f4SPaul Zimmerman 174616e80218SDouglas Anderson if (qh->channel && qh->channel->qh == qh) 174716e80218SDouglas Anderson qh->channel->qh = NULL; 174816e80218SDouglas Anderson 1749197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 1750197ba5f4SPaul Zimmerman dwc2_hcd_qh_free(hsotg, qh); 1751197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 1752197ba5f4SPaul Zimmerman } 1753197ba5f4SPaul Zimmerman 1754197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 1755197ba5f4SPaul Zimmerman } 1756197ba5f4SPaul Zimmerman 1757197ba5f4SPaul Zimmerman /* 1758197ba5f4SPaul Zimmerman * Responds with an error status of -ETIMEDOUT to all URBs in the non-periodic 1759197ba5f4SPaul Zimmerman * and periodic schedules. The QTD associated with each URB is removed from 1760197ba5f4SPaul Zimmerman * the schedule and freed. This function may be called when a disconnect is 1761197ba5f4SPaul Zimmerman * detected or when the HCD is being stopped. 1762197ba5f4SPaul Zimmerman * 1763197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 1764197ba5f4SPaul Zimmerman */ 1765197ba5f4SPaul Zimmerman static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg) 1766197ba5f4SPaul Zimmerman { 1767197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_inactive); 1768197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_active); 1769197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_inactive); 1770197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_ready); 1771197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_assigned); 1772197ba5f4SPaul Zimmerman dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_queued); 1773197ba5f4SPaul Zimmerman } 1774197ba5f4SPaul Zimmerman 1775197ba5f4SPaul Zimmerman /** 1776197ba5f4SPaul Zimmerman * dwc2_hcd_start() - Starts the HCD when switching to Host mode 1777197ba5f4SPaul Zimmerman * 1778197ba5f4SPaul Zimmerman * @hsotg: Pointer to struct dwc2_hsotg 1779197ba5f4SPaul Zimmerman */ 1780197ba5f4SPaul Zimmerman void dwc2_hcd_start(struct dwc2_hsotg *hsotg) 1781197ba5f4SPaul Zimmerman { 1782197ba5f4SPaul Zimmerman u32 hprt0; 1783197ba5f4SPaul Zimmerman 1784197ba5f4SPaul Zimmerman if (hsotg->op_state == OTG_STATE_B_HOST) { 1785197ba5f4SPaul Zimmerman /* 1786197ba5f4SPaul Zimmerman * Reset the port. During a HNP mode switch the reset 1787197ba5f4SPaul Zimmerman * needs to occur within 1ms and have a duration of at 1788197ba5f4SPaul Zimmerman * least 50ms. 1789197ba5f4SPaul Zimmerman */ 1790197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 1791197ba5f4SPaul Zimmerman hprt0 |= HPRT0_RST; 179295c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 1793197ba5f4SPaul Zimmerman } 1794197ba5f4SPaul Zimmerman 1795197ba5f4SPaul Zimmerman queue_delayed_work(hsotg->wq_otg, &hsotg->start_work, 1796197ba5f4SPaul Zimmerman msecs_to_jiffies(50)); 1797197ba5f4SPaul Zimmerman } 1798197ba5f4SPaul Zimmerman 1799197ba5f4SPaul Zimmerman /* Must be called with interrupt disabled and spinlock held */ 1800197ba5f4SPaul Zimmerman static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) 1801197ba5f4SPaul Zimmerman { 1802bea8e86cSJohn Youn int num_channels = hsotg->params.host_channels; 1803197ba5f4SPaul Zimmerman struct dwc2_host_chan *channel; 1804197ba5f4SPaul Zimmerman u32 hcchar; 1805197ba5f4SPaul Zimmerman int i; 1806197ba5f4SPaul Zimmerman 1807*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) { 1808197ba5f4SPaul Zimmerman /* Flush out any channel requests in slave mode */ 1809197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 1810197ba5f4SPaul Zimmerman channel = hsotg->hc_ptr_array[i]; 1811197ba5f4SPaul Zimmerman if (!list_empty(&channel->hc_list_entry)) 1812197ba5f4SPaul Zimmerman continue; 181395c8bc36SAntti Seppälä hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 1814197ba5f4SPaul Zimmerman if (hcchar & HCCHAR_CHENA) { 1815197ba5f4SPaul Zimmerman hcchar &= ~(HCCHAR_CHENA | HCCHAR_EPDIR); 1816197ba5f4SPaul Zimmerman hcchar |= HCCHAR_CHDIS; 181795c8bc36SAntti Seppälä dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); 1818197ba5f4SPaul Zimmerman } 1819197ba5f4SPaul Zimmerman } 1820197ba5f4SPaul Zimmerman } 1821197ba5f4SPaul Zimmerman 1822197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 1823197ba5f4SPaul Zimmerman channel = hsotg->hc_ptr_array[i]; 1824197ba5f4SPaul Zimmerman if (!list_empty(&channel->hc_list_entry)) 1825197ba5f4SPaul Zimmerman continue; 182695c8bc36SAntti Seppälä hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 1827197ba5f4SPaul Zimmerman if (hcchar & HCCHAR_CHENA) { 1828197ba5f4SPaul Zimmerman /* Halt the channel */ 1829197ba5f4SPaul Zimmerman hcchar |= HCCHAR_CHDIS; 183095c8bc36SAntti Seppälä dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); 1831197ba5f4SPaul Zimmerman } 1832197ba5f4SPaul Zimmerman 1833197ba5f4SPaul Zimmerman dwc2_hc_cleanup(hsotg, channel); 1834197ba5f4SPaul Zimmerman list_add_tail(&channel->hc_list_entry, &hsotg->free_hc_list); 1835197ba5f4SPaul Zimmerman /* 1836197ba5f4SPaul Zimmerman * Added for Descriptor DMA to prevent channel double cleanup in 1837197ba5f4SPaul Zimmerman * release_channel_ddma(), which is called from ep_disable when 1838197ba5f4SPaul Zimmerman * device disconnects 1839197ba5f4SPaul Zimmerman */ 1840197ba5f4SPaul Zimmerman channel->qh = NULL; 1841197ba5f4SPaul Zimmerman } 18427252f1bfSVincent Palatin /* All channels have been freed, mark them available */ 1843bea8e86cSJohn Youn if (hsotg->params.uframe_sched > 0) { 18447252f1bfSVincent Palatin hsotg->available_host_channels = 1845bea8e86cSJohn Youn hsotg->params.host_channels; 18467252f1bfSVincent Palatin } else { 18477252f1bfSVincent Palatin hsotg->non_periodic_channels = 0; 18487252f1bfSVincent Palatin hsotg->periodic_channels = 0; 18497252f1bfSVincent Palatin } 1850197ba5f4SPaul Zimmerman } 1851197ba5f4SPaul Zimmerman 1852197ba5f4SPaul Zimmerman /** 18536a659531SDouglas Anderson * dwc2_hcd_connect() - Handles connect of the HCD 1854197ba5f4SPaul Zimmerman * 1855197ba5f4SPaul Zimmerman * @hsotg: Pointer to struct dwc2_hsotg 1856197ba5f4SPaul Zimmerman * 1857197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 1858197ba5f4SPaul Zimmerman */ 18596a659531SDouglas Anderson void dwc2_hcd_connect(struct dwc2_hsotg *hsotg) 18606a659531SDouglas Anderson { 18616a659531SDouglas Anderson if (hsotg->lx_state != DWC2_L0) 18626a659531SDouglas Anderson usb_hcd_resume_root_hub(hsotg->priv); 18636a659531SDouglas Anderson 18646a659531SDouglas Anderson hsotg->flags.b.port_connect_status_change = 1; 18656a659531SDouglas Anderson hsotg->flags.b.port_connect_status = 1; 18666a659531SDouglas Anderson } 18676a659531SDouglas Anderson 18686a659531SDouglas Anderson /** 18696a659531SDouglas Anderson * dwc2_hcd_disconnect() - Handles disconnect of the HCD 18706a659531SDouglas Anderson * 18716a659531SDouglas Anderson * @hsotg: Pointer to struct dwc2_hsotg 18726a659531SDouglas Anderson * @force: If true, we won't try to reconnect even if we see device connected. 18736a659531SDouglas Anderson * 18746a659531SDouglas Anderson * Must be called with interrupt disabled and spinlock held 18756a659531SDouglas Anderson */ 18766a659531SDouglas Anderson void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) 1877197ba5f4SPaul Zimmerman { 1878197ba5f4SPaul Zimmerman u32 intr; 18796a659531SDouglas Anderson u32 hprt0; 1880197ba5f4SPaul Zimmerman 1881197ba5f4SPaul Zimmerman /* Set status flags for the hub driver */ 1882197ba5f4SPaul Zimmerman hsotg->flags.b.port_connect_status_change = 1; 1883197ba5f4SPaul Zimmerman hsotg->flags.b.port_connect_status = 0; 1884197ba5f4SPaul Zimmerman 1885197ba5f4SPaul Zimmerman /* 1886197ba5f4SPaul Zimmerman * Shutdown any transfers in process by clearing the Tx FIFO Empty 1887197ba5f4SPaul Zimmerman * interrupt mask and status bits and disabling subsequent host 1888197ba5f4SPaul Zimmerman * channel interrupts. 1889197ba5f4SPaul Zimmerman */ 189095c8bc36SAntti Seppälä intr = dwc2_readl(hsotg->regs + GINTMSK); 1891197ba5f4SPaul Zimmerman intr &= ~(GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT); 189295c8bc36SAntti Seppälä dwc2_writel(intr, hsotg->regs + GINTMSK); 1893197ba5f4SPaul Zimmerman intr = GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT; 189495c8bc36SAntti Seppälä dwc2_writel(intr, hsotg->regs + GINTSTS); 1895197ba5f4SPaul Zimmerman 1896197ba5f4SPaul Zimmerman /* 1897197ba5f4SPaul Zimmerman * Turn off the vbus power only if the core has transitioned to device 1898197ba5f4SPaul Zimmerman * mode. If still in host mode, need to keep power on to detect a 1899197ba5f4SPaul Zimmerman * reconnection. 1900197ba5f4SPaul Zimmerman */ 1901197ba5f4SPaul Zimmerman if (dwc2_is_device_mode(hsotg)) { 1902197ba5f4SPaul Zimmerman if (hsotg->op_state != OTG_STATE_A_SUSPEND) { 1903197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Disconnect: PortPower off\n"); 190495c8bc36SAntti Seppälä dwc2_writel(0, hsotg->regs + HPRT0); 1905197ba5f4SPaul Zimmerman } 1906197ba5f4SPaul Zimmerman 1907197ba5f4SPaul Zimmerman dwc2_disable_host_interrupts(hsotg); 1908197ba5f4SPaul Zimmerman } 1909197ba5f4SPaul Zimmerman 1910197ba5f4SPaul Zimmerman /* Respond with an error status to all URBs in the schedule */ 1911197ba5f4SPaul Zimmerman dwc2_kill_all_urbs(hsotg); 1912197ba5f4SPaul Zimmerman 1913197ba5f4SPaul Zimmerman if (dwc2_is_host_mode(hsotg)) 1914197ba5f4SPaul Zimmerman /* Clean up any host channels that were in use */ 1915197ba5f4SPaul Zimmerman dwc2_hcd_cleanup_channels(hsotg); 1916197ba5f4SPaul Zimmerman 1917197ba5f4SPaul Zimmerman dwc2_host_disconnect(hsotg); 19186a659531SDouglas Anderson 19196a659531SDouglas Anderson /* 19206a659531SDouglas Anderson * Add an extra check here to see if we're actually connected but 19216a659531SDouglas Anderson * we don't have a detection interrupt pending. This can happen if: 19226a659531SDouglas Anderson * 1. hardware sees connect 19236a659531SDouglas Anderson * 2. hardware sees disconnect 19246a659531SDouglas Anderson * 3. hardware sees connect 19256a659531SDouglas Anderson * 4. dwc2_port_intr() - clears connect interrupt 19266a659531SDouglas Anderson * 5. dwc2_handle_common_intr() - calls here 19276a659531SDouglas Anderson * 19286a659531SDouglas Anderson * Without the extra check here we will end calling disconnect 19296a659531SDouglas Anderson * and won't get any future interrupts to handle the connect. 19306a659531SDouglas Anderson */ 19316a659531SDouglas Anderson if (!force) { 19326a659531SDouglas Anderson hprt0 = dwc2_readl(hsotg->regs + HPRT0); 19336a659531SDouglas Anderson if (!(hprt0 & HPRT0_CONNDET) && (hprt0 & HPRT0_CONNSTS)) 19346a659531SDouglas Anderson dwc2_hcd_connect(hsotg); 19356a659531SDouglas Anderson } 1936197ba5f4SPaul Zimmerman } 1937197ba5f4SPaul Zimmerman 1938197ba5f4SPaul Zimmerman /** 1939197ba5f4SPaul Zimmerman * dwc2_hcd_rem_wakeup() - Handles Remote Wakeup 1940197ba5f4SPaul Zimmerman * 1941197ba5f4SPaul Zimmerman * @hsotg: Pointer to struct dwc2_hsotg 1942197ba5f4SPaul Zimmerman */ 1943197ba5f4SPaul Zimmerman static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) 1944197ba5f4SPaul Zimmerman { 19451fb7f12dSDouglas Anderson if (hsotg->bus_suspended) { 1946197ba5f4SPaul Zimmerman hsotg->flags.b.port_suspend_change = 1; 1947b46146d5SGregory Herrero usb_hcd_resume_root_hub(hsotg->priv); 1948197ba5f4SPaul Zimmerman } 19491fb7f12dSDouglas Anderson 19501fb7f12dSDouglas Anderson if (hsotg->lx_state == DWC2_L1) 19511fb7f12dSDouglas Anderson hsotg->flags.b.port_l1_change = 1; 1952b46146d5SGregory Herrero } 1953197ba5f4SPaul Zimmerman 1954197ba5f4SPaul Zimmerman /** 1955197ba5f4SPaul Zimmerman * dwc2_hcd_stop() - Halts the DWC_otg host mode operations in a clean manner 1956197ba5f4SPaul Zimmerman * 1957197ba5f4SPaul Zimmerman * @hsotg: Pointer to struct dwc2_hsotg 1958197ba5f4SPaul Zimmerman * 1959197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 1960197ba5f4SPaul Zimmerman */ 1961197ba5f4SPaul Zimmerman void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) 1962197ba5f4SPaul Zimmerman { 1963197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD STOP\n"); 1964197ba5f4SPaul Zimmerman 1965197ba5f4SPaul Zimmerman /* 1966197ba5f4SPaul Zimmerman * The root hub should be disconnected before this function is called. 1967197ba5f4SPaul Zimmerman * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) 1968197ba5f4SPaul Zimmerman * and the QH lists (via ..._hcd_endpoint_disable). 1969197ba5f4SPaul Zimmerman */ 1970197ba5f4SPaul Zimmerman 1971197ba5f4SPaul Zimmerman /* Turn off all host-specific interrupts */ 1972197ba5f4SPaul Zimmerman dwc2_disable_host_interrupts(hsotg); 1973197ba5f4SPaul Zimmerman 1974197ba5f4SPaul Zimmerman /* Turn off the vbus power */ 1975197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "PortPower off\n"); 197695c8bc36SAntti Seppälä dwc2_writel(0, hsotg->regs + HPRT0); 1977197ba5f4SPaul Zimmerman } 1978197ba5f4SPaul Zimmerman 197933ad261aSGregory Herrero /* Caller must hold driver lock */ 1980197ba5f4SPaul Zimmerman static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, 1981b58e6ceeSMian Yousaf Kaukab struct dwc2_hcd_urb *urb, struct dwc2_qh *qh, 1982b5a468a6SMian Yousaf Kaukab struct dwc2_qtd *qtd) 1983197ba5f4SPaul Zimmerman { 1984197ba5f4SPaul Zimmerman u32 intr_mask; 1985197ba5f4SPaul Zimmerman int retval; 1986197ba5f4SPaul Zimmerman int dev_speed; 1987197ba5f4SPaul Zimmerman 1988197ba5f4SPaul Zimmerman if (!hsotg->flags.b.port_connect_status) { 1989197ba5f4SPaul Zimmerman /* No longer connected */ 1990197ba5f4SPaul Zimmerman dev_err(hsotg->dev, "Not connected\n"); 1991197ba5f4SPaul Zimmerman return -ENODEV; 1992197ba5f4SPaul Zimmerman } 1993197ba5f4SPaul Zimmerman 1994197ba5f4SPaul Zimmerman dev_speed = dwc2_host_get_speed(hsotg, urb->priv); 1995197ba5f4SPaul Zimmerman 1996197ba5f4SPaul Zimmerman /* Some configurations cannot support LS traffic on a FS root port */ 1997197ba5f4SPaul Zimmerman if ((dev_speed == USB_SPEED_LOW) && 1998197ba5f4SPaul Zimmerman (hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) && 1999197ba5f4SPaul Zimmerman (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) { 200095c8bc36SAntti Seppälä u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0); 2001197ba5f4SPaul Zimmerman u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; 2002197ba5f4SPaul Zimmerman 2003197ba5f4SPaul Zimmerman if (prtspd == HPRT0_SPD_FULL_SPEED) 2004197ba5f4SPaul Zimmerman return -ENODEV; 2005197ba5f4SPaul Zimmerman } 2006197ba5f4SPaul Zimmerman 2007197ba5f4SPaul Zimmerman if (!qtd) 2008b5a468a6SMian Yousaf Kaukab return -EINVAL; 2009197ba5f4SPaul Zimmerman 2010197ba5f4SPaul Zimmerman dwc2_hcd_qtd_init(qtd, urb); 2011b58e6ceeSMian Yousaf Kaukab retval = dwc2_hcd_qtd_add(hsotg, qtd, qh); 2012197ba5f4SPaul Zimmerman if (retval) { 2013197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 2014197ba5f4SPaul Zimmerman "DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n", 2015197ba5f4SPaul Zimmerman retval); 2016197ba5f4SPaul Zimmerman return retval; 2017197ba5f4SPaul Zimmerman } 2018197ba5f4SPaul Zimmerman 201995c8bc36SAntti Seppälä intr_mask = dwc2_readl(hsotg->regs + GINTMSK); 2020197ba5f4SPaul Zimmerman if (!(intr_mask & GINTSTS_SOF)) { 2021197ba5f4SPaul Zimmerman enum dwc2_transaction_type tr_type; 2022197ba5f4SPaul Zimmerman 2023197ba5f4SPaul Zimmerman if (qtd->qh->ep_type == USB_ENDPOINT_XFER_BULK && 2024197ba5f4SPaul Zimmerman !(qtd->urb->flags & URB_GIVEBACK_ASAP)) 2025197ba5f4SPaul Zimmerman /* 2026197ba5f4SPaul Zimmerman * Do not schedule SG transactions until qtd has 2027197ba5f4SPaul Zimmerman * URB_GIVEBACK_ASAP set 2028197ba5f4SPaul Zimmerman */ 2029197ba5f4SPaul Zimmerman return 0; 2030197ba5f4SPaul Zimmerman 2031197ba5f4SPaul Zimmerman tr_type = dwc2_hcd_select_transactions(hsotg); 2032197ba5f4SPaul Zimmerman if (tr_type != DWC2_TRANSACTION_NONE) 2033197ba5f4SPaul Zimmerman dwc2_hcd_queue_transactions(hsotg, tr_type); 2034197ba5f4SPaul Zimmerman } 2035197ba5f4SPaul Zimmerman 2036197ba5f4SPaul Zimmerman return 0; 2037197ba5f4SPaul Zimmerman } 2038197ba5f4SPaul Zimmerman 2039197ba5f4SPaul Zimmerman /* Must be called with interrupt disabled and spinlock held */ 2040197ba5f4SPaul Zimmerman static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg, 2041197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb) 2042197ba5f4SPaul Zimmerman { 2043197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 2044197ba5f4SPaul Zimmerman struct dwc2_qtd *urb_qtd; 2045197ba5f4SPaul Zimmerman 2046197ba5f4SPaul Zimmerman urb_qtd = urb->qtd; 2047197ba5f4SPaul Zimmerman if (!urb_qtd) { 2048197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## Urb QTD is NULL ##\n"); 2049197ba5f4SPaul Zimmerman return -EINVAL; 2050197ba5f4SPaul Zimmerman } 2051197ba5f4SPaul Zimmerman 2052197ba5f4SPaul Zimmerman qh = urb_qtd->qh; 2053197ba5f4SPaul Zimmerman if (!qh) { 2054197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## Urb QTD QH is NULL ##\n"); 2055197ba5f4SPaul Zimmerman return -EINVAL; 2056197ba5f4SPaul Zimmerman } 2057197ba5f4SPaul Zimmerman 2058197ba5f4SPaul Zimmerman urb->priv = NULL; 2059197ba5f4SPaul Zimmerman 2060197ba5f4SPaul Zimmerman if (urb_qtd->in_process && qh->channel) { 2061197ba5f4SPaul Zimmerman dwc2_dump_channel_info(hsotg, qh->channel); 2062197ba5f4SPaul Zimmerman 2063197ba5f4SPaul Zimmerman /* The QTD is in process (it has been assigned to a channel) */ 2064197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_connect_status) 2065197ba5f4SPaul Zimmerman /* 2066197ba5f4SPaul Zimmerman * If still connected (i.e. in host mode), halt the 2067197ba5f4SPaul Zimmerman * channel so it can be used for other transfers. If 2068197ba5f4SPaul Zimmerman * no longer connected, the host registers can't be 2069197ba5f4SPaul Zimmerman * written to halt the channel since the core is in 2070197ba5f4SPaul Zimmerman * device mode. 2071197ba5f4SPaul Zimmerman */ 2072197ba5f4SPaul Zimmerman dwc2_hc_halt(hsotg, qh->channel, 2073197ba5f4SPaul Zimmerman DWC2_HC_XFER_URB_DEQUEUE); 2074197ba5f4SPaul Zimmerman } 2075197ba5f4SPaul Zimmerman 2076197ba5f4SPaul Zimmerman /* 2077197ba5f4SPaul Zimmerman * Free the QTD and clean up the associated QH. Leave the QH in the 2078197ba5f4SPaul Zimmerman * schedule if it has any remaining QTDs. 2079197ba5f4SPaul Zimmerman */ 2080bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable <= 0) { 2081197ba5f4SPaul Zimmerman u8 in_process = urb_qtd->in_process; 2082197ba5f4SPaul Zimmerman 2083197ba5f4SPaul Zimmerman dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh); 2084197ba5f4SPaul Zimmerman if (in_process) { 2085197ba5f4SPaul Zimmerman dwc2_hcd_qh_deactivate(hsotg, qh, 0); 2086197ba5f4SPaul Zimmerman qh->channel = NULL; 2087197ba5f4SPaul Zimmerman } else if (list_empty(&qh->qtd_list)) { 2088197ba5f4SPaul Zimmerman dwc2_hcd_qh_unlink(hsotg, qh); 2089197ba5f4SPaul Zimmerman } 2090197ba5f4SPaul Zimmerman } else { 2091197ba5f4SPaul Zimmerman dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh); 2092197ba5f4SPaul Zimmerman } 2093197ba5f4SPaul Zimmerman 2094197ba5f4SPaul Zimmerman return 0; 2095197ba5f4SPaul Zimmerman } 2096197ba5f4SPaul Zimmerman 2097197ba5f4SPaul Zimmerman /* Must NOT be called with interrupt disabled or spinlock held */ 2098197ba5f4SPaul Zimmerman static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg, 2099197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep, int retry) 2100197ba5f4SPaul Zimmerman { 2101197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd, *qtd_tmp; 2102197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 2103197ba5f4SPaul Zimmerman unsigned long flags; 2104197ba5f4SPaul Zimmerman int rc; 2105197ba5f4SPaul Zimmerman 2106197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 2107197ba5f4SPaul Zimmerman 2108197ba5f4SPaul Zimmerman qh = ep->hcpriv; 2109197ba5f4SPaul Zimmerman if (!qh) { 2110197ba5f4SPaul Zimmerman rc = -EINVAL; 2111197ba5f4SPaul Zimmerman goto err; 2112197ba5f4SPaul Zimmerman } 2113197ba5f4SPaul Zimmerman 2114197ba5f4SPaul Zimmerman while (!list_empty(&qh->qtd_list) && retry--) { 2115197ba5f4SPaul Zimmerman if (retry == 0) { 2116197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 2117197ba5f4SPaul Zimmerman "## timeout in dwc2_hcd_endpoint_disable() ##\n"); 2118197ba5f4SPaul Zimmerman rc = -EBUSY; 2119197ba5f4SPaul Zimmerman goto err; 2120197ba5f4SPaul Zimmerman } 2121197ba5f4SPaul Zimmerman 2122197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 2123197ba5f4SPaul Zimmerman usleep_range(20000, 40000); 2124197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 2125197ba5f4SPaul Zimmerman qh = ep->hcpriv; 2126197ba5f4SPaul Zimmerman if (!qh) { 2127197ba5f4SPaul Zimmerman rc = -EINVAL; 2128197ba5f4SPaul Zimmerman goto err; 2129197ba5f4SPaul Zimmerman } 2130197ba5f4SPaul Zimmerman } 2131197ba5f4SPaul Zimmerman 2132197ba5f4SPaul Zimmerman dwc2_hcd_qh_unlink(hsotg, qh); 2133197ba5f4SPaul Zimmerman 2134197ba5f4SPaul Zimmerman /* Free each QTD in the QH's QTD list */ 2135197ba5f4SPaul Zimmerman list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) 2136197ba5f4SPaul Zimmerman dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); 2137197ba5f4SPaul Zimmerman 2138197ba5f4SPaul Zimmerman ep->hcpriv = NULL; 213916e80218SDouglas Anderson 214016e80218SDouglas Anderson if (qh->channel && qh->channel->qh == qh) 214116e80218SDouglas Anderson qh->channel->qh = NULL; 214216e80218SDouglas Anderson 2143197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 214416e80218SDouglas Anderson 2145197ba5f4SPaul Zimmerman dwc2_hcd_qh_free(hsotg, qh); 2146197ba5f4SPaul Zimmerman 2147197ba5f4SPaul Zimmerman return 0; 2148197ba5f4SPaul Zimmerman 2149197ba5f4SPaul Zimmerman err: 2150197ba5f4SPaul Zimmerman ep->hcpriv = NULL; 2151197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 2152197ba5f4SPaul Zimmerman 2153197ba5f4SPaul Zimmerman return rc; 2154197ba5f4SPaul Zimmerman } 2155197ba5f4SPaul Zimmerman 2156197ba5f4SPaul Zimmerman /* Must be called with interrupt disabled and spinlock held */ 2157197ba5f4SPaul Zimmerman static int dwc2_hcd_endpoint_reset(struct dwc2_hsotg *hsotg, 2158197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep) 2159197ba5f4SPaul Zimmerman { 2160197ba5f4SPaul Zimmerman struct dwc2_qh *qh = ep->hcpriv; 2161197ba5f4SPaul Zimmerman 2162197ba5f4SPaul Zimmerman if (!qh) 2163197ba5f4SPaul Zimmerman return -EINVAL; 2164197ba5f4SPaul Zimmerman 2165197ba5f4SPaul Zimmerman qh->data_toggle = DWC2_HC_PID_DATA0; 2166197ba5f4SPaul Zimmerman 2167197ba5f4SPaul Zimmerman return 0; 2168197ba5f4SPaul Zimmerman } 2169197ba5f4SPaul Zimmerman 2170b02038faSJohn Youn /** 2171b02038faSJohn Youn * dwc2_core_init() - Initializes the DWC_otg controller registers and 2172b02038faSJohn Youn * prepares the core for device mode or host mode operation 2173b02038faSJohn Youn * 2174b02038faSJohn Youn * @hsotg: Programming view of the DWC_otg controller 2175b02038faSJohn Youn * @initial_setup: If true then this is the first init for this instance. 2176b02038faSJohn Youn */ 2177b02038faSJohn Youn static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) 2178b02038faSJohn Youn { 2179b02038faSJohn Youn u32 usbcfg, otgctl; 2180b02038faSJohn Youn int retval; 2181b02038faSJohn Youn 2182b02038faSJohn Youn dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg); 2183b02038faSJohn Youn 2184b02038faSJohn Youn usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 2185b02038faSJohn Youn 2186b02038faSJohn Youn /* Set ULPI External VBUS bit if needed */ 2187b02038faSJohn Youn usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV; 2188bea8e86cSJohn Youn if (hsotg->params.phy_ulpi_ext_vbus == 2189b02038faSJohn Youn DWC2_PHY_ULPI_EXTERNAL_VBUS) 2190b02038faSJohn Youn usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV; 2191b02038faSJohn Youn 2192b02038faSJohn Youn /* Set external TS Dline pulsing bit if needed */ 2193b02038faSJohn Youn usbcfg &= ~GUSBCFG_TERMSELDLPULSE; 2194bea8e86cSJohn Youn if (hsotg->params.ts_dline > 0) 2195b02038faSJohn Youn usbcfg |= GUSBCFG_TERMSELDLPULSE; 2196b02038faSJohn Youn 2197b02038faSJohn Youn dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); 2198b02038faSJohn Youn 2199b02038faSJohn Youn /* 2200b02038faSJohn Youn * Reset the Controller 2201b02038faSJohn Youn * 2202b02038faSJohn Youn * We only need to reset the controller if this is a re-init. 2203b02038faSJohn Youn * For the first init we know for sure that earlier code reset us (it 2204b02038faSJohn Youn * needed to in order to properly detect various parameters). 2205b02038faSJohn Youn */ 2206b02038faSJohn Youn if (!initial_setup) { 2207b02038faSJohn Youn retval = dwc2_core_reset_and_force_dr_mode(hsotg); 2208b02038faSJohn Youn if (retval) { 2209b02038faSJohn Youn dev_err(hsotg->dev, "%s(): Reset failed, aborting\n", 2210b02038faSJohn Youn __func__); 2211b02038faSJohn Youn return retval; 2212b02038faSJohn Youn } 2213b02038faSJohn Youn } 2214b02038faSJohn Youn 2215b02038faSJohn Youn /* 2216b02038faSJohn Youn * This needs to happen in FS mode before any other programming occurs 2217b02038faSJohn Youn */ 2218b02038faSJohn Youn retval = dwc2_phy_init(hsotg, initial_setup); 2219b02038faSJohn Youn if (retval) 2220b02038faSJohn Youn return retval; 2221b02038faSJohn Youn 2222b02038faSJohn Youn /* Program the GAHBCFG Register */ 2223b02038faSJohn Youn retval = dwc2_gahbcfg_init(hsotg); 2224b02038faSJohn Youn if (retval) 2225b02038faSJohn Youn return retval; 2226b02038faSJohn Youn 2227b02038faSJohn Youn /* Program the GUSBCFG register */ 2228b02038faSJohn Youn dwc2_gusbcfg_init(hsotg); 2229b02038faSJohn Youn 2230b02038faSJohn Youn /* Program the GOTGCTL register */ 2231b02038faSJohn Youn otgctl = dwc2_readl(hsotg->regs + GOTGCTL); 2232b02038faSJohn Youn otgctl &= ~GOTGCTL_OTGVER; 2233bea8e86cSJohn Youn if (hsotg->params.otg_ver > 0) 2234b02038faSJohn Youn otgctl |= GOTGCTL_OTGVER; 2235b02038faSJohn Youn dwc2_writel(otgctl, hsotg->regs + GOTGCTL); 2236bea8e86cSJohn Youn dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->params.otg_ver); 2237b02038faSJohn Youn 2238b02038faSJohn Youn /* Clear the SRP success bit for FS-I2c */ 2239b02038faSJohn Youn hsotg->srp_success = 0; 2240b02038faSJohn Youn 2241b02038faSJohn Youn /* Enable common interrupts */ 2242b02038faSJohn Youn dwc2_enable_common_interrupts(hsotg); 2243b02038faSJohn Youn 2244b02038faSJohn Youn /* 2245b02038faSJohn Youn * Do device or host initialization based on mode during PCD and 2246b02038faSJohn Youn * HCD initialization 2247b02038faSJohn Youn */ 2248b02038faSJohn Youn if (dwc2_is_host_mode(hsotg)) { 2249b02038faSJohn Youn dev_dbg(hsotg->dev, "Host Mode\n"); 2250b02038faSJohn Youn hsotg->op_state = OTG_STATE_A_HOST; 2251b02038faSJohn Youn } else { 2252b02038faSJohn Youn dev_dbg(hsotg->dev, "Device Mode\n"); 2253b02038faSJohn Youn hsotg->op_state = OTG_STATE_B_PERIPHERAL; 2254b02038faSJohn Youn } 2255b02038faSJohn Youn 2256b02038faSJohn Youn return 0; 2257b02038faSJohn Youn } 2258b02038faSJohn Youn 2259b02038faSJohn Youn /** 2260b02038faSJohn Youn * dwc2_core_host_init() - Initializes the DWC_otg controller registers for 2261b02038faSJohn Youn * Host mode 2262b02038faSJohn Youn * 2263b02038faSJohn Youn * @hsotg: Programming view of DWC_otg controller 2264b02038faSJohn Youn * 2265b02038faSJohn Youn * This function flushes the Tx and Rx FIFOs and flushes any entries in the 2266b02038faSJohn Youn * request queues. Host channels are reset to ensure that they are ready for 2267b02038faSJohn Youn * performing transfers. 2268b02038faSJohn Youn */ 2269b02038faSJohn Youn static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) 2270b02038faSJohn Youn { 2271b02038faSJohn Youn u32 hcfg, hfir, otgctl; 2272b02038faSJohn Youn 2273b02038faSJohn Youn dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg); 2274b02038faSJohn Youn 2275b02038faSJohn Youn /* Restart the Phy Clock */ 2276b02038faSJohn Youn dwc2_writel(0, hsotg->regs + PCGCTL); 2277b02038faSJohn Youn 2278b02038faSJohn Youn /* Initialize Host Configuration Register */ 2279b02038faSJohn Youn dwc2_init_fs_ls_pclk_sel(hsotg); 2280bea8e86cSJohn Youn if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL) { 2281b02038faSJohn Youn hcfg = dwc2_readl(hsotg->regs + HCFG); 2282b02038faSJohn Youn hcfg |= HCFG_FSLSSUPP; 2283b02038faSJohn Youn dwc2_writel(hcfg, hsotg->regs + HCFG); 2284b02038faSJohn Youn } 2285b02038faSJohn Youn 2286b02038faSJohn Youn /* 2287b02038faSJohn Youn * This bit allows dynamic reloading of the HFIR register during 2288b02038faSJohn Youn * runtime. This bit needs to be programmed during initial configuration 2289b02038faSJohn Youn * and its value must not be changed during runtime. 2290b02038faSJohn Youn */ 2291bea8e86cSJohn Youn if (hsotg->params.reload_ctl > 0) { 2292b02038faSJohn Youn hfir = dwc2_readl(hsotg->regs + HFIR); 2293b02038faSJohn Youn hfir |= HFIR_RLDCTRL; 2294b02038faSJohn Youn dwc2_writel(hfir, hsotg->regs + HFIR); 2295b02038faSJohn Youn } 2296b02038faSJohn Youn 2297bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable > 0) { 2298b02038faSJohn Youn u32 op_mode = hsotg->hw_params.op_mode; 2299b02038faSJohn Youn 2300b02038faSJohn Youn if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a || 2301b02038faSJohn Youn !hsotg->hw_params.dma_desc_enable || 2302b02038faSJohn Youn op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE || 2303b02038faSJohn Youn op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE || 2304b02038faSJohn Youn op_mode == GHWCFG2_OP_MODE_UNDEFINED) { 2305b02038faSJohn Youn dev_err(hsotg->dev, 2306b02038faSJohn Youn "Hardware does not support descriptor DMA mode -\n"); 2307b02038faSJohn Youn dev_err(hsotg->dev, 2308b02038faSJohn Youn "falling back to buffer DMA mode.\n"); 2309bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 0; 2310b02038faSJohn Youn } else { 2311b02038faSJohn Youn hcfg = dwc2_readl(hsotg->regs + HCFG); 2312b02038faSJohn Youn hcfg |= HCFG_DESCDMA; 2313b02038faSJohn Youn dwc2_writel(hcfg, hsotg->regs + HCFG); 2314b02038faSJohn Youn } 2315b02038faSJohn Youn } 2316b02038faSJohn Youn 2317b02038faSJohn Youn /* Configure data FIFO sizes */ 2318b02038faSJohn Youn dwc2_config_fifos(hsotg); 2319b02038faSJohn Youn 2320b02038faSJohn Youn /* TODO - check this */ 2321b02038faSJohn Youn /* Clear Host Set HNP Enable in the OTG Control Register */ 2322b02038faSJohn Youn otgctl = dwc2_readl(hsotg->regs + GOTGCTL); 2323b02038faSJohn Youn otgctl &= ~GOTGCTL_HSTSETHNPEN; 2324b02038faSJohn Youn dwc2_writel(otgctl, hsotg->regs + GOTGCTL); 2325b02038faSJohn Youn 2326b02038faSJohn Youn /* Make sure the FIFOs are flushed */ 2327b02038faSJohn Youn dwc2_flush_tx_fifo(hsotg, 0x10 /* all TX FIFOs */); 2328b02038faSJohn Youn dwc2_flush_rx_fifo(hsotg); 2329b02038faSJohn Youn 2330b02038faSJohn Youn /* Clear Host Set HNP Enable in the OTG Control Register */ 2331b02038faSJohn Youn otgctl = dwc2_readl(hsotg->regs + GOTGCTL); 2332b02038faSJohn Youn otgctl &= ~GOTGCTL_HSTSETHNPEN; 2333b02038faSJohn Youn dwc2_writel(otgctl, hsotg->regs + GOTGCTL); 2334b02038faSJohn Youn 2335bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable <= 0) { 2336b02038faSJohn Youn int num_channels, i; 2337b02038faSJohn Youn u32 hcchar; 2338b02038faSJohn Youn 2339b02038faSJohn Youn /* Flush out any leftover queued requests */ 2340bea8e86cSJohn Youn num_channels = hsotg->params.host_channels; 2341b02038faSJohn Youn for (i = 0; i < num_channels; i++) { 2342b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 2343b02038faSJohn Youn hcchar &= ~HCCHAR_CHENA; 2344b02038faSJohn Youn hcchar |= HCCHAR_CHDIS; 2345b02038faSJohn Youn hcchar &= ~HCCHAR_EPDIR; 2346b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); 2347b02038faSJohn Youn } 2348b02038faSJohn Youn 2349b02038faSJohn Youn /* Halt all channels to put them into a known state */ 2350b02038faSJohn Youn for (i = 0; i < num_channels; i++) { 2351b02038faSJohn Youn int count = 0; 2352b02038faSJohn Youn 2353b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 2354b02038faSJohn Youn hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS; 2355b02038faSJohn Youn hcchar &= ~HCCHAR_EPDIR; 2356b02038faSJohn Youn dwc2_writel(hcchar, hsotg->regs + HCCHAR(i)); 2357b02038faSJohn Youn dev_dbg(hsotg->dev, "%s: Halt channel %d\n", 2358b02038faSJohn Youn __func__, i); 2359b02038faSJohn Youn do { 2360b02038faSJohn Youn hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 2361b02038faSJohn Youn if (++count > 1000) { 2362b02038faSJohn Youn dev_err(hsotg->dev, 2363b02038faSJohn Youn "Unable to clear enable on channel %d\n", 2364b02038faSJohn Youn i); 2365b02038faSJohn Youn break; 2366b02038faSJohn Youn } 2367b02038faSJohn Youn udelay(1); 2368b02038faSJohn Youn } while (hcchar & HCCHAR_CHENA); 2369b02038faSJohn Youn } 2370b02038faSJohn Youn } 2371b02038faSJohn Youn 2372b02038faSJohn Youn /* Turn on the vbus power */ 2373b02038faSJohn Youn dev_dbg(hsotg->dev, "Init: Port Power? op_state=%d\n", hsotg->op_state); 2374b02038faSJohn Youn if (hsotg->op_state == OTG_STATE_A_HOST) { 2375b02038faSJohn Youn u32 hprt0 = dwc2_read_hprt0(hsotg); 2376b02038faSJohn Youn 2377b02038faSJohn Youn dev_dbg(hsotg->dev, "Init: Power Port (%d)\n", 2378b02038faSJohn Youn !!(hprt0 & HPRT0_PWR)); 2379b02038faSJohn Youn if (!(hprt0 & HPRT0_PWR)) { 2380b02038faSJohn Youn hprt0 |= HPRT0_PWR; 2381b02038faSJohn Youn dwc2_writel(hprt0, hsotg->regs + HPRT0); 2382b02038faSJohn Youn } 2383b02038faSJohn Youn } 2384b02038faSJohn Youn 2385b02038faSJohn Youn dwc2_enable_host_interrupts(hsotg); 2386b02038faSJohn Youn } 2387b02038faSJohn Youn 2388197ba5f4SPaul Zimmerman /* 2389197ba5f4SPaul Zimmerman * Initializes dynamic portions of the DWC_otg HCD state 2390197ba5f4SPaul Zimmerman * 2391197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 2392197ba5f4SPaul Zimmerman */ 2393197ba5f4SPaul Zimmerman static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg) 2394197ba5f4SPaul Zimmerman { 2395197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan, *chan_tmp; 2396197ba5f4SPaul Zimmerman int num_channels; 2397197ba5f4SPaul Zimmerman int i; 2398197ba5f4SPaul Zimmerman 2399197ba5f4SPaul Zimmerman hsotg->flags.d32 = 0; 2400197ba5f4SPaul Zimmerman hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active; 2401197ba5f4SPaul Zimmerman 2402bea8e86cSJohn Youn if (hsotg->params.uframe_sched > 0) { 2403197ba5f4SPaul Zimmerman hsotg->available_host_channels = 2404bea8e86cSJohn Youn hsotg->params.host_channels; 2405197ba5f4SPaul Zimmerman } else { 2406197ba5f4SPaul Zimmerman hsotg->non_periodic_channels = 0; 2407197ba5f4SPaul Zimmerman hsotg->periodic_channels = 0; 2408197ba5f4SPaul Zimmerman } 2409197ba5f4SPaul Zimmerman 2410197ba5f4SPaul Zimmerman /* 2411197ba5f4SPaul Zimmerman * Put all channels in the free channel list and clean up channel 2412197ba5f4SPaul Zimmerman * states 2413197ba5f4SPaul Zimmerman */ 2414197ba5f4SPaul Zimmerman list_for_each_entry_safe(chan, chan_tmp, &hsotg->free_hc_list, 2415197ba5f4SPaul Zimmerman hc_list_entry) 2416197ba5f4SPaul Zimmerman list_del_init(&chan->hc_list_entry); 2417197ba5f4SPaul Zimmerman 2418bea8e86cSJohn Youn num_channels = hsotg->params.host_channels; 2419197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 2420197ba5f4SPaul Zimmerman chan = hsotg->hc_ptr_array[i]; 2421197ba5f4SPaul Zimmerman list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list); 2422197ba5f4SPaul Zimmerman dwc2_hc_cleanup(hsotg, chan); 2423197ba5f4SPaul Zimmerman } 2424197ba5f4SPaul Zimmerman 2425197ba5f4SPaul Zimmerman /* Initialize the DWC core for host mode operation */ 2426197ba5f4SPaul Zimmerman dwc2_core_host_init(hsotg); 2427197ba5f4SPaul Zimmerman } 2428197ba5f4SPaul Zimmerman 2429197ba5f4SPaul Zimmerman static void dwc2_hc_init_split(struct dwc2_hsotg *hsotg, 2430197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan, 2431197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) 2432197ba5f4SPaul Zimmerman { 2433197ba5f4SPaul Zimmerman int hub_addr, hub_port; 2434197ba5f4SPaul Zimmerman 2435197ba5f4SPaul Zimmerman chan->do_split = 1; 2436197ba5f4SPaul Zimmerman chan->xact_pos = qtd->isoc_split_pos; 2437197ba5f4SPaul Zimmerman chan->complete_split = qtd->complete_split; 2438197ba5f4SPaul Zimmerman dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port); 2439197ba5f4SPaul Zimmerman chan->hub_addr = (u8)hub_addr; 2440197ba5f4SPaul Zimmerman chan->hub_port = (u8)hub_port; 2441197ba5f4SPaul Zimmerman } 2442197ba5f4SPaul Zimmerman 24433bc04e28SDouglas Anderson static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, 2444197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan, 24453bc04e28SDouglas Anderson struct dwc2_qtd *qtd) 2446197ba5f4SPaul Zimmerman { 2447197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb = qtd->urb; 2448197ba5f4SPaul Zimmerman struct dwc2_hcd_iso_packet_desc *frame_desc; 2449197ba5f4SPaul Zimmerman 2450197ba5f4SPaul Zimmerman switch (dwc2_hcd_get_pipe_type(&urb->pipe_info)) { 2451197ba5f4SPaul Zimmerman case USB_ENDPOINT_XFER_CONTROL: 2452197ba5f4SPaul Zimmerman chan->ep_type = USB_ENDPOINT_XFER_CONTROL; 2453197ba5f4SPaul Zimmerman 2454197ba5f4SPaul Zimmerman switch (qtd->control_phase) { 2455197ba5f4SPaul Zimmerman case DWC2_CONTROL_SETUP: 2456197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Control setup transaction\n"); 2457197ba5f4SPaul Zimmerman chan->do_ping = 0; 2458197ba5f4SPaul Zimmerman chan->ep_is_in = 0; 2459197ba5f4SPaul Zimmerman chan->data_pid_start = DWC2_HC_PID_SETUP; 2460*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) 2461197ba5f4SPaul Zimmerman chan->xfer_dma = urb->setup_dma; 2462197ba5f4SPaul Zimmerman else 2463197ba5f4SPaul Zimmerman chan->xfer_buf = urb->setup_packet; 2464197ba5f4SPaul Zimmerman chan->xfer_len = 8; 2465197ba5f4SPaul Zimmerman break; 2466197ba5f4SPaul Zimmerman 2467197ba5f4SPaul Zimmerman case DWC2_CONTROL_DATA: 2468197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Control data transaction\n"); 2469197ba5f4SPaul Zimmerman chan->data_pid_start = qtd->data_toggle; 2470197ba5f4SPaul Zimmerman break; 2471197ba5f4SPaul Zimmerman 2472197ba5f4SPaul Zimmerman case DWC2_CONTROL_STATUS: 2473197ba5f4SPaul Zimmerman /* 2474197ba5f4SPaul Zimmerman * Direction is opposite of data direction or IN if no 2475197ba5f4SPaul Zimmerman * data 2476197ba5f4SPaul Zimmerman */ 2477197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Control status transaction\n"); 2478197ba5f4SPaul Zimmerman if (urb->length == 0) 2479197ba5f4SPaul Zimmerman chan->ep_is_in = 1; 2480197ba5f4SPaul Zimmerman else 2481197ba5f4SPaul Zimmerman chan->ep_is_in = 2482197ba5f4SPaul Zimmerman dwc2_hcd_is_pipe_out(&urb->pipe_info); 2483197ba5f4SPaul Zimmerman if (chan->ep_is_in) 2484197ba5f4SPaul Zimmerman chan->do_ping = 0; 2485197ba5f4SPaul Zimmerman chan->data_pid_start = DWC2_HC_PID_DATA1; 2486197ba5f4SPaul Zimmerman chan->xfer_len = 0; 2487*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) 2488197ba5f4SPaul Zimmerman chan->xfer_dma = hsotg->status_buf_dma; 2489197ba5f4SPaul Zimmerman else 2490197ba5f4SPaul Zimmerman chan->xfer_buf = hsotg->status_buf; 2491197ba5f4SPaul Zimmerman break; 2492197ba5f4SPaul Zimmerman } 2493197ba5f4SPaul Zimmerman break; 2494197ba5f4SPaul Zimmerman 2495197ba5f4SPaul Zimmerman case USB_ENDPOINT_XFER_BULK: 2496197ba5f4SPaul Zimmerman chan->ep_type = USB_ENDPOINT_XFER_BULK; 2497197ba5f4SPaul Zimmerman break; 2498197ba5f4SPaul Zimmerman 2499197ba5f4SPaul Zimmerman case USB_ENDPOINT_XFER_INT: 2500197ba5f4SPaul Zimmerman chan->ep_type = USB_ENDPOINT_XFER_INT; 2501197ba5f4SPaul Zimmerman break; 2502197ba5f4SPaul Zimmerman 2503197ba5f4SPaul Zimmerman case USB_ENDPOINT_XFER_ISOC: 2504197ba5f4SPaul Zimmerman chan->ep_type = USB_ENDPOINT_XFER_ISOC; 2505bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable > 0) 2506197ba5f4SPaul Zimmerman break; 2507197ba5f4SPaul Zimmerman 2508197ba5f4SPaul Zimmerman frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; 2509197ba5f4SPaul Zimmerman frame_desc->status = 0; 2510197ba5f4SPaul Zimmerman 2511*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 2512197ba5f4SPaul Zimmerman chan->xfer_dma = urb->dma; 2513197ba5f4SPaul Zimmerman chan->xfer_dma += frame_desc->offset + 2514197ba5f4SPaul Zimmerman qtd->isoc_split_offset; 2515197ba5f4SPaul Zimmerman } else { 2516197ba5f4SPaul Zimmerman chan->xfer_buf = urb->buf; 2517197ba5f4SPaul Zimmerman chan->xfer_buf += frame_desc->offset + 2518197ba5f4SPaul Zimmerman qtd->isoc_split_offset; 2519197ba5f4SPaul Zimmerman } 2520197ba5f4SPaul Zimmerman 2521197ba5f4SPaul Zimmerman chan->xfer_len = frame_desc->length - qtd->isoc_split_offset; 2522197ba5f4SPaul Zimmerman 2523197ba5f4SPaul Zimmerman if (chan->xact_pos == DWC2_HCSPLT_XACTPOS_ALL) { 2524197ba5f4SPaul Zimmerman if (chan->xfer_len <= 188) 2525197ba5f4SPaul Zimmerman chan->xact_pos = DWC2_HCSPLT_XACTPOS_ALL; 2526197ba5f4SPaul Zimmerman else 2527197ba5f4SPaul Zimmerman chan->xact_pos = DWC2_HCSPLT_XACTPOS_BEGIN; 2528197ba5f4SPaul Zimmerman } 2529197ba5f4SPaul Zimmerman break; 2530197ba5f4SPaul Zimmerman } 2531197ba5f4SPaul Zimmerman } 2532197ba5f4SPaul Zimmerman 25333bc04e28SDouglas Anderson #define DWC2_USB_DMA_ALIGN 4 25343bc04e28SDouglas Anderson 25353bc04e28SDouglas Anderson struct dma_aligned_buffer { 25363bc04e28SDouglas Anderson void *kmalloc_ptr; 25373bc04e28SDouglas Anderson void *old_xfer_buffer; 25383bc04e28SDouglas Anderson u8 data[0]; 25393bc04e28SDouglas Anderson }; 25403bc04e28SDouglas Anderson 25413bc04e28SDouglas Anderson static void dwc2_free_dma_aligned_buffer(struct urb *urb) 2542197ba5f4SPaul Zimmerman { 25433bc04e28SDouglas Anderson struct dma_aligned_buffer *temp; 2544197ba5f4SPaul Zimmerman 25453bc04e28SDouglas Anderson if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 25463bc04e28SDouglas Anderson return; 2547197ba5f4SPaul Zimmerman 25483bc04e28SDouglas Anderson temp = container_of(urb->transfer_buffer, 25493bc04e28SDouglas Anderson struct dma_aligned_buffer, data); 25503bc04e28SDouglas Anderson 25513bc04e28SDouglas Anderson if (usb_urb_dir_in(urb)) 25523bc04e28SDouglas Anderson memcpy(temp->old_xfer_buffer, temp->data, 25533bc04e28SDouglas Anderson urb->transfer_buffer_length); 25543bc04e28SDouglas Anderson urb->transfer_buffer = temp->old_xfer_buffer; 25553bc04e28SDouglas Anderson kfree(temp->kmalloc_ptr); 25563bc04e28SDouglas Anderson 25573bc04e28SDouglas Anderson urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 2558197ba5f4SPaul Zimmerman } 2559197ba5f4SPaul Zimmerman 25603bc04e28SDouglas Anderson static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) 25613bc04e28SDouglas Anderson { 25623bc04e28SDouglas Anderson struct dma_aligned_buffer *temp, *kmalloc_ptr; 25633bc04e28SDouglas Anderson size_t kmalloc_size; 25645dce9555SPaul Zimmerman 25653bc04e28SDouglas Anderson if (urb->num_sgs || urb->sg || 25663bc04e28SDouglas Anderson urb->transfer_buffer_length == 0 || 25673bc04e28SDouglas Anderson !((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1))) 2568197ba5f4SPaul Zimmerman return 0; 25693bc04e28SDouglas Anderson 25703bc04e28SDouglas Anderson /* Allocate a buffer with enough padding for alignment */ 25713bc04e28SDouglas Anderson kmalloc_size = urb->transfer_buffer_length + 25723bc04e28SDouglas Anderson sizeof(struct dma_aligned_buffer) + DWC2_USB_DMA_ALIGN - 1; 25733bc04e28SDouglas Anderson 25743bc04e28SDouglas Anderson kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 25753bc04e28SDouglas Anderson if (!kmalloc_ptr) 25763bc04e28SDouglas Anderson return -ENOMEM; 25773bc04e28SDouglas Anderson 25783bc04e28SDouglas Anderson /* Position our struct dma_aligned_buffer such that data is aligned */ 25793bc04e28SDouglas Anderson temp = PTR_ALIGN(kmalloc_ptr + 1, DWC2_USB_DMA_ALIGN) - 1; 25803bc04e28SDouglas Anderson temp->kmalloc_ptr = kmalloc_ptr; 25813bc04e28SDouglas Anderson temp->old_xfer_buffer = urb->transfer_buffer; 25823bc04e28SDouglas Anderson if (usb_urb_dir_out(urb)) 25833bc04e28SDouglas Anderson memcpy(temp->data, urb->transfer_buffer, 25843bc04e28SDouglas Anderson urb->transfer_buffer_length); 25853bc04e28SDouglas Anderson urb->transfer_buffer = temp->data; 25863bc04e28SDouglas Anderson 25873bc04e28SDouglas Anderson urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; 25883bc04e28SDouglas Anderson 25893bc04e28SDouglas Anderson return 0; 25903bc04e28SDouglas Anderson } 25913bc04e28SDouglas Anderson 25923bc04e28SDouglas Anderson static int dwc2_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 25933bc04e28SDouglas Anderson gfp_t mem_flags) 25943bc04e28SDouglas Anderson { 25953bc04e28SDouglas Anderson int ret; 25963bc04e28SDouglas Anderson 25973bc04e28SDouglas Anderson /* We assume setup_dma is always aligned; warn if not */ 25983bc04e28SDouglas Anderson WARN_ON_ONCE(urb->setup_dma && 25993bc04e28SDouglas Anderson (urb->setup_dma & (DWC2_USB_DMA_ALIGN - 1))); 26003bc04e28SDouglas Anderson 26013bc04e28SDouglas Anderson ret = dwc2_alloc_dma_aligned_buffer(urb, mem_flags); 26023bc04e28SDouglas Anderson if (ret) 26033bc04e28SDouglas Anderson return ret; 26043bc04e28SDouglas Anderson 26053bc04e28SDouglas Anderson ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 26063bc04e28SDouglas Anderson if (ret) 26073bc04e28SDouglas Anderson dwc2_free_dma_aligned_buffer(urb); 26083bc04e28SDouglas Anderson 26093bc04e28SDouglas Anderson return ret; 26103bc04e28SDouglas Anderson } 26113bc04e28SDouglas Anderson 26123bc04e28SDouglas Anderson static void dwc2_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 26133bc04e28SDouglas Anderson { 26143bc04e28SDouglas Anderson usb_hcd_unmap_urb_for_dma(hcd, urb); 26153bc04e28SDouglas Anderson dwc2_free_dma_aligned_buffer(urb); 2616197ba5f4SPaul Zimmerman } 2617197ba5f4SPaul Zimmerman 2618197ba5f4SPaul Zimmerman /** 2619197ba5f4SPaul Zimmerman * dwc2_assign_and_init_hc() - Assigns transactions from a QTD to a free host 2620197ba5f4SPaul Zimmerman * channel and initializes the host channel to perform the transactions. The 2621197ba5f4SPaul Zimmerman * host channel is removed from the free list. 2622197ba5f4SPaul Zimmerman * 2623197ba5f4SPaul Zimmerman * @hsotg: The HCD state structure 2624197ba5f4SPaul Zimmerman * @qh: Transactions from the first QTD for this QH are selected and assigned 2625197ba5f4SPaul Zimmerman * to a free host channel 2626197ba5f4SPaul Zimmerman */ 2627197ba5f4SPaul Zimmerman static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) 2628197ba5f4SPaul Zimmerman { 2629197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan; 2630197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb; 2631197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd; 2632197ba5f4SPaul Zimmerman 2633197ba5f4SPaul Zimmerman if (dbg_qh(qh)) 2634197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "%s(%p,%p)\n", __func__, hsotg, qh); 2635197ba5f4SPaul Zimmerman 2636197ba5f4SPaul Zimmerman if (list_empty(&qh->qtd_list)) { 2637197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "No QTDs in QH list\n"); 2638197ba5f4SPaul Zimmerman return -ENOMEM; 2639197ba5f4SPaul Zimmerman } 2640197ba5f4SPaul Zimmerman 2641197ba5f4SPaul Zimmerman if (list_empty(&hsotg->free_hc_list)) { 2642197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "No free channel to assign\n"); 2643197ba5f4SPaul Zimmerman return -ENOMEM; 2644197ba5f4SPaul Zimmerman } 2645197ba5f4SPaul Zimmerman 2646197ba5f4SPaul Zimmerman chan = list_first_entry(&hsotg->free_hc_list, struct dwc2_host_chan, 2647197ba5f4SPaul Zimmerman hc_list_entry); 2648197ba5f4SPaul Zimmerman 2649197ba5f4SPaul Zimmerman /* Remove host channel from free list */ 2650197ba5f4SPaul Zimmerman list_del_init(&chan->hc_list_entry); 2651197ba5f4SPaul Zimmerman 2652197ba5f4SPaul Zimmerman qtd = list_first_entry(&qh->qtd_list, struct dwc2_qtd, qtd_list_entry); 2653197ba5f4SPaul Zimmerman urb = qtd->urb; 2654197ba5f4SPaul Zimmerman qh->channel = chan; 2655197ba5f4SPaul Zimmerman qtd->in_process = 1; 2656197ba5f4SPaul Zimmerman 2657197ba5f4SPaul Zimmerman /* 2658197ba5f4SPaul Zimmerman * Use usb_pipedevice to determine device address. This address is 2659197ba5f4SPaul Zimmerman * 0 before the SET_ADDRESS command and the correct address afterward. 2660197ba5f4SPaul Zimmerman */ 2661197ba5f4SPaul Zimmerman chan->dev_addr = dwc2_hcd_get_dev_addr(&urb->pipe_info); 2662197ba5f4SPaul Zimmerman chan->ep_num = dwc2_hcd_get_ep_num(&urb->pipe_info); 2663197ba5f4SPaul Zimmerman chan->speed = qh->dev_speed; 2664197ba5f4SPaul Zimmerman chan->max_packet = dwc2_max_packet(qh->maxp); 2665197ba5f4SPaul Zimmerman 2666197ba5f4SPaul Zimmerman chan->xfer_started = 0; 2667197ba5f4SPaul Zimmerman chan->halt_status = DWC2_HC_XFER_NO_HALT_STATUS; 2668197ba5f4SPaul Zimmerman chan->error_state = (qtd->error_count > 0); 2669197ba5f4SPaul Zimmerman chan->halt_on_queue = 0; 2670197ba5f4SPaul Zimmerman chan->halt_pending = 0; 2671197ba5f4SPaul Zimmerman chan->requests = 0; 2672197ba5f4SPaul Zimmerman 2673197ba5f4SPaul Zimmerman /* 2674197ba5f4SPaul Zimmerman * The following values may be modified in the transfer type section 2675197ba5f4SPaul Zimmerman * below. The xfer_len value may be reduced when the transfer is 2676197ba5f4SPaul Zimmerman * started to accommodate the max widths of the XferSize and PktCnt 2677197ba5f4SPaul Zimmerman * fields in the HCTSIZn register. 2678197ba5f4SPaul Zimmerman */ 2679197ba5f4SPaul Zimmerman 2680197ba5f4SPaul Zimmerman chan->ep_is_in = (dwc2_hcd_is_pipe_in(&urb->pipe_info) != 0); 2681197ba5f4SPaul Zimmerman if (chan->ep_is_in) 2682197ba5f4SPaul Zimmerman chan->do_ping = 0; 2683197ba5f4SPaul Zimmerman else 2684197ba5f4SPaul Zimmerman chan->do_ping = qh->ping_state; 2685197ba5f4SPaul Zimmerman 2686197ba5f4SPaul Zimmerman chan->data_pid_start = qh->data_toggle; 2687197ba5f4SPaul Zimmerman chan->multi_count = 1; 2688197ba5f4SPaul Zimmerman 2689197ba5f4SPaul Zimmerman if (urb->actual_length > urb->length && 2690197ba5f4SPaul Zimmerman !dwc2_hcd_is_pipe_in(&urb->pipe_info)) 2691197ba5f4SPaul Zimmerman urb->actual_length = urb->length; 2692197ba5f4SPaul Zimmerman 2693*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) 2694197ba5f4SPaul Zimmerman chan->xfer_dma = urb->dma + urb->actual_length; 26953bc04e28SDouglas Anderson else 2696197ba5f4SPaul Zimmerman chan->xfer_buf = (u8 *)urb->buf + urb->actual_length; 2697197ba5f4SPaul Zimmerman 2698197ba5f4SPaul Zimmerman chan->xfer_len = urb->length - urb->actual_length; 2699197ba5f4SPaul Zimmerman chan->xfer_count = 0; 2700197ba5f4SPaul Zimmerman 2701197ba5f4SPaul Zimmerman /* Set the split attributes if required */ 2702197ba5f4SPaul Zimmerman if (qh->do_split) 2703197ba5f4SPaul Zimmerman dwc2_hc_init_split(hsotg, chan, qtd, urb); 2704197ba5f4SPaul Zimmerman else 2705197ba5f4SPaul Zimmerman chan->do_split = 0; 2706197ba5f4SPaul Zimmerman 2707197ba5f4SPaul Zimmerman /* Set the transfer attributes */ 27083bc04e28SDouglas Anderson dwc2_hc_init_xfer(hsotg, chan, qtd); 2709197ba5f4SPaul Zimmerman 2710197ba5f4SPaul Zimmerman if (chan->ep_type == USB_ENDPOINT_XFER_INT || 2711197ba5f4SPaul Zimmerman chan->ep_type == USB_ENDPOINT_XFER_ISOC) 2712197ba5f4SPaul Zimmerman /* 2713197ba5f4SPaul Zimmerman * This value may be modified when the transfer is started 2714197ba5f4SPaul Zimmerman * to reflect the actual transfer length 2715197ba5f4SPaul Zimmerman */ 2716197ba5f4SPaul Zimmerman chan->multi_count = dwc2_hb_mult(qh->maxp); 2717197ba5f4SPaul Zimmerman 2718bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable > 0) { 2719197ba5f4SPaul Zimmerman chan->desc_list_addr = qh->desc_list_dma; 272095105a99SGregory Herrero chan->desc_list_sz = qh->desc_list_sz; 272195105a99SGregory Herrero } 2722197ba5f4SPaul Zimmerman 2723197ba5f4SPaul Zimmerman dwc2_hc_init(hsotg, chan); 2724197ba5f4SPaul Zimmerman chan->qh = qh; 2725197ba5f4SPaul Zimmerman 2726197ba5f4SPaul Zimmerman return 0; 2727197ba5f4SPaul Zimmerman } 2728197ba5f4SPaul Zimmerman 2729197ba5f4SPaul Zimmerman /** 2730197ba5f4SPaul Zimmerman * dwc2_hcd_select_transactions() - Selects transactions from the HCD transfer 2731197ba5f4SPaul Zimmerman * schedule and assigns them to available host channels. Called from the HCD 2732197ba5f4SPaul Zimmerman * interrupt handler functions. 2733197ba5f4SPaul Zimmerman * 2734197ba5f4SPaul Zimmerman * @hsotg: The HCD state structure 2735197ba5f4SPaul Zimmerman * 2736197ba5f4SPaul Zimmerman * Return: The types of new transactions that were assigned to host channels 2737197ba5f4SPaul Zimmerman */ 2738197ba5f4SPaul Zimmerman enum dwc2_transaction_type dwc2_hcd_select_transactions( 2739197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg) 2740197ba5f4SPaul Zimmerman { 2741197ba5f4SPaul Zimmerman enum dwc2_transaction_type ret_val = DWC2_TRANSACTION_NONE; 2742197ba5f4SPaul Zimmerman struct list_head *qh_ptr; 2743197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 2744197ba5f4SPaul Zimmerman int num_channels; 2745197ba5f4SPaul Zimmerman 2746197ba5f4SPaul Zimmerman #ifdef DWC2_DEBUG_SOF 2747197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Select Transactions\n"); 2748197ba5f4SPaul Zimmerman #endif 2749197ba5f4SPaul Zimmerman 2750197ba5f4SPaul Zimmerman /* Process entries in the periodic ready list */ 2751197ba5f4SPaul Zimmerman qh_ptr = hsotg->periodic_sched_ready.next; 2752197ba5f4SPaul Zimmerman while (qh_ptr != &hsotg->periodic_sched_ready) { 2753197ba5f4SPaul Zimmerman if (list_empty(&hsotg->free_hc_list)) 2754197ba5f4SPaul Zimmerman break; 2755bea8e86cSJohn Youn if (hsotg->params.uframe_sched > 0) { 2756197ba5f4SPaul Zimmerman if (hsotg->available_host_channels <= 1) 2757197ba5f4SPaul Zimmerman break; 2758197ba5f4SPaul Zimmerman hsotg->available_host_channels--; 2759197ba5f4SPaul Zimmerman } 2760197ba5f4SPaul Zimmerman qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); 2761197ba5f4SPaul Zimmerman if (dwc2_assign_and_init_hc(hsotg, qh)) 2762197ba5f4SPaul Zimmerman break; 2763197ba5f4SPaul Zimmerman 2764197ba5f4SPaul Zimmerman /* 2765197ba5f4SPaul Zimmerman * Move the QH from the periodic ready schedule to the 2766197ba5f4SPaul Zimmerman * periodic assigned schedule 2767197ba5f4SPaul Zimmerman */ 2768197ba5f4SPaul Zimmerman qh_ptr = qh_ptr->next; 276994ef7aeeSDouglas Anderson list_move_tail(&qh->qh_list_entry, 277094ef7aeeSDouglas Anderson &hsotg->periodic_sched_assigned); 2771197ba5f4SPaul Zimmerman ret_val = DWC2_TRANSACTION_PERIODIC; 2772197ba5f4SPaul Zimmerman } 2773197ba5f4SPaul Zimmerman 2774197ba5f4SPaul Zimmerman /* 2775197ba5f4SPaul Zimmerman * Process entries in the inactive portion of the non-periodic 2776197ba5f4SPaul Zimmerman * schedule. Some free host channels may not be used if they are 2777197ba5f4SPaul Zimmerman * reserved for periodic transfers. 2778197ba5f4SPaul Zimmerman */ 2779bea8e86cSJohn Youn num_channels = hsotg->params.host_channels; 2780197ba5f4SPaul Zimmerman qh_ptr = hsotg->non_periodic_sched_inactive.next; 2781197ba5f4SPaul Zimmerman while (qh_ptr != &hsotg->non_periodic_sched_inactive) { 2782bea8e86cSJohn Youn if (hsotg->params.uframe_sched <= 0 && 2783197ba5f4SPaul Zimmerman hsotg->non_periodic_channels >= num_channels - 2784197ba5f4SPaul Zimmerman hsotg->periodic_channels) 2785197ba5f4SPaul Zimmerman break; 2786197ba5f4SPaul Zimmerman if (list_empty(&hsotg->free_hc_list)) 2787197ba5f4SPaul Zimmerman break; 2788197ba5f4SPaul Zimmerman qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); 2789bea8e86cSJohn Youn if (hsotg->params.uframe_sched > 0) { 2790197ba5f4SPaul Zimmerman if (hsotg->available_host_channels < 1) 2791197ba5f4SPaul Zimmerman break; 2792197ba5f4SPaul Zimmerman hsotg->available_host_channels--; 2793197ba5f4SPaul Zimmerman } 2794197ba5f4SPaul Zimmerman 2795197ba5f4SPaul Zimmerman if (dwc2_assign_and_init_hc(hsotg, qh)) 2796197ba5f4SPaul Zimmerman break; 2797197ba5f4SPaul Zimmerman 2798197ba5f4SPaul Zimmerman /* 2799197ba5f4SPaul Zimmerman * Move the QH from the non-periodic inactive schedule to the 2800197ba5f4SPaul Zimmerman * non-periodic active schedule 2801197ba5f4SPaul Zimmerman */ 2802197ba5f4SPaul Zimmerman qh_ptr = qh_ptr->next; 280394ef7aeeSDouglas Anderson list_move_tail(&qh->qh_list_entry, 2804197ba5f4SPaul Zimmerman &hsotg->non_periodic_sched_active); 2805197ba5f4SPaul Zimmerman 2806197ba5f4SPaul Zimmerman if (ret_val == DWC2_TRANSACTION_NONE) 2807197ba5f4SPaul Zimmerman ret_val = DWC2_TRANSACTION_NON_PERIODIC; 2808197ba5f4SPaul Zimmerman else 2809197ba5f4SPaul Zimmerman ret_val = DWC2_TRANSACTION_ALL; 2810197ba5f4SPaul Zimmerman 2811bea8e86cSJohn Youn if (hsotg->params.uframe_sched <= 0) 2812197ba5f4SPaul Zimmerman hsotg->non_periodic_channels++; 2813197ba5f4SPaul Zimmerman } 2814197ba5f4SPaul Zimmerman 2815197ba5f4SPaul Zimmerman return ret_val; 2816197ba5f4SPaul Zimmerman } 2817197ba5f4SPaul Zimmerman 2818197ba5f4SPaul Zimmerman /** 2819197ba5f4SPaul Zimmerman * dwc2_queue_transaction() - Attempts to queue a single transaction request for 2820197ba5f4SPaul Zimmerman * a host channel associated with either a periodic or non-periodic transfer 2821197ba5f4SPaul Zimmerman * 2822197ba5f4SPaul Zimmerman * @hsotg: The HCD state structure 2823197ba5f4SPaul Zimmerman * @chan: Host channel descriptor associated with either a periodic or 2824197ba5f4SPaul Zimmerman * non-periodic transfer 2825197ba5f4SPaul Zimmerman * @fifo_dwords_avail: Number of DWORDs available in the periodic Tx FIFO 2826197ba5f4SPaul Zimmerman * for periodic transfers or the non-periodic Tx FIFO 2827197ba5f4SPaul Zimmerman * for non-periodic transfers 2828197ba5f4SPaul Zimmerman * 2829197ba5f4SPaul Zimmerman * Return: 1 if a request is queued and more requests may be needed to 2830197ba5f4SPaul Zimmerman * complete the transfer, 0 if no more requests are required for this 2831197ba5f4SPaul Zimmerman * transfer, -1 if there is insufficient space in the Tx FIFO 2832197ba5f4SPaul Zimmerman * 2833197ba5f4SPaul Zimmerman * This function assumes that there is space available in the appropriate 2834197ba5f4SPaul Zimmerman * request queue. For an OUT transfer or SETUP transaction in Slave mode, 2835197ba5f4SPaul Zimmerman * it checks whether space is available in the appropriate Tx FIFO. 2836197ba5f4SPaul Zimmerman * 2837197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 2838197ba5f4SPaul Zimmerman */ 2839197ba5f4SPaul Zimmerman static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, 2840197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan, 2841197ba5f4SPaul Zimmerman u16 fifo_dwords_avail) 2842197ba5f4SPaul Zimmerman { 2843197ba5f4SPaul Zimmerman int retval = 0; 2844197ba5f4SPaul Zimmerman 2845c9c8ac01SDouglas Anderson if (chan->do_split) 2846c9c8ac01SDouglas Anderson /* Put ourselves on the list to keep order straight */ 2847c9c8ac01SDouglas Anderson list_move_tail(&chan->split_order_list_entry, 2848c9c8ac01SDouglas Anderson &hsotg->split_order); 2849c9c8ac01SDouglas Anderson 2850*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 2851bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable > 0) { 2852197ba5f4SPaul Zimmerman if (!chan->xfer_started || 2853197ba5f4SPaul Zimmerman chan->ep_type == USB_ENDPOINT_XFER_ISOC) { 2854197ba5f4SPaul Zimmerman dwc2_hcd_start_xfer_ddma(hsotg, chan->qh); 2855197ba5f4SPaul Zimmerman chan->qh->ping_state = 0; 2856197ba5f4SPaul Zimmerman } 2857197ba5f4SPaul Zimmerman } else if (!chan->xfer_started) { 2858197ba5f4SPaul Zimmerman dwc2_hc_start_transfer(hsotg, chan); 2859197ba5f4SPaul Zimmerman chan->qh->ping_state = 0; 2860197ba5f4SPaul Zimmerman } 2861197ba5f4SPaul Zimmerman } else if (chan->halt_pending) { 2862197ba5f4SPaul Zimmerman /* Don't queue a request if the channel has been halted */ 2863197ba5f4SPaul Zimmerman } else if (chan->halt_on_queue) { 2864197ba5f4SPaul Zimmerman dwc2_hc_halt(hsotg, chan, chan->halt_status); 2865197ba5f4SPaul Zimmerman } else if (chan->do_ping) { 2866197ba5f4SPaul Zimmerman if (!chan->xfer_started) 2867197ba5f4SPaul Zimmerman dwc2_hc_start_transfer(hsotg, chan); 2868197ba5f4SPaul Zimmerman } else if (!chan->ep_is_in || 2869197ba5f4SPaul Zimmerman chan->data_pid_start == DWC2_HC_PID_SETUP) { 2870197ba5f4SPaul Zimmerman if ((fifo_dwords_avail * 4) >= chan->max_packet) { 2871197ba5f4SPaul Zimmerman if (!chan->xfer_started) { 2872197ba5f4SPaul Zimmerman dwc2_hc_start_transfer(hsotg, chan); 2873197ba5f4SPaul Zimmerman retval = 1; 2874197ba5f4SPaul Zimmerman } else { 2875197ba5f4SPaul Zimmerman retval = dwc2_hc_continue_transfer(hsotg, chan); 2876197ba5f4SPaul Zimmerman } 2877197ba5f4SPaul Zimmerman } else { 2878197ba5f4SPaul Zimmerman retval = -1; 2879197ba5f4SPaul Zimmerman } 2880197ba5f4SPaul Zimmerman } else { 2881197ba5f4SPaul Zimmerman if (!chan->xfer_started) { 2882197ba5f4SPaul Zimmerman dwc2_hc_start_transfer(hsotg, chan); 2883197ba5f4SPaul Zimmerman retval = 1; 2884197ba5f4SPaul Zimmerman } else { 2885197ba5f4SPaul Zimmerman retval = dwc2_hc_continue_transfer(hsotg, chan); 2886197ba5f4SPaul Zimmerman } 2887197ba5f4SPaul Zimmerman } 2888197ba5f4SPaul Zimmerman 2889197ba5f4SPaul Zimmerman return retval; 2890197ba5f4SPaul Zimmerman } 2891197ba5f4SPaul Zimmerman 2892197ba5f4SPaul Zimmerman /* 2893197ba5f4SPaul Zimmerman * Processes periodic channels for the next frame and queues transactions for 2894197ba5f4SPaul Zimmerman * these channels to the DWC_otg controller. After queueing transactions, the 2895197ba5f4SPaul Zimmerman * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions 2896197ba5f4SPaul Zimmerman * to queue as Periodic Tx FIFO or request queue space becomes available. 2897197ba5f4SPaul Zimmerman * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. 2898197ba5f4SPaul Zimmerman * 2899197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 2900197ba5f4SPaul Zimmerman */ 2901197ba5f4SPaul Zimmerman static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) 2902197ba5f4SPaul Zimmerman { 2903197ba5f4SPaul Zimmerman struct list_head *qh_ptr; 2904197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 2905197ba5f4SPaul Zimmerman u32 tx_status; 2906197ba5f4SPaul Zimmerman u32 fspcavail; 2907197ba5f4SPaul Zimmerman u32 gintmsk; 2908197ba5f4SPaul Zimmerman int status; 29094e50e011SDouglas Anderson bool no_queue_space = false; 29104e50e011SDouglas Anderson bool no_fifo_space = false; 2911197ba5f4SPaul Zimmerman u32 qspcavail; 2912197ba5f4SPaul Zimmerman 29134e50e011SDouglas Anderson /* If empty list then just adjust interrupt enables */ 29144e50e011SDouglas Anderson if (list_empty(&hsotg->periodic_sched_assigned)) 29154e50e011SDouglas Anderson goto exit; 29164e50e011SDouglas Anderson 2917197ba5f4SPaul Zimmerman if (dbg_perio()) 2918197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "Queue periodic transactions\n"); 2919197ba5f4SPaul Zimmerman 292095c8bc36SAntti Seppälä tx_status = dwc2_readl(hsotg->regs + HPTXSTS); 2921197ba5f4SPaul Zimmerman qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> 2922197ba5f4SPaul Zimmerman TXSTS_QSPCAVAIL_SHIFT; 2923197ba5f4SPaul Zimmerman fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> 2924197ba5f4SPaul Zimmerman TXSTS_FSPCAVAIL_SHIFT; 2925197ba5f4SPaul Zimmerman 2926197ba5f4SPaul Zimmerman if (dbg_perio()) { 2927197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " P Tx Req Queue Space Avail (before queue): %d\n", 2928197ba5f4SPaul Zimmerman qspcavail); 2929197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " P Tx FIFO Space Avail (before queue): %d\n", 2930197ba5f4SPaul Zimmerman fspcavail); 2931197ba5f4SPaul Zimmerman } 2932197ba5f4SPaul Zimmerman 2933197ba5f4SPaul Zimmerman qh_ptr = hsotg->periodic_sched_assigned.next; 2934197ba5f4SPaul Zimmerman while (qh_ptr != &hsotg->periodic_sched_assigned) { 293595c8bc36SAntti Seppälä tx_status = dwc2_readl(hsotg->regs + HPTXSTS); 2936197ba5f4SPaul Zimmerman qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> 2937197ba5f4SPaul Zimmerman TXSTS_QSPCAVAIL_SHIFT; 2938197ba5f4SPaul Zimmerman if (qspcavail == 0) { 2939197ba5f4SPaul Zimmerman no_queue_space = 1; 2940197ba5f4SPaul Zimmerman break; 2941197ba5f4SPaul Zimmerman } 2942197ba5f4SPaul Zimmerman 2943197ba5f4SPaul Zimmerman qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); 2944197ba5f4SPaul Zimmerman if (!qh->channel) { 2945197ba5f4SPaul Zimmerman qh_ptr = qh_ptr->next; 2946197ba5f4SPaul Zimmerman continue; 2947197ba5f4SPaul Zimmerman } 2948197ba5f4SPaul Zimmerman 2949197ba5f4SPaul Zimmerman /* Make sure EP's TT buffer is clean before queueing qtds */ 2950197ba5f4SPaul Zimmerman if (qh->tt_buffer_dirty) { 2951197ba5f4SPaul Zimmerman qh_ptr = qh_ptr->next; 2952197ba5f4SPaul Zimmerman continue; 2953197ba5f4SPaul Zimmerman } 2954197ba5f4SPaul Zimmerman 2955197ba5f4SPaul Zimmerman /* 2956197ba5f4SPaul Zimmerman * Set a flag if we're queuing high-bandwidth in slave mode. 2957197ba5f4SPaul Zimmerman * The flag prevents any halts to get into the request queue in 2958197ba5f4SPaul Zimmerman * the middle of multiple high-bandwidth packets getting queued. 2959197ba5f4SPaul Zimmerman */ 2960*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0 && 2961197ba5f4SPaul Zimmerman qh->channel->multi_count > 1) 2962197ba5f4SPaul Zimmerman hsotg->queuing_high_bandwidth = 1; 2963197ba5f4SPaul Zimmerman 2964197ba5f4SPaul Zimmerman fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> 2965197ba5f4SPaul Zimmerman TXSTS_FSPCAVAIL_SHIFT; 2966197ba5f4SPaul Zimmerman status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail); 2967197ba5f4SPaul Zimmerman if (status < 0) { 2968197ba5f4SPaul Zimmerman no_fifo_space = 1; 2969197ba5f4SPaul Zimmerman break; 2970197ba5f4SPaul Zimmerman } 2971197ba5f4SPaul Zimmerman 2972197ba5f4SPaul Zimmerman /* 2973197ba5f4SPaul Zimmerman * In Slave mode, stay on the current transfer until there is 2974197ba5f4SPaul Zimmerman * nothing more to do or the high-bandwidth request count is 2975197ba5f4SPaul Zimmerman * reached. In DMA mode, only need to queue one request. The 2976197ba5f4SPaul Zimmerman * controller automatically handles multiple packets for 2977197ba5f4SPaul Zimmerman * high-bandwidth transfers. 2978197ba5f4SPaul Zimmerman */ 2979*e7839f99SJohn Youn if (hsotg->params.host_dma > 0 || status == 0 || 2980197ba5f4SPaul Zimmerman qh->channel->requests == qh->channel->multi_count) { 2981197ba5f4SPaul Zimmerman qh_ptr = qh_ptr->next; 2982197ba5f4SPaul Zimmerman /* 2983197ba5f4SPaul Zimmerman * Move the QH from the periodic assigned schedule to 2984197ba5f4SPaul Zimmerman * the periodic queued schedule 2985197ba5f4SPaul Zimmerman */ 298694ef7aeeSDouglas Anderson list_move_tail(&qh->qh_list_entry, 2987197ba5f4SPaul Zimmerman &hsotg->periodic_sched_queued); 2988197ba5f4SPaul Zimmerman 2989197ba5f4SPaul Zimmerman /* done queuing high bandwidth */ 2990197ba5f4SPaul Zimmerman hsotg->queuing_high_bandwidth = 0; 2991197ba5f4SPaul Zimmerman } 2992197ba5f4SPaul Zimmerman } 2993197ba5f4SPaul Zimmerman 29944e50e011SDouglas Anderson exit: 29954e50e011SDouglas Anderson if (no_queue_space || no_fifo_space || 2996*e7839f99SJohn Youn (hsotg->params.host_dma <= 0 && 29974e50e011SDouglas Anderson !list_empty(&hsotg->periodic_sched_assigned))) { 2998197ba5f4SPaul Zimmerman /* 2999197ba5f4SPaul Zimmerman * May need to queue more transactions as the request 3000197ba5f4SPaul Zimmerman * queue or Tx FIFO empties. Enable the periodic Tx 3001197ba5f4SPaul Zimmerman * FIFO empty interrupt. (Always use the half-empty 3002197ba5f4SPaul Zimmerman * level to ensure that new requests are loaded as 3003197ba5f4SPaul Zimmerman * soon as possible.) 3004197ba5f4SPaul Zimmerman */ 300595c8bc36SAntti Seppälä gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 30064e50e011SDouglas Anderson if (!(gintmsk & GINTSTS_PTXFEMP)) { 3007197ba5f4SPaul Zimmerman gintmsk |= GINTSTS_PTXFEMP; 300895c8bc36SAntti Seppälä dwc2_writel(gintmsk, hsotg->regs + GINTMSK); 30094e50e011SDouglas Anderson } 3010197ba5f4SPaul Zimmerman } else { 3011197ba5f4SPaul Zimmerman /* 3012197ba5f4SPaul Zimmerman * Disable the Tx FIFO empty interrupt since there are 3013197ba5f4SPaul Zimmerman * no more transactions that need to be queued right 3014197ba5f4SPaul Zimmerman * now. This function is called from interrupt 3015197ba5f4SPaul Zimmerman * handlers to queue more transactions as transfer 3016197ba5f4SPaul Zimmerman * states change. 3017197ba5f4SPaul Zimmerman */ 301895c8bc36SAntti Seppälä gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 30194e50e011SDouglas Anderson if (gintmsk & GINTSTS_PTXFEMP) { 3020197ba5f4SPaul Zimmerman gintmsk &= ~GINTSTS_PTXFEMP; 302195c8bc36SAntti Seppälä dwc2_writel(gintmsk, hsotg->regs + GINTMSK); 3022197ba5f4SPaul Zimmerman } 3023197ba5f4SPaul Zimmerman } 3024197ba5f4SPaul Zimmerman } 3025197ba5f4SPaul Zimmerman 3026197ba5f4SPaul Zimmerman /* 3027197ba5f4SPaul Zimmerman * Processes active non-periodic channels and queues transactions for these 3028197ba5f4SPaul Zimmerman * channels to the DWC_otg controller. After queueing transactions, the NP Tx 3029197ba5f4SPaul Zimmerman * FIFO Empty interrupt is enabled if there are more transactions to queue as 3030197ba5f4SPaul Zimmerman * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx 3031197ba5f4SPaul Zimmerman * FIFO Empty interrupt is disabled. 3032197ba5f4SPaul Zimmerman * 3033197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 3034197ba5f4SPaul Zimmerman */ 3035197ba5f4SPaul Zimmerman static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) 3036197ba5f4SPaul Zimmerman { 3037197ba5f4SPaul Zimmerman struct list_head *orig_qh_ptr; 3038197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 3039197ba5f4SPaul Zimmerman u32 tx_status; 3040197ba5f4SPaul Zimmerman u32 qspcavail; 3041197ba5f4SPaul Zimmerman u32 fspcavail; 3042197ba5f4SPaul Zimmerman u32 gintmsk; 3043197ba5f4SPaul Zimmerman int status; 3044197ba5f4SPaul Zimmerman int no_queue_space = 0; 3045197ba5f4SPaul Zimmerman int no_fifo_space = 0; 3046197ba5f4SPaul Zimmerman int more_to_do = 0; 3047197ba5f4SPaul Zimmerman 3048197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n"); 3049197ba5f4SPaul Zimmerman 305095c8bc36SAntti Seppälä tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); 3051197ba5f4SPaul Zimmerman qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> 3052197ba5f4SPaul Zimmerman TXSTS_QSPCAVAIL_SHIFT; 3053197ba5f4SPaul Zimmerman fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> 3054197ba5f4SPaul Zimmerman TXSTS_FSPCAVAIL_SHIFT; 3055197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " NP Tx Req Queue Space Avail (before queue): %d\n", 3056197ba5f4SPaul Zimmerman qspcavail); 3057197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " NP Tx FIFO Space Avail (before queue): %d\n", 3058197ba5f4SPaul Zimmerman fspcavail); 3059197ba5f4SPaul Zimmerman 3060197ba5f4SPaul Zimmerman /* 3061197ba5f4SPaul Zimmerman * Keep track of the starting point. Skip over the start-of-list 3062197ba5f4SPaul Zimmerman * entry. 3063197ba5f4SPaul Zimmerman */ 3064197ba5f4SPaul Zimmerman if (hsotg->non_periodic_qh_ptr == &hsotg->non_periodic_sched_active) 3065197ba5f4SPaul Zimmerman hsotg->non_periodic_qh_ptr = hsotg->non_periodic_qh_ptr->next; 3066197ba5f4SPaul Zimmerman orig_qh_ptr = hsotg->non_periodic_qh_ptr; 3067197ba5f4SPaul Zimmerman 3068197ba5f4SPaul Zimmerman /* 3069197ba5f4SPaul Zimmerman * Process once through the active list or until no more space is 3070197ba5f4SPaul Zimmerman * available in the request queue or the Tx FIFO 3071197ba5f4SPaul Zimmerman */ 3072197ba5f4SPaul Zimmerman do { 307395c8bc36SAntti Seppälä tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); 3074197ba5f4SPaul Zimmerman qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> 3075197ba5f4SPaul Zimmerman TXSTS_QSPCAVAIL_SHIFT; 3076*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0 && qspcavail == 0) { 3077197ba5f4SPaul Zimmerman no_queue_space = 1; 3078197ba5f4SPaul Zimmerman break; 3079197ba5f4SPaul Zimmerman } 3080197ba5f4SPaul Zimmerman 3081197ba5f4SPaul Zimmerman qh = list_entry(hsotg->non_periodic_qh_ptr, struct dwc2_qh, 3082197ba5f4SPaul Zimmerman qh_list_entry); 3083197ba5f4SPaul Zimmerman if (!qh->channel) 3084197ba5f4SPaul Zimmerman goto next; 3085197ba5f4SPaul Zimmerman 3086197ba5f4SPaul Zimmerman /* Make sure EP's TT buffer is clean before queueing qtds */ 3087197ba5f4SPaul Zimmerman if (qh->tt_buffer_dirty) 3088197ba5f4SPaul Zimmerman goto next; 3089197ba5f4SPaul Zimmerman 3090197ba5f4SPaul Zimmerman fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> 3091197ba5f4SPaul Zimmerman TXSTS_FSPCAVAIL_SHIFT; 3092197ba5f4SPaul Zimmerman status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail); 3093197ba5f4SPaul Zimmerman 3094197ba5f4SPaul Zimmerman if (status > 0) { 3095197ba5f4SPaul Zimmerman more_to_do = 1; 3096197ba5f4SPaul Zimmerman } else if (status < 0) { 3097197ba5f4SPaul Zimmerman no_fifo_space = 1; 3098197ba5f4SPaul Zimmerman break; 3099197ba5f4SPaul Zimmerman } 3100197ba5f4SPaul Zimmerman next: 3101197ba5f4SPaul Zimmerman /* Advance to next QH, skipping start-of-list entry */ 3102197ba5f4SPaul Zimmerman hsotg->non_periodic_qh_ptr = hsotg->non_periodic_qh_ptr->next; 3103197ba5f4SPaul Zimmerman if (hsotg->non_periodic_qh_ptr == 3104197ba5f4SPaul Zimmerman &hsotg->non_periodic_sched_active) 3105197ba5f4SPaul Zimmerman hsotg->non_periodic_qh_ptr = 3106197ba5f4SPaul Zimmerman hsotg->non_periodic_qh_ptr->next; 3107197ba5f4SPaul Zimmerman } while (hsotg->non_periodic_qh_ptr != orig_qh_ptr); 3108197ba5f4SPaul Zimmerman 3109*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) { 311095c8bc36SAntti Seppälä tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); 3111197ba5f4SPaul Zimmerman qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> 3112197ba5f4SPaul Zimmerman TXSTS_QSPCAVAIL_SHIFT; 3113197ba5f4SPaul Zimmerman fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> 3114197ba5f4SPaul Zimmerman TXSTS_FSPCAVAIL_SHIFT; 3115197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, 3116197ba5f4SPaul Zimmerman " NP Tx Req Queue Space Avail (after queue): %d\n", 3117197ba5f4SPaul Zimmerman qspcavail); 3118197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, 3119197ba5f4SPaul Zimmerman " NP Tx FIFO Space Avail (after queue): %d\n", 3120197ba5f4SPaul Zimmerman fspcavail); 3121197ba5f4SPaul Zimmerman 3122197ba5f4SPaul Zimmerman if (more_to_do || no_queue_space || no_fifo_space) { 3123197ba5f4SPaul Zimmerman /* 3124197ba5f4SPaul Zimmerman * May need to queue more transactions as the request 3125197ba5f4SPaul Zimmerman * queue or Tx FIFO empties. Enable the non-periodic 3126197ba5f4SPaul Zimmerman * Tx FIFO empty interrupt. (Always use the half-empty 3127197ba5f4SPaul Zimmerman * level to ensure that new requests are loaded as 3128197ba5f4SPaul Zimmerman * soon as possible.) 3129197ba5f4SPaul Zimmerman */ 313095c8bc36SAntti Seppälä gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 3131197ba5f4SPaul Zimmerman gintmsk |= GINTSTS_NPTXFEMP; 313295c8bc36SAntti Seppälä dwc2_writel(gintmsk, hsotg->regs + GINTMSK); 3133197ba5f4SPaul Zimmerman } else { 3134197ba5f4SPaul Zimmerman /* 3135197ba5f4SPaul Zimmerman * Disable the Tx FIFO empty interrupt since there are 3136197ba5f4SPaul Zimmerman * no more transactions that need to be queued right 3137197ba5f4SPaul Zimmerman * now. This function is called from interrupt 3138197ba5f4SPaul Zimmerman * handlers to queue more transactions as transfer 3139197ba5f4SPaul Zimmerman * states change. 3140197ba5f4SPaul Zimmerman */ 314195c8bc36SAntti Seppälä gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 3142197ba5f4SPaul Zimmerman gintmsk &= ~GINTSTS_NPTXFEMP; 314395c8bc36SAntti Seppälä dwc2_writel(gintmsk, hsotg->regs + GINTMSK); 3144197ba5f4SPaul Zimmerman } 3145197ba5f4SPaul Zimmerman } 3146197ba5f4SPaul Zimmerman } 3147197ba5f4SPaul Zimmerman 3148197ba5f4SPaul Zimmerman /** 3149197ba5f4SPaul Zimmerman * dwc2_hcd_queue_transactions() - Processes the currently active host channels 3150197ba5f4SPaul Zimmerman * and queues transactions for these channels to the DWC_otg controller. Called 3151197ba5f4SPaul Zimmerman * from the HCD interrupt handler functions. 3152197ba5f4SPaul Zimmerman * 3153197ba5f4SPaul Zimmerman * @hsotg: The HCD state structure 3154197ba5f4SPaul Zimmerman * @tr_type: The type(s) of transactions to queue (non-periodic, periodic, 3155197ba5f4SPaul Zimmerman * or both) 3156197ba5f4SPaul Zimmerman * 3157197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 3158197ba5f4SPaul Zimmerman */ 3159197ba5f4SPaul Zimmerman void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, 3160197ba5f4SPaul Zimmerman enum dwc2_transaction_type tr_type) 3161197ba5f4SPaul Zimmerman { 3162197ba5f4SPaul Zimmerman #ifdef DWC2_DEBUG_SOF 3163197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "Queue Transactions\n"); 3164197ba5f4SPaul Zimmerman #endif 3165197ba5f4SPaul Zimmerman /* Process host channels associated with periodic transfers */ 31664e50e011SDouglas Anderson if (tr_type == DWC2_TRANSACTION_PERIODIC || 31674e50e011SDouglas Anderson tr_type == DWC2_TRANSACTION_ALL) 3168197ba5f4SPaul Zimmerman dwc2_process_periodic_channels(hsotg); 3169197ba5f4SPaul Zimmerman 3170197ba5f4SPaul Zimmerman /* Process host channels associated with non-periodic transfers */ 3171197ba5f4SPaul Zimmerman if (tr_type == DWC2_TRANSACTION_NON_PERIODIC || 3172197ba5f4SPaul Zimmerman tr_type == DWC2_TRANSACTION_ALL) { 3173197ba5f4SPaul Zimmerman if (!list_empty(&hsotg->non_periodic_sched_active)) { 3174197ba5f4SPaul Zimmerman dwc2_process_non_periodic_channels(hsotg); 3175197ba5f4SPaul Zimmerman } else { 3176197ba5f4SPaul Zimmerman /* 3177197ba5f4SPaul Zimmerman * Ensure NP Tx FIFO empty interrupt is disabled when 3178197ba5f4SPaul Zimmerman * there are no non-periodic transfers to process 3179197ba5f4SPaul Zimmerman */ 318095c8bc36SAntti Seppälä u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 3181197ba5f4SPaul Zimmerman 3182197ba5f4SPaul Zimmerman gintmsk &= ~GINTSTS_NPTXFEMP; 318395c8bc36SAntti Seppälä dwc2_writel(gintmsk, hsotg->regs + GINTMSK); 3184197ba5f4SPaul Zimmerman } 3185197ba5f4SPaul Zimmerman } 3186197ba5f4SPaul Zimmerman } 3187197ba5f4SPaul Zimmerman 3188197ba5f4SPaul Zimmerman static void dwc2_conn_id_status_change(struct work_struct *work) 3189197ba5f4SPaul Zimmerman { 3190197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, 3191197ba5f4SPaul Zimmerman wf_otg); 3192197ba5f4SPaul Zimmerman u32 count = 0; 3193197ba5f4SPaul Zimmerman u32 gotgctl; 31945390d438SMian Yousaf Kaukab unsigned long flags; 3195197ba5f4SPaul Zimmerman 3196197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "%s()\n", __func__); 3197197ba5f4SPaul Zimmerman 319895c8bc36SAntti Seppälä gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); 3199197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl); 3200197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n", 3201197ba5f4SPaul Zimmerman !!(gotgctl & GOTGCTL_CONID_B)); 3202197ba5f4SPaul Zimmerman 3203197ba5f4SPaul Zimmerman /* B-Device connector (Device Mode) */ 3204197ba5f4SPaul Zimmerman if (gotgctl & GOTGCTL_CONID_B) { 3205197ba5f4SPaul Zimmerman /* Wait for switch to device mode */ 3206197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "connId B\n"); 3207197ba5f4SPaul Zimmerman while (!dwc2_is_device_mode(hsotg)) { 3208197ba5f4SPaul Zimmerman dev_info(hsotg->dev, 3209197ba5f4SPaul Zimmerman "Waiting for Peripheral Mode, Mode=%s\n", 3210197ba5f4SPaul Zimmerman dwc2_is_host_mode(hsotg) ? "Host" : 3211197ba5f4SPaul Zimmerman "Peripheral"); 3212197ba5f4SPaul Zimmerman usleep_range(20000, 40000); 3213197ba5f4SPaul Zimmerman if (++count > 250) 3214197ba5f4SPaul Zimmerman break; 3215197ba5f4SPaul Zimmerman } 3216197ba5f4SPaul Zimmerman if (count > 250) 3217197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 3218197ba5f4SPaul Zimmerman "Connection id status change timed out\n"); 3219197ba5f4SPaul Zimmerman hsotg->op_state = OTG_STATE_B_PERIPHERAL; 32200fe239bcSDouglas Anderson dwc2_core_init(hsotg, false); 3221197ba5f4SPaul Zimmerman dwc2_enable_global_interrupts(hsotg); 32225390d438SMian Yousaf Kaukab spin_lock_irqsave(&hsotg->lock, flags); 32231f91b4ccSFelipe Balbi dwc2_hsotg_core_init_disconnected(hsotg, false); 32245390d438SMian Yousaf Kaukab spin_unlock_irqrestore(&hsotg->lock, flags); 32251f91b4ccSFelipe Balbi dwc2_hsotg_core_connect(hsotg); 3226197ba5f4SPaul Zimmerman } else { 3227197ba5f4SPaul Zimmerman /* A-Device connector (Host Mode) */ 3228197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "connId A\n"); 3229197ba5f4SPaul Zimmerman while (!dwc2_is_host_mode(hsotg)) { 3230197ba5f4SPaul Zimmerman dev_info(hsotg->dev, "Waiting for Host Mode, Mode=%s\n", 3231197ba5f4SPaul Zimmerman dwc2_is_host_mode(hsotg) ? 3232197ba5f4SPaul Zimmerman "Host" : "Peripheral"); 3233197ba5f4SPaul Zimmerman usleep_range(20000, 40000); 3234197ba5f4SPaul Zimmerman if (++count > 250) 3235197ba5f4SPaul Zimmerman break; 3236197ba5f4SPaul Zimmerman } 3237197ba5f4SPaul Zimmerman if (count > 250) 3238197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 3239197ba5f4SPaul Zimmerman "Connection id status change timed out\n"); 3240197ba5f4SPaul Zimmerman hsotg->op_state = OTG_STATE_A_HOST; 3241197ba5f4SPaul Zimmerman 3242197ba5f4SPaul Zimmerman /* Initialize the Core for Host mode */ 32430fe239bcSDouglas Anderson dwc2_core_init(hsotg, false); 3244197ba5f4SPaul Zimmerman dwc2_enable_global_interrupts(hsotg); 3245197ba5f4SPaul Zimmerman dwc2_hcd_start(hsotg); 3246197ba5f4SPaul Zimmerman } 3247197ba5f4SPaul Zimmerman } 3248197ba5f4SPaul Zimmerman 3249197ba5f4SPaul Zimmerman static void dwc2_wakeup_detected(unsigned long data) 3250197ba5f4SPaul Zimmerman { 3251197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = (struct dwc2_hsotg *)data; 3252197ba5f4SPaul Zimmerman u32 hprt0; 3253197ba5f4SPaul Zimmerman 3254197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "%s()\n", __func__); 3255197ba5f4SPaul Zimmerman 3256197ba5f4SPaul Zimmerman /* 3257197ba5f4SPaul Zimmerman * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms 3258197ba5f4SPaul Zimmerman * so that OPT tests pass with all PHYs.) 3259197ba5f4SPaul Zimmerman */ 3260197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3261197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Resume: HPRT0=%0x\n", hprt0); 3262197ba5f4SPaul Zimmerman hprt0 &= ~HPRT0_RES; 326395c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3264197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n", 326595c8bc36SAntti Seppälä dwc2_readl(hsotg->regs + HPRT0)); 3266197ba5f4SPaul Zimmerman 3267197ba5f4SPaul Zimmerman dwc2_hcd_rem_wakeup(hsotg); 32681fb7f12dSDouglas Anderson hsotg->bus_suspended = 0; 3269197ba5f4SPaul Zimmerman 3270197ba5f4SPaul Zimmerman /* Change to L0 state */ 3271197ba5f4SPaul Zimmerman hsotg->lx_state = DWC2_L0; 3272197ba5f4SPaul Zimmerman } 3273197ba5f4SPaul Zimmerman 3274197ba5f4SPaul Zimmerman static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg) 3275197ba5f4SPaul Zimmerman { 3276197ba5f4SPaul Zimmerman struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg); 3277197ba5f4SPaul Zimmerman 3278197ba5f4SPaul Zimmerman return hcd->self.b_hnp_enable; 3279197ba5f4SPaul Zimmerman } 3280197ba5f4SPaul Zimmerman 3281197ba5f4SPaul Zimmerman /* Must NOT be called with interrupt disabled or spinlock held */ 3282197ba5f4SPaul Zimmerman static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) 3283197ba5f4SPaul Zimmerman { 3284197ba5f4SPaul Zimmerman unsigned long flags; 3285197ba5f4SPaul Zimmerman u32 hprt0; 3286197ba5f4SPaul Zimmerman u32 pcgctl; 3287197ba5f4SPaul Zimmerman u32 gotgctl; 3288197ba5f4SPaul Zimmerman 3289197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "%s()\n", __func__); 3290197ba5f4SPaul Zimmerman 3291197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 3292197ba5f4SPaul Zimmerman 3293197ba5f4SPaul Zimmerman if (windex == hsotg->otg_port && dwc2_host_is_b_hnp_enabled(hsotg)) { 329495c8bc36SAntti Seppälä gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); 3295197ba5f4SPaul Zimmerman gotgctl |= GOTGCTL_HSTSETHNPEN; 329695c8bc36SAntti Seppälä dwc2_writel(gotgctl, hsotg->regs + GOTGCTL); 3297197ba5f4SPaul Zimmerman hsotg->op_state = OTG_STATE_A_SUSPEND; 3298197ba5f4SPaul Zimmerman } 3299197ba5f4SPaul Zimmerman 3300197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3301197ba5f4SPaul Zimmerman hprt0 |= HPRT0_SUSP; 330295c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3303197ba5f4SPaul Zimmerman 3304734643dfSGregory Herrero hsotg->bus_suspended = 1; 3305197ba5f4SPaul Zimmerman 3306a2a23d3fSGregory Herrero /* 3307a2a23d3fSGregory Herrero * If hibernation is supported, Phy clock will be suspended 3308a2a23d3fSGregory Herrero * after registers are backuped. 3309a2a23d3fSGregory Herrero */ 3310bea8e86cSJohn Youn if (!hsotg->params.hibernation) { 3311197ba5f4SPaul Zimmerman /* Suspend the Phy Clock */ 331295c8bc36SAntti Seppälä pcgctl = dwc2_readl(hsotg->regs + PCGCTL); 3313197ba5f4SPaul Zimmerman pcgctl |= PCGCTL_STOPPCLK; 331495c8bc36SAntti Seppälä dwc2_writel(pcgctl, hsotg->regs + PCGCTL); 3315197ba5f4SPaul Zimmerman udelay(10); 3316a2a23d3fSGregory Herrero } 3317197ba5f4SPaul Zimmerman 3318197ba5f4SPaul Zimmerman /* For HNP the bus must be suspended for at least 200ms */ 3319197ba5f4SPaul Zimmerman if (dwc2_host_is_b_hnp_enabled(hsotg)) { 332095c8bc36SAntti Seppälä pcgctl = dwc2_readl(hsotg->regs + PCGCTL); 3321197ba5f4SPaul Zimmerman pcgctl &= ~PCGCTL_STOPPCLK; 332295c8bc36SAntti Seppälä dwc2_writel(pcgctl, hsotg->regs + PCGCTL); 3323197ba5f4SPaul Zimmerman 3324197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 3325197ba5f4SPaul Zimmerman 3326197ba5f4SPaul Zimmerman usleep_range(200000, 250000); 3327197ba5f4SPaul Zimmerman } else { 3328197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 3329197ba5f4SPaul Zimmerman } 3330197ba5f4SPaul Zimmerman } 3331197ba5f4SPaul Zimmerman 333230db103cSGregory Herrero /* Must NOT be called with interrupt disabled or spinlock held */ 333330db103cSGregory Herrero static void dwc2_port_resume(struct dwc2_hsotg *hsotg) 333430db103cSGregory Herrero { 333530db103cSGregory Herrero unsigned long flags; 333630db103cSGregory Herrero u32 hprt0; 333730db103cSGregory Herrero u32 pcgctl; 333830db103cSGregory Herrero 33394d273c2aSDouglas Anderson spin_lock_irqsave(&hsotg->lock, flags); 33404d273c2aSDouglas Anderson 3341a2a23d3fSGregory Herrero /* 3342a2a23d3fSGregory Herrero * If hibernation is supported, Phy clock is already resumed 3343a2a23d3fSGregory Herrero * after registers restore. 3344a2a23d3fSGregory Herrero */ 3345bea8e86cSJohn Youn if (!hsotg->params.hibernation) { 334630db103cSGregory Herrero pcgctl = dwc2_readl(hsotg->regs + PCGCTL); 334730db103cSGregory Herrero pcgctl &= ~PCGCTL_STOPPCLK; 334830db103cSGregory Herrero dwc2_writel(pcgctl, hsotg->regs + PCGCTL); 33494d273c2aSDouglas Anderson spin_unlock_irqrestore(&hsotg->lock, flags); 335030db103cSGregory Herrero usleep_range(20000, 40000); 33514d273c2aSDouglas Anderson spin_lock_irqsave(&hsotg->lock, flags); 3352a2a23d3fSGregory Herrero } 335330db103cSGregory Herrero 335430db103cSGregory Herrero hprt0 = dwc2_read_hprt0(hsotg); 335530db103cSGregory Herrero hprt0 |= HPRT0_RES; 335630db103cSGregory Herrero hprt0 &= ~HPRT0_SUSP; 335730db103cSGregory Herrero dwc2_writel(hprt0, hsotg->regs + HPRT0); 335830db103cSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 335930db103cSGregory Herrero 336030db103cSGregory Herrero msleep(USB_RESUME_TIMEOUT); 336130db103cSGregory Herrero 336230db103cSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 336330db103cSGregory Herrero hprt0 = dwc2_read_hprt0(hsotg); 336430db103cSGregory Herrero hprt0 &= ~(HPRT0_RES | HPRT0_SUSP); 336530db103cSGregory Herrero dwc2_writel(hprt0, hsotg->regs + HPRT0); 3366734643dfSGregory Herrero hsotg->bus_suspended = 0; 336730db103cSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 336830db103cSGregory Herrero } 336930db103cSGregory Herrero 3370197ba5f4SPaul Zimmerman /* Handles hub class-specific requests */ 3371197ba5f4SPaul Zimmerman static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, 3372197ba5f4SPaul Zimmerman u16 wvalue, u16 windex, char *buf, u16 wlength) 3373197ba5f4SPaul Zimmerman { 3374197ba5f4SPaul Zimmerman struct usb_hub_descriptor *hub_desc; 3375197ba5f4SPaul Zimmerman int retval = 0; 3376197ba5f4SPaul Zimmerman u32 hprt0; 3377197ba5f4SPaul Zimmerman u32 port_status; 3378197ba5f4SPaul Zimmerman u32 speed; 3379197ba5f4SPaul Zimmerman u32 pcgctl; 3380197ba5f4SPaul Zimmerman 3381197ba5f4SPaul Zimmerman switch (typereq) { 3382197ba5f4SPaul Zimmerman case ClearHubFeature: 3383197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "ClearHubFeature %1xh\n", wvalue); 3384197ba5f4SPaul Zimmerman 3385197ba5f4SPaul Zimmerman switch (wvalue) { 3386197ba5f4SPaul Zimmerman case C_HUB_LOCAL_POWER: 3387197ba5f4SPaul Zimmerman case C_HUB_OVER_CURRENT: 3388197ba5f4SPaul Zimmerman /* Nothing required here */ 3389197ba5f4SPaul Zimmerman break; 3390197ba5f4SPaul Zimmerman 3391197ba5f4SPaul Zimmerman default: 3392197ba5f4SPaul Zimmerman retval = -EINVAL; 3393197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 3394197ba5f4SPaul Zimmerman "ClearHubFeature request %1xh unknown\n", 3395197ba5f4SPaul Zimmerman wvalue); 3396197ba5f4SPaul Zimmerman } 3397197ba5f4SPaul Zimmerman break; 3398197ba5f4SPaul Zimmerman 3399197ba5f4SPaul Zimmerman case ClearPortFeature: 3400197ba5f4SPaul Zimmerman if (wvalue != USB_PORT_FEAT_L1) 3401197ba5f4SPaul Zimmerman if (!windex || windex > 1) 3402197ba5f4SPaul Zimmerman goto error; 3403197ba5f4SPaul Zimmerman switch (wvalue) { 3404197ba5f4SPaul Zimmerman case USB_PORT_FEAT_ENABLE: 3405197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3406197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); 3407197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3408197ba5f4SPaul Zimmerman hprt0 |= HPRT0_ENA; 340995c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3410197ba5f4SPaul Zimmerman break; 3411197ba5f4SPaul Zimmerman 3412197ba5f4SPaul Zimmerman case USB_PORT_FEAT_SUSPEND: 3413197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3414197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); 3415b0bb9bb6SPaul Zimmerman 3416bea78555SGregory Herrero if (hsotg->bus_suspended) 341730db103cSGregory Herrero dwc2_port_resume(hsotg); 3418197ba5f4SPaul Zimmerman break; 3419197ba5f4SPaul Zimmerman 3420197ba5f4SPaul Zimmerman case USB_PORT_FEAT_POWER: 3421197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3422197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_POWER\n"); 3423197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3424197ba5f4SPaul Zimmerman hprt0 &= ~HPRT0_PWR; 342595c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3426197ba5f4SPaul Zimmerman break; 3427197ba5f4SPaul Zimmerman 3428197ba5f4SPaul Zimmerman case USB_PORT_FEAT_INDICATOR: 3429197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3430197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); 3431197ba5f4SPaul Zimmerman /* Port indicator not supported */ 3432197ba5f4SPaul Zimmerman break; 3433197ba5f4SPaul Zimmerman 3434197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_CONNECTION: 3435197ba5f4SPaul Zimmerman /* 3436197ba5f4SPaul Zimmerman * Clears driver's internal Connect Status Change flag 3437197ba5f4SPaul Zimmerman */ 3438197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3439197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); 3440197ba5f4SPaul Zimmerman hsotg->flags.b.port_connect_status_change = 0; 3441197ba5f4SPaul Zimmerman break; 3442197ba5f4SPaul Zimmerman 3443197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_RESET: 3444197ba5f4SPaul Zimmerman /* Clears driver's internal Port Reset Change flag */ 3445197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3446197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); 3447197ba5f4SPaul Zimmerman hsotg->flags.b.port_reset_change = 0; 3448197ba5f4SPaul Zimmerman break; 3449197ba5f4SPaul Zimmerman 3450197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_ENABLE: 3451197ba5f4SPaul Zimmerman /* 3452197ba5f4SPaul Zimmerman * Clears the driver's internal Port Enable/Disable 3453197ba5f4SPaul Zimmerman * Change flag 3454197ba5f4SPaul Zimmerman */ 3455197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3456197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); 3457197ba5f4SPaul Zimmerman hsotg->flags.b.port_enable_change = 0; 3458197ba5f4SPaul Zimmerman break; 3459197ba5f4SPaul Zimmerman 3460197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_SUSPEND: 3461197ba5f4SPaul Zimmerman /* 3462197ba5f4SPaul Zimmerman * Clears the driver's internal Port Suspend Change 3463197ba5f4SPaul Zimmerman * flag, which is set when resume signaling on the host 3464197ba5f4SPaul Zimmerman * port is complete 3465197ba5f4SPaul Zimmerman */ 3466197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3467197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); 3468197ba5f4SPaul Zimmerman hsotg->flags.b.port_suspend_change = 0; 3469197ba5f4SPaul Zimmerman break; 3470197ba5f4SPaul Zimmerman 3471197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_PORT_L1: 3472197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3473197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_PORT_L1\n"); 3474197ba5f4SPaul Zimmerman hsotg->flags.b.port_l1_change = 0; 3475197ba5f4SPaul Zimmerman break; 3476197ba5f4SPaul Zimmerman 3477197ba5f4SPaul Zimmerman case USB_PORT_FEAT_C_OVER_CURRENT: 3478197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3479197ba5f4SPaul Zimmerman "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); 3480197ba5f4SPaul Zimmerman hsotg->flags.b.port_over_current_change = 0; 3481197ba5f4SPaul Zimmerman break; 3482197ba5f4SPaul Zimmerman 3483197ba5f4SPaul Zimmerman default: 3484197ba5f4SPaul Zimmerman retval = -EINVAL; 3485197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 3486197ba5f4SPaul Zimmerman "ClearPortFeature request %1xh unknown or unsupported\n", 3487197ba5f4SPaul Zimmerman wvalue); 3488197ba5f4SPaul Zimmerman } 3489197ba5f4SPaul Zimmerman break; 3490197ba5f4SPaul Zimmerman 3491197ba5f4SPaul Zimmerman case GetHubDescriptor: 3492197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GetHubDescriptor\n"); 3493197ba5f4SPaul Zimmerman hub_desc = (struct usb_hub_descriptor *)buf; 3494197ba5f4SPaul Zimmerman hub_desc->bDescLength = 9; 3495a5dd0395SSergei Shtylyov hub_desc->bDescriptorType = USB_DT_HUB; 3496197ba5f4SPaul Zimmerman hub_desc->bNbrPorts = 1; 34973d040de8SSergei Shtylyov hub_desc->wHubCharacteristics = 34983d040de8SSergei Shtylyov cpu_to_le16(HUB_CHAR_COMMON_LPSM | 34993d040de8SSergei Shtylyov HUB_CHAR_INDV_PORT_OCPM); 3500197ba5f4SPaul Zimmerman hub_desc->bPwrOn2PwrGood = 1; 3501197ba5f4SPaul Zimmerman hub_desc->bHubContrCurrent = 0; 3502197ba5f4SPaul Zimmerman hub_desc->u.hs.DeviceRemovable[0] = 0; 3503197ba5f4SPaul Zimmerman hub_desc->u.hs.DeviceRemovable[1] = 0xff; 3504197ba5f4SPaul Zimmerman break; 3505197ba5f4SPaul Zimmerman 3506197ba5f4SPaul Zimmerman case GetHubStatus: 3507197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GetHubStatus\n"); 3508197ba5f4SPaul Zimmerman memset(buf, 0, 4); 3509197ba5f4SPaul Zimmerman break; 3510197ba5f4SPaul Zimmerman 3511197ba5f4SPaul Zimmerman case GetPortStatus: 3512197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, 3513197ba5f4SPaul Zimmerman "GetPortStatus wIndex=0x%04x flags=0x%08x\n", windex, 3514197ba5f4SPaul Zimmerman hsotg->flags.d32); 3515197ba5f4SPaul Zimmerman if (!windex || windex > 1) 3516197ba5f4SPaul Zimmerman goto error; 3517197ba5f4SPaul Zimmerman 3518197ba5f4SPaul Zimmerman port_status = 0; 3519197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_connect_status_change) 3520197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_CONNECTION << 16; 3521197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_enable_change) 3522197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_ENABLE << 16; 3523197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_suspend_change) 3524197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_SUSPEND << 16; 3525197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_l1_change) 3526197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_L1 << 16; 3527197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_reset_change) 3528197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_RESET << 16; 3529197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_over_current_change) { 3530197ba5f4SPaul Zimmerman dev_warn(hsotg->dev, "Overcurrent change detected\n"); 3531197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_C_OVERCURRENT << 16; 3532197ba5f4SPaul Zimmerman } 3533197ba5f4SPaul Zimmerman 3534197ba5f4SPaul Zimmerman if (!hsotg->flags.b.port_connect_status) { 3535197ba5f4SPaul Zimmerman /* 3536197ba5f4SPaul Zimmerman * The port is disconnected, which means the core is 3537197ba5f4SPaul Zimmerman * either in device mode or it soon will be. Just 3538197ba5f4SPaul Zimmerman * return 0's for the remainder of the port status 3539197ba5f4SPaul Zimmerman * since the port register can't be read if the core 3540197ba5f4SPaul Zimmerman * is in device mode. 3541197ba5f4SPaul Zimmerman */ 3542197ba5f4SPaul Zimmerman *(__le32 *)buf = cpu_to_le32(port_status); 3543197ba5f4SPaul Zimmerman break; 3544197ba5f4SPaul Zimmerman } 3545197ba5f4SPaul Zimmerman 354695c8bc36SAntti Seppälä hprt0 = dwc2_readl(hsotg->regs + HPRT0); 3547197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " HPRT0: 0x%08x\n", hprt0); 3548197ba5f4SPaul Zimmerman 3549197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_CONNSTS) 3550197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_CONNECTION; 3551197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_ENA) 3552197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_ENABLE; 3553197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_SUSP) 3554197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_SUSPEND; 3555197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_OVRCURRACT) 3556197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_OVERCURRENT; 3557197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_RST) 3558197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_RESET; 3559197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_PWR) 3560197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_POWER; 3561197ba5f4SPaul Zimmerman 3562197ba5f4SPaul Zimmerman speed = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; 3563197ba5f4SPaul Zimmerman if (speed == HPRT0_SPD_HIGH_SPEED) 3564197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_HIGH_SPEED; 3565197ba5f4SPaul Zimmerman else if (speed == HPRT0_SPD_LOW_SPEED) 3566197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_LOW_SPEED; 3567197ba5f4SPaul Zimmerman 3568197ba5f4SPaul Zimmerman if (hprt0 & HPRT0_TSTCTL_MASK) 3569197ba5f4SPaul Zimmerman port_status |= USB_PORT_STAT_TEST; 3570197ba5f4SPaul Zimmerman /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ 3571197ba5f4SPaul Zimmerman 3572bea8e86cSJohn Youn if (hsotg->params.dma_desc_fs_enable) { 3573fbb9e22bSMian Yousaf Kaukab /* 3574fbb9e22bSMian Yousaf Kaukab * Enable descriptor DMA only if a full speed 3575fbb9e22bSMian Yousaf Kaukab * device is connected. 3576fbb9e22bSMian Yousaf Kaukab */ 3577fbb9e22bSMian Yousaf Kaukab if (hsotg->new_connection && 3578fbb9e22bSMian Yousaf Kaukab ((port_status & 3579fbb9e22bSMian Yousaf Kaukab (USB_PORT_STAT_CONNECTION | 3580fbb9e22bSMian Yousaf Kaukab USB_PORT_STAT_HIGH_SPEED | 3581fbb9e22bSMian Yousaf Kaukab USB_PORT_STAT_LOW_SPEED)) == 3582fbb9e22bSMian Yousaf Kaukab USB_PORT_STAT_CONNECTION)) { 3583fbb9e22bSMian Yousaf Kaukab u32 hcfg; 3584fbb9e22bSMian Yousaf Kaukab 3585fbb9e22bSMian Yousaf Kaukab dev_info(hsotg->dev, "Enabling descriptor DMA mode\n"); 3586bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 1; 3587fbb9e22bSMian Yousaf Kaukab hcfg = dwc2_readl(hsotg->regs + HCFG); 3588fbb9e22bSMian Yousaf Kaukab hcfg |= HCFG_DESCDMA; 3589fbb9e22bSMian Yousaf Kaukab dwc2_writel(hcfg, hsotg->regs + HCFG); 3590fbb9e22bSMian Yousaf Kaukab hsotg->new_connection = false; 3591fbb9e22bSMian Yousaf Kaukab } 3592fbb9e22bSMian Yousaf Kaukab } 3593fbb9e22bSMian Yousaf Kaukab 3594197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "port_status=%08x\n", port_status); 3595197ba5f4SPaul Zimmerman *(__le32 *)buf = cpu_to_le32(port_status); 3596197ba5f4SPaul Zimmerman break; 3597197ba5f4SPaul Zimmerman 3598197ba5f4SPaul Zimmerman case SetHubFeature: 3599197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "SetHubFeature\n"); 3600197ba5f4SPaul Zimmerman /* No HUB features supported */ 3601197ba5f4SPaul Zimmerman break; 3602197ba5f4SPaul Zimmerman 3603197ba5f4SPaul Zimmerman case SetPortFeature: 3604197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "SetPortFeature\n"); 3605197ba5f4SPaul Zimmerman if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) 3606197ba5f4SPaul Zimmerman goto error; 3607197ba5f4SPaul Zimmerman 3608197ba5f4SPaul Zimmerman if (!hsotg->flags.b.port_connect_status) { 3609197ba5f4SPaul Zimmerman /* 3610197ba5f4SPaul Zimmerman * The port is disconnected, which means the core is 3611197ba5f4SPaul Zimmerman * either in device mode or it soon will be. Just 3612197ba5f4SPaul Zimmerman * return without doing anything since the port 3613197ba5f4SPaul Zimmerman * register can't be written if the core is in device 3614197ba5f4SPaul Zimmerman * mode. 3615197ba5f4SPaul Zimmerman */ 3616197ba5f4SPaul Zimmerman break; 3617197ba5f4SPaul Zimmerman } 3618197ba5f4SPaul Zimmerman 3619197ba5f4SPaul Zimmerman switch (wvalue) { 3620197ba5f4SPaul Zimmerman case USB_PORT_FEAT_SUSPEND: 3621197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3622197ba5f4SPaul Zimmerman "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); 3623197ba5f4SPaul Zimmerman if (windex != hsotg->otg_port) 3624197ba5f4SPaul Zimmerman goto error; 3625197ba5f4SPaul Zimmerman dwc2_port_suspend(hsotg, windex); 3626197ba5f4SPaul Zimmerman break; 3627197ba5f4SPaul Zimmerman 3628197ba5f4SPaul Zimmerman case USB_PORT_FEAT_POWER: 3629197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3630197ba5f4SPaul Zimmerman "SetPortFeature - USB_PORT_FEAT_POWER\n"); 3631197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3632197ba5f4SPaul Zimmerman hprt0 |= HPRT0_PWR; 363395c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3634197ba5f4SPaul Zimmerman break; 3635197ba5f4SPaul Zimmerman 3636197ba5f4SPaul Zimmerman case USB_PORT_FEAT_RESET: 3637197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3638197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3639197ba5f4SPaul Zimmerman "SetPortFeature - USB_PORT_FEAT_RESET\n"); 364095c8bc36SAntti Seppälä pcgctl = dwc2_readl(hsotg->regs + PCGCTL); 3641197ba5f4SPaul Zimmerman pcgctl &= ~(PCGCTL_ENBL_SLEEP_GATING | PCGCTL_STOPPCLK); 364295c8bc36SAntti Seppälä dwc2_writel(pcgctl, hsotg->regs + PCGCTL); 3643197ba5f4SPaul Zimmerman /* ??? Original driver does this */ 364495c8bc36SAntti Seppälä dwc2_writel(0, hsotg->regs + PCGCTL); 3645197ba5f4SPaul Zimmerman 3646197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 3647197ba5f4SPaul Zimmerman /* Clear suspend bit if resetting from suspend state */ 3648197ba5f4SPaul Zimmerman hprt0 &= ~HPRT0_SUSP; 3649197ba5f4SPaul Zimmerman 3650197ba5f4SPaul Zimmerman /* 3651197ba5f4SPaul Zimmerman * When B-Host the Port reset bit is set in the Start 3652197ba5f4SPaul Zimmerman * HCD Callback function, so that the reset is started 3653197ba5f4SPaul Zimmerman * within 1ms of the HNP success interrupt 3654197ba5f4SPaul Zimmerman */ 3655197ba5f4SPaul Zimmerman if (!dwc2_hcd_is_b_host(hsotg)) { 3656197ba5f4SPaul Zimmerman hprt0 |= HPRT0_PWR | HPRT0_RST; 3657197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3658197ba5f4SPaul Zimmerman "In host mode, hprt0=%08x\n", hprt0); 365995c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3660197ba5f4SPaul Zimmerman } 3661197ba5f4SPaul Zimmerman 3662197ba5f4SPaul Zimmerman /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ 3663197ba5f4SPaul Zimmerman usleep_range(50000, 70000); 3664197ba5f4SPaul Zimmerman hprt0 &= ~HPRT0_RST; 366595c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 3666197ba5f4SPaul Zimmerman hsotg->lx_state = DWC2_L0; /* Now back to On state */ 3667197ba5f4SPaul Zimmerman break; 3668197ba5f4SPaul Zimmerman 3669197ba5f4SPaul Zimmerman case USB_PORT_FEAT_INDICATOR: 3670197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3671197ba5f4SPaul Zimmerman "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); 3672197ba5f4SPaul Zimmerman /* Not supported */ 3673197ba5f4SPaul Zimmerman break; 3674197ba5f4SPaul Zimmerman 367596d480e6SJingwu Lin case USB_PORT_FEAT_TEST: 367696d480e6SJingwu Lin hprt0 = dwc2_read_hprt0(hsotg); 367796d480e6SJingwu Lin dev_dbg(hsotg->dev, 367896d480e6SJingwu Lin "SetPortFeature - USB_PORT_FEAT_TEST\n"); 367996d480e6SJingwu Lin hprt0 &= ~HPRT0_TSTCTL_MASK; 368096d480e6SJingwu Lin hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT; 368195c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 368296d480e6SJingwu Lin break; 368396d480e6SJingwu Lin 3684197ba5f4SPaul Zimmerman default: 3685197ba5f4SPaul Zimmerman retval = -EINVAL; 3686197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 3687197ba5f4SPaul Zimmerman "SetPortFeature %1xh unknown or unsupported\n", 3688197ba5f4SPaul Zimmerman wvalue); 3689197ba5f4SPaul Zimmerman break; 3690197ba5f4SPaul Zimmerman } 3691197ba5f4SPaul Zimmerman break; 3692197ba5f4SPaul Zimmerman 3693197ba5f4SPaul Zimmerman default: 3694197ba5f4SPaul Zimmerman error: 3695197ba5f4SPaul Zimmerman retval = -EINVAL; 3696197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3697197ba5f4SPaul Zimmerman "Unknown hub control request: %1xh wIndex: %1xh wValue: %1xh\n", 3698197ba5f4SPaul Zimmerman typereq, windex, wvalue); 3699197ba5f4SPaul Zimmerman break; 3700197ba5f4SPaul Zimmerman } 3701197ba5f4SPaul Zimmerman 3702197ba5f4SPaul Zimmerman return retval; 3703197ba5f4SPaul Zimmerman } 3704197ba5f4SPaul Zimmerman 3705197ba5f4SPaul Zimmerman static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port) 3706197ba5f4SPaul Zimmerman { 3707197ba5f4SPaul Zimmerman int retval; 3708197ba5f4SPaul Zimmerman 3709197ba5f4SPaul Zimmerman if (port != 1) 3710197ba5f4SPaul Zimmerman return -EINVAL; 3711197ba5f4SPaul Zimmerman 3712197ba5f4SPaul Zimmerman retval = (hsotg->flags.b.port_connect_status_change || 3713197ba5f4SPaul Zimmerman hsotg->flags.b.port_reset_change || 3714197ba5f4SPaul Zimmerman hsotg->flags.b.port_enable_change || 3715197ba5f4SPaul Zimmerman hsotg->flags.b.port_suspend_change || 3716197ba5f4SPaul Zimmerman hsotg->flags.b.port_over_current_change); 3717197ba5f4SPaul Zimmerman 3718197ba5f4SPaul Zimmerman if (retval) { 3719197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3720197ba5f4SPaul Zimmerman "DWC OTG HCD HUB STATUS DATA: Root port status changed\n"); 3721197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " port_connect_status_change: %d\n", 3722197ba5f4SPaul Zimmerman hsotg->flags.b.port_connect_status_change); 3723197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " port_reset_change: %d\n", 3724197ba5f4SPaul Zimmerman hsotg->flags.b.port_reset_change); 3725197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " port_enable_change: %d\n", 3726197ba5f4SPaul Zimmerman hsotg->flags.b.port_enable_change); 3727197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " port_suspend_change: %d\n", 3728197ba5f4SPaul Zimmerman hsotg->flags.b.port_suspend_change); 3729197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " port_over_current_change: %d\n", 3730197ba5f4SPaul Zimmerman hsotg->flags.b.port_over_current_change); 3731197ba5f4SPaul Zimmerman } 3732197ba5f4SPaul Zimmerman 3733197ba5f4SPaul Zimmerman return retval; 3734197ba5f4SPaul Zimmerman } 3735197ba5f4SPaul Zimmerman 3736197ba5f4SPaul Zimmerman int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) 3737197ba5f4SPaul Zimmerman { 373895c8bc36SAntti Seppälä u32 hfnum = dwc2_readl(hsotg->regs + HFNUM); 3739197ba5f4SPaul Zimmerman 3740197ba5f4SPaul Zimmerman #ifdef DWC2_DEBUG_SOF 3741197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n", 3742197ba5f4SPaul Zimmerman (hfnum & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT); 3743197ba5f4SPaul Zimmerman #endif 3744197ba5f4SPaul Zimmerman return (hfnum & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT; 3745197ba5f4SPaul Zimmerman } 3746197ba5f4SPaul Zimmerman 3747fae4e826SDouglas Anderson int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us) 3748fae4e826SDouglas Anderson { 3749fae4e826SDouglas Anderson u32 hprt = dwc2_readl(hsotg->regs + HPRT0); 3750fae4e826SDouglas Anderson u32 hfir = dwc2_readl(hsotg->regs + HFIR); 3751fae4e826SDouglas Anderson u32 hfnum = dwc2_readl(hsotg->regs + HFNUM); 3752fae4e826SDouglas Anderson unsigned int us_per_frame; 3753fae4e826SDouglas Anderson unsigned int frame_number; 3754fae4e826SDouglas Anderson unsigned int remaining; 3755fae4e826SDouglas Anderson unsigned int interval; 3756fae4e826SDouglas Anderson unsigned int phy_clks; 3757fae4e826SDouglas Anderson 3758fae4e826SDouglas Anderson /* High speed has 125 us per (micro) frame; others are 1 ms per */ 3759fae4e826SDouglas Anderson us_per_frame = (hprt & HPRT0_SPD_MASK) ? 1000 : 125; 3760fae4e826SDouglas Anderson 3761fae4e826SDouglas Anderson /* Extract fields */ 3762fae4e826SDouglas Anderson frame_number = (hfnum & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT; 3763fae4e826SDouglas Anderson remaining = (hfnum & HFNUM_FRREM_MASK) >> HFNUM_FRREM_SHIFT; 3764fae4e826SDouglas Anderson interval = (hfir & HFIR_FRINT_MASK) >> HFIR_FRINT_SHIFT; 3765fae4e826SDouglas Anderson 3766fae4e826SDouglas Anderson /* 3767fae4e826SDouglas Anderson * Number of phy clocks since the last tick of the frame number after 3768fae4e826SDouglas Anderson * "us" has passed. 3769fae4e826SDouglas Anderson */ 3770fae4e826SDouglas Anderson phy_clks = (interval - remaining) + 3771fae4e826SDouglas Anderson DIV_ROUND_UP(interval * us, us_per_frame); 3772fae4e826SDouglas Anderson 3773fae4e826SDouglas Anderson return dwc2_frame_num_inc(frame_number, phy_clks / interval); 3774fae4e826SDouglas Anderson } 3775fae4e826SDouglas Anderson 3776197ba5f4SPaul Zimmerman int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg) 3777197ba5f4SPaul Zimmerman { 3778197ba5f4SPaul Zimmerman return hsotg->op_state == OTG_STATE_B_HOST; 3779197ba5f4SPaul Zimmerman } 3780197ba5f4SPaul Zimmerman 3781197ba5f4SPaul Zimmerman static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg, 3782197ba5f4SPaul Zimmerman int iso_desc_count, 3783197ba5f4SPaul Zimmerman gfp_t mem_flags) 3784197ba5f4SPaul Zimmerman { 3785197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb; 3786197ba5f4SPaul Zimmerman u32 size = sizeof(*urb) + iso_desc_count * 3787197ba5f4SPaul Zimmerman sizeof(struct dwc2_hcd_iso_packet_desc); 3788197ba5f4SPaul Zimmerman 3789197ba5f4SPaul Zimmerman urb = kzalloc(size, mem_flags); 3790197ba5f4SPaul Zimmerman if (urb) 3791197ba5f4SPaul Zimmerman urb->packet_count = iso_desc_count; 3792197ba5f4SPaul Zimmerman return urb; 3793197ba5f4SPaul Zimmerman } 3794197ba5f4SPaul Zimmerman 3795197ba5f4SPaul Zimmerman static void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *hsotg, 3796197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb, u8 dev_addr, 3797197ba5f4SPaul Zimmerman u8 ep_num, u8 ep_type, u8 ep_dir, u16 mps) 3798197ba5f4SPaul Zimmerman { 3799197ba5f4SPaul Zimmerman if (dbg_perio() || 3800197ba5f4SPaul Zimmerman ep_type == USB_ENDPOINT_XFER_BULK || 3801197ba5f4SPaul Zimmerman ep_type == USB_ENDPOINT_XFER_CONTROL) 3802197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, 3803197ba5f4SPaul Zimmerman "addr=%d, ep_num=%d, ep_dir=%1x, ep_type=%1x, mps=%d\n", 3804197ba5f4SPaul Zimmerman dev_addr, ep_num, ep_dir, ep_type, mps); 3805197ba5f4SPaul Zimmerman urb->pipe_info.dev_addr = dev_addr; 3806197ba5f4SPaul Zimmerman urb->pipe_info.ep_num = ep_num; 3807197ba5f4SPaul Zimmerman urb->pipe_info.pipe_type = ep_type; 3808197ba5f4SPaul Zimmerman urb->pipe_info.pipe_dir = ep_dir; 3809197ba5f4SPaul Zimmerman urb->pipe_info.mps = mps; 3810197ba5f4SPaul Zimmerman } 3811197ba5f4SPaul Zimmerman 3812197ba5f4SPaul Zimmerman /* 3813197ba5f4SPaul Zimmerman * NOTE: This function will be removed once the peripheral controller code 3814197ba5f4SPaul Zimmerman * is integrated and the driver is stable 3815197ba5f4SPaul Zimmerman */ 3816197ba5f4SPaul Zimmerman void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg) 3817197ba5f4SPaul Zimmerman { 3818197ba5f4SPaul Zimmerman #ifdef DEBUG 3819197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan; 3820197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *urb; 3821197ba5f4SPaul Zimmerman struct dwc2_qtd *qtd; 3822197ba5f4SPaul Zimmerman int num_channels; 3823197ba5f4SPaul Zimmerman u32 np_tx_status; 3824197ba5f4SPaul Zimmerman u32 p_tx_status; 3825197ba5f4SPaul Zimmerman int i; 3826197ba5f4SPaul Zimmerman 3827bea8e86cSJohn Youn num_channels = hsotg->params.host_channels; 3828197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "\n"); 3829197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3830197ba5f4SPaul Zimmerman "************************************************************\n"); 3831197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCD State:\n"); 3832197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " Num channels: %d\n", num_channels); 3833197ba5f4SPaul Zimmerman 3834197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 3835197ba5f4SPaul Zimmerman chan = hsotg->hc_ptr_array[i]; 3836197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " Channel %d:\n", i); 3837197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3838197ba5f4SPaul Zimmerman " dev_addr: %d, ep_num: %d, ep_is_in: %d\n", 3839197ba5f4SPaul Zimmerman chan->dev_addr, chan->ep_num, chan->ep_is_in); 3840197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " speed: %d\n", chan->speed); 3841197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " ep_type: %d\n", chan->ep_type); 3842197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " max_packet: %d\n", chan->max_packet); 3843197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " data_pid_start: %d\n", 3844197ba5f4SPaul Zimmerman chan->data_pid_start); 3845197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " multi_count: %d\n", chan->multi_count); 3846197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_started: %d\n", 3847197ba5f4SPaul Zimmerman chan->xfer_started); 3848197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_buf: %p\n", chan->xfer_buf); 3849197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_dma: %08lx\n", 3850197ba5f4SPaul Zimmerman (unsigned long)chan->xfer_dma); 3851197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_len: %d\n", chan->xfer_len); 3852197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xfer_count: %d\n", chan->xfer_count); 3853197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " halt_on_queue: %d\n", 3854197ba5f4SPaul Zimmerman chan->halt_on_queue); 3855197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " halt_pending: %d\n", 3856197ba5f4SPaul Zimmerman chan->halt_pending); 3857197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " halt_status: %d\n", chan->halt_status); 3858197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " do_split: %d\n", chan->do_split); 3859197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " complete_split: %d\n", 3860197ba5f4SPaul Zimmerman chan->complete_split); 3861197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hub_addr: %d\n", chan->hub_addr); 3862197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hub_port: %d\n", chan->hub_port); 3863197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " xact_pos: %d\n", chan->xact_pos); 3864197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " requests: %d\n", chan->requests); 3865197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " qh: %p\n", chan->qh); 3866197ba5f4SPaul Zimmerman 3867197ba5f4SPaul Zimmerman if (chan->xfer_started) { 3868197ba5f4SPaul Zimmerman u32 hfnum, hcchar, hctsiz, hcint, hcintmsk; 3869197ba5f4SPaul Zimmerman 387095c8bc36SAntti Seppälä hfnum = dwc2_readl(hsotg->regs + HFNUM); 387195c8bc36SAntti Seppälä hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); 387295c8bc36SAntti Seppälä hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(i)); 387395c8bc36SAntti Seppälä hcint = dwc2_readl(hsotg->regs + HCINT(i)); 387495c8bc36SAntti Seppälä hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(i)); 3875197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hfnum: 0x%08x\n", hfnum); 3876197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hcchar: 0x%08x\n", hcchar); 3877197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hctsiz: 0x%08x\n", hctsiz); 3878197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hcint: 0x%08x\n", hcint); 3879197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " hcintmsk: 0x%08x\n", hcintmsk); 3880197ba5f4SPaul Zimmerman } 3881197ba5f4SPaul Zimmerman 3882197ba5f4SPaul Zimmerman if (!(chan->xfer_started && chan->qh)) 3883197ba5f4SPaul Zimmerman continue; 3884197ba5f4SPaul Zimmerman 3885197ba5f4SPaul Zimmerman list_for_each_entry(qtd, &chan->qh->qtd_list, qtd_list_entry) { 3886197ba5f4SPaul Zimmerman if (!qtd->in_process) 3887197ba5f4SPaul Zimmerman break; 3888197ba5f4SPaul Zimmerman urb = qtd->urb; 3889197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " URB Info:\n"); 3890197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " qtd: %p, urb: %p\n", 3891197ba5f4SPaul Zimmerman qtd, urb); 3892197ba5f4SPaul Zimmerman if (urb) { 3893197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3894197ba5f4SPaul Zimmerman " Dev: %d, EP: %d %s\n", 3895197ba5f4SPaul Zimmerman dwc2_hcd_get_dev_addr(&urb->pipe_info), 3896197ba5f4SPaul Zimmerman dwc2_hcd_get_ep_num(&urb->pipe_info), 3897197ba5f4SPaul Zimmerman dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 3898197ba5f4SPaul Zimmerman "IN" : "OUT"); 3899197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3900197ba5f4SPaul Zimmerman " Max packet size: %d\n", 3901197ba5f4SPaul Zimmerman dwc2_hcd_get_mps(&urb->pipe_info)); 3902197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3903197ba5f4SPaul Zimmerman " transfer_buffer: %p\n", 3904197ba5f4SPaul Zimmerman urb->buf); 3905197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3906197ba5f4SPaul Zimmerman " transfer_dma: %08lx\n", 3907197ba5f4SPaul Zimmerman (unsigned long)urb->dma); 3908197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3909197ba5f4SPaul Zimmerman " transfer_buffer_length: %d\n", 3910197ba5f4SPaul Zimmerman urb->length); 3911197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " actual_length: %d\n", 3912197ba5f4SPaul Zimmerman urb->actual_length); 3913197ba5f4SPaul Zimmerman } 3914197ba5f4SPaul Zimmerman } 3915197ba5f4SPaul Zimmerman } 3916197ba5f4SPaul Zimmerman 3917197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " non_periodic_channels: %d\n", 3918197ba5f4SPaul Zimmerman hsotg->non_periodic_channels); 3919197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " periodic_channels: %d\n", 3920197ba5f4SPaul Zimmerman hsotg->periodic_channels); 3921197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " periodic_usecs: %d\n", hsotg->periodic_usecs); 392295c8bc36SAntti Seppälä np_tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); 3923197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " NP Tx Req Queue Space Avail: %d\n", 3924197ba5f4SPaul Zimmerman (np_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); 3925197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " NP Tx FIFO Space Avail: %d\n", 3926197ba5f4SPaul Zimmerman (np_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT); 392795c8bc36SAntti Seppälä p_tx_status = dwc2_readl(hsotg->regs + HPTXSTS); 3928197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " P Tx Req Queue Space Avail: %d\n", 3929197ba5f4SPaul Zimmerman (p_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); 3930197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " P Tx FIFO Space Avail: %d\n", 3931197ba5f4SPaul Zimmerman (p_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT); 3932197ba5f4SPaul Zimmerman dwc2_hcd_dump_frrem(hsotg); 3933197ba5f4SPaul Zimmerman dwc2_dump_global_registers(hsotg); 3934197ba5f4SPaul Zimmerman dwc2_dump_host_registers(hsotg); 3935197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 3936197ba5f4SPaul Zimmerman "************************************************************\n"); 3937197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "\n"); 3938197ba5f4SPaul Zimmerman #endif 3939197ba5f4SPaul Zimmerman } 3940197ba5f4SPaul Zimmerman 3941197ba5f4SPaul Zimmerman /* 3942197ba5f4SPaul Zimmerman * NOTE: This function will be removed once the peripheral controller code 3943197ba5f4SPaul Zimmerman * is integrated and the driver is stable 3944197ba5f4SPaul Zimmerman */ 3945197ba5f4SPaul Zimmerman void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg) 3946197ba5f4SPaul Zimmerman { 3947197ba5f4SPaul Zimmerman #ifdef DWC2_DUMP_FRREM 3948197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at SOF:\n"); 3949197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3950197ba5f4SPaul Zimmerman hsotg->frrem_samples, hsotg->frrem_accum, 3951197ba5f4SPaul Zimmerman hsotg->frrem_samples > 0 ? 3952197ba5f4SPaul Zimmerman hsotg->frrem_accum / hsotg->frrem_samples : 0); 3953197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "\n"); 3954197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 7):\n"); 3955197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3956197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples, 3957197ba5f4SPaul Zimmerman hsotg->hfnum_7_frrem_accum, 3958197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples > 0 ? 3959197ba5f4SPaul Zimmerman hsotg->hfnum_7_frrem_accum / hsotg->hfnum_7_samples : 0); 3960197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 0):\n"); 3961197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3962197ba5f4SPaul Zimmerman hsotg->hfnum_0_samples, 3963197ba5f4SPaul Zimmerman hsotg->hfnum_0_frrem_accum, 3964197ba5f4SPaul Zimmerman hsotg->hfnum_0_samples > 0 ? 3965197ba5f4SPaul Zimmerman hsotg->hfnum_0_frrem_accum / hsotg->hfnum_0_samples : 0); 3966197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 1-6):\n"); 3967197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3968197ba5f4SPaul Zimmerman hsotg->hfnum_other_samples, 3969197ba5f4SPaul Zimmerman hsotg->hfnum_other_frrem_accum, 3970197ba5f4SPaul Zimmerman hsotg->hfnum_other_samples > 0 ? 3971197ba5f4SPaul Zimmerman hsotg->hfnum_other_frrem_accum / hsotg->hfnum_other_samples : 3972197ba5f4SPaul Zimmerman 0); 3973197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "\n"); 3974197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 7):\n"); 3975197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3976197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples_a, hsotg->hfnum_7_frrem_accum_a, 3977197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples_a > 0 ? 3978197ba5f4SPaul Zimmerman hsotg->hfnum_7_frrem_accum_a / hsotg->hfnum_7_samples_a : 0); 3979197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 0):\n"); 3980197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3981197ba5f4SPaul Zimmerman hsotg->hfnum_0_samples_a, hsotg->hfnum_0_frrem_accum_a, 3982197ba5f4SPaul Zimmerman hsotg->hfnum_0_samples_a > 0 ? 3983197ba5f4SPaul Zimmerman hsotg->hfnum_0_frrem_accum_a / hsotg->hfnum_0_samples_a : 0); 3984197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 1-6):\n"); 3985197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3986197ba5f4SPaul Zimmerman hsotg->hfnum_other_samples_a, hsotg->hfnum_other_frrem_accum_a, 3987197ba5f4SPaul Zimmerman hsotg->hfnum_other_samples_a > 0 ? 3988197ba5f4SPaul Zimmerman hsotg->hfnum_other_frrem_accum_a / hsotg->hfnum_other_samples_a 3989197ba5f4SPaul Zimmerman : 0); 3990197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "\n"); 3991197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 7):\n"); 3992197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3993197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples_b, hsotg->hfnum_7_frrem_accum_b, 3994197ba5f4SPaul Zimmerman hsotg->hfnum_7_samples_b > 0 ? 3995197ba5f4SPaul Zimmerman hsotg->hfnum_7_frrem_accum_b / hsotg->hfnum_7_samples_b : 0); 3996197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 0):\n"); 3997197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 3998197ba5f4SPaul Zimmerman hsotg->hfnum_0_samples_b, hsotg->hfnum_0_frrem_accum_b, 3999197ba5f4SPaul Zimmerman (hsotg->hfnum_0_samples_b > 0) ? 4000197ba5f4SPaul Zimmerman hsotg->hfnum_0_frrem_accum_b / hsotg->hfnum_0_samples_b : 0); 4001197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 1-6):\n"); 4002197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " samples %u, accum %llu, avg %llu\n", 4003197ba5f4SPaul Zimmerman hsotg->hfnum_other_samples_b, hsotg->hfnum_other_frrem_accum_b, 4004197ba5f4SPaul Zimmerman (hsotg->hfnum_other_samples_b > 0) ? 4005197ba5f4SPaul Zimmerman hsotg->hfnum_other_frrem_accum_b / hsotg->hfnum_other_samples_b 4006197ba5f4SPaul Zimmerman : 0); 4007197ba5f4SPaul Zimmerman #endif 4008197ba5f4SPaul Zimmerman } 4009197ba5f4SPaul Zimmerman 4010197ba5f4SPaul Zimmerman struct wrapper_priv_data { 4011197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg; 4012197ba5f4SPaul Zimmerman }; 4013197ba5f4SPaul Zimmerman 4014197ba5f4SPaul Zimmerman /* Gets the dwc2_hsotg from a usb_hcd */ 4015197ba5f4SPaul Zimmerman static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) 4016197ba5f4SPaul Zimmerman { 4017197ba5f4SPaul Zimmerman struct wrapper_priv_data *p; 4018197ba5f4SPaul Zimmerman 4019197ba5f4SPaul Zimmerman p = (struct wrapper_priv_data *) &hcd->hcd_priv; 4020197ba5f4SPaul Zimmerman return p->hsotg; 4021197ba5f4SPaul Zimmerman } 4022197ba5f4SPaul Zimmerman 4023197ba5f4SPaul Zimmerman static int _dwc2_hcd_start(struct usb_hcd *hcd); 4024197ba5f4SPaul Zimmerman 4025197ba5f4SPaul Zimmerman void dwc2_host_start(struct dwc2_hsotg *hsotg) 4026197ba5f4SPaul Zimmerman { 4027197ba5f4SPaul Zimmerman struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg); 4028197ba5f4SPaul Zimmerman 4029197ba5f4SPaul Zimmerman hcd->self.is_b_host = dwc2_hcd_is_b_host(hsotg); 4030197ba5f4SPaul Zimmerman _dwc2_hcd_start(hcd); 4031197ba5f4SPaul Zimmerman } 4032197ba5f4SPaul Zimmerman 4033197ba5f4SPaul Zimmerman void dwc2_host_disconnect(struct dwc2_hsotg *hsotg) 4034197ba5f4SPaul Zimmerman { 4035197ba5f4SPaul Zimmerman struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg); 4036197ba5f4SPaul Zimmerman 4037197ba5f4SPaul Zimmerman hcd->self.is_b_host = 0; 4038197ba5f4SPaul Zimmerman } 4039197ba5f4SPaul Zimmerman 4040197ba5f4SPaul Zimmerman void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr, 4041197ba5f4SPaul Zimmerman int *hub_port) 4042197ba5f4SPaul Zimmerman { 4043197ba5f4SPaul Zimmerman struct urb *urb = context; 4044197ba5f4SPaul Zimmerman 4045197ba5f4SPaul Zimmerman if (urb->dev->tt) 4046197ba5f4SPaul Zimmerman *hub_addr = urb->dev->tt->hub->devnum; 4047197ba5f4SPaul Zimmerman else 4048197ba5f4SPaul Zimmerman *hub_addr = 0; 4049197ba5f4SPaul Zimmerman *hub_port = urb->dev->ttport; 4050197ba5f4SPaul Zimmerman } 4051197ba5f4SPaul Zimmerman 40529f9f09b0SDouglas Anderson /** 40539f9f09b0SDouglas Anderson * dwc2_host_get_tt_info() - Get the dwc2_tt associated with context 40549f9f09b0SDouglas Anderson * 40559f9f09b0SDouglas Anderson * This will get the dwc2_tt structure (and ttport) associated with the given 40569f9f09b0SDouglas Anderson * context (which is really just a struct urb pointer). 40579f9f09b0SDouglas Anderson * 40589f9f09b0SDouglas Anderson * The first time this is called for a given TT we allocate memory for our 40599f9f09b0SDouglas Anderson * structure. When everyone is done and has called dwc2_host_put_tt_info() 40609f9f09b0SDouglas Anderson * then the refcount for the structure will go to 0 and we'll free it. 40619f9f09b0SDouglas Anderson * 40629f9f09b0SDouglas Anderson * @hsotg: The HCD state structure for the DWC OTG controller. 40639f9f09b0SDouglas Anderson * @qh: The QH structure. 40649f9f09b0SDouglas Anderson * @context: The priv pointer from a struct dwc2_hcd_urb. 40659f9f09b0SDouglas Anderson * @mem_flags: Flags for allocating memory. 40669f9f09b0SDouglas Anderson * @ttport: We'll return this device's port number here. That's used to 40679f9f09b0SDouglas Anderson * reference into the bitmap if we're on a multi_tt hub. 40689f9f09b0SDouglas Anderson * 40699f9f09b0SDouglas Anderson * Return: a pointer to a struct dwc2_tt. Don't forget to call 40709f9f09b0SDouglas Anderson * dwc2_host_put_tt_info()! Returns NULL upon memory alloc failure. 40719f9f09b0SDouglas Anderson */ 40729f9f09b0SDouglas Anderson 40739f9f09b0SDouglas Anderson struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context, 40749f9f09b0SDouglas Anderson gfp_t mem_flags, int *ttport) 40759f9f09b0SDouglas Anderson { 40769f9f09b0SDouglas Anderson struct urb *urb = context; 40779f9f09b0SDouglas Anderson struct dwc2_tt *dwc_tt = NULL; 40789f9f09b0SDouglas Anderson 40799f9f09b0SDouglas Anderson if (urb->dev->tt) { 40809f9f09b0SDouglas Anderson *ttport = urb->dev->ttport; 40819f9f09b0SDouglas Anderson 40829f9f09b0SDouglas Anderson dwc_tt = urb->dev->tt->hcpriv; 40839f9f09b0SDouglas Anderson if (dwc_tt == NULL) { 40849f9f09b0SDouglas Anderson size_t bitmap_size; 40859f9f09b0SDouglas Anderson 40869f9f09b0SDouglas Anderson /* 40879f9f09b0SDouglas Anderson * For single_tt we need one schedule. For multi_tt 40889f9f09b0SDouglas Anderson * we need one per port. 40899f9f09b0SDouglas Anderson */ 40909f9f09b0SDouglas Anderson bitmap_size = DWC2_ELEMENTS_PER_LS_BITMAP * 40919f9f09b0SDouglas Anderson sizeof(dwc_tt->periodic_bitmaps[0]); 40929f9f09b0SDouglas Anderson if (urb->dev->tt->multi) 40939f9f09b0SDouglas Anderson bitmap_size *= urb->dev->tt->hub->maxchild; 40949f9f09b0SDouglas Anderson 40959f9f09b0SDouglas Anderson dwc_tt = kzalloc(sizeof(*dwc_tt) + bitmap_size, 40969f9f09b0SDouglas Anderson mem_flags); 40979f9f09b0SDouglas Anderson if (dwc_tt == NULL) 40989f9f09b0SDouglas Anderson return NULL; 40999f9f09b0SDouglas Anderson 41009f9f09b0SDouglas Anderson dwc_tt->usb_tt = urb->dev->tt; 41019f9f09b0SDouglas Anderson dwc_tt->usb_tt->hcpriv = dwc_tt; 41029f9f09b0SDouglas Anderson } 41039f9f09b0SDouglas Anderson 41049f9f09b0SDouglas Anderson dwc_tt->refcount++; 41059f9f09b0SDouglas Anderson } 41069f9f09b0SDouglas Anderson 41079f9f09b0SDouglas Anderson return dwc_tt; 41089f9f09b0SDouglas Anderson } 41099f9f09b0SDouglas Anderson 41109f9f09b0SDouglas Anderson /** 41119f9f09b0SDouglas Anderson * dwc2_host_put_tt_info() - Put the dwc2_tt from dwc2_host_get_tt_info() 41129f9f09b0SDouglas Anderson * 41139f9f09b0SDouglas Anderson * Frees resources allocated by dwc2_host_get_tt_info() if all current holders 41149f9f09b0SDouglas Anderson * of the structure are done. 41159f9f09b0SDouglas Anderson * 41169f9f09b0SDouglas Anderson * It's OK to call this with NULL. 41179f9f09b0SDouglas Anderson * 41189f9f09b0SDouglas Anderson * @hsotg: The HCD state structure for the DWC OTG controller. 41199f9f09b0SDouglas Anderson * @dwc_tt: The pointer returned by dwc2_host_get_tt_info. 41209f9f09b0SDouglas Anderson */ 41219f9f09b0SDouglas Anderson void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, struct dwc2_tt *dwc_tt) 41229f9f09b0SDouglas Anderson { 41239f9f09b0SDouglas Anderson /* Model kfree and make put of NULL a no-op */ 41249f9f09b0SDouglas Anderson if (dwc_tt == NULL) 41259f9f09b0SDouglas Anderson return; 41269f9f09b0SDouglas Anderson 41279f9f09b0SDouglas Anderson WARN_ON(dwc_tt->refcount < 1); 41289f9f09b0SDouglas Anderson 41299f9f09b0SDouglas Anderson dwc_tt->refcount--; 41309f9f09b0SDouglas Anderson if (!dwc_tt->refcount) { 41319f9f09b0SDouglas Anderson dwc_tt->usb_tt->hcpriv = NULL; 41329f9f09b0SDouglas Anderson kfree(dwc_tt); 41339f9f09b0SDouglas Anderson } 41349f9f09b0SDouglas Anderson } 41359f9f09b0SDouglas Anderson 4136197ba5f4SPaul Zimmerman int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context) 4137197ba5f4SPaul Zimmerman { 4138197ba5f4SPaul Zimmerman struct urb *urb = context; 4139197ba5f4SPaul Zimmerman 4140197ba5f4SPaul Zimmerman return urb->dev->speed; 4141197ba5f4SPaul Zimmerman } 4142197ba5f4SPaul Zimmerman 4143197ba5f4SPaul Zimmerman static void dwc2_allocate_bus_bandwidth(struct usb_hcd *hcd, u16 bw, 4144197ba5f4SPaul Zimmerman struct urb *urb) 4145197ba5f4SPaul Zimmerman { 4146197ba5f4SPaul Zimmerman struct usb_bus *bus = hcd_to_bus(hcd); 4147197ba5f4SPaul Zimmerman 4148197ba5f4SPaul Zimmerman if (urb->interval) 4149197ba5f4SPaul Zimmerman bus->bandwidth_allocated += bw / urb->interval; 4150197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) 4151197ba5f4SPaul Zimmerman bus->bandwidth_isoc_reqs++; 4152197ba5f4SPaul Zimmerman else 4153197ba5f4SPaul Zimmerman bus->bandwidth_int_reqs++; 4154197ba5f4SPaul Zimmerman } 4155197ba5f4SPaul Zimmerman 4156197ba5f4SPaul Zimmerman static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw, 4157197ba5f4SPaul Zimmerman struct urb *urb) 4158197ba5f4SPaul Zimmerman { 4159197ba5f4SPaul Zimmerman struct usb_bus *bus = hcd_to_bus(hcd); 4160197ba5f4SPaul Zimmerman 4161197ba5f4SPaul Zimmerman if (urb->interval) 4162197ba5f4SPaul Zimmerman bus->bandwidth_allocated -= bw / urb->interval; 4163197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) 4164197ba5f4SPaul Zimmerman bus->bandwidth_isoc_reqs--; 4165197ba5f4SPaul Zimmerman else 4166197ba5f4SPaul Zimmerman bus->bandwidth_int_reqs--; 4167197ba5f4SPaul Zimmerman } 4168197ba5f4SPaul Zimmerman 4169197ba5f4SPaul Zimmerman /* 4170197ba5f4SPaul Zimmerman * Sets the final status of an URB and returns it to the upper layer. Any 4171197ba5f4SPaul Zimmerman * required cleanup of the URB is performed. 4172197ba5f4SPaul Zimmerman * 4173197ba5f4SPaul Zimmerman * Must be called with interrupt disabled and spinlock held 4174197ba5f4SPaul Zimmerman */ 4175197ba5f4SPaul Zimmerman void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, 4176197ba5f4SPaul Zimmerman int status) 4177197ba5f4SPaul Zimmerman { 4178197ba5f4SPaul Zimmerman struct urb *urb; 4179197ba5f4SPaul Zimmerman int i; 4180197ba5f4SPaul Zimmerman 4181197ba5f4SPaul Zimmerman if (!qtd) { 4182197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## %s: qtd is NULL ##\n", __func__); 4183197ba5f4SPaul Zimmerman return; 4184197ba5f4SPaul Zimmerman } 4185197ba5f4SPaul Zimmerman 4186197ba5f4SPaul Zimmerman if (!qtd->urb) { 4187197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## %s: qtd->urb is NULL ##\n", __func__); 4188197ba5f4SPaul Zimmerman return; 4189197ba5f4SPaul Zimmerman } 4190197ba5f4SPaul Zimmerman 4191197ba5f4SPaul Zimmerman urb = qtd->urb->priv; 4192197ba5f4SPaul Zimmerman if (!urb) { 4193197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## %s: urb->priv is NULL ##\n", __func__); 4194197ba5f4SPaul Zimmerman return; 4195197ba5f4SPaul Zimmerman } 4196197ba5f4SPaul Zimmerman 4197197ba5f4SPaul Zimmerman urb->actual_length = dwc2_hcd_urb_get_actual_length(qtd->urb); 4198197ba5f4SPaul Zimmerman 4199197ba5f4SPaul Zimmerman if (dbg_urb(urb)) 4200197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, 4201197ba5f4SPaul Zimmerman "%s: urb %p device %d ep %d-%s status %d actual %d\n", 4202197ba5f4SPaul Zimmerman __func__, urb, usb_pipedevice(urb->pipe), 4203197ba5f4SPaul Zimmerman usb_pipeendpoint(urb->pipe), 4204197ba5f4SPaul Zimmerman usb_pipein(urb->pipe) ? "IN" : "OUT", status, 4205197ba5f4SPaul Zimmerman urb->actual_length); 4206197ba5f4SPaul Zimmerman 4207197ba5f4SPaul Zimmerman 4208197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { 4209197ba5f4SPaul Zimmerman urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); 4210197ba5f4SPaul Zimmerman for (i = 0; i < urb->number_of_packets; ++i) { 4211197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].actual_length = 4212197ba5f4SPaul Zimmerman dwc2_hcd_urb_get_iso_desc_actual_length( 4213197ba5f4SPaul Zimmerman qtd->urb, i); 4214197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].status = 4215197ba5f4SPaul Zimmerman dwc2_hcd_urb_get_iso_desc_status(qtd->urb, i); 4216197ba5f4SPaul Zimmerman } 4217197ba5f4SPaul Zimmerman } 4218197ba5f4SPaul Zimmerman 4219fe9b1773SGregory Herrero if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) { 4220fe9b1773SGregory Herrero for (i = 0; i < urb->number_of_packets; i++) 4221fe9b1773SGregory Herrero dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n", 4222fe9b1773SGregory Herrero i, urb->iso_frame_desc[i].status); 4223fe9b1773SGregory Herrero } 4224fe9b1773SGregory Herrero 4225197ba5f4SPaul Zimmerman urb->status = status; 4226197ba5f4SPaul Zimmerman if (!status) { 4227197ba5f4SPaul Zimmerman if ((urb->transfer_flags & URB_SHORT_NOT_OK) && 4228197ba5f4SPaul Zimmerman urb->actual_length < urb->transfer_buffer_length) 4229197ba5f4SPaul Zimmerman urb->status = -EREMOTEIO; 4230197ba5f4SPaul Zimmerman } 4231197ba5f4SPaul Zimmerman 4232197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS || 4233197ba5f4SPaul Zimmerman usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { 4234197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep = urb->ep; 4235197ba5f4SPaul Zimmerman 4236197ba5f4SPaul Zimmerman if (ep) 4237197ba5f4SPaul Zimmerman dwc2_free_bus_bandwidth(dwc2_hsotg_to_hcd(hsotg), 4238197ba5f4SPaul Zimmerman dwc2_hcd_get_ep_bandwidth(hsotg, ep), 4239197ba5f4SPaul Zimmerman urb); 4240197ba5f4SPaul Zimmerman } 4241197ba5f4SPaul Zimmerman 4242197ba5f4SPaul Zimmerman usb_hcd_unlink_urb_from_ep(dwc2_hsotg_to_hcd(hsotg), urb); 4243197ba5f4SPaul Zimmerman urb->hcpriv = NULL; 4244197ba5f4SPaul Zimmerman kfree(qtd->urb); 4245197ba5f4SPaul Zimmerman qtd->urb = NULL; 4246197ba5f4SPaul Zimmerman 4247197ba5f4SPaul Zimmerman usb_hcd_giveback_urb(dwc2_hsotg_to_hcd(hsotg), urb, status); 4248197ba5f4SPaul Zimmerman } 4249197ba5f4SPaul Zimmerman 4250197ba5f4SPaul Zimmerman /* 4251197ba5f4SPaul Zimmerman * Work queue function for starting the HCD when A-Cable is connected 4252197ba5f4SPaul Zimmerman */ 4253197ba5f4SPaul Zimmerman static void dwc2_hcd_start_func(struct work_struct *work) 4254197ba5f4SPaul Zimmerman { 4255197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, 4256197ba5f4SPaul Zimmerman start_work.work); 4257197ba5f4SPaul Zimmerman 4258197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "%s() %p\n", __func__, hsotg); 4259197ba5f4SPaul Zimmerman dwc2_host_start(hsotg); 4260197ba5f4SPaul Zimmerman } 4261197ba5f4SPaul Zimmerman 4262197ba5f4SPaul Zimmerman /* 4263197ba5f4SPaul Zimmerman * Reset work queue function 4264197ba5f4SPaul Zimmerman */ 4265197ba5f4SPaul Zimmerman static void dwc2_hcd_reset_func(struct work_struct *work) 4266197ba5f4SPaul Zimmerman { 4267197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, 4268197ba5f4SPaul Zimmerman reset_work.work); 42694a065c7bSDouglas Anderson unsigned long flags; 4270197ba5f4SPaul Zimmerman u32 hprt0; 4271197ba5f4SPaul Zimmerman 4272197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "USB RESET function called\n"); 42734a065c7bSDouglas Anderson 42744a065c7bSDouglas Anderson spin_lock_irqsave(&hsotg->lock, flags); 42754a065c7bSDouglas Anderson 4276197ba5f4SPaul Zimmerman hprt0 = dwc2_read_hprt0(hsotg); 4277197ba5f4SPaul Zimmerman hprt0 &= ~HPRT0_RST; 427895c8bc36SAntti Seppälä dwc2_writel(hprt0, hsotg->regs + HPRT0); 4279197ba5f4SPaul Zimmerman hsotg->flags.b.port_reset_change = 1; 42804a065c7bSDouglas Anderson 42814a065c7bSDouglas Anderson spin_unlock_irqrestore(&hsotg->lock, flags); 4282197ba5f4SPaul Zimmerman } 4283197ba5f4SPaul Zimmerman 4284197ba5f4SPaul Zimmerman /* 4285197ba5f4SPaul Zimmerman * ========================================================================= 4286197ba5f4SPaul Zimmerman * Linux HC Driver Functions 4287197ba5f4SPaul Zimmerman * ========================================================================= 4288197ba5f4SPaul Zimmerman */ 4289197ba5f4SPaul Zimmerman 4290197ba5f4SPaul Zimmerman /* 4291197ba5f4SPaul Zimmerman * Initializes the DWC_otg controller and its root hub and prepares it for host 4292197ba5f4SPaul Zimmerman * mode operation. Activates the root port. Returns 0 on success and a negative 4293197ba5f4SPaul Zimmerman * error code on failure. 4294197ba5f4SPaul Zimmerman */ 4295197ba5f4SPaul Zimmerman static int _dwc2_hcd_start(struct usb_hcd *hcd) 4296197ba5f4SPaul Zimmerman { 4297197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4298197ba5f4SPaul Zimmerman struct usb_bus *bus = hcd_to_bus(hcd); 4299197ba5f4SPaul Zimmerman unsigned long flags; 4300197ba5f4SPaul Zimmerman 4301197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); 4302197ba5f4SPaul Zimmerman 4303197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 430431927b6bSGregory Herrero hsotg->lx_state = DWC2_L0; 4305197ba5f4SPaul Zimmerman hcd->state = HC_STATE_RUNNING; 430631927b6bSGregory Herrero set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 4307197ba5f4SPaul Zimmerman 4308197ba5f4SPaul Zimmerman if (dwc2_is_device_mode(hsotg)) { 4309197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4310197ba5f4SPaul Zimmerman return 0; /* why 0 ?? */ 4311197ba5f4SPaul Zimmerman } 4312197ba5f4SPaul Zimmerman 4313197ba5f4SPaul Zimmerman dwc2_hcd_reinit(hsotg); 4314197ba5f4SPaul Zimmerman 4315197ba5f4SPaul Zimmerman /* Initialize and connect root hub if one is not already attached */ 4316197ba5f4SPaul Zimmerman if (bus->root_hub) { 4317197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n"); 4318197ba5f4SPaul Zimmerman /* Inform the HUB driver to resume */ 4319197ba5f4SPaul Zimmerman usb_hcd_resume_root_hub(hcd); 4320197ba5f4SPaul Zimmerman } 4321197ba5f4SPaul Zimmerman 4322197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4323197ba5f4SPaul Zimmerman return 0; 4324197ba5f4SPaul Zimmerman } 4325197ba5f4SPaul Zimmerman 4326197ba5f4SPaul Zimmerman /* 4327197ba5f4SPaul Zimmerman * Halts the DWC_otg host mode operations in a clean manner. USB transfers are 4328197ba5f4SPaul Zimmerman * stopped. 4329197ba5f4SPaul Zimmerman */ 4330197ba5f4SPaul Zimmerman static void _dwc2_hcd_stop(struct usb_hcd *hcd) 4331197ba5f4SPaul Zimmerman { 4332197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4333197ba5f4SPaul Zimmerman unsigned long flags; 4334197ba5f4SPaul Zimmerman 43355bbf6ce0SGregory Herrero /* Turn off all host-specific interrupts */ 43365bbf6ce0SGregory Herrero dwc2_disable_host_interrupts(hsotg); 43375bbf6ce0SGregory Herrero 4338091473adSGregory Herrero /* Wait for interrupt processing to finish */ 4339091473adSGregory Herrero synchronize_irq(hcd->irq); 4340091473adSGregory Herrero 4341197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4342091473adSGregory Herrero /* Ensure hcd is disconnected */ 43436a659531SDouglas Anderson dwc2_hcd_disconnect(hsotg, true); 4344197ba5f4SPaul Zimmerman dwc2_hcd_stop(hsotg); 434531927b6bSGregory Herrero hsotg->lx_state = DWC2_L3; 434631927b6bSGregory Herrero hcd->state = HC_STATE_HALT; 434731927b6bSGregory Herrero clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 4348197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4349197ba5f4SPaul Zimmerman 4350197ba5f4SPaul Zimmerman usleep_range(1000, 3000); 4351197ba5f4SPaul Zimmerman } 4352197ba5f4SPaul Zimmerman 435399a65798SGregory Herrero static int _dwc2_hcd_suspend(struct usb_hcd *hcd) 435499a65798SGregory Herrero { 435599a65798SGregory Herrero struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4356a2a23d3fSGregory Herrero unsigned long flags; 4357a2a23d3fSGregory Herrero int ret = 0; 4358a2a23d3fSGregory Herrero u32 hprt0; 435999a65798SGregory Herrero 4360a2a23d3fSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 4361a2a23d3fSGregory Herrero 4362a2a23d3fSGregory Herrero if (hsotg->lx_state != DWC2_L0) 4363a2a23d3fSGregory Herrero goto unlock; 4364a2a23d3fSGregory Herrero 4365a2a23d3fSGregory Herrero if (!HCD_HW_ACCESSIBLE(hcd)) 4366a2a23d3fSGregory Herrero goto unlock; 4367a2a23d3fSGregory Herrero 4368bea8e86cSJohn Youn if (!hsotg->params.hibernation) 4369a2a23d3fSGregory Herrero goto skip_power_saving; 4370a2a23d3fSGregory Herrero 4371a2a23d3fSGregory Herrero /* 4372a2a23d3fSGregory Herrero * Drive USB suspend and disable port Power 4373a2a23d3fSGregory Herrero * if usb bus is not suspended. 4374a2a23d3fSGregory Herrero */ 4375a2a23d3fSGregory Herrero if (!hsotg->bus_suspended) { 4376a2a23d3fSGregory Herrero hprt0 = dwc2_read_hprt0(hsotg); 4377a2a23d3fSGregory Herrero hprt0 |= HPRT0_SUSP; 4378a2a23d3fSGregory Herrero hprt0 &= ~HPRT0_PWR; 4379a2a23d3fSGregory Herrero dwc2_writel(hprt0, hsotg->regs + HPRT0); 4380a2a23d3fSGregory Herrero } 4381a2a23d3fSGregory Herrero 4382a2a23d3fSGregory Herrero /* Enter hibernation */ 4383a2a23d3fSGregory Herrero ret = dwc2_enter_hibernation(hsotg); 4384a2a23d3fSGregory Herrero if (ret) { 4385a2a23d3fSGregory Herrero if (ret != -ENOTSUPP) 4386a2a23d3fSGregory Herrero dev_err(hsotg->dev, 4387a2a23d3fSGregory Herrero "enter hibernation failed\n"); 4388a2a23d3fSGregory Herrero goto skip_power_saving; 4389a2a23d3fSGregory Herrero } 4390a2a23d3fSGregory Herrero 4391a2a23d3fSGregory Herrero /* Ask phy to be suspended */ 4392a2a23d3fSGregory Herrero if (!IS_ERR_OR_NULL(hsotg->uphy)) { 4393a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4394a2a23d3fSGregory Herrero usb_phy_set_suspend(hsotg->uphy, true); 4395a2a23d3fSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 4396a2a23d3fSGregory Herrero } 4397a2a23d3fSGregory Herrero 4398a2a23d3fSGregory Herrero /* After entering hibernation, hardware is no more accessible */ 4399a2a23d3fSGregory Herrero clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 4400a2a23d3fSGregory Herrero 4401a2a23d3fSGregory Herrero skip_power_saving: 440299a65798SGregory Herrero hsotg->lx_state = DWC2_L2; 4403a2a23d3fSGregory Herrero unlock: 4404a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4405a2a23d3fSGregory Herrero 4406a2a23d3fSGregory Herrero return ret; 440799a65798SGregory Herrero } 440899a65798SGregory Herrero 440999a65798SGregory Herrero static int _dwc2_hcd_resume(struct usb_hcd *hcd) 441099a65798SGregory Herrero { 441199a65798SGregory Herrero struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4412a2a23d3fSGregory Herrero unsigned long flags; 4413a2a23d3fSGregory Herrero int ret = 0; 4414a2a23d3fSGregory Herrero 4415a2a23d3fSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 4416a2a23d3fSGregory Herrero 4417a2a23d3fSGregory Herrero if (hsotg->lx_state != DWC2_L2) 4418a2a23d3fSGregory Herrero goto unlock; 4419a2a23d3fSGregory Herrero 4420bea8e86cSJohn Youn if (!hsotg->params.hibernation) { 4421a2a23d3fSGregory Herrero hsotg->lx_state = DWC2_L0; 4422a2a23d3fSGregory Herrero goto unlock; 4423a2a23d3fSGregory Herrero } 4424a2a23d3fSGregory Herrero 4425a2a23d3fSGregory Herrero /* 4426a2a23d3fSGregory Herrero * Set HW accessible bit before powering on the controller 4427a2a23d3fSGregory Herrero * since an interrupt may rise. 4428a2a23d3fSGregory Herrero */ 4429a2a23d3fSGregory Herrero set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 4430a2a23d3fSGregory Herrero 4431a2a23d3fSGregory Herrero /* 4432a2a23d3fSGregory Herrero * Enable power if not already done. 4433a2a23d3fSGregory Herrero * This must not be spinlocked since duration 4434a2a23d3fSGregory Herrero * of this call is unknown. 4435a2a23d3fSGregory Herrero */ 4436a2a23d3fSGregory Herrero if (!IS_ERR_OR_NULL(hsotg->uphy)) { 4437a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4438a2a23d3fSGregory Herrero usb_phy_set_suspend(hsotg->uphy, false); 4439a2a23d3fSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 4440a2a23d3fSGregory Herrero } 4441a2a23d3fSGregory Herrero 4442a2a23d3fSGregory Herrero /* Exit hibernation */ 4443a2a23d3fSGregory Herrero ret = dwc2_exit_hibernation(hsotg, true); 4444a2a23d3fSGregory Herrero if (ret && (ret != -ENOTSUPP)) 4445a2a23d3fSGregory Herrero dev_err(hsotg->dev, "exit hibernation failed\n"); 444699a65798SGregory Herrero 444799a65798SGregory Herrero hsotg->lx_state = DWC2_L0; 4448a2a23d3fSGregory Herrero 4449a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4450a2a23d3fSGregory Herrero 4451a2a23d3fSGregory Herrero if (hsotg->bus_suspended) { 4452a2a23d3fSGregory Herrero spin_lock_irqsave(&hsotg->lock, flags); 4453a2a23d3fSGregory Herrero hsotg->flags.b.port_suspend_change = 1; 4454a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4455a2a23d3fSGregory Herrero dwc2_port_resume(hsotg); 4456a2a23d3fSGregory Herrero } else { 44575634e016SGregory Herrero /* Wait for controller to correctly update D+/D- level */ 44585634e016SGregory Herrero usleep_range(3000, 5000); 44595634e016SGregory Herrero 4460a2a23d3fSGregory Herrero /* 4461a2a23d3fSGregory Herrero * Clear Port Enable and Port Status changes. 4462a2a23d3fSGregory Herrero * Enable Port Power. 4463a2a23d3fSGregory Herrero */ 4464a2a23d3fSGregory Herrero dwc2_writel(HPRT0_PWR | HPRT0_CONNDET | 4465a2a23d3fSGregory Herrero HPRT0_ENACHG, hsotg->regs + HPRT0); 4466a2a23d3fSGregory Herrero /* Wait for controller to detect Port Connect */ 44675634e016SGregory Herrero usleep_range(5000, 7000); 4468a2a23d3fSGregory Herrero } 4469a2a23d3fSGregory Herrero 4470a2a23d3fSGregory Herrero return ret; 4471a2a23d3fSGregory Herrero unlock: 4472a2a23d3fSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4473a2a23d3fSGregory Herrero 4474a2a23d3fSGregory Herrero return ret; 447599a65798SGregory Herrero } 447699a65798SGregory Herrero 4477197ba5f4SPaul Zimmerman /* Returns the current frame number */ 4478197ba5f4SPaul Zimmerman static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd) 4479197ba5f4SPaul Zimmerman { 4480197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4481197ba5f4SPaul Zimmerman 4482197ba5f4SPaul Zimmerman return dwc2_hcd_get_frame_number(hsotg); 4483197ba5f4SPaul Zimmerman } 4484197ba5f4SPaul Zimmerman 4485197ba5f4SPaul Zimmerman static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb, 4486197ba5f4SPaul Zimmerman char *fn_name) 4487197ba5f4SPaul Zimmerman { 4488197ba5f4SPaul Zimmerman #ifdef VERBOSE_DEBUG 4489197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4490197ba5f4SPaul Zimmerman char *pipetype; 4491197ba5f4SPaul Zimmerman char *speed; 4492197ba5f4SPaul Zimmerman 4493197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "%s, urb %p\n", fn_name, urb); 4494197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Device address: %d\n", 4495197ba5f4SPaul Zimmerman usb_pipedevice(urb->pipe)); 4496197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Endpoint: %d, %s\n", 4497197ba5f4SPaul Zimmerman usb_pipeendpoint(urb->pipe), 4498197ba5f4SPaul Zimmerman usb_pipein(urb->pipe) ? "IN" : "OUT"); 4499197ba5f4SPaul Zimmerman 4500197ba5f4SPaul Zimmerman switch (usb_pipetype(urb->pipe)) { 4501197ba5f4SPaul Zimmerman case PIPE_CONTROL: 4502197ba5f4SPaul Zimmerman pipetype = "CONTROL"; 4503197ba5f4SPaul Zimmerman break; 4504197ba5f4SPaul Zimmerman case PIPE_BULK: 4505197ba5f4SPaul Zimmerman pipetype = "BULK"; 4506197ba5f4SPaul Zimmerman break; 4507197ba5f4SPaul Zimmerman case PIPE_INTERRUPT: 4508197ba5f4SPaul Zimmerman pipetype = "INTERRUPT"; 4509197ba5f4SPaul Zimmerman break; 4510197ba5f4SPaul Zimmerman case PIPE_ISOCHRONOUS: 4511197ba5f4SPaul Zimmerman pipetype = "ISOCHRONOUS"; 4512197ba5f4SPaul Zimmerman break; 4513197ba5f4SPaul Zimmerman default: 4514197ba5f4SPaul Zimmerman pipetype = "UNKNOWN"; 4515197ba5f4SPaul Zimmerman break; 4516197ba5f4SPaul Zimmerman } 4517197ba5f4SPaul Zimmerman 4518197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Endpoint type: %s %s (%s)\n", pipetype, 4519197ba5f4SPaul Zimmerman usb_urb_dir_in(urb) ? "IN" : "OUT", usb_pipein(urb->pipe) ? 4520197ba5f4SPaul Zimmerman "IN" : "OUT"); 4521197ba5f4SPaul Zimmerman 4522197ba5f4SPaul Zimmerman switch (urb->dev->speed) { 4523197ba5f4SPaul Zimmerman case USB_SPEED_HIGH: 4524197ba5f4SPaul Zimmerman speed = "HIGH"; 4525197ba5f4SPaul Zimmerman break; 4526197ba5f4SPaul Zimmerman case USB_SPEED_FULL: 4527197ba5f4SPaul Zimmerman speed = "FULL"; 4528197ba5f4SPaul Zimmerman break; 4529197ba5f4SPaul Zimmerman case USB_SPEED_LOW: 4530197ba5f4SPaul Zimmerman speed = "LOW"; 4531197ba5f4SPaul Zimmerman break; 4532197ba5f4SPaul Zimmerman default: 4533197ba5f4SPaul Zimmerman speed = "UNKNOWN"; 4534197ba5f4SPaul Zimmerman break; 4535197ba5f4SPaul Zimmerman } 4536197ba5f4SPaul Zimmerman 4537197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Speed: %s\n", speed); 4538197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Max packet size: %d\n", 4539197ba5f4SPaul Zimmerman usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); 4540197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Data buffer length: %d\n", 4541197ba5f4SPaul Zimmerman urb->transfer_buffer_length); 4542197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Transfer buffer: %p, Transfer DMA: %08lx\n", 4543197ba5f4SPaul Zimmerman urb->transfer_buffer, (unsigned long)urb->transfer_dma); 4544197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Setup buffer: %p, Setup DMA: %08lx\n", 4545197ba5f4SPaul Zimmerman urb->setup_packet, (unsigned long)urb->setup_dma); 4546197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " Interval: %d\n", urb->interval); 4547197ba5f4SPaul Zimmerman 4548197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { 4549197ba5f4SPaul Zimmerman int i; 4550197ba5f4SPaul Zimmerman 4551197ba5f4SPaul Zimmerman for (i = 0; i < urb->number_of_packets; i++) { 4552197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " ISO Desc %d:\n", i); 4553197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, " offset: %d, length %d\n", 4554197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].offset, 4555197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].length); 4556197ba5f4SPaul Zimmerman } 4557197ba5f4SPaul Zimmerman } 4558197ba5f4SPaul Zimmerman #endif 4559197ba5f4SPaul Zimmerman } 4560197ba5f4SPaul Zimmerman 4561197ba5f4SPaul Zimmerman /* 4562197ba5f4SPaul Zimmerman * Starts processing a USB transfer request specified by a USB Request Block 4563197ba5f4SPaul Zimmerman * (URB). mem_flags indicates the type of memory allocation to use while 4564197ba5f4SPaul Zimmerman * processing this URB. 4565197ba5f4SPaul Zimmerman */ 4566197ba5f4SPaul Zimmerman static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, 4567197ba5f4SPaul Zimmerman gfp_t mem_flags) 4568197ba5f4SPaul Zimmerman { 4569197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4570197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep = urb->ep; 4571197ba5f4SPaul Zimmerman struct dwc2_hcd_urb *dwc2_urb; 4572197ba5f4SPaul Zimmerman int i; 4573197ba5f4SPaul Zimmerman int retval; 4574197ba5f4SPaul Zimmerman int alloc_bandwidth = 0; 4575197ba5f4SPaul Zimmerman u8 ep_type = 0; 4576197ba5f4SPaul Zimmerman u32 tflags = 0; 4577197ba5f4SPaul Zimmerman void *buf; 4578197ba5f4SPaul Zimmerman unsigned long flags; 4579b58e6ceeSMian Yousaf Kaukab struct dwc2_qh *qh; 4580b58e6ceeSMian Yousaf Kaukab bool qh_allocated = false; 4581b5a468a6SMian Yousaf Kaukab struct dwc2_qtd *qtd; 4582197ba5f4SPaul Zimmerman 4583197ba5f4SPaul Zimmerman if (dbg_urb(urb)) { 4584197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n"); 4585197ba5f4SPaul Zimmerman dwc2_dump_urb_info(hcd, urb, "urb_enqueue"); 4586197ba5f4SPaul Zimmerman } 4587197ba5f4SPaul Zimmerman 4588197ba5f4SPaul Zimmerman if (ep == NULL) 4589197ba5f4SPaul Zimmerman return -EINVAL; 4590197ba5f4SPaul Zimmerman 4591197ba5f4SPaul Zimmerman if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS || 4592197ba5f4SPaul Zimmerman usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { 4593197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4594197ba5f4SPaul Zimmerman if (!dwc2_hcd_is_bandwidth_allocated(hsotg, ep)) 4595197ba5f4SPaul Zimmerman alloc_bandwidth = 1; 4596197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4597197ba5f4SPaul Zimmerman } 4598197ba5f4SPaul Zimmerman 4599197ba5f4SPaul Zimmerman switch (usb_pipetype(urb->pipe)) { 4600197ba5f4SPaul Zimmerman case PIPE_CONTROL: 4601197ba5f4SPaul Zimmerman ep_type = USB_ENDPOINT_XFER_CONTROL; 4602197ba5f4SPaul Zimmerman break; 4603197ba5f4SPaul Zimmerman case PIPE_ISOCHRONOUS: 4604197ba5f4SPaul Zimmerman ep_type = USB_ENDPOINT_XFER_ISOC; 4605197ba5f4SPaul Zimmerman break; 4606197ba5f4SPaul Zimmerman case PIPE_BULK: 4607197ba5f4SPaul Zimmerman ep_type = USB_ENDPOINT_XFER_BULK; 4608197ba5f4SPaul Zimmerman break; 4609197ba5f4SPaul Zimmerman case PIPE_INTERRUPT: 4610197ba5f4SPaul Zimmerman ep_type = USB_ENDPOINT_XFER_INT; 4611197ba5f4SPaul Zimmerman break; 4612197ba5f4SPaul Zimmerman default: 4613197ba5f4SPaul Zimmerman dev_warn(hsotg->dev, "Wrong ep type\n"); 4614197ba5f4SPaul Zimmerman } 4615197ba5f4SPaul Zimmerman 4616197ba5f4SPaul Zimmerman dwc2_urb = dwc2_hcd_urb_alloc(hsotg, urb->number_of_packets, 4617197ba5f4SPaul Zimmerman mem_flags); 4618197ba5f4SPaul Zimmerman if (!dwc2_urb) 4619197ba5f4SPaul Zimmerman return -ENOMEM; 4620197ba5f4SPaul Zimmerman 4621197ba5f4SPaul Zimmerman dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, usb_pipedevice(urb->pipe), 4622197ba5f4SPaul Zimmerman usb_pipeendpoint(urb->pipe), ep_type, 4623197ba5f4SPaul Zimmerman usb_pipein(urb->pipe), 4624197ba5f4SPaul Zimmerman usb_maxpacket(urb->dev, urb->pipe, 4625197ba5f4SPaul Zimmerman !(usb_pipein(urb->pipe)))); 4626197ba5f4SPaul Zimmerman 4627197ba5f4SPaul Zimmerman buf = urb->transfer_buffer; 4628197ba5f4SPaul Zimmerman 4629197ba5f4SPaul Zimmerman if (hcd->self.uses_dma) { 4630197ba5f4SPaul Zimmerman if (!buf && (urb->transfer_dma & 3)) { 4631197ba5f4SPaul Zimmerman dev_err(hsotg->dev, 4632197ba5f4SPaul Zimmerman "%s: unaligned transfer with no transfer_buffer", 4633197ba5f4SPaul Zimmerman __func__); 4634197ba5f4SPaul Zimmerman retval = -EINVAL; 463533ad261aSGregory Herrero goto fail0; 4636197ba5f4SPaul Zimmerman } 4637197ba5f4SPaul Zimmerman } 4638197ba5f4SPaul Zimmerman 4639197ba5f4SPaul Zimmerman if (!(urb->transfer_flags & URB_NO_INTERRUPT)) 4640197ba5f4SPaul Zimmerman tflags |= URB_GIVEBACK_ASAP; 4641197ba5f4SPaul Zimmerman if (urb->transfer_flags & URB_ZERO_PACKET) 4642197ba5f4SPaul Zimmerman tflags |= URB_SEND_ZERO_PACKET; 4643197ba5f4SPaul Zimmerman 4644197ba5f4SPaul Zimmerman dwc2_urb->priv = urb; 4645197ba5f4SPaul Zimmerman dwc2_urb->buf = buf; 4646197ba5f4SPaul Zimmerman dwc2_urb->dma = urb->transfer_dma; 4647197ba5f4SPaul Zimmerman dwc2_urb->length = urb->transfer_buffer_length; 4648197ba5f4SPaul Zimmerman dwc2_urb->setup_packet = urb->setup_packet; 4649197ba5f4SPaul Zimmerman dwc2_urb->setup_dma = urb->setup_dma; 4650197ba5f4SPaul Zimmerman dwc2_urb->flags = tflags; 4651197ba5f4SPaul Zimmerman dwc2_urb->interval = urb->interval; 4652197ba5f4SPaul Zimmerman dwc2_urb->status = -EINPROGRESS; 4653197ba5f4SPaul Zimmerman 4654197ba5f4SPaul Zimmerman for (i = 0; i < urb->number_of_packets; ++i) 4655197ba5f4SPaul Zimmerman dwc2_hcd_urb_set_iso_desc_params(dwc2_urb, i, 4656197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].offset, 4657197ba5f4SPaul Zimmerman urb->iso_frame_desc[i].length); 4658197ba5f4SPaul Zimmerman 4659197ba5f4SPaul Zimmerman urb->hcpriv = dwc2_urb; 4660b58e6ceeSMian Yousaf Kaukab qh = (struct dwc2_qh *) ep->hcpriv; 4661b58e6ceeSMian Yousaf Kaukab /* Create QH for the endpoint if it doesn't exist */ 4662b58e6ceeSMian Yousaf Kaukab if (!qh) { 4663b58e6ceeSMian Yousaf Kaukab qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags); 4664b58e6ceeSMian Yousaf Kaukab if (!qh) { 4665b58e6ceeSMian Yousaf Kaukab retval = -ENOMEM; 4666b58e6ceeSMian Yousaf Kaukab goto fail0; 4667b58e6ceeSMian Yousaf Kaukab } 4668b58e6ceeSMian Yousaf Kaukab ep->hcpriv = qh; 4669b58e6ceeSMian Yousaf Kaukab qh_allocated = true; 4670b58e6ceeSMian Yousaf Kaukab } 4671197ba5f4SPaul Zimmerman 4672b5a468a6SMian Yousaf Kaukab qtd = kzalloc(sizeof(*qtd), mem_flags); 4673b5a468a6SMian Yousaf Kaukab if (!qtd) { 4674b5a468a6SMian Yousaf Kaukab retval = -ENOMEM; 4675b5a468a6SMian Yousaf Kaukab goto fail1; 4676b5a468a6SMian Yousaf Kaukab } 4677b5a468a6SMian Yousaf Kaukab 4678197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4679197ba5f4SPaul Zimmerman retval = usb_hcd_link_urb_to_ep(hcd, urb); 4680197ba5f4SPaul Zimmerman if (retval) 4681197ba5f4SPaul Zimmerman goto fail2; 4682197ba5f4SPaul Zimmerman 4683b5a468a6SMian Yousaf Kaukab retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd); 4684b5a468a6SMian Yousaf Kaukab if (retval) 4685b5a468a6SMian Yousaf Kaukab goto fail3; 4686b5a468a6SMian Yousaf Kaukab 4687197ba5f4SPaul Zimmerman if (alloc_bandwidth) { 4688197ba5f4SPaul Zimmerman dwc2_allocate_bus_bandwidth(hcd, 4689197ba5f4SPaul Zimmerman dwc2_hcd_get_ep_bandwidth(hsotg, ep), 4690197ba5f4SPaul Zimmerman urb); 4691197ba5f4SPaul Zimmerman } 4692197ba5f4SPaul Zimmerman 469333ad261aSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 469433ad261aSGregory Herrero 4695197ba5f4SPaul Zimmerman return 0; 4696197ba5f4SPaul Zimmerman 4697b5a468a6SMian Yousaf Kaukab fail3: 4698197ba5f4SPaul Zimmerman dwc2_urb->priv = NULL; 4699197ba5f4SPaul Zimmerman usb_hcd_unlink_urb_from_ep(hcd, urb); 470016e80218SDouglas Anderson if (qh_allocated && qh->channel && qh->channel->qh == qh) 470116e80218SDouglas Anderson qh->channel->qh = NULL; 4702b5a468a6SMian Yousaf Kaukab fail2: 470333ad261aSGregory Herrero spin_unlock_irqrestore(&hsotg->lock, flags); 4704197ba5f4SPaul Zimmerman urb->hcpriv = NULL; 4705b5a468a6SMian Yousaf Kaukab kfree(qtd); 4706b0d65902SVardan Mikayelyan qtd = NULL; 4707b5a468a6SMian Yousaf Kaukab fail1: 4708b58e6ceeSMian Yousaf Kaukab if (qh_allocated) { 4709b58e6ceeSMian Yousaf Kaukab struct dwc2_qtd *qtd2, *qtd2_tmp; 4710b58e6ceeSMian Yousaf Kaukab 4711b58e6ceeSMian Yousaf Kaukab ep->hcpriv = NULL; 4712b58e6ceeSMian Yousaf Kaukab dwc2_hcd_qh_unlink(hsotg, qh); 4713b58e6ceeSMian Yousaf Kaukab /* Free each QTD in the QH's QTD list */ 4714b58e6ceeSMian Yousaf Kaukab list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list, 4715b58e6ceeSMian Yousaf Kaukab qtd_list_entry) 4716b58e6ceeSMian Yousaf Kaukab dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh); 4717b58e6ceeSMian Yousaf Kaukab dwc2_hcd_qh_free(hsotg, qh); 4718b58e6ceeSMian Yousaf Kaukab } 471933ad261aSGregory Herrero fail0: 4720197ba5f4SPaul Zimmerman kfree(dwc2_urb); 4721197ba5f4SPaul Zimmerman 4722197ba5f4SPaul Zimmerman return retval; 4723197ba5f4SPaul Zimmerman } 4724197ba5f4SPaul Zimmerman 4725197ba5f4SPaul Zimmerman /* 4726197ba5f4SPaul Zimmerman * Aborts/cancels a USB transfer request. Always returns 0 to indicate success. 4727197ba5f4SPaul Zimmerman */ 4728197ba5f4SPaul Zimmerman static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, 4729197ba5f4SPaul Zimmerman int status) 4730197ba5f4SPaul Zimmerman { 4731197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4732197ba5f4SPaul Zimmerman int rc; 4733197ba5f4SPaul Zimmerman unsigned long flags; 4734197ba5f4SPaul Zimmerman 4735197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD URB Dequeue\n"); 4736197ba5f4SPaul Zimmerman dwc2_dump_urb_info(hcd, urb, "urb_dequeue"); 4737197ba5f4SPaul Zimmerman 4738197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4739197ba5f4SPaul Zimmerman 4740197ba5f4SPaul Zimmerman rc = usb_hcd_check_unlink_urb(hcd, urb, status); 4741197ba5f4SPaul Zimmerman if (rc) 4742197ba5f4SPaul Zimmerman goto out; 4743197ba5f4SPaul Zimmerman 4744197ba5f4SPaul Zimmerman if (!urb->hcpriv) { 4745197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n"); 4746197ba5f4SPaul Zimmerman goto out; 4747197ba5f4SPaul Zimmerman } 4748197ba5f4SPaul Zimmerman 4749197ba5f4SPaul Zimmerman rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv); 4750197ba5f4SPaul Zimmerman 4751197ba5f4SPaul Zimmerman usb_hcd_unlink_urb_from_ep(hcd, urb); 4752197ba5f4SPaul Zimmerman 4753197ba5f4SPaul Zimmerman kfree(urb->hcpriv); 4754197ba5f4SPaul Zimmerman urb->hcpriv = NULL; 4755197ba5f4SPaul Zimmerman 4756197ba5f4SPaul Zimmerman /* Higher layer software sets URB status */ 4757197ba5f4SPaul Zimmerman spin_unlock(&hsotg->lock); 4758197ba5f4SPaul Zimmerman usb_hcd_giveback_urb(hcd, urb, status); 4759197ba5f4SPaul Zimmerman spin_lock(&hsotg->lock); 4760197ba5f4SPaul Zimmerman 4761197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Called usb_hcd_giveback_urb()\n"); 4762197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, " urb->status = %d\n", urb->status); 4763197ba5f4SPaul Zimmerman out: 4764197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4765197ba5f4SPaul Zimmerman 4766197ba5f4SPaul Zimmerman return rc; 4767197ba5f4SPaul Zimmerman } 4768197ba5f4SPaul Zimmerman 4769197ba5f4SPaul Zimmerman /* 4770197ba5f4SPaul Zimmerman * Frees resources in the DWC_otg controller related to a given endpoint. Also 4771197ba5f4SPaul Zimmerman * clears state in the HCD related to the endpoint. Any URBs for the endpoint 4772197ba5f4SPaul Zimmerman * must already be dequeued. 4773197ba5f4SPaul Zimmerman */ 4774197ba5f4SPaul Zimmerman static void _dwc2_hcd_endpoint_disable(struct usb_hcd *hcd, 4775197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep) 4776197ba5f4SPaul Zimmerman { 4777197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4778197ba5f4SPaul Zimmerman 4779197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 4780197ba5f4SPaul Zimmerman "DWC OTG HCD EP DISABLE: bEndpointAddress=0x%02x, ep->hcpriv=%p\n", 4781197ba5f4SPaul Zimmerman ep->desc.bEndpointAddress, ep->hcpriv); 4782197ba5f4SPaul Zimmerman dwc2_hcd_endpoint_disable(hsotg, ep, 250); 4783197ba5f4SPaul Zimmerman } 4784197ba5f4SPaul Zimmerman 4785197ba5f4SPaul Zimmerman /* 4786197ba5f4SPaul Zimmerman * Resets endpoint specific parameter values, in current version used to reset 4787197ba5f4SPaul Zimmerman * the data toggle (as a WA). This function can be called from usb_clear_halt 4788197ba5f4SPaul Zimmerman * routine. 4789197ba5f4SPaul Zimmerman */ 4790197ba5f4SPaul Zimmerman static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd, 4791197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep) 4792197ba5f4SPaul Zimmerman { 4793197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4794197ba5f4SPaul Zimmerman unsigned long flags; 4795197ba5f4SPaul Zimmerman 4796197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, 4797197ba5f4SPaul Zimmerman "DWC OTG HCD EP RESET: bEndpointAddress=0x%02x\n", 4798197ba5f4SPaul Zimmerman ep->desc.bEndpointAddress); 4799197ba5f4SPaul Zimmerman 4800197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4801197ba5f4SPaul Zimmerman dwc2_hcd_endpoint_reset(hsotg, ep); 4802197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4803197ba5f4SPaul Zimmerman } 4804197ba5f4SPaul Zimmerman 4805197ba5f4SPaul Zimmerman /* 4806197ba5f4SPaul Zimmerman * Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if 4807197ba5f4SPaul Zimmerman * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid 4808197ba5f4SPaul Zimmerman * interrupt. 4809197ba5f4SPaul Zimmerman * 4810197ba5f4SPaul Zimmerman * This function is called by the USB core when an interrupt occurs 4811197ba5f4SPaul Zimmerman */ 4812197ba5f4SPaul Zimmerman static irqreturn_t _dwc2_hcd_irq(struct usb_hcd *hcd) 4813197ba5f4SPaul Zimmerman { 4814197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4815197ba5f4SPaul Zimmerman 4816197ba5f4SPaul Zimmerman return dwc2_handle_hcd_intr(hsotg); 4817197ba5f4SPaul Zimmerman } 4818197ba5f4SPaul Zimmerman 4819197ba5f4SPaul Zimmerman /* 4820197ba5f4SPaul Zimmerman * Creates Status Change bitmap for the root hub and root port. The bitmap is 4821197ba5f4SPaul Zimmerman * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 4822197ba5f4SPaul Zimmerman * is the status change indicator for the single root port. Returns 1 if either 4823197ba5f4SPaul Zimmerman * change indicator is 1, otherwise returns 0. 4824197ba5f4SPaul Zimmerman */ 4825197ba5f4SPaul Zimmerman static int _dwc2_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) 4826197ba5f4SPaul Zimmerman { 4827197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4828197ba5f4SPaul Zimmerman 4829197ba5f4SPaul Zimmerman buf[0] = dwc2_hcd_is_status_changed(hsotg, 1) << 1; 4830197ba5f4SPaul Zimmerman return buf[0] != 0; 4831197ba5f4SPaul Zimmerman } 4832197ba5f4SPaul Zimmerman 4833197ba5f4SPaul Zimmerman /* Handles hub class-specific requests */ 4834197ba5f4SPaul Zimmerman static int _dwc2_hcd_hub_control(struct usb_hcd *hcd, u16 typereq, u16 wvalue, 4835197ba5f4SPaul Zimmerman u16 windex, char *buf, u16 wlength) 4836197ba5f4SPaul Zimmerman { 4837197ba5f4SPaul Zimmerman int retval = dwc2_hcd_hub_control(dwc2_hcd_to_hsotg(hcd), typereq, 4838197ba5f4SPaul Zimmerman wvalue, windex, buf, wlength); 4839197ba5f4SPaul Zimmerman return retval; 4840197ba5f4SPaul Zimmerman } 4841197ba5f4SPaul Zimmerman 4842197ba5f4SPaul Zimmerman /* Handles hub TT buffer clear completions */ 4843197ba5f4SPaul Zimmerman static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd, 4844197ba5f4SPaul Zimmerman struct usb_host_endpoint *ep) 4845197ba5f4SPaul Zimmerman { 4846197ba5f4SPaul Zimmerman struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); 4847197ba5f4SPaul Zimmerman struct dwc2_qh *qh; 4848197ba5f4SPaul Zimmerman unsigned long flags; 4849197ba5f4SPaul Zimmerman 4850197ba5f4SPaul Zimmerman qh = ep->hcpriv; 4851197ba5f4SPaul Zimmerman if (!qh) 4852197ba5f4SPaul Zimmerman return; 4853197ba5f4SPaul Zimmerman 4854197ba5f4SPaul Zimmerman spin_lock_irqsave(&hsotg->lock, flags); 4855197ba5f4SPaul Zimmerman qh->tt_buffer_dirty = 0; 4856197ba5f4SPaul Zimmerman 4857197ba5f4SPaul Zimmerman if (hsotg->flags.b.port_connect_status) 4858197ba5f4SPaul Zimmerman dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_ALL); 4859197ba5f4SPaul Zimmerman 4860197ba5f4SPaul Zimmerman spin_unlock_irqrestore(&hsotg->lock, flags); 4861197ba5f4SPaul Zimmerman } 4862197ba5f4SPaul Zimmerman 4863197ba5f4SPaul Zimmerman static struct hc_driver dwc2_hc_driver = { 4864197ba5f4SPaul Zimmerman .description = "dwc2_hsotg", 4865197ba5f4SPaul Zimmerman .product_desc = "DWC OTG Controller", 4866197ba5f4SPaul Zimmerman .hcd_priv_size = sizeof(struct wrapper_priv_data), 4867197ba5f4SPaul Zimmerman 4868197ba5f4SPaul Zimmerman .irq = _dwc2_hcd_irq, 48698add17cfSDouglas Anderson .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, 4870197ba5f4SPaul Zimmerman 4871197ba5f4SPaul Zimmerman .start = _dwc2_hcd_start, 4872197ba5f4SPaul Zimmerman .stop = _dwc2_hcd_stop, 4873197ba5f4SPaul Zimmerman .urb_enqueue = _dwc2_hcd_urb_enqueue, 4874197ba5f4SPaul Zimmerman .urb_dequeue = _dwc2_hcd_urb_dequeue, 4875197ba5f4SPaul Zimmerman .endpoint_disable = _dwc2_hcd_endpoint_disable, 4876197ba5f4SPaul Zimmerman .endpoint_reset = _dwc2_hcd_endpoint_reset, 4877197ba5f4SPaul Zimmerman .get_frame_number = _dwc2_hcd_get_frame_number, 4878197ba5f4SPaul Zimmerman 4879197ba5f4SPaul Zimmerman .hub_status_data = _dwc2_hcd_hub_status_data, 4880197ba5f4SPaul Zimmerman .hub_control = _dwc2_hcd_hub_control, 4881197ba5f4SPaul Zimmerman .clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete, 488299a65798SGregory Herrero 488399a65798SGregory Herrero .bus_suspend = _dwc2_hcd_suspend, 488499a65798SGregory Herrero .bus_resume = _dwc2_hcd_resume, 48853bc04e28SDouglas Anderson 48863bc04e28SDouglas Anderson .map_urb_for_dma = dwc2_map_urb_for_dma, 48873bc04e28SDouglas Anderson .unmap_urb_for_dma = dwc2_unmap_urb_for_dma, 4888197ba5f4SPaul Zimmerman }; 4889197ba5f4SPaul Zimmerman 4890197ba5f4SPaul Zimmerman /* 4891197ba5f4SPaul Zimmerman * Frees secondary storage associated with the dwc2_hsotg structure contained 4892197ba5f4SPaul Zimmerman * in the struct usb_hcd field 4893197ba5f4SPaul Zimmerman */ 4894197ba5f4SPaul Zimmerman static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) 4895197ba5f4SPaul Zimmerman { 4896197ba5f4SPaul Zimmerman u32 ahbcfg; 4897197ba5f4SPaul Zimmerman u32 dctl; 4898197ba5f4SPaul Zimmerman int i; 4899197ba5f4SPaul Zimmerman 4900197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD FREE\n"); 4901197ba5f4SPaul Zimmerman 4902197ba5f4SPaul Zimmerman /* Free memory for QH/QTD lists */ 4903197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_inactive); 4904197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_active); 4905197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_inactive); 4906197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_ready); 4907197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_assigned); 4908197ba5f4SPaul Zimmerman dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_queued); 4909197ba5f4SPaul Zimmerman 4910197ba5f4SPaul Zimmerman /* Free memory for the host channels */ 4911197ba5f4SPaul Zimmerman for (i = 0; i < MAX_EPS_CHANNELS; i++) { 4912197ba5f4SPaul Zimmerman struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i]; 4913197ba5f4SPaul Zimmerman 4914197ba5f4SPaul Zimmerman if (chan != NULL) { 4915197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCD Free channel #%i, chan=%p\n", 4916197ba5f4SPaul Zimmerman i, chan); 4917197ba5f4SPaul Zimmerman hsotg->hc_ptr_array[i] = NULL; 4918197ba5f4SPaul Zimmerman kfree(chan); 4919197ba5f4SPaul Zimmerman } 4920197ba5f4SPaul Zimmerman } 4921197ba5f4SPaul Zimmerman 4922*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 4923197ba5f4SPaul Zimmerman if (hsotg->status_buf) { 4924197ba5f4SPaul Zimmerman dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE, 4925197ba5f4SPaul Zimmerman hsotg->status_buf, 4926197ba5f4SPaul Zimmerman hsotg->status_buf_dma); 4927197ba5f4SPaul Zimmerman hsotg->status_buf = NULL; 4928197ba5f4SPaul Zimmerman } 4929197ba5f4SPaul Zimmerman } else { 4930197ba5f4SPaul Zimmerman kfree(hsotg->status_buf); 4931197ba5f4SPaul Zimmerman hsotg->status_buf = NULL; 4932197ba5f4SPaul Zimmerman } 4933197ba5f4SPaul Zimmerman 493495c8bc36SAntti Seppälä ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); 4935197ba5f4SPaul Zimmerman 4936197ba5f4SPaul Zimmerman /* Disable all interrupts */ 4937197ba5f4SPaul Zimmerman ahbcfg &= ~GAHBCFG_GLBL_INTR_EN; 493895c8bc36SAntti Seppälä dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); 493995c8bc36SAntti Seppälä dwc2_writel(0, hsotg->regs + GINTMSK); 4940197ba5f4SPaul Zimmerman 4941197ba5f4SPaul Zimmerman if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) { 494295c8bc36SAntti Seppälä dctl = dwc2_readl(hsotg->regs + DCTL); 4943197ba5f4SPaul Zimmerman dctl |= DCTL_SFTDISCON; 494495c8bc36SAntti Seppälä dwc2_writel(dctl, hsotg->regs + DCTL); 4945197ba5f4SPaul Zimmerman } 4946197ba5f4SPaul Zimmerman 4947197ba5f4SPaul Zimmerman if (hsotg->wq_otg) { 4948197ba5f4SPaul Zimmerman if (!cancel_work_sync(&hsotg->wf_otg)) 4949197ba5f4SPaul Zimmerman flush_workqueue(hsotg->wq_otg); 4950197ba5f4SPaul Zimmerman destroy_workqueue(hsotg->wq_otg); 4951197ba5f4SPaul Zimmerman } 4952197ba5f4SPaul Zimmerman 4953197ba5f4SPaul Zimmerman del_timer(&hsotg->wkp_timer); 4954197ba5f4SPaul Zimmerman } 4955197ba5f4SPaul Zimmerman 4956197ba5f4SPaul Zimmerman static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) 4957197ba5f4SPaul Zimmerman { 4958197ba5f4SPaul Zimmerman /* Turn off all host-specific interrupts */ 4959197ba5f4SPaul Zimmerman dwc2_disable_host_interrupts(hsotg); 4960197ba5f4SPaul Zimmerman 4961197ba5f4SPaul Zimmerman dwc2_hcd_free(hsotg); 4962197ba5f4SPaul Zimmerman } 4963197ba5f4SPaul Zimmerman 4964197ba5f4SPaul Zimmerman /* 4965197ba5f4SPaul Zimmerman * Initializes the HCD. This function allocates memory for and initializes the 4966197ba5f4SPaul Zimmerman * static parts of the usb_hcd and dwc2_hsotg structures. It also registers the 4967197ba5f4SPaul Zimmerman * USB bus with the core and calls the hc_driver->start() function. It returns 4968197ba5f4SPaul Zimmerman * a negative error on failure. 4969197ba5f4SPaul Zimmerman */ 4970ecb176c6SMian Yousaf Kaukab int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) 4971197ba5f4SPaul Zimmerman { 4972197ba5f4SPaul Zimmerman struct usb_hcd *hcd; 4973197ba5f4SPaul Zimmerman struct dwc2_host_chan *channel; 4974197ba5f4SPaul Zimmerman u32 hcfg; 4975197ba5f4SPaul Zimmerman int i, num_channels; 4976197ba5f4SPaul Zimmerman int retval; 4977197ba5f4SPaul Zimmerman 4978f5500eccSDinh Nguyen if (usb_disabled()) 4979f5500eccSDinh Nguyen return -ENODEV; 4980f5500eccSDinh Nguyen 4981197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); 4982197ba5f4SPaul Zimmerman 4983197ba5f4SPaul Zimmerman retval = -ENOMEM; 4984197ba5f4SPaul Zimmerman 498595c8bc36SAntti Seppälä hcfg = dwc2_readl(hsotg->regs + HCFG); 4986197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); 4987197ba5f4SPaul Zimmerman 4988197ba5f4SPaul Zimmerman #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS 4989197ba5f4SPaul Zimmerman hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) * 4990197ba5f4SPaul Zimmerman FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); 4991197ba5f4SPaul Zimmerman if (!hsotg->frame_num_array) 4992197ba5f4SPaul Zimmerman goto error1; 4993197ba5f4SPaul Zimmerman hsotg->last_frame_num_array = kzalloc( 4994197ba5f4SPaul Zimmerman sizeof(*hsotg->last_frame_num_array) * 4995197ba5f4SPaul Zimmerman FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); 4996197ba5f4SPaul Zimmerman if (!hsotg->last_frame_num_array) 4997197ba5f4SPaul Zimmerman goto error1; 4998197ba5f4SPaul Zimmerman #endif 4999483bb254SDouglas Anderson hsotg->last_frame_num = HFNUM_MAX_FRNUM; 5000197ba5f4SPaul Zimmerman 5001197ba5f4SPaul Zimmerman /* Check if the bus driver or platform code has setup a dma_mask */ 5002*e7839f99SJohn Youn if (hsotg->params.host_dma > 0 && 5003197ba5f4SPaul Zimmerman hsotg->dev->dma_mask == NULL) { 5004197ba5f4SPaul Zimmerman dev_warn(hsotg->dev, 5005197ba5f4SPaul Zimmerman "dma_mask not set, disabling DMA\n"); 5006*e7839f99SJohn Youn hsotg->params.host_dma = 0; 5007bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 0; 5008197ba5f4SPaul Zimmerman } 5009197ba5f4SPaul Zimmerman 5010197ba5f4SPaul Zimmerman /* Set device flags indicating whether the HCD supports DMA */ 5011*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) { 5012197ba5f4SPaul Zimmerman if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) 5013197ba5f4SPaul Zimmerman dev_warn(hsotg->dev, "can't set DMA mask\n"); 5014197ba5f4SPaul Zimmerman if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) 5015197ba5f4SPaul Zimmerman dev_warn(hsotg->dev, "can't set coherent DMA mask\n"); 5016197ba5f4SPaul Zimmerman } 5017197ba5f4SPaul Zimmerman 5018197ba5f4SPaul Zimmerman hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); 5019197ba5f4SPaul Zimmerman if (!hcd) 5020197ba5f4SPaul Zimmerman goto error1; 5021197ba5f4SPaul Zimmerman 5022*e7839f99SJohn Youn if (hsotg->params.host_dma <= 0) 5023197ba5f4SPaul Zimmerman hcd->self.uses_dma = 0; 5024197ba5f4SPaul Zimmerman 5025197ba5f4SPaul Zimmerman hcd->has_tt = 1; 5026197ba5f4SPaul Zimmerman 5027197ba5f4SPaul Zimmerman ((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg; 5028197ba5f4SPaul Zimmerman hsotg->priv = hcd; 5029197ba5f4SPaul Zimmerman 5030197ba5f4SPaul Zimmerman /* 5031197ba5f4SPaul Zimmerman * Disable the global interrupt until all the interrupt handlers are 5032197ba5f4SPaul Zimmerman * installed 5033197ba5f4SPaul Zimmerman */ 5034197ba5f4SPaul Zimmerman dwc2_disable_global_interrupts(hsotg); 5035197ba5f4SPaul Zimmerman 5036197ba5f4SPaul Zimmerman /* Initialize the DWC_otg core, and select the Phy type */ 50370fe239bcSDouglas Anderson retval = dwc2_core_init(hsotg, true); 5038197ba5f4SPaul Zimmerman if (retval) 5039197ba5f4SPaul Zimmerman goto error2; 5040197ba5f4SPaul Zimmerman 5041197ba5f4SPaul Zimmerman /* Create new workqueue and init work */ 5042197ba5f4SPaul Zimmerman retval = -ENOMEM; 5043ec7b1268SBhaktipriya Shridhar hsotg->wq_otg = alloc_ordered_workqueue("dwc2", 0); 5044197ba5f4SPaul Zimmerman if (!hsotg->wq_otg) { 5045197ba5f4SPaul Zimmerman dev_err(hsotg->dev, "Failed to create workqueue\n"); 5046197ba5f4SPaul Zimmerman goto error2; 5047197ba5f4SPaul Zimmerman } 5048197ba5f4SPaul Zimmerman INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change); 5049197ba5f4SPaul Zimmerman 5050197ba5f4SPaul Zimmerman setup_timer(&hsotg->wkp_timer, dwc2_wakeup_detected, 5051197ba5f4SPaul Zimmerman (unsigned long)hsotg); 5052197ba5f4SPaul Zimmerman 5053197ba5f4SPaul Zimmerman /* Initialize the non-periodic schedule */ 5054197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->non_periodic_sched_inactive); 5055197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->non_periodic_sched_active); 5056197ba5f4SPaul Zimmerman 5057197ba5f4SPaul Zimmerman /* Initialize the periodic schedule */ 5058197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->periodic_sched_inactive); 5059197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->periodic_sched_ready); 5060197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->periodic_sched_assigned); 5061197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->periodic_sched_queued); 5062197ba5f4SPaul Zimmerman 5063c9c8ac01SDouglas Anderson INIT_LIST_HEAD(&hsotg->split_order); 5064c9c8ac01SDouglas Anderson 5065197ba5f4SPaul Zimmerman /* 5066197ba5f4SPaul Zimmerman * Create a host channel descriptor for each host channel implemented 5067197ba5f4SPaul Zimmerman * in the controller. Initialize the channel descriptor array. 5068197ba5f4SPaul Zimmerman */ 5069197ba5f4SPaul Zimmerman INIT_LIST_HEAD(&hsotg->free_hc_list); 5070bea8e86cSJohn Youn num_channels = hsotg->params.host_channels; 5071197ba5f4SPaul Zimmerman memset(&hsotg->hc_ptr_array[0], 0, sizeof(hsotg->hc_ptr_array)); 5072197ba5f4SPaul Zimmerman 5073197ba5f4SPaul Zimmerman for (i = 0; i < num_channels; i++) { 5074197ba5f4SPaul Zimmerman channel = kzalloc(sizeof(*channel), GFP_KERNEL); 5075197ba5f4SPaul Zimmerman if (channel == NULL) 5076197ba5f4SPaul Zimmerman goto error3; 5077197ba5f4SPaul Zimmerman channel->hc_num = i; 5078c9c8ac01SDouglas Anderson INIT_LIST_HEAD(&channel->split_order_list_entry); 5079197ba5f4SPaul Zimmerman hsotg->hc_ptr_array[i] = channel; 5080197ba5f4SPaul Zimmerman } 5081197ba5f4SPaul Zimmerman 5082197ba5f4SPaul Zimmerman /* Initialize hsotg start work */ 5083197ba5f4SPaul Zimmerman INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func); 5084197ba5f4SPaul Zimmerman 5085197ba5f4SPaul Zimmerman /* Initialize port reset work */ 5086197ba5f4SPaul Zimmerman INIT_DELAYED_WORK(&hsotg->reset_work, dwc2_hcd_reset_func); 5087197ba5f4SPaul Zimmerman 5088197ba5f4SPaul Zimmerman /* 5089197ba5f4SPaul Zimmerman * Allocate space for storing data on status transactions. Normally no 5090197ba5f4SPaul Zimmerman * data is sent, but this space acts as a bit bucket. This must be 5091197ba5f4SPaul Zimmerman * done after usb_add_hcd since that function allocates the DMA buffer 5092197ba5f4SPaul Zimmerman * pool. 5093197ba5f4SPaul Zimmerman */ 5094*e7839f99SJohn Youn if (hsotg->params.host_dma > 0) 5095197ba5f4SPaul Zimmerman hsotg->status_buf = dma_alloc_coherent(hsotg->dev, 5096197ba5f4SPaul Zimmerman DWC2_HCD_STATUS_BUF_SIZE, 5097197ba5f4SPaul Zimmerman &hsotg->status_buf_dma, GFP_KERNEL); 5098197ba5f4SPaul Zimmerman else 5099197ba5f4SPaul Zimmerman hsotg->status_buf = kzalloc(DWC2_HCD_STATUS_BUF_SIZE, 5100197ba5f4SPaul Zimmerman GFP_KERNEL); 5101197ba5f4SPaul Zimmerman 5102197ba5f4SPaul Zimmerman if (!hsotg->status_buf) 5103197ba5f4SPaul Zimmerman goto error3; 5104197ba5f4SPaul Zimmerman 51053b5fcc9aSGregory Herrero /* 51063b5fcc9aSGregory Herrero * Create kmem caches to handle descriptor buffers in descriptor 51073b5fcc9aSGregory Herrero * DMA mode. 51083b5fcc9aSGregory Herrero * Alignment must be set to 512 bytes. 51093b5fcc9aSGregory Herrero */ 5110bea8e86cSJohn Youn if (hsotg->params.dma_desc_enable || 5111bea8e86cSJohn Youn hsotg->params.dma_desc_fs_enable) { 51123b5fcc9aSGregory Herrero hsotg->desc_gen_cache = kmem_cache_create("dwc2-gen-desc", 51133b5fcc9aSGregory Herrero sizeof(struct dwc2_hcd_dma_desc) * 51143b5fcc9aSGregory Herrero MAX_DMA_DESC_NUM_GENERIC, 512, SLAB_CACHE_DMA, 51153b5fcc9aSGregory Herrero NULL); 51163b5fcc9aSGregory Herrero if (!hsotg->desc_gen_cache) { 51173b5fcc9aSGregory Herrero dev_err(hsotg->dev, 51183b5fcc9aSGregory Herrero "unable to create dwc2 generic desc cache\n"); 51193b5fcc9aSGregory Herrero 51203b5fcc9aSGregory Herrero /* 51213b5fcc9aSGregory Herrero * Disable descriptor dma mode since it will not be 51223b5fcc9aSGregory Herrero * usable. 51233b5fcc9aSGregory Herrero */ 5124bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 0; 5125bea8e86cSJohn Youn hsotg->params.dma_desc_fs_enable = 0; 51263b5fcc9aSGregory Herrero } 51273b5fcc9aSGregory Herrero 51283b5fcc9aSGregory Herrero hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc", 51293b5fcc9aSGregory Herrero sizeof(struct dwc2_hcd_dma_desc) * 51303b5fcc9aSGregory Herrero MAX_DMA_DESC_NUM_HS_ISOC, 512, 0, NULL); 51313b5fcc9aSGregory Herrero if (!hsotg->desc_hsisoc_cache) { 51323b5fcc9aSGregory Herrero dev_err(hsotg->dev, 51333b5fcc9aSGregory Herrero "unable to create dwc2 hs isoc desc cache\n"); 51343b5fcc9aSGregory Herrero 51353b5fcc9aSGregory Herrero kmem_cache_destroy(hsotg->desc_gen_cache); 51363b5fcc9aSGregory Herrero 51373b5fcc9aSGregory Herrero /* 51383b5fcc9aSGregory Herrero * Disable descriptor dma mode since it will not be 51393b5fcc9aSGregory Herrero * usable. 51403b5fcc9aSGregory Herrero */ 5141bea8e86cSJohn Youn hsotg->params.dma_desc_enable = 0; 5142bea8e86cSJohn Youn hsotg->params.dma_desc_fs_enable = 0; 51433b5fcc9aSGregory Herrero } 51443b5fcc9aSGregory Herrero } 51453b5fcc9aSGregory Herrero 5146197ba5f4SPaul Zimmerman hsotg->otg_port = 1; 5147197ba5f4SPaul Zimmerman hsotg->frame_list = NULL; 5148197ba5f4SPaul Zimmerman hsotg->frame_list_dma = 0; 5149197ba5f4SPaul Zimmerman hsotg->periodic_qh_count = 0; 5150197ba5f4SPaul Zimmerman 5151197ba5f4SPaul Zimmerman /* Initiate lx_state to L3 disconnected state */ 5152197ba5f4SPaul Zimmerman hsotg->lx_state = DWC2_L3; 5153197ba5f4SPaul Zimmerman 5154197ba5f4SPaul Zimmerman hcd->self.otg_port = hsotg->otg_port; 5155197ba5f4SPaul Zimmerman 5156197ba5f4SPaul Zimmerman /* Don't support SG list at this point */ 5157197ba5f4SPaul Zimmerman hcd->self.sg_tablesize = 0; 5158197ba5f4SPaul Zimmerman 51599df4ceacSMian Yousaf Kaukab if (!IS_ERR_OR_NULL(hsotg->uphy)) 51609df4ceacSMian Yousaf Kaukab otg_set_host(hsotg->uphy->otg, &hcd->self); 51619df4ceacSMian Yousaf Kaukab 5162197ba5f4SPaul Zimmerman /* 5163197ba5f4SPaul Zimmerman * Finish generic HCD initialization and start the HCD. This function 5164197ba5f4SPaul Zimmerman * allocates the DMA buffer pool, registers the USB bus, requests the 5165197ba5f4SPaul Zimmerman * IRQ line, and calls hcd_start method. 5166197ba5f4SPaul Zimmerman */ 5167197ba5f4SPaul Zimmerman retval = usb_add_hcd(hcd, irq, IRQF_SHARED); 5168197ba5f4SPaul Zimmerman if (retval < 0) 51693b5fcc9aSGregory Herrero goto error4; 5170197ba5f4SPaul Zimmerman 5171ec513b16SLinus Torvalds device_wakeup_enable(hcd->self.controller); 5172ec513b16SLinus Torvalds 5173197ba5f4SPaul Zimmerman dwc2_hcd_dump_state(hsotg); 5174197ba5f4SPaul Zimmerman 5175197ba5f4SPaul Zimmerman dwc2_enable_global_interrupts(hsotg); 5176197ba5f4SPaul Zimmerman 5177197ba5f4SPaul Zimmerman return 0; 5178197ba5f4SPaul Zimmerman 51793b5fcc9aSGregory Herrero error4: 51803b5fcc9aSGregory Herrero kmem_cache_destroy(hsotg->desc_gen_cache); 51813b5fcc9aSGregory Herrero kmem_cache_destroy(hsotg->desc_hsisoc_cache); 5182197ba5f4SPaul Zimmerman error3: 5183197ba5f4SPaul Zimmerman dwc2_hcd_release(hsotg); 5184197ba5f4SPaul Zimmerman error2: 5185197ba5f4SPaul Zimmerman usb_put_hcd(hcd); 5186197ba5f4SPaul Zimmerman error1: 5187197ba5f4SPaul Zimmerman 5188197ba5f4SPaul Zimmerman #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS 5189197ba5f4SPaul Zimmerman kfree(hsotg->last_frame_num_array); 5190197ba5f4SPaul Zimmerman kfree(hsotg->frame_num_array); 5191197ba5f4SPaul Zimmerman #endif 5192197ba5f4SPaul Zimmerman 5193197ba5f4SPaul Zimmerman dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval); 5194197ba5f4SPaul Zimmerman return retval; 5195197ba5f4SPaul Zimmerman } 5196197ba5f4SPaul Zimmerman 5197197ba5f4SPaul Zimmerman /* 5198197ba5f4SPaul Zimmerman * Removes the HCD. 5199197ba5f4SPaul Zimmerman * Frees memory and resources associated with the HCD and deregisters the bus. 5200197ba5f4SPaul Zimmerman */ 5201197ba5f4SPaul Zimmerman void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) 5202197ba5f4SPaul Zimmerman { 5203197ba5f4SPaul Zimmerman struct usb_hcd *hcd; 5204197ba5f4SPaul Zimmerman 5205197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "DWC OTG HCD REMOVE\n"); 5206197ba5f4SPaul Zimmerman 5207197ba5f4SPaul Zimmerman hcd = dwc2_hsotg_to_hcd(hsotg); 5208197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "hsotg->hcd = %p\n", hcd); 5209197ba5f4SPaul Zimmerman 5210197ba5f4SPaul Zimmerman if (!hcd) { 5211197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "%s: dwc2_hsotg_to_hcd(hsotg) NULL!\n", 5212197ba5f4SPaul Zimmerman __func__); 5213197ba5f4SPaul Zimmerman return; 5214197ba5f4SPaul Zimmerman } 5215197ba5f4SPaul Zimmerman 52169df4ceacSMian Yousaf Kaukab if (!IS_ERR_OR_NULL(hsotg->uphy)) 52179df4ceacSMian Yousaf Kaukab otg_set_host(hsotg->uphy->otg, NULL); 52189df4ceacSMian Yousaf Kaukab 5219197ba5f4SPaul Zimmerman usb_remove_hcd(hcd); 5220197ba5f4SPaul Zimmerman hsotg->priv = NULL; 52213b5fcc9aSGregory Herrero 52223b5fcc9aSGregory Herrero kmem_cache_destroy(hsotg->desc_gen_cache); 52233b5fcc9aSGregory Herrero kmem_cache_destroy(hsotg->desc_hsisoc_cache); 52243b5fcc9aSGregory Herrero 5225197ba5f4SPaul Zimmerman dwc2_hcd_release(hsotg); 5226197ba5f4SPaul Zimmerman usb_put_hcd(hcd); 5227197ba5f4SPaul Zimmerman 5228197ba5f4SPaul Zimmerman #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS 5229197ba5f4SPaul Zimmerman kfree(hsotg->last_frame_num_array); 5230197ba5f4SPaul Zimmerman kfree(hsotg->frame_num_array); 5231197ba5f4SPaul Zimmerman #endif 5232197ba5f4SPaul Zimmerman } 523358e52ff6SJohn Youn 523458e52ff6SJohn Youn /** 523558e52ff6SJohn Youn * dwc2_backup_host_registers() - Backup controller host registers. 523658e52ff6SJohn Youn * When suspending usb bus, registers needs to be backuped 523758e52ff6SJohn Youn * if controller power is disabled once suspended. 523858e52ff6SJohn Youn * 523958e52ff6SJohn Youn * @hsotg: Programming view of the DWC_otg controller 524058e52ff6SJohn Youn */ 524158e52ff6SJohn Youn int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) 524258e52ff6SJohn Youn { 524358e52ff6SJohn Youn struct dwc2_hregs_backup *hr; 524458e52ff6SJohn Youn int i; 524558e52ff6SJohn Youn 524658e52ff6SJohn Youn dev_dbg(hsotg->dev, "%s\n", __func__); 524758e52ff6SJohn Youn 524858e52ff6SJohn Youn /* Backup Host regs */ 524958e52ff6SJohn Youn hr = &hsotg->hr_backup; 525058e52ff6SJohn Youn hr->hcfg = dwc2_readl(hsotg->regs + HCFG); 525158e52ff6SJohn Youn hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK); 5252bea8e86cSJohn Youn for (i = 0; i < hsotg->params.host_channels; ++i) 525358e52ff6SJohn Youn hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i)); 525458e52ff6SJohn Youn 525558e52ff6SJohn Youn hr->hprt0 = dwc2_read_hprt0(hsotg); 525658e52ff6SJohn Youn hr->hfir = dwc2_readl(hsotg->regs + HFIR); 525758e52ff6SJohn Youn hr->valid = true; 525858e52ff6SJohn Youn 525958e52ff6SJohn Youn return 0; 526058e52ff6SJohn Youn } 526158e52ff6SJohn Youn 526258e52ff6SJohn Youn /** 526358e52ff6SJohn Youn * dwc2_restore_host_registers() - Restore controller host registers. 526458e52ff6SJohn Youn * When resuming usb bus, device registers needs to be restored 526558e52ff6SJohn Youn * if controller power were disabled. 526658e52ff6SJohn Youn * 526758e52ff6SJohn Youn * @hsotg: Programming view of the DWC_otg controller 526858e52ff6SJohn Youn */ 526958e52ff6SJohn Youn int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) 527058e52ff6SJohn Youn { 527158e52ff6SJohn Youn struct dwc2_hregs_backup *hr; 527258e52ff6SJohn Youn int i; 527358e52ff6SJohn Youn 527458e52ff6SJohn Youn dev_dbg(hsotg->dev, "%s\n", __func__); 527558e52ff6SJohn Youn 527658e52ff6SJohn Youn /* Restore host regs */ 527758e52ff6SJohn Youn hr = &hsotg->hr_backup; 527858e52ff6SJohn Youn if (!hr->valid) { 527958e52ff6SJohn Youn dev_err(hsotg->dev, "%s: no host registers to restore\n", 528058e52ff6SJohn Youn __func__); 528158e52ff6SJohn Youn return -EINVAL; 528258e52ff6SJohn Youn } 528358e52ff6SJohn Youn hr->valid = false; 528458e52ff6SJohn Youn 528558e52ff6SJohn Youn dwc2_writel(hr->hcfg, hsotg->regs + HCFG); 528658e52ff6SJohn Youn dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK); 528758e52ff6SJohn Youn 5288bea8e86cSJohn Youn for (i = 0; i < hsotg->params.host_channels; ++i) 528958e52ff6SJohn Youn dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i)); 529058e52ff6SJohn Youn 529158e52ff6SJohn Youn dwc2_writel(hr->hprt0, hsotg->regs + HPRT0); 529258e52ff6SJohn Youn dwc2_writel(hr->hfir, hsotg->regs + HFIR); 529358e52ff6SJohn Youn hsotg->frame_number = 0; 529458e52ff6SJohn Youn 529558e52ff6SJohn Youn return 0; 529658e52ff6SJohn Youn } 5297