172246da4SFelipe Balbi /** 272246da4SFelipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 372246da4SFelipe Balbi * 472246da4SFelipe Balbi * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com 572246da4SFelipe Balbi * 672246da4SFelipe Balbi * Authors: Felipe Balbi <balbi@ti.com>, 772246da4SFelipe Balbi * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 872246da4SFelipe Balbi * 972246da4SFelipe Balbi * Redistribution and use in source and binary forms, with or without 1072246da4SFelipe Balbi * modification, are permitted provided that the following conditions 1172246da4SFelipe Balbi * are met: 1272246da4SFelipe Balbi * 1. Redistributions of source code must retain the above copyright 1372246da4SFelipe Balbi * notice, this list of conditions, and the following disclaimer, 1472246da4SFelipe Balbi * without modification. 1572246da4SFelipe Balbi * 2. Redistributions in binary form must reproduce the above copyright 1672246da4SFelipe Balbi * notice, this list of conditions and the following disclaimer in the 1772246da4SFelipe Balbi * documentation and/or other materials provided with the distribution. 1872246da4SFelipe Balbi * 3. The names of the above-listed copyright holders may not be used 1972246da4SFelipe Balbi * to endorse or promote products derived from this software without 2072246da4SFelipe Balbi * specific prior written permission. 2172246da4SFelipe Balbi * 2272246da4SFelipe Balbi * ALTERNATIVELY, this software may be distributed under the terms of the 2372246da4SFelipe Balbi * GNU General Public License ("GPL") version 2, as published by the Free 2472246da4SFelipe Balbi * Software Foundation. 2572246da4SFelipe Balbi * 2672246da4SFelipe Balbi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 2772246da4SFelipe Balbi * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2872246da4SFelipe Balbi * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2972246da4SFelipe Balbi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 3072246da4SFelipe Balbi * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 3172246da4SFelipe Balbi * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 3272246da4SFelipe Balbi * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3372246da4SFelipe Balbi * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3472246da4SFelipe Balbi * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3572246da4SFelipe Balbi * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3672246da4SFelipe Balbi * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3772246da4SFelipe Balbi */ 3872246da4SFelipe Balbi 39a72e658bSFelipe Balbi #include <linux/module.h> 4072246da4SFelipe Balbi #include <linux/kernel.h> 4172246da4SFelipe Balbi #include <linux/slab.h> 4272246da4SFelipe Balbi #include <linux/spinlock.h> 4372246da4SFelipe Balbi #include <linux/platform_device.h> 4472246da4SFelipe Balbi #include <linux/pm_runtime.h> 4572246da4SFelipe Balbi #include <linux/interrupt.h> 4672246da4SFelipe Balbi #include <linux/ioport.h> 4772246da4SFelipe Balbi #include <linux/io.h> 4872246da4SFelipe Balbi #include <linux/list.h> 4972246da4SFelipe Balbi #include <linux/delay.h> 5072246da4SFelipe Balbi #include <linux/dma-mapping.h> 51457e84b6SFelipe Balbi #include <linux/of.h> 5272246da4SFelipe Balbi 5351e1e7bcSFelipe Balbi #include <linux/usb/otg.h> 5472246da4SFelipe Balbi #include <linux/usb/ch9.h> 5572246da4SFelipe Balbi #include <linux/usb/gadget.h> 5672246da4SFelipe Balbi 5772246da4SFelipe Balbi #include "core.h" 5872246da4SFelipe Balbi #include "gadget.h" 5972246da4SFelipe Balbi #include "io.h" 6072246da4SFelipe Balbi 6172246da4SFelipe Balbi #include "debug.h" 6272246da4SFelipe Balbi 636c167fc9SFelipe Balbi static char *maximum_speed = "super"; 646c167fc9SFelipe Balbi module_param(maximum_speed, charp, 0); 656c167fc9SFelipe Balbi MODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); 666c167fc9SFelipe Balbi 678300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 688300dd23SFelipe Balbi 693140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 703140e8cbSSebastian Andrzej Siewior { 713140e8cbSSebastian Andrzej Siewior u32 reg; 723140e8cbSSebastian Andrzej Siewior 733140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 743140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 753140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 763140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 773140e8cbSSebastian Andrzej Siewior } 788300dd23SFelipe Balbi 7972246da4SFelipe Balbi /** 8072246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 8172246da4SFelipe Balbi * @dwc: pointer to our context structure 8272246da4SFelipe Balbi */ 8372246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc) 8472246da4SFelipe Balbi { 8572246da4SFelipe Balbi u32 reg; 8672246da4SFelipe Balbi 8772246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 8872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 8972246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 9072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 9172246da4SFelipe Balbi 9272246da4SFelipe Balbi /* Assert USB3 PHY reset */ 9372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 9472246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 9572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 9672246da4SFelipe Balbi 9772246da4SFelipe Balbi /* Assert USB2 PHY reset */ 9872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 9972246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 10072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10172246da4SFelipe Balbi 10251e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 10351e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 10472246da4SFelipe Balbi mdelay(100); 10572246da4SFelipe Balbi 10672246da4SFelipe Balbi /* Clear USB3 PHY reset */ 10772246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 10872246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 10972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 11072246da4SFelipe Balbi 11172246da4SFelipe Balbi /* Clear USB2 PHY reset */ 11272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 11372246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 11472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 11572246da4SFelipe Balbi 11645627ac6SPratyush Anand mdelay(100); 11745627ac6SPratyush Anand 11872246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 11972246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 12072246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 12172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 12272246da4SFelipe Balbi } 12372246da4SFelipe Balbi 12472246da4SFelipe Balbi /** 12572246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 12672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 12772246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 12872246da4SFelipe Balbi */ 12972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 13072246da4SFelipe Balbi struct dwc3_event_buffer *evt) 13172246da4SFelipe Balbi { 13272246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 13372246da4SFelipe Balbi } 13472246da4SFelipe Balbi 13572246da4SFelipe Balbi /** 1361d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 13772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 13872246da4SFelipe Balbi * @length: size of the event buffer 13972246da4SFelipe Balbi * 1401d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 14172246da4SFelipe Balbi * otherwise ERR_PTR(errno). 14272246da4SFelipe Balbi */ 14367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 14467d0b500SFelipe Balbi unsigned length) 14572246da4SFelipe Balbi { 14672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 14772246da4SFelipe Balbi 148380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 14972246da4SFelipe Balbi if (!evt) 15072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 15172246da4SFelipe Balbi 15272246da4SFelipe Balbi evt->dwc = dwc; 15372246da4SFelipe Balbi evt->length = length; 15472246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 15572246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 156e32672f0SFelipe Balbi if (!evt->buf) 15772246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 15872246da4SFelipe Balbi 15972246da4SFelipe Balbi return evt; 16072246da4SFelipe Balbi } 16172246da4SFelipe Balbi 16272246da4SFelipe Balbi /** 16372246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 16472246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 16572246da4SFelipe Balbi */ 16672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 16772246da4SFelipe Balbi { 16872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 16972246da4SFelipe Balbi int i; 17072246da4SFelipe Balbi 1719f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 17272246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 17364b6c8a7SAnton Tikhomirov if (evt) 17472246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 17572246da4SFelipe Balbi } 17672246da4SFelipe Balbi } 17772246da4SFelipe Balbi 17872246da4SFelipe Balbi /** 17972246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 1801d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 18172246da4SFelipe Balbi * @length: size of event buffer 18272246da4SFelipe Balbi * 1831d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 18472246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 18572246da4SFelipe Balbi */ 18641ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 18772246da4SFelipe Balbi { 1889f622b2aSFelipe Balbi int num; 18972246da4SFelipe Balbi int i; 19072246da4SFelipe Balbi 1919f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 1929f622b2aSFelipe Balbi dwc->num_event_buffers = num; 1939f622b2aSFelipe Balbi 194380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 195380f0d28SFelipe Balbi GFP_KERNEL); 196457d3f21SFelipe Balbi if (!dwc->ev_buffs) { 197457d3f21SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffers array\n"); 198457d3f21SFelipe Balbi return -ENOMEM; 199457d3f21SFelipe Balbi } 200457d3f21SFelipe Balbi 20172246da4SFelipe Balbi for (i = 0; i < num; i++) { 20272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 20372246da4SFelipe Balbi 20472246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 20572246da4SFelipe Balbi if (IS_ERR(evt)) { 20672246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 20772246da4SFelipe Balbi return PTR_ERR(evt); 20872246da4SFelipe Balbi } 20972246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 21072246da4SFelipe Balbi } 21172246da4SFelipe Balbi 21272246da4SFelipe Balbi return 0; 21372246da4SFelipe Balbi } 21472246da4SFelipe Balbi 21572246da4SFelipe Balbi /** 21672246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2171d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 21872246da4SFelipe Balbi * 21972246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 22072246da4SFelipe Balbi */ 2217acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 22272246da4SFelipe Balbi { 22372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 22472246da4SFelipe Balbi int n; 22572246da4SFelipe Balbi 2269f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 22772246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 22872246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 22972246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 23072246da4SFelipe Balbi evt->length); 23172246da4SFelipe Balbi 2327acd85e0SPaul Zimmerman evt->lpos = 0; 2337acd85e0SPaul Zimmerman 23472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 23572246da4SFelipe Balbi lower_32_bits(evt->dma)); 23672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 23772246da4SFelipe Balbi upper_32_bits(evt->dma)); 23872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 23972246da4SFelipe Balbi evt->length & 0xffff); 24072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 24172246da4SFelipe Balbi } 24272246da4SFelipe Balbi 24372246da4SFelipe Balbi return 0; 24472246da4SFelipe Balbi } 24572246da4SFelipe Balbi 24672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 24772246da4SFelipe Balbi { 24872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24972246da4SFelipe Balbi int n; 25072246da4SFelipe Balbi 2519f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 25272246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2537acd85e0SPaul Zimmerman 2547acd85e0SPaul Zimmerman evt->lpos = 0; 2557acd85e0SPaul Zimmerman 25672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 25772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 25872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 25972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 26072246da4SFelipe Balbi } 26172246da4SFelipe Balbi } 26272246da4SFelipe Balbi 263789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 264789451f6SFelipe Balbi { 265789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 266789451f6SFelipe Balbi 267789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 268789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 269789451f6SFelipe Balbi 270789451f6SFelipe Balbi dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", 271789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 272789451f6SFelipe Balbi } 273789451f6SFelipe Balbi 27441ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 27526ceca97SFelipe Balbi { 27626ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 27726ceca97SFelipe Balbi 27826ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 27926ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 28026ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 28126ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 28226ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 28326ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 28426ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 28526ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 28626ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 28726ceca97SFelipe Balbi } 28826ceca97SFelipe Balbi 28972246da4SFelipe Balbi /** 29072246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 29172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 29272246da4SFelipe Balbi * 29372246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 29472246da4SFelipe Balbi */ 29541ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 29672246da4SFelipe Balbi { 29772246da4SFelipe Balbi unsigned long timeout; 29872246da4SFelipe Balbi u32 reg; 29972246da4SFelipe Balbi int ret; 30072246da4SFelipe Balbi 3017650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3027650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3037650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3047650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3057650bd74SSebastian Andrzej Siewior ret = -ENODEV; 3067650bd74SSebastian Andrzej Siewior goto err0; 3077650bd74SSebastian Andrzej Siewior } 308248b122bSFelipe Balbi dwc->revision = reg; 3097650bd74SSebastian Andrzej Siewior 31072246da4SFelipe Balbi /* issue device SoftReset too */ 31172246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 31272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 31372246da4SFelipe Balbi do { 31472246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 31572246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 31672246da4SFelipe Balbi break; 31772246da4SFelipe Balbi 31872246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 31972246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 32072246da4SFelipe Balbi ret = -ETIMEDOUT; 32172246da4SFelipe Balbi goto err0; 32272246da4SFelipe Balbi } 32372246da4SFelipe Balbi 32472246da4SFelipe Balbi cpu_relax(); 32572246da4SFelipe Balbi } while (true); 32672246da4SFelipe Balbi 32758a0f23fSPratyush Anand dwc3_core_soft_reset(dwc); 32858a0f23fSPratyush Anand 3294878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 3303e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 3314878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 3324878a028SSebastian Andrzej Siewior 333164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 3344878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 3354878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 3364878a028SSebastian Andrzej Siewior break; 3374878a028SSebastian Andrzej Siewior default: 3384878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 3394878a028SSebastian Andrzej Siewior } 3404878a028SSebastian Andrzej Siewior 3414878a028SSebastian Andrzej Siewior /* 3424878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 3431d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 3444878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 3451d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 3464878a028SSebastian Andrzej Siewior */ 3474878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 3484878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 3494878a028SSebastian Andrzej Siewior 350789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 351789451f6SFelipe Balbi 3524878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 3534878a028SSebastian Andrzej Siewior 35472246da4SFelipe Balbi return 0; 35572246da4SFelipe Balbi 35672246da4SFelipe Balbi err0: 35772246da4SFelipe Balbi return ret; 35872246da4SFelipe Balbi } 35972246da4SFelipe Balbi 36072246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 36172246da4SFelipe Balbi { 36201b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 36301b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 36472246da4SFelipe Balbi } 36572246da4SFelipe Balbi 36672246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 36772246da4SFelipe Balbi 36841ac7b3aSBill Pemberton static int dwc3_probe(struct platform_device *pdev) 36972246da4SFelipe Balbi { 370457e84b6SFelipe Balbi struct device_node *node = pdev->dev.of_node; 37172246da4SFelipe Balbi struct resource *res; 37272246da4SFelipe Balbi struct dwc3 *dwc; 373802ca850SChanho Park struct device *dev = &pdev->dev; 3740949e99bSFelipe Balbi 37572246da4SFelipe Balbi int ret = -ENOMEM; 3760949e99bSFelipe Balbi 3770949e99bSFelipe Balbi void __iomem *regs; 37872246da4SFelipe Balbi void *mem; 37972246da4SFelipe Balbi 3800949e99bSFelipe Balbi u8 mode; 3810949e99bSFelipe Balbi 382802ca850SChanho Park mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 38372246da4SFelipe Balbi if (!mem) { 384802ca850SChanho Park dev_err(dev, "not enough memory\n"); 385802ca850SChanho Park return -ENOMEM; 38672246da4SFelipe Balbi } 38772246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 38872246da4SFelipe Balbi dwc->mem = mem; 38972246da4SFelipe Balbi 39051249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 39172246da4SFelipe Balbi if (!res) { 39251249dcaSIdo Shayevitz dev_err(dev, "missing IRQ\n"); 393802ca850SChanho Park return -ENODEV; 39472246da4SFelipe Balbi } 395066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].start = res->start; 396066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].end = res->end; 397066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].flags = res->flags; 398066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].name = res->name; 39972246da4SFelipe Balbi 40051249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 40151249dcaSIdo Shayevitz if (!res) { 40251249dcaSIdo Shayevitz dev_err(dev, "missing memory resource\n"); 40351249dcaSIdo Shayevitz return -ENODEV; 40451249dcaSIdo Shayevitz } 405066618bcSKishon Vijay Abraham I dwc->xhci_resources[0].start = res->start; 40651249dcaSIdo Shayevitz dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 40751249dcaSIdo Shayevitz DWC3_XHCI_REGS_END; 408066618bcSKishon Vijay Abraham I dwc->xhci_resources[0].flags = res->flags; 409066618bcSKishon Vijay Abraham I dwc->xhci_resources[0].name = res->name; 410d07e8819SFelipe Balbi 41151249dcaSIdo Shayevitz /* 41251249dcaSIdo Shayevitz * Request memory region but exclude xHCI regs, 41351249dcaSIdo Shayevitz * since it will be requested by the xhci-plat driver. 41451249dcaSIdo Shayevitz */ 41551249dcaSIdo Shayevitz res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START, 41651249dcaSIdo Shayevitz resource_size(res) - DWC3_GLOBALS_REGS_START, 417802ca850SChanho Park dev_name(dev)); 41872246da4SFelipe Balbi if (!res) { 419802ca850SChanho Park dev_err(dev, "can't request mem region\n"); 420802ca850SChanho Park return -ENOMEM; 42172246da4SFelipe Balbi } 42272246da4SFelipe Balbi 423b7e38aa6SFelipe Balbi regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); 42472246da4SFelipe Balbi if (!regs) { 425802ca850SChanho Park dev_err(dev, "ioremap failed\n"); 426802ca850SChanho Park return -ENOMEM; 42772246da4SFelipe Balbi } 42872246da4SFelipe Balbi 4295088b6f5SKishon Vijay Abraham I if (node) { 4305088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 4315088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 4325088b6f5SKishon Vijay Abraham I } else { 43351e1e7bcSFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 4345088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 4355088b6f5SKishon Vijay Abraham I } 4365088b6f5SKishon Vijay Abraham I 43751e1e7bcSFelipe Balbi if (IS_ERR_OR_NULL(dwc->usb2_phy)) { 43851e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 43951e1e7bcSFelipe Balbi return -EPROBE_DEFER; 44051e1e7bcSFelipe Balbi } 44151e1e7bcSFelipe Balbi 44251e1e7bcSFelipe Balbi if (IS_ERR_OR_NULL(dwc->usb3_phy)) { 44351e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 44451e1e7bcSFelipe Balbi return -EPROBE_DEFER; 44551e1e7bcSFelipe Balbi } 44651e1e7bcSFelipe Balbi 4478ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 4488ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 4498ba007a9SKishon Vijay Abraham I 45072246da4SFelipe Balbi spin_lock_init(&dwc->lock); 45172246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 45272246da4SFelipe Balbi 45372246da4SFelipe Balbi dwc->regs = regs; 45472246da4SFelipe Balbi dwc->regs_size = resource_size(res); 455802ca850SChanho Park dwc->dev = dev; 45672246da4SFelipe Balbi 457ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 458ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 459ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 460ddff14f1SKishon Vijay Abraham I 4616c167fc9SFelipe Balbi if (!strncmp("super", maximum_speed, 5)) 4626c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4636c167fc9SFelipe Balbi else if (!strncmp("high", maximum_speed, 4)) 4646c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; 4656c167fc9SFelipe Balbi else if (!strncmp("full", maximum_speed, 4)) 4666c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; 4676c167fc9SFelipe Balbi else if (!strncmp("low", maximum_speed, 3)) 4686c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_LOWSPEED; 4696c167fc9SFelipe Balbi else 4706c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4716c167fc9SFelipe Balbi 4725088b6f5SKishon Vijay Abraham I dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); 473457e84b6SFelipe Balbi 474802ca850SChanho Park pm_runtime_enable(dev); 475802ca850SChanho Park pm_runtime_get_sync(dev); 476802ca850SChanho Park pm_runtime_forbid(dev); 47772246da4SFelipe Balbi 4784fd24483SKishon Vijay Abraham I dwc3_cache_hwparams(dwc); 4794fd24483SKishon Vijay Abraham I 4803921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 4813921426bSFelipe Balbi if (ret) { 4823921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 4833921426bSFelipe Balbi ret = -ENOMEM; 4843921426bSFelipe Balbi goto err0; 4853921426bSFelipe Balbi } 4863921426bSFelipe Balbi 48772246da4SFelipe Balbi ret = dwc3_core_init(dwc); 48872246da4SFelipe Balbi if (ret) { 489802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 4903921426bSFelipe Balbi goto err0; 49172246da4SFelipe Balbi } 49272246da4SFelipe Balbi 493f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 494f122d33eSFelipe Balbi if (ret) { 495f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 496f122d33eSFelipe Balbi goto err1; 497f122d33eSFelipe Balbi } 498f122d33eSFelipe Balbi 499cd051da2SVivek Gautam if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 500cd051da2SVivek Gautam mode = DWC3_MODE_HOST; 501cd051da2SVivek Gautam else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 502cd051da2SVivek Gautam mode = DWC3_MODE_DEVICE; 503cd051da2SVivek Gautam else 504cd051da2SVivek Gautam mode = DWC3_MODE_DRD; 5050949e99bSFelipe Balbi 5060949e99bSFelipe Balbi switch (mode) { 5070949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 5083140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 50972246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 51072246da4SFelipe Balbi if (ret) { 511802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 512f122d33eSFelipe Balbi goto err2; 51372246da4SFelipe Balbi } 5140949e99bSFelipe Balbi break; 515d07e8819SFelipe Balbi case DWC3_MODE_HOST: 5163140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 517d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 518d07e8819SFelipe Balbi if (ret) { 519802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 520f122d33eSFelipe Balbi goto err2; 52172246da4SFelipe Balbi } 522d07e8819SFelipe Balbi break; 523d07e8819SFelipe Balbi case DWC3_MODE_DRD: 5243140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 525d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 526d07e8819SFelipe Balbi if (ret) { 527802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 528f122d33eSFelipe Balbi goto err2; 529d07e8819SFelipe Balbi } 530d07e8819SFelipe Balbi 531d07e8819SFelipe Balbi ret = dwc3_gadget_init(dwc); 532d07e8819SFelipe Balbi if (ret) { 533802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 534f122d33eSFelipe Balbi goto err2; 535d07e8819SFelipe Balbi } 536d07e8819SFelipe Balbi break; 5370949e99bSFelipe Balbi default: 538802ca850SChanho Park dev_err(dev, "Unsupported mode of operation %d\n", mode); 539f122d33eSFelipe Balbi goto err2; 54072246da4SFelipe Balbi } 5410949e99bSFelipe Balbi dwc->mode = mode; 54272246da4SFelipe Balbi 54372246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 54472246da4SFelipe Balbi if (ret) { 545802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 546f122d33eSFelipe Balbi goto err3; 54772246da4SFelipe Balbi } 54872246da4SFelipe Balbi 549802ca850SChanho Park pm_runtime_allow(dev); 55072246da4SFelipe Balbi 55172246da4SFelipe Balbi return 0; 55272246da4SFelipe Balbi 553f122d33eSFelipe Balbi err3: 5540949e99bSFelipe Balbi switch (mode) { 5550949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 55672246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5570949e99bSFelipe Balbi break; 558d07e8819SFelipe Balbi case DWC3_MODE_HOST: 559d07e8819SFelipe Balbi dwc3_host_exit(dwc); 560d07e8819SFelipe Balbi break; 561d07e8819SFelipe Balbi case DWC3_MODE_DRD: 562d07e8819SFelipe Balbi dwc3_host_exit(dwc); 563d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 564d07e8819SFelipe Balbi break; 5650949e99bSFelipe Balbi default: 5660949e99bSFelipe Balbi /* do nothing */ 5670949e99bSFelipe Balbi break; 5680949e99bSFelipe Balbi } 56972246da4SFelipe Balbi 570f122d33eSFelipe Balbi err2: 571f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 572f122d33eSFelipe Balbi 573802ca850SChanho Park err1: 57472246da4SFelipe Balbi dwc3_core_exit(dwc); 57572246da4SFelipe Balbi 5763921426bSFelipe Balbi err0: 5773921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 5783921426bSFelipe Balbi 57972246da4SFelipe Balbi return ret; 58072246da4SFelipe Balbi } 58172246da4SFelipe Balbi 582fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 58372246da4SFelipe Balbi { 58472246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 58572246da4SFelipe Balbi 5868ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 5878ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 5888ba007a9SKishon Vijay Abraham I 58972246da4SFelipe Balbi pm_runtime_put(&pdev->dev); 59072246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 59172246da4SFelipe Balbi 59272246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 59372246da4SFelipe Balbi 5940949e99bSFelipe Balbi switch (dwc->mode) { 5950949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 59672246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5970949e99bSFelipe Balbi break; 598d07e8819SFelipe Balbi case DWC3_MODE_HOST: 599d07e8819SFelipe Balbi dwc3_host_exit(dwc); 600d07e8819SFelipe Balbi break; 601d07e8819SFelipe Balbi case DWC3_MODE_DRD: 602d07e8819SFelipe Balbi dwc3_host_exit(dwc); 603d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 604d07e8819SFelipe Balbi break; 6050949e99bSFelipe Balbi default: 6060949e99bSFelipe Balbi /* do nothing */ 6070949e99bSFelipe Balbi break; 6080949e99bSFelipe Balbi } 60972246da4SFelipe Balbi 610f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 611d9b4330aSFelipe Balbi dwc3_free_event_buffers(dwc); 61272246da4SFelipe Balbi dwc3_core_exit(dwc); 61372246da4SFelipe Balbi 61472246da4SFelipe Balbi return 0; 61572246da4SFelipe Balbi } 61672246da4SFelipe Balbi 6177415f17cSFelipe Balbi #ifdef CONFIG_PM 6187415f17cSFelipe Balbi static int dwc3_prepare(struct device *dev) 6197415f17cSFelipe Balbi { 6207415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6217415f17cSFelipe Balbi unsigned long flags; 6227415f17cSFelipe Balbi 6237415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6247415f17cSFelipe Balbi 6257415f17cSFelipe Balbi switch (dwc->mode) { 6267415f17cSFelipe Balbi case DWC3_MODE_DEVICE: 6277415f17cSFelipe Balbi case DWC3_MODE_DRD: 6287415f17cSFelipe Balbi dwc3_gadget_prepare(dwc); 6297415f17cSFelipe Balbi /* FALLTHROUGH */ 6307415f17cSFelipe Balbi case DWC3_MODE_HOST: 6317415f17cSFelipe Balbi default: 6327415f17cSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 6337415f17cSFelipe Balbi break; 6347415f17cSFelipe Balbi } 6357415f17cSFelipe Balbi 6367415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6377415f17cSFelipe Balbi 6387415f17cSFelipe Balbi return 0; 6397415f17cSFelipe Balbi } 6407415f17cSFelipe Balbi 6417415f17cSFelipe Balbi static void dwc3_complete(struct device *dev) 6427415f17cSFelipe Balbi { 6437415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6447415f17cSFelipe Balbi unsigned long flags; 6457415f17cSFelipe Balbi 6467415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6477415f17cSFelipe Balbi 6487415f17cSFelipe Balbi switch (dwc->mode) { 6497415f17cSFelipe Balbi case DWC3_MODE_DEVICE: 6507415f17cSFelipe Balbi case DWC3_MODE_DRD: 6517415f17cSFelipe Balbi dwc3_gadget_complete(dwc); 6527415f17cSFelipe Balbi /* FALLTHROUGH */ 6537415f17cSFelipe Balbi case DWC3_MODE_HOST: 6547415f17cSFelipe Balbi default: 6557415f17cSFelipe Balbi dwc3_event_buffers_setup(dwc); 6567415f17cSFelipe Balbi break; 6577415f17cSFelipe Balbi } 6587415f17cSFelipe Balbi 6597415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6607415f17cSFelipe Balbi } 6617415f17cSFelipe Balbi 6627415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 6637415f17cSFelipe Balbi { 6647415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6657415f17cSFelipe Balbi unsigned long flags; 6667415f17cSFelipe Balbi 6677415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6687415f17cSFelipe Balbi 6697415f17cSFelipe Balbi switch (dwc->mode) { 6707415f17cSFelipe Balbi case DWC3_MODE_DEVICE: 6717415f17cSFelipe Balbi case DWC3_MODE_DRD: 6727415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 6737415f17cSFelipe Balbi /* FALLTHROUGH */ 6747415f17cSFelipe Balbi case DWC3_MODE_HOST: 6757415f17cSFelipe Balbi default: 6767415f17cSFelipe Balbi /* do nothing */ 6777415f17cSFelipe Balbi break; 6787415f17cSFelipe Balbi } 6797415f17cSFelipe Balbi 6807415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 6817415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6827415f17cSFelipe Balbi 6837415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 6847415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6857415f17cSFelipe Balbi 6867415f17cSFelipe Balbi return 0; 6877415f17cSFelipe Balbi } 6887415f17cSFelipe Balbi 6897415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 6907415f17cSFelipe Balbi { 6917415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6927415f17cSFelipe Balbi unsigned long flags; 6937415f17cSFelipe Balbi 6947415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 6957415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 6967415f17cSFelipe Balbi msleep(100); 6977415f17cSFelipe Balbi 6987415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6997415f17cSFelipe Balbi 7007415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 7017415f17cSFelipe Balbi 7027415f17cSFelipe Balbi switch (dwc->mode) { 7037415f17cSFelipe Balbi case DWC3_MODE_DEVICE: 7047415f17cSFelipe Balbi case DWC3_MODE_DRD: 7057415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 7067415f17cSFelipe Balbi /* FALLTHROUGH */ 7077415f17cSFelipe Balbi case DWC3_MODE_HOST: 7087415f17cSFelipe Balbi default: 7097415f17cSFelipe Balbi /* do nothing */ 7107415f17cSFelipe Balbi break; 7117415f17cSFelipe Balbi } 7127415f17cSFelipe Balbi 7137415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 7147415f17cSFelipe Balbi 7157415f17cSFelipe Balbi pm_runtime_disable(dev); 7167415f17cSFelipe Balbi pm_runtime_set_active(dev); 7177415f17cSFelipe Balbi pm_runtime_enable(dev); 7187415f17cSFelipe Balbi 7197415f17cSFelipe Balbi return 0; 7207415f17cSFelipe Balbi } 7217415f17cSFelipe Balbi 7227415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 7237415f17cSFelipe Balbi .prepare = dwc3_prepare, 7247415f17cSFelipe Balbi .complete = dwc3_complete, 7257415f17cSFelipe Balbi 7267415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 7277415f17cSFelipe Balbi }; 7287415f17cSFelipe Balbi 7297415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 7307415f17cSFelipe Balbi #else 7317415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 7327415f17cSFelipe Balbi #endif 7337415f17cSFelipe Balbi 7345088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 7355088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 7365088b6f5SKishon Vijay Abraham I { 7375088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 7385088b6f5SKishon Vijay Abraham I }, 7395088b6f5SKishon Vijay Abraham I { }, 7405088b6f5SKishon Vijay Abraham I }; 7415088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 7425088b6f5SKishon Vijay Abraham I #endif 7435088b6f5SKishon Vijay Abraham I 74472246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 74572246da4SFelipe Balbi .probe = dwc3_probe, 7467690417dSBill Pemberton .remove = dwc3_remove, 74772246da4SFelipe Balbi .driver = { 74872246da4SFelipe Balbi .name = "dwc3", 7495088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 7507415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 75172246da4SFelipe Balbi }, 75272246da4SFelipe Balbi }; 75372246da4SFelipe Balbi 754b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 755b1116dccSTobias Klauser 7567ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 75772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 75872246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL"); 75972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 760