15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2197ba5f4SPaul Zimmerman /* 3197ba5f4SPaul Zimmerman * core.c - DesignWare HS OTG Controller common routines 4197ba5f4SPaul Zimmerman * 5197ba5f4SPaul Zimmerman * Copyright (C) 2004-2013 Synopsys, Inc. 6197ba5f4SPaul Zimmerman * 7197ba5f4SPaul Zimmerman * Redistribution and use in source and binary forms, with or without 8197ba5f4SPaul Zimmerman * modification, are permitted provided that the following conditions 9197ba5f4SPaul Zimmerman * are met: 10197ba5f4SPaul Zimmerman * 1. Redistributions of source code must retain the above copyright 11197ba5f4SPaul Zimmerman * notice, this list of conditions, and the following disclaimer, 12197ba5f4SPaul Zimmerman * without modification. 13197ba5f4SPaul Zimmerman * 2. Redistributions in binary form must reproduce the above copyright 14197ba5f4SPaul Zimmerman * notice, this list of conditions and the following disclaimer in the 15197ba5f4SPaul Zimmerman * documentation and/or other materials provided with the distribution. 16197ba5f4SPaul Zimmerman * 3. The names of the above-listed copyright holders may not be used 17197ba5f4SPaul Zimmerman * to endorse or promote products derived from this software without 18197ba5f4SPaul Zimmerman * specific prior written permission. 19197ba5f4SPaul Zimmerman * 20197ba5f4SPaul Zimmerman * ALTERNATIVELY, this software may be distributed under the terms of the 21197ba5f4SPaul Zimmerman * GNU General Public License ("GPL") as published by the Free Software 22197ba5f4SPaul Zimmerman * Foundation; either version 2 of the License, or (at your option) any 23197ba5f4SPaul Zimmerman * later version. 24197ba5f4SPaul Zimmerman * 25197ba5f4SPaul Zimmerman * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 26197ba5f4SPaul Zimmerman * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27197ba5f4SPaul Zimmerman * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28197ba5f4SPaul Zimmerman * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 29197ba5f4SPaul Zimmerman * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30197ba5f4SPaul Zimmerman * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31197ba5f4SPaul Zimmerman * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 32197ba5f4SPaul Zimmerman * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33197ba5f4SPaul Zimmerman * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34197ba5f4SPaul Zimmerman * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35197ba5f4SPaul Zimmerman * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36197ba5f4SPaul Zimmerman */ 37197ba5f4SPaul Zimmerman 38197ba5f4SPaul Zimmerman /* 39197ba5f4SPaul Zimmerman * The Core code provides basic services for accessing and managing the 40197ba5f4SPaul Zimmerman * DWC_otg hardware. These services are used by both the Host Controller 41197ba5f4SPaul Zimmerman * Driver and the Peripheral Controller Driver. 42197ba5f4SPaul Zimmerman */ 43197ba5f4SPaul Zimmerman #include <linux/kernel.h> 44197ba5f4SPaul Zimmerman #include <linux/module.h> 45197ba5f4SPaul Zimmerman #include <linux/moduleparam.h> 46197ba5f4SPaul Zimmerman #include <linux/spinlock.h> 47197ba5f4SPaul Zimmerman #include <linux/interrupt.h> 48197ba5f4SPaul Zimmerman #include <linux/dma-mapping.h> 49197ba5f4SPaul Zimmerman #include <linux/delay.h> 50197ba5f4SPaul Zimmerman #include <linux/io.h> 51197ba5f4SPaul Zimmerman #include <linux/slab.h> 52197ba5f4SPaul Zimmerman #include <linux/usb.h> 53197ba5f4SPaul Zimmerman 54197ba5f4SPaul Zimmerman #include <linux/usb/hcd.h> 55197ba5f4SPaul Zimmerman #include <linux/usb/ch11.h> 56197ba5f4SPaul Zimmerman 57197ba5f4SPaul Zimmerman #include "core.h" 58197ba5f4SPaul Zimmerman #include "hcd.h" 59197ba5f4SPaul Zimmerman 60d17ee77bSGregory Herrero /** 61d17ee77bSGregory Herrero * dwc2_backup_global_registers() - Backup global controller registers. 62d17ee77bSGregory Herrero * When suspending usb bus, registers needs to be backuped 63d17ee77bSGregory Herrero * if controller power is disabled once suspended. 64d17ee77bSGregory Herrero * 65d17ee77bSGregory Herrero * @hsotg: Programming view of the DWC_otg controller 66d17ee77bSGregory Herrero */ 67d17ee77bSGregory Herrero static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) 68d17ee77bSGregory Herrero { 69d17ee77bSGregory Herrero struct dwc2_gregs_backup *gr; 70d17ee77bSGregory Herrero int i; 71d17ee77bSGregory Herrero 72d17ee77bSGregory Herrero /* Backup global regs */ 73cc1e204cSMian Yousaf Kaukab gr = &hsotg->gr_backup; 74d17ee77bSGregory Herrero 7595c8bc36SAntti Seppälä gr->gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); 7695c8bc36SAntti Seppälä gr->gintmsk = dwc2_readl(hsotg->regs + GINTMSK); 7795c8bc36SAntti Seppälä gr->gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); 7895c8bc36SAntti Seppälä gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 7995c8bc36SAntti Seppälä gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); 8095c8bc36SAntti Seppälä gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); 8195c8bc36SAntti Seppälä gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ); 8295c8bc36SAntti Seppälä gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG); 83600a490eSRazmik Karapetyan gr->pcgcctl1 = dwc2_readl(hsotg->regs + PCGCCTL1); 84d17ee77bSGregory Herrero for (i = 0; i < MAX_EPS_CHANNELS; i++) 8595c8bc36SAntti Seppälä gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i)); 86d17ee77bSGregory Herrero 87cc1e204cSMian Yousaf Kaukab gr->valid = true; 88d17ee77bSGregory Herrero return 0; 89d17ee77bSGregory Herrero } 90d17ee77bSGregory Herrero 91d17ee77bSGregory Herrero /** 92d17ee77bSGregory Herrero * dwc2_restore_global_registers() - Restore controller global registers. 93d17ee77bSGregory Herrero * When resuming usb bus, device registers needs to be restored 94d17ee77bSGregory Herrero * if controller power were disabled. 95d17ee77bSGregory Herrero * 96d17ee77bSGregory Herrero * @hsotg: Programming view of the DWC_otg controller 97d17ee77bSGregory Herrero */ 98d17ee77bSGregory Herrero static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) 99d17ee77bSGregory Herrero { 100d17ee77bSGregory Herrero struct dwc2_gregs_backup *gr; 101d17ee77bSGregory Herrero int i; 102d17ee77bSGregory Herrero 103d17ee77bSGregory Herrero dev_dbg(hsotg->dev, "%s\n", __func__); 104d17ee77bSGregory Herrero 105d17ee77bSGregory Herrero /* Restore global regs */ 106cc1e204cSMian Yousaf Kaukab gr = &hsotg->gr_backup; 107cc1e204cSMian Yousaf Kaukab if (!gr->valid) { 108d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: no global registers to restore\n", 109d17ee77bSGregory Herrero __func__); 110d17ee77bSGregory Herrero return -EINVAL; 111d17ee77bSGregory Herrero } 112cc1e204cSMian Yousaf Kaukab gr->valid = false; 113d17ee77bSGregory Herrero 11495c8bc36SAntti Seppälä dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); 11595c8bc36SAntti Seppälä dwc2_writel(gr->gotgctl, hsotg->regs + GOTGCTL); 11695c8bc36SAntti Seppälä dwc2_writel(gr->gintmsk, hsotg->regs + GINTMSK); 11795c8bc36SAntti Seppälä dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG); 11895c8bc36SAntti Seppälä dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG); 11995c8bc36SAntti Seppälä dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ); 12095c8bc36SAntti Seppälä dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ); 12195c8bc36SAntti Seppälä dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ); 12295c8bc36SAntti Seppälä dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG); 123600a490eSRazmik Karapetyan dwc2_writel(gr->pcgcctl1, hsotg->regs + PCGCCTL1); 124d17ee77bSGregory Herrero for (i = 0; i < MAX_EPS_CHANNELS; i++) 12595c8bc36SAntti Seppälä dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i)); 126d17ee77bSGregory Herrero 127d17ee77bSGregory Herrero return 0; 128d17ee77bSGregory Herrero } 129d17ee77bSGregory Herrero 130d17ee77bSGregory Herrero /** 131*41ba9b9bSVardan Mikayelyan * dwc2_exit_partial_power_down() - Exit controller from Partial Power Down. 132d17ee77bSGregory Herrero * 133d17ee77bSGregory Herrero * @hsotg: Programming view of the DWC_otg controller 134d17ee77bSGregory Herrero * @restore: Controller registers need to be restored 135d17ee77bSGregory Herrero */ 136*41ba9b9bSVardan Mikayelyan int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) 137d17ee77bSGregory Herrero { 138d17ee77bSGregory Herrero u32 pcgcctl; 139d17ee77bSGregory Herrero int ret = 0; 140d17ee77bSGregory Herrero 141*41ba9b9bSVardan Mikayelyan if (!hsotg->params.power_down) 142285046aaSGregory Herrero return -ENOTSUPP; 143285046aaSGregory Herrero 14495c8bc36SAntti Seppälä pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); 145d17ee77bSGregory Herrero pcgcctl &= ~PCGCTL_STOPPCLK; 14695c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 147d17ee77bSGregory Herrero 14895c8bc36SAntti Seppälä pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); 149d17ee77bSGregory Herrero pcgcctl &= ~PCGCTL_PWRCLMP; 15095c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 151d17ee77bSGregory Herrero 15295c8bc36SAntti Seppälä pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); 153d17ee77bSGregory Herrero pcgcctl &= ~PCGCTL_RSTPDWNMODULE; 15495c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 155d17ee77bSGregory Herrero 156d17ee77bSGregory Herrero udelay(100); 157d17ee77bSGregory Herrero if (restore) { 158d17ee77bSGregory Herrero ret = dwc2_restore_global_registers(hsotg); 159d17ee77bSGregory Herrero if (ret) { 160d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to restore registers\n", 161d17ee77bSGregory Herrero __func__); 162d17ee77bSGregory Herrero return ret; 163d17ee77bSGregory Herrero } 164d17ee77bSGregory Herrero if (dwc2_is_host_mode(hsotg)) { 165d17ee77bSGregory Herrero ret = dwc2_restore_host_registers(hsotg); 166d17ee77bSGregory Herrero if (ret) { 167d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to restore host registers\n", 168d17ee77bSGregory Herrero __func__); 169d17ee77bSGregory Herrero return ret; 170d17ee77bSGregory Herrero } 171d17ee77bSGregory Herrero } else { 172d17ee77bSGregory Herrero ret = dwc2_restore_device_registers(hsotg); 173d17ee77bSGregory Herrero if (ret) { 174d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to restore device registers\n", 175d17ee77bSGregory Herrero __func__); 176d17ee77bSGregory Herrero return ret; 177d17ee77bSGregory Herrero } 178d17ee77bSGregory Herrero } 179d17ee77bSGregory Herrero } 180d17ee77bSGregory Herrero 181d17ee77bSGregory Herrero return ret; 182d17ee77bSGregory Herrero } 183d17ee77bSGregory Herrero 184d17ee77bSGregory Herrero /** 185*41ba9b9bSVardan Mikayelyan * dwc2_enter_partial_power_down() - Put controller in Partial Power Down. 186d17ee77bSGregory Herrero * 187d17ee77bSGregory Herrero * @hsotg: Programming view of the DWC_otg controller 188d17ee77bSGregory Herrero */ 189*41ba9b9bSVardan Mikayelyan int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg) 190d17ee77bSGregory Herrero { 191d17ee77bSGregory Herrero u32 pcgcctl; 192d17ee77bSGregory Herrero int ret = 0; 193d17ee77bSGregory Herrero 194*41ba9b9bSVardan Mikayelyan if (!hsotg->params.power_down) 195285046aaSGregory Herrero return -ENOTSUPP; 196285046aaSGregory Herrero 197d17ee77bSGregory Herrero /* Backup all registers */ 198d17ee77bSGregory Herrero ret = dwc2_backup_global_registers(hsotg); 199d17ee77bSGregory Herrero if (ret) { 200d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to backup global registers\n", 201d17ee77bSGregory Herrero __func__); 202d17ee77bSGregory Herrero return ret; 203d17ee77bSGregory Herrero } 204d17ee77bSGregory Herrero 205d17ee77bSGregory Herrero if (dwc2_is_host_mode(hsotg)) { 206d17ee77bSGregory Herrero ret = dwc2_backup_host_registers(hsotg); 207d17ee77bSGregory Herrero if (ret) { 208d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to backup host registers\n", 209d17ee77bSGregory Herrero __func__); 210d17ee77bSGregory Herrero return ret; 211d17ee77bSGregory Herrero } 212d17ee77bSGregory Herrero } else { 213d17ee77bSGregory Herrero ret = dwc2_backup_device_registers(hsotg); 214d17ee77bSGregory Herrero if (ret) { 215d17ee77bSGregory Herrero dev_err(hsotg->dev, "%s: failed to backup device registers\n", 216d17ee77bSGregory Herrero __func__); 217d17ee77bSGregory Herrero return ret; 218d17ee77bSGregory Herrero } 219d17ee77bSGregory Herrero } 220d17ee77bSGregory Herrero 221cad73da2SGregory Herrero /* 222cad73da2SGregory Herrero * Clear any pending interrupts since dwc2 will not be able to 223*41ba9b9bSVardan Mikayelyan * clear them after entering partial_power_down. 224cad73da2SGregory Herrero */ 225cad73da2SGregory Herrero dwc2_writel(0xffffffff, hsotg->regs + GINTSTS); 226cad73da2SGregory Herrero 227d17ee77bSGregory Herrero /* Put the controller in low power state */ 22895c8bc36SAntti Seppälä pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); 229d17ee77bSGregory Herrero 230d17ee77bSGregory Herrero pcgcctl |= PCGCTL_PWRCLMP; 23195c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 232d17ee77bSGregory Herrero ndelay(20); 233d17ee77bSGregory Herrero 234d17ee77bSGregory Herrero pcgcctl |= PCGCTL_RSTPDWNMODULE; 23595c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 236d17ee77bSGregory Herrero ndelay(20); 237d17ee77bSGregory Herrero 238d17ee77bSGregory Herrero pcgcctl |= PCGCTL_STOPPCLK; 23995c8bc36SAntti Seppälä dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); 240d17ee77bSGregory Herrero 241d17ee77bSGregory Herrero return ret; 242d17ee77bSGregory Herrero } 243d17ee77bSGregory Herrero 244fef6bc37SJohn Youn /** 245fef6bc37SJohn Youn * dwc2_wait_for_mode() - Waits for the controller mode. 246fef6bc37SJohn Youn * @hsotg: Programming view of the DWC_otg controller. 247fef6bc37SJohn Youn * @host_mode: If true, waits for host mode, otherwise device mode. 248fef6bc37SJohn Youn */ 249fef6bc37SJohn Youn static void dwc2_wait_for_mode(struct dwc2_hsotg *hsotg, 250fef6bc37SJohn Youn bool host_mode) 251fef6bc37SJohn Youn { 252fef6bc37SJohn Youn ktime_t start; 253fef6bc37SJohn Youn ktime_t end; 254fef6bc37SJohn Youn unsigned int timeout = 110; 255fef6bc37SJohn Youn 256fef6bc37SJohn Youn dev_vdbg(hsotg->dev, "Waiting for %s mode\n", 257fef6bc37SJohn Youn host_mode ? "host" : "device"); 258fef6bc37SJohn Youn 259fef6bc37SJohn Youn start = ktime_get(); 260fef6bc37SJohn Youn 261fef6bc37SJohn Youn while (1) { 262fef6bc37SJohn Youn s64 ms; 263fef6bc37SJohn Youn 264fef6bc37SJohn Youn if (dwc2_is_host_mode(hsotg) == host_mode) { 265fef6bc37SJohn Youn dev_vdbg(hsotg->dev, "%s mode set\n", 266fef6bc37SJohn Youn host_mode ? "Host" : "Device"); 267fef6bc37SJohn Youn break; 268fef6bc37SJohn Youn } 269fef6bc37SJohn Youn 270fef6bc37SJohn Youn end = ktime_get(); 271fef6bc37SJohn Youn ms = ktime_to_ms(ktime_sub(end, start)); 272fef6bc37SJohn Youn 273fef6bc37SJohn Youn if (ms >= (s64)timeout) { 274fef6bc37SJohn Youn dev_warn(hsotg->dev, "%s: Couldn't set %s mode\n", 275fef6bc37SJohn Youn __func__, host_mode ? "host" : "device"); 276fef6bc37SJohn Youn break; 277fef6bc37SJohn Youn } 278fef6bc37SJohn Youn 279fef6bc37SJohn Youn usleep_range(1000, 2000); 280fef6bc37SJohn Youn } 281fef6bc37SJohn Youn } 282fef6bc37SJohn Youn 283fef6bc37SJohn Youn /** 284fef6bc37SJohn Youn * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce 285fef6bc37SJohn Youn * filter is enabled. 286fef6bc37SJohn Youn */ 287fef6bc37SJohn Youn static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg) 288fef6bc37SJohn Youn { 289fef6bc37SJohn Youn u32 gsnpsid; 290fef6bc37SJohn Youn u32 ghwcfg4; 291fef6bc37SJohn Youn 292fef6bc37SJohn Youn if (!dwc2_hw_is_otg(hsotg)) 293fef6bc37SJohn Youn return false; 294fef6bc37SJohn Youn 295fef6bc37SJohn Youn /* Check if core configuration includes the IDDIG filter. */ 296fef6bc37SJohn Youn ghwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4); 297fef6bc37SJohn Youn if (!(ghwcfg4 & GHWCFG4_IDDIG_FILT_EN)) 298fef6bc37SJohn Youn return false; 299fef6bc37SJohn Youn 300fef6bc37SJohn Youn /* 301fef6bc37SJohn Youn * Check if the IDDIG debounce filter is bypassed. Available 302fef6bc37SJohn Youn * in core version >= 3.10a. 303fef6bc37SJohn Youn */ 304fef6bc37SJohn Youn gsnpsid = dwc2_readl(hsotg->regs + GSNPSID); 305fef6bc37SJohn Youn if (gsnpsid >= DWC2_CORE_REV_3_10a) { 306fef6bc37SJohn Youn u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); 307fef6bc37SJohn Youn 308fef6bc37SJohn Youn if (gotgctl & GOTGCTL_DBNCE_FLTR_BYPASS) 309fef6bc37SJohn Youn return false; 310fef6bc37SJohn Youn } 311fef6bc37SJohn Youn 312fef6bc37SJohn Youn return true; 313fef6bc37SJohn Youn } 314fef6bc37SJohn Youn 315197ba5f4SPaul Zimmerman /* 316197ba5f4SPaul Zimmerman * Do core a soft reset of the core. Be careful with this because it 317197ba5f4SPaul Zimmerman * resets all the internal state machines of the core. 318197ba5f4SPaul Zimmerman */ 3196e6360b6SJohn Stultz int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait) 320197ba5f4SPaul Zimmerman { 321197ba5f4SPaul Zimmerman u32 greset; 322fef6bc37SJohn Youn bool wait_for_host_mode = false; 323197ba5f4SPaul Zimmerman 324197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "%s()\n", __func__); 325197ba5f4SPaul Zimmerman 326fef6bc37SJohn Youn /* 327fef6bc37SJohn Youn * If the current mode is host, either due to the force mode 328fef6bc37SJohn Youn * bit being set (which persists after core reset) or the 329fef6bc37SJohn Youn * connector id pin, a core soft reset will temporarily reset 330fef6bc37SJohn Youn * the mode to device. A delay from the IDDIG debounce filter 331fef6bc37SJohn Youn * will occur before going back to host mode. 332fef6bc37SJohn Youn * 333fef6bc37SJohn Youn * Determine whether we will go back into host mode after a 334fef6bc37SJohn Youn * reset and account for this delay after the reset. 335fef6bc37SJohn Youn */ 336fef6bc37SJohn Youn if (dwc2_iddig_filter_enabled(hsotg)) { 337fef6bc37SJohn Youn u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); 338fef6bc37SJohn Youn u32 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 339fef6bc37SJohn Youn 340fef6bc37SJohn Youn if (!(gotgctl & GOTGCTL_CONID_B) || 341fef6bc37SJohn Youn (gusbcfg & GUSBCFG_FORCEHOSTMODE)) { 342fef6bc37SJohn Youn wait_for_host_mode = true; 343fef6bc37SJohn Youn } 344fef6bc37SJohn Youn } 345fef6bc37SJohn Youn 346197ba5f4SPaul Zimmerman /* Core Soft Reset */ 347b8ccc593SJohn Youn greset = dwc2_readl(hsotg->regs + GRSTCTL); 348197ba5f4SPaul Zimmerman greset |= GRSTCTL_CSFTRST; 34995c8bc36SAntti Seppälä dwc2_writel(greset, hsotg->regs + GRSTCTL); 35079d6b8c5SSevak Arakelyan 35179d6b8c5SSevak Arakelyan if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 50)) { 35279d6b8c5SSevak Arakelyan dev_warn(hsotg->dev, "%s: HANG! Soft Reset timeout GRSTCTL GRSTCTL_CSFTRST\n", 35379d6b8c5SSevak Arakelyan __func__); 354197ba5f4SPaul Zimmerman return -EBUSY; 355197ba5f4SPaul Zimmerman } 356197ba5f4SPaul Zimmerman 357b8ccc593SJohn Youn /* Wait for AHB master IDLE state */ 35879d6b8c5SSevak Arakelyan if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 50)) { 35979d6b8c5SSevak Arakelyan dev_warn(hsotg->dev, "%s: HANG! AHB Idle timeout GRSTCTL GRSTCTL_AHBIDLE\n", 36079d6b8c5SSevak Arakelyan __func__); 361b8ccc593SJohn Youn return -EBUSY; 362b8ccc593SJohn Youn } 363b8ccc593SJohn Youn 3646e6360b6SJohn Stultz if (wait_for_host_mode && !skip_wait) 365fef6bc37SJohn Youn dwc2_wait_for_mode(hsotg, true); 366fef6bc37SJohn Youn 367b5d308abSJohn Youn return 0; 368b5d308abSJohn Youn } 369b5d308abSJohn Youn 370b5d308abSJohn Youn /* 37109c96980SJohn Youn * Force the mode of the controller. 37209c96980SJohn Youn * 37309c96980SJohn Youn * Forcing the mode is needed for two cases: 37409c96980SJohn Youn * 37509c96980SJohn Youn * 1) If the dr_mode is set to either HOST or PERIPHERAL we force the 37609c96980SJohn Youn * controller to stay in a particular mode regardless of ID pin 37709c96980SJohn Youn * changes. We do this usually after a core reset. 37809c96980SJohn Youn * 37909c96980SJohn Youn * 2) During probe we want to read reset values of the hw 38009c96980SJohn Youn * configuration registers that are only available in either host or 38109c96980SJohn Youn * device mode. We may need to force the mode if the current mode does 38209c96980SJohn Youn * not allow us to access the register in the mode that we want. 38309c96980SJohn Youn * 38409c96980SJohn Youn * In either case it only makes sense to force the mode if the 38509c96980SJohn Youn * controller hardware is OTG capable. 38609c96980SJohn Youn * 38709c96980SJohn Youn * Checks are done in this function to determine whether doing a force 38809c96980SJohn Youn * would be valid or not. 38909c96980SJohn Youn * 3902938fc63SJohn Youn * If a force is done, it requires a IDDIG debounce filter delay if 3912938fc63SJohn Youn * the filter is configured and enabled. We poll the current mode of 3922938fc63SJohn Youn * the controller to account for this delay. 39309c96980SJohn Youn */ 39409c96980SJohn Youn static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) 39509c96980SJohn Youn { 39609c96980SJohn Youn u32 gusbcfg; 39709c96980SJohn Youn u32 set; 39809c96980SJohn Youn u32 clear; 39909c96980SJohn Youn 40009c96980SJohn Youn dev_dbg(hsotg->dev, "Forcing mode to %s\n", host ? "host" : "device"); 40109c96980SJohn Youn 40209c96980SJohn Youn /* 40309c96980SJohn Youn * Force mode has no effect if the hardware is not OTG. 40409c96980SJohn Youn */ 40509c96980SJohn Youn if (!dwc2_hw_is_otg(hsotg)) 40609c96980SJohn Youn return false; 40709c96980SJohn Youn 40809c96980SJohn Youn /* 40909c96980SJohn Youn * If dr_mode is either peripheral or host only, there is no 41009c96980SJohn Youn * need to ever force the mode to the opposite mode. 41109c96980SJohn Youn */ 41209c96980SJohn Youn if (WARN_ON(host && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)) 41309c96980SJohn Youn return false; 41409c96980SJohn Youn 41509c96980SJohn Youn if (WARN_ON(!host && hsotg->dr_mode == USB_DR_MODE_HOST)) 41609c96980SJohn Youn return false; 41709c96980SJohn Youn 41809c96980SJohn Youn gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 41909c96980SJohn Youn 42009c96980SJohn Youn set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE; 42109c96980SJohn Youn clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE; 42209c96980SJohn Youn 42309c96980SJohn Youn gusbcfg &= ~clear; 42409c96980SJohn Youn gusbcfg |= set; 42509c96980SJohn Youn dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); 42609c96980SJohn Youn 4272938fc63SJohn Youn dwc2_wait_for_mode(hsotg, host); 42809c96980SJohn Youn return true; 42909c96980SJohn Youn } 43009c96980SJohn Youn 4312938fc63SJohn Youn /** 4322938fc63SJohn Youn * dwc2_clear_force_mode() - Clears the force mode bits. 4332938fc63SJohn Youn * 4342938fc63SJohn Youn * After clearing the bits, wait up to 100 ms to account for any 4352938fc63SJohn Youn * potential IDDIG filter delay. We can't know if we expect this delay 4362938fc63SJohn Youn * or not because the value of the connector ID status is affected by 4372938fc63SJohn Youn * the force mode. We only need to call this once during probe if 4382938fc63SJohn Youn * dr_mode == OTG. 43909c96980SJohn Youn */ 440323230efSJohn Youn void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) 44109c96980SJohn Youn { 44209c96980SJohn Youn u32 gusbcfg; 44309c96980SJohn Youn 44409c96980SJohn Youn gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG); 44509c96980SJohn Youn gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; 44609c96980SJohn Youn gusbcfg &= ~GUSBCFG_FORCEDEVMODE; 44709c96980SJohn Youn dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); 44809c96980SJohn Youn 4492938fc63SJohn Youn if (dwc2_iddig_filter_enabled(hsotg)) 450d3fe81d2SNicholas Mc Guire msleep(100); 45109c96980SJohn Youn } 45209c96980SJohn Youn 45309c96980SJohn Youn /* 45409c96980SJohn Youn * Sets or clears force mode based on the dr_mode parameter. 45509c96980SJohn Youn */ 45609c96980SJohn Youn void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) 45709c96980SJohn Youn { 458a07ce8d3SHeiko Stuebner bool ret; 459a07ce8d3SHeiko Stuebner 46009c96980SJohn Youn switch (hsotg->dr_mode) { 46109c96980SJohn Youn case USB_DR_MODE_HOST: 462a07ce8d3SHeiko Stuebner ret = dwc2_force_mode(hsotg, true); 463a07ce8d3SHeiko Stuebner /* 464a07ce8d3SHeiko Stuebner * NOTE: This is required for some rockchip soc based 465a07ce8d3SHeiko Stuebner * platforms on their host-only dwc2. 466a07ce8d3SHeiko Stuebner */ 467a07ce8d3SHeiko Stuebner if (!ret) 468a07ce8d3SHeiko Stuebner msleep(50); 469a07ce8d3SHeiko Stuebner 47009c96980SJohn Youn break; 47109c96980SJohn Youn case USB_DR_MODE_PERIPHERAL: 47209c96980SJohn Youn dwc2_force_mode(hsotg, false); 47309c96980SJohn Youn break; 47409c96980SJohn Youn case USB_DR_MODE_OTG: 47509c96980SJohn Youn dwc2_clear_force_mode(hsotg); 47609c96980SJohn Youn break; 47709c96980SJohn Youn default: 47809c96980SJohn Youn dev_warn(hsotg->dev, "%s() Invalid dr_mode=%d\n", 47909c96980SJohn Youn __func__, hsotg->dr_mode); 48009c96980SJohn Youn break; 48109c96980SJohn Youn } 48209c96980SJohn Youn } 48309c96980SJohn Youn 48409c96980SJohn Youn /* 485b5d308abSJohn Youn * Do core a soft reset of the core. Be careful with this because it 486b5d308abSJohn Youn * resets all the internal state machines of the core. 487b5d308abSJohn Youn * 488b5d308abSJohn Youn * Additionally this will apply force mode as per the hsotg->dr_mode 489b5d308abSJohn Youn * parameter. 490b5d308abSJohn Youn */ 491b5d308abSJohn Youn int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg) 492b5d308abSJohn Youn { 493b5d308abSJohn Youn int retval; 494b5d308abSJohn Youn 4956e6360b6SJohn Stultz retval = dwc2_core_reset(hsotg, false); 496b5d308abSJohn Youn if (retval) 497b5d308abSJohn Youn return retval; 498b5d308abSJohn Youn 49909c96980SJohn Youn dwc2_force_dr_mode(hsotg); 500197ba5f4SPaul Zimmerman return 0; 501197ba5f4SPaul Zimmerman } 502197ba5f4SPaul Zimmerman 50366e77a24SRazmik Karapetyan /* 50466e77a24SRazmik Karapetyan * dwc2_enable_acg - enable active clock gating feature 50566e77a24SRazmik Karapetyan */ 50666e77a24SRazmik Karapetyan void dwc2_enable_acg(struct dwc2_hsotg *hsotg) 50766e77a24SRazmik Karapetyan { 50866e77a24SRazmik Karapetyan if (hsotg->params.acg_enable) { 50966e77a24SRazmik Karapetyan u32 pcgcctl1 = dwc2_readl(hsotg->regs + PCGCCTL1); 51066e77a24SRazmik Karapetyan 51166e77a24SRazmik Karapetyan dev_dbg(hsotg->dev, "Enabling Active Clock Gating\n"); 51266e77a24SRazmik Karapetyan pcgcctl1 |= PCGCCTL1_GATEEN; 51366e77a24SRazmik Karapetyan dwc2_writel(pcgcctl1, hsotg->regs + PCGCCTL1); 51466e77a24SRazmik Karapetyan } 51566e77a24SRazmik Karapetyan } 51666e77a24SRazmik Karapetyan 517197ba5f4SPaul Zimmerman /** 518197ba5f4SPaul Zimmerman * dwc2_dump_host_registers() - Prints the host registers 519197ba5f4SPaul Zimmerman * 520197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 521197ba5f4SPaul Zimmerman * 522197ba5f4SPaul Zimmerman * NOTE: This function will be removed once the peripheral controller code 523197ba5f4SPaul Zimmerman * is integrated and the driver is stable 524197ba5f4SPaul Zimmerman */ 525197ba5f4SPaul Zimmerman void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg) 526197ba5f4SPaul Zimmerman { 527197ba5f4SPaul Zimmerman #ifdef DEBUG 528197ba5f4SPaul Zimmerman u32 __iomem *addr; 529197ba5f4SPaul Zimmerman int i; 530197ba5f4SPaul Zimmerman 531197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Host Global Registers\n"); 532197ba5f4SPaul Zimmerman addr = hsotg->regs + HCFG; 533197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCFG @0x%08lX : 0x%08X\n", 53495c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 535197ba5f4SPaul Zimmerman addr = hsotg->regs + HFIR; 536197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HFIR @0x%08lX : 0x%08X\n", 53795c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 538197ba5f4SPaul Zimmerman addr = hsotg->regs + HFNUM; 539197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HFNUM @0x%08lX : 0x%08X\n", 54095c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 541197ba5f4SPaul Zimmerman addr = hsotg->regs + HPTXSTS; 542197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HPTXSTS @0x%08lX : 0x%08X\n", 54395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 544197ba5f4SPaul Zimmerman addr = hsotg->regs + HAINT; 545197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HAINT @0x%08lX : 0x%08X\n", 54695c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 547197ba5f4SPaul Zimmerman addr = hsotg->regs + HAINTMSK; 548197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n", 54995c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 55095832c00SJohn Youn if (hsotg->params.dma_desc_enable) { 551197ba5f4SPaul Zimmerman addr = hsotg->regs + HFLBADDR; 552197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n", 55395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 554197ba5f4SPaul Zimmerman } 555197ba5f4SPaul Zimmerman 556197ba5f4SPaul Zimmerman addr = hsotg->regs + HPRT0; 557197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HPRT0 @0x%08lX : 0x%08X\n", 55895c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 559197ba5f4SPaul Zimmerman 560bea8e86cSJohn Youn for (i = 0; i < hsotg->params.host_channels; i++) { 561197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i); 562197ba5f4SPaul Zimmerman addr = hsotg->regs + HCCHAR(i); 563197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCCHAR @0x%08lX : 0x%08X\n", 56495c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 565197ba5f4SPaul Zimmerman addr = hsotg->regs + HCSPLT(i); 566197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCSPLT @0x%08lX : 0x%08X\n", 56795c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 568197ba5f4SPaul Zimmerman addr = hsotg->regs + HCINT(i); 569197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCINT @0x%08lX : 0x%08X\n", 57095c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 571197ba5f4SPaul Zimmerman addr = hsotg->regs + HCINTMSK(i); 572197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCINTMSK @0x%08lX : 0x%08X\n", 57395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 574197ba5f4SPaul Zimmerman addr = hsotg->regs + HCTSIZ(i); 575197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCTSIZ @0x%08lX : 0x%08X\n", 57695c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 577197ba5f4SPaul Zimmerman addr = hsotg->regs + HCDMA(i); 578197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n", 57995c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 58095832c00SJohn Youn if (hsotg->params.dma_desc_enable) { 581197ba5f4SPaul Zimmerman addr = hsotg->regs + HCDMAB(i); 582197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n", 58395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 584197ba5f4SPaul Zimmerman } 585197ba5f4SPaul Zimmerman } 586197ba5f4SPaul Zimmerman #endif 587197ba5f4SPaul Zimmerman } 588197ba5f4SPaul Zimmerman 589197ba5f4SPaul Zimmerman /** 590197ba5f4SPaul Zimmerman * dwc2_dump_global_registers() - Prints the core global registers 591197ba5f4SPaul Zimmerman * 592197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 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 void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg) 598197ba5f4SPaul Zimmerman { 599197ba5f4SPaul Zimmerman #ifdef DEBUG 600197ba5f4SPaul Zimmerman u32 __iomem *addr; 601197ba5f4SPaul Zimmerman 602197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "Core Global Registers\n"); 603197ba5f4SPaul Zimmerman addr = hsotg->regs + GOTGCTL; 604197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GOTGCTL @0x%08lX : 0x%08X\n", 60595c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 606197ba5f4SPaul Zimmerman addr = hsotg->regs + GOTGINT; 607197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GOTGINT @0x%08lX : 0x%08X\n", 60895c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 609197ba5f4SPaul Zimmerman addr = hsotg->regs + GAHBCFG; 610197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GAHBCFG @0x%08lX : 0x%08X\n", 61195c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 612197ba5f4SPaul Zimmerman addr = hsotg->regs + GUSBCFG; 613197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GUSBCFG @0x%08lX : 0x%08X\n", 61495c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 615197ba5f4SPaul Zimmerman addr = hsotg->regs + GRSTCTL; 616197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GRSTCTL @0x%08lX : 0x%08X\n", 61795c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 618197ba5f4SPaul Zimmerman addr = hsotg->regs + GINTSTS; 619197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GINTSTS @0x%08lX : 0x%08X\n", 62095c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 621197ba5f4SPaul Zimmerman addr = hsotg->regs + GINTMSK; 622197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GINTMSK @0x%08lX : 0x%08X\n", 62395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 624197ba5f4SPaul Zimmerman addr = hsotg->regs + GRXSTSR; 625197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GRXSTSR @0x%08lX : 0x%08X\n", 62695c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 627197ba5f4SPaul Zimmerman addr = hsotg->regs + GRXFSIZ; 628197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GRXFSIZ @0x%08lX : 0x%08X\n", 62995c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 630197ba5f4SPaul Zimmerman addr = hsotg->regs + GNPTXFSIZ; 631197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GNPTXFSIZ @0x%08lX : 0x%08X\n", 63295c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 633197ba5f4SPaul Zimmerman addr = hsotg->regs + GNPTXSTS; 634197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GNPTXSTS @0x%08lX : 0x%08X\n", 63595c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 636197ba5f4SPaul Zimmerman addr = hsotg->regs + GI2CCTL; 637197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GI2CCTL @0x%08lX : 0x%08X\n", 63895c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 639197ba5f4SPaul Zimmerman addr = hsotg->regs + GPVNDCTL; 640197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GPVNDCTL @0x%08lX : 0x%08X\n", 64195c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 642197ba5f4SPaul Zimmerman addr = hsotg->regs + GGPIO; 643197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GGPIO @0x%08lX : 0x%08X\n", 64495c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 645197ba5f4SPaul Zimmerman addr = hsotg->regs + GUID; 646197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GUID @0x%08lX : 0x%08X\n", 64795c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 648197ba5f4SPaul Zimmerman addr = hsotg->regs + GSNPSID; 649197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GSNPSID @0x%08lX : 0x%08X\n", 65095c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 651197ba5f4SPaul Zimmerman addr = hsotg->regs + GHWCFG1; 652197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GHWCFG1 @0x%08lX : 0x%08X\n", 65395c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 654197ba5f4SPaul Zimmerman addr = hsotg->regs + GHWCFG2; 655197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GHWCFG2 @0x%08lX : 0x%08X\n", 65695c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 657197ba5f4SPaul Zimmerman addr = hsotg->regs + GHWCFG3; 658197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GHWCFG3 @0x%08lX : 0x%08X\n", 65995c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 660197ba5f4SPaul Zimmerman addr = hsotg->regs + GHWCFG4; 661197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GHWCFG4 @0x%08lX : 0x%08X\n", 66295c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 663197ba5f4SPaul Zimmerman addr = hsotg->regs + GLPMCFG; 664197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GLPMCFG @0x%08lX : 0x%08X\n", 66595c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 666197ba5f4SPaul Zimmerman addr = hsotg->regs + GPWRDN; 667197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GPWRDN @0x%08lX : 0x%08X\n", 66895c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 669197ba5f4SPaul Zimmerman addr = hsotg->regs + GDFIFOCFG; 670197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "GDFIFOCFG @0x%08lX : 0x%08X\n", 67195c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 672197ba5f4SPaul Zimmerman addr = hsotg->regs + HPTXFSIZ; 673197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "HPTXFSIZ @0x%08lX : 0x%08X\n", 67495c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 675197ba5f4SPaul Zimmerman 676197ba5f4SPaul Zimmerman addr = hsotg->regs + PCGCTL; 677197ba5f4SPaul Zimmerman dev_dbg(hsotg->dev, "PCGCTL @0x%08lX : 0x%08X\n", 67895c8bc36SAntti Seppälä (unsigned long)addr, dwc2_readl(addr)); 679197ba5f4SPaul Zimmerman #endif 680197ba5f4SPaul Zimmerman } 681197ba5f4SPaul Zimmerman 682197ba5f4SPaul Zimmerman /** 683197ba5f4SPaul Zimmerman * dwc2_flush_tx_fifo() - Flushes a Tx FIFO 684197ba5f4SPaul Zimmerman * 685197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 686197ba5f4SPaul Zimmerman * @num: Tx FIFO to flush 687197ba5f4SPaul Zimmerman */ 688197ba5f4SPaul Zimmerman void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num) 689197ba5f4SPaul Zimmerman { 690197ba5f4SPaul Zimmerman u32 greset; 691197ba5f4SPaul Zimmerman 692197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "Flush Tx FIFO %d\n", num); 693197ba5f4SPaul Zimmerman 6948f55fd60SMinas Harutyunyan /* Wait for AHB master IDLE state */ 6958f55fd60SMinas Harutyunyan if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 10000)) 6968f55fd60SMinas Harutyunyan dev_warn(hsotg->dev, "%s: HANG! AHB Idle GRSCTL\n", 6978f55fd60SMinas Harutyunyan __func__); 6988f55fd60SMinas Harutyunyan 699197ba5f4SPaul Zimmerman greset = GRSTCTL_TXFFLSH; 700197ba5f4SPaul Zimmerman greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK; 70195c8bc36SAntti Seppälä dwc2_writel(greset, hsotg->regs + GRSTCTL); 702197ba5f4SPaul Zimmerman 70379d6b8c5SSevak Arakelyan if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_TXFFLSH, 10000)) 70479d6b8c5SSevak Arakelyan dev_warn(hsotg->dev, "%s: HANG! timeout GRSTCTL GRSTCTL_TXFFLSH\n", 70579d6b8c5SSevak Arakelyan __func__); 706197ba5f4SPaul Zimmerman 707197ba5f4SPaul Zimmerman /* Wait for at least 3 PHY Clocks */ 708197ba5f4SPaul Zimmerman udelay(1); 709197ba5f4SPaul Zimmerman } 710197ba5f4SPaul Zimmerman 711197ba5f4SPaul Zimmerman /** 712197ba5f4SPaul Zimmerman * dwc2_flush_rx_fifo() - Flushes the Rx FIFO 713197ba5f4SPaul Zimmerman * 714197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 715197ba5f4SPaul Zimmerman */ 716197ba5f4SPaul Zimmerman void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg) 717197ba5f4SPaul Zimmerman { 718197ba5f4SPaul Zimmerman u32 greset; 719197ba5f4SPaul Zimmerman 720197ba5f4SPaul Zimmerman dev_vdbg(hsotg->dev, "%s()\n", __func__); 721197ba5f4SPaul Zimmerman 7228f55fd60SMinas Harutyunyan /* Wait for AHB master IDLE state */ 7238f55fd60SMinas Harutyunyan if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 10000)) 7248f55fd60SMinas Harutyunyan dev_warn(hsotg->dev, "%s: HANG! AHB Idle GRSCTL\n", 7258f55fd60SMinas Harutyunyan __func__); 7268f55fd60SMinas Harutyunyan 727197ba5f4SPaul Zimmerman greset = GRSTCTL_RXFFLSH; 72895c8bc36SAntti Seppälä dwc2_writel(greset, hsotg->regs + GRSTCTL); 729197ba5f4SPaul Zimmerman 73079d6b8c5SSevak Arakelyan /* Wait for RxFIFO flush done */ 73179d6b8c5SSevak Arakelyan if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_RXFFLSH, 10000)) 73279d6b8c5SSevak Arakelyan dev_warn(hsotg->dev, "%s: HANG! timeout GRSTCTL GRSTCTL_RXFFLSH\n", 73379d6b8c5SSevak Arakelyan __func__); 734197ba5f4SPaul Zimmerman 735197ba5f4SPaul Zimmerman /* Wait for at least 3 PHY Clocks */ 736197ba5f4SPaul Zimmerman udelay(1); 737197ba5f4SPaul Zimmerman } 738197ba5f4SPaul Zimmerman 73909c96980SJohn Youn /* 74009c96980SJohn Youn * Forces either host or device mode if the controller is not 74109c96980SJohn Youn * currently in that mode. 74209c96980SJohn Youn * 74309c96980SJohn Youn * Returns true if the mode was forced. 74409c96980SJohn Youn */ 745323230efSJohn Youn bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host) 74609c96980SJohn Youn { 74709c96980SJohn Youn if (host && dwc2_is_host_mode(hsotg)) 74809c96980SJohn Youn return false; 74909c96980SJohn Youn else if (!host && dwc2_is_device_mode(hsotg)) 75009c96980SJohn Youn return false; 75109c96980SJohn Youn 75209c96980SJohn Youn return dwc2_force_mode(hsotg, host); 75309c96980SJohn Youn } 75409c96980SJohn Youn 755197ba5f4SPaul Zimmerman bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) 756197ba5f4SPaul Zimmerman { 75795c8bc36SAntti Seppälä if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff) 758197ba5f4SPaul Zimmerman return false; 759197ba5f4SPaul Zimmerman else 760197ba5f4SPaul Zimmerman return true; 761197ba5f4SPaul Zimmerman } 762197ba5f4SPaul Zimmerman 763197ba5f4SPaul Zimmerman /** 764197ba5f4SPaul Zimmerman * dwc2_enable_global_interrupts() - Enables the controller's Global 765197ba5f4SPaul Zimmerman * Interrupt in the AHB Config register 766197ba5f4SPaul Zimmerman * 767197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 768197ba5f4SPaul Zimmerman */ 769197ba5f4SPaul Zimmerman void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg) 770197ba5f4SPaul Zimmerman { 77195c8bc36SAntti Seppälä u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); 772197ba5f4SPaul Zimmerman 773197ba5f4SPaul Zimmerman ahbcfg |= GAHBCFG_GLBL_INTR_EN; 77495c8bc36SAntti Seppälä dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); 775197ba5f4SPaul Zimmerman } 776197ba5f4SPaul Zimmerman 777197ba5f4SPaul Zimmerman /** 778197ba5f4SPaul Zimmerman * dwc2_disable_global_interrupts() - Disables the controller's Global 779197ba5f4SPaul Zimmerman * Interrupt in the AHB Config register 780197ba5f4SPaul Zimmerman * 781197ba5f4SPaul Zimmerman * @hsotg: Programming view of DWC_otg controller 782197ba5f4SPaul Zimmerman */ 783197ba5f4SPaul Zimmerman void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg) 784197ba5f4SPaul Zimmerman { 78595c8bc36SAntti Seppälä u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG); 786197ba5f4SPaul Zimmerman 787197ba5f4SPaul Zimmerman ahbcfg &= ~GAHBCFG_GLBL_INTR_EN; 78895c8bc36SAntti Seppälä dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); 789197ba5f4SPaul Zimmerman } 790197ba5f4SPaul Zimmerman 7916bea9620SJohn Youn /* Returns the controller's GHWCFG2.OTG_MODE. */ 7929da51974SJohn Youn unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg) 7936bea9620SJohn Youn { 7946bea9620SJohn Youn u32 ghwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2); 7956bea9620SJohn Youn 7966bea9620SJohn Youn return (ghwcfg2 & GHWCFG2_OP_MODE_MASK) >> 7976bea9620SJohn Youn GHWCFG2_OP_MODE_SHIFT; 7986bea9620SJohn Youn } 7996bea9620SJohn Youn 8006bea9620SJohn Youn /* Returns true if the controller is capable of DRD. */ 8016bea9620SJohn Youn bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg) 8026bea9620SJohn Youn { 8039da51974SJohn Youn unsigned int op_mode = dwc2_op_mode(hsotg); 8046bea9620SJohn Youn 8056bea9620SJohn Youn return (op_mode == GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) || 8066bea9620SJohn Youn (op_mode == GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE) || 8076bea9620SJohn Youn (op_mode == GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE); 8086bea9620SJohn Youn } 8096bea9620SJohn Youn 8106bea9620SJohn Youn /* Returns true if the controller is host-only. */ 8116bea9620SJohn Youn bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg) 8126bea9620SJohn Youn { 8139da51974SJohn Youn unsigned int op_mode = dwc2_op_mode(hsotg); 8146bea9620SJohn Youn 8156bea9620SJohn Youn return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_HOST) || 8166bea9620SJohn Youn (op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST); 8176bea9620SJohn Youn } 8186bea9620SJohn Youn 8196bea9620SJohn Youn /* Returns true if the controller is device-only. */ 8206bea9620SJohn Youn bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg) 8216bea9620SJohn Youn { 8229da51974SJohn Youn unsigned int op_mode = dwc2_op_mode(hsotg); 8236bea9620SJohn Youn 8246bea9620SJohn Youn return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) || 8256bea9620SJohn Youn (op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE); 8266bea9620SJohn Youn } 8276bea9620SJohn Youn 82879d6b8c5SSevak Arakelyan /** 82979d6b8c5SSevak Arakelyan * dwc2_hsotg_wait_bit_set - Waits for bit to be set. 83079d6b8c5SSevak Arakelyan * @hsotg: Programming view of DWC_otg controller. 83179d6b8c5SSevak Arakelyan * @offset: Register's offset where bit/bits must be set. 83279d6b8c5SSevak Arakelyan * @mask: Mask of the bit/bits which must be set. 83379d6b8c5SSevak Arakelyan * @timeout: Timeout to wait. 83479d6b8c5SSevak Arakelyan * 83579d6b8c5SSevak Arakelyan * Return: 0 if bit/bits are set or -ETIMEDOUT in case of timeout. 83679d6b8c5SSevak Arakelyan */ 83779d6b8c5SSevak Arakelyan int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hsotg, u32 offset, u32 mask, 83879d6b8c5SSevak Arakelyan u32 timeout) 83979d6b8c5SSevak Arakelyan { 84079d6b8c5SSevak Arakelyan u32 i; 84179d6b8c5SSevak Arakelyan 84279d6b8c5SSevak Arakelyan for (i = 0; i < timeout; i++) { 84379d6b8c5SSevak Arakelyan if (dwc2_readl(hsotg->regs + offset) & mask) 84479d6b8c5SSevak Arakelyan return 0; 84579d6b8c5SSevak Arakelyan udelay(1); 84679d6b8c5SSevak Arakelyan } 84779d6b8c5SSevak Arakelyan 84879d6b8c5SSevak Arakelyan return -ETIMEDOUT; 84979d6b8c5SSevak Arakelyan } 85079d6b8c5SSevak Arakelyan 85179d6b8c5SSevak Arakelyan /** 85279d6b8c5SSevak Arakelyan * dwc2_hsotg_wait_bit_clear - Waits for bit to be clear. 85379d6b8c5SSevak Arakelyan * @hsotg: Programming view of DWC_otg controller. 85479d6b8c5SSevak Arakelyan * @offset: Register's offset where bit/bits must be set. 85579d6b8c5SSevak Arakelyan * @mask: Mask of the bit/bits which must be set. 85679d6b8c5SSevak Arakelyan * @timeout: Timeout to wait. 85779d6b8c5SSevak Arakelyan * 85879d6b8c5SSevak Arakelyan * Return: 0 if bit/bits are set or -ETIMEDOUT in case of timeout. 85979d6b8c5SSevak Arakelyan */ 86079d6b8c5SSevak Arakelyan int dwc2_hsotg_wait_bit_clear(struct dwc2_hsotg *hsotg, u32 offset, u32 mask, 86179d6b8c5SSevak Arakelyan u32 timeout) 86279d6b8c5SSevak Arakelyan { 86379d6b8c5SSevak Arakelyan u32 i; 86479d6b8c5SSevak Arakelyan 86579d6b8c5SSevak Arakelyan for (i = 0; i < timeout; i++) { 86679d6b8c5SSevak Arakelyan if (!(dwc2_readl(hsotg->regs + offset) & mask)) 86779d6b8c5SSevak Arakelyan return 0; 86879d6b8c5SSevak Arakelyan udelay(1); 86979d6b8c5SSevak Arakelyan } 87079d6b8c5SSevak Arakelyan 87179d6b8c5SSevak Arakelyan return -ETIMEDOUT; 87279d6b8c5SSevak Arakelyan } 87379d6b8c5SSevak Arakelyan 874197ba5f4SPaul Zimmerman MODULE_DESCRIPTION("DESIGNWARE HS OTG Core"); 875197ba5f4SPaul Zimmerman MODULE_AUTHOR("Synopsys, Inc."); 876197ba5f4SPaul Zimmerman MODULE_LICENSE("Dual BSD/GPL"); 877