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> 5172246da4SFelipe Balbi 5272246da4SFelipe Balbi #include <linux/usb/ch9.h> 5372246da4SFelipe Balbi #include <linux/usb/gadget.h> 542204fdeeSPaul Gortmaker #include <linux/module.h> 5572246da4SFelipe Balbi 5672246da4SFelipe Balbi #include "core.h" 5772246da4SFelipe Balbi #include "gadget.h" 5872246da4SFelipe Balbi #include "io.h" 5972246da4SFelipe Balbi 6072246da4SFelipe Balbi #include "debug.h" 6172246da4SFelipe Balbi 626c167fc9SFelipe Balbi static char *maximum_speed = "super"; 636c167fc9SFelipe Balbi module_param(maximum_speed, charp, 0); 646c167fc9SFelipe Balbi MODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); 656c167fc9SFelipe Balbi 6672246da4SFelipe Balbi /** 6772246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6872246da4SFelipe Balbi * @dwc: pointer to our context structure 6972246da4SFelipe Balbi */ 7072246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc) 7172246da4SFelipe Balbi { 7272246da4SFelipe Balbi u32 reg; 7372246da4SFelipe Balbi 7472246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7672246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7872246da4SFelipe Balbi 7972246da4SFelipe Balbi /* Assert USB3 PHY reset */ 8072246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 8172246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 8272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 8372246da4SFelipe Balbi 8472246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8672246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8872246da4SFelipe Balbi 8972246da4SFelipe Balbi mdelay(100); 9072246da4SFelipe Balbi 9172246da4SFelipe Balbi /* Clear USB3 PHY reset */ 9272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 9372246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 9472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 9572246da4SFelipe Balbi 9672246da4SFelipe Balbi /* Clear USB2 PHY reset */ 9772246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 9872246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 9972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10072246da4SFelipe Balbi 10172246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 10272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 10372246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 10472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 10572246da4SFelipe Balbi } 10672246da4SFelipe Balbi 10772246da4SFelipe Balbi /** 10872246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 10972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 11072246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 11172246da4SFelipe Balbi */ 11272246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 11372246da4SFelipe Balbi struct dwc3_event_buffer *evt) 11472246da4SFelipe Balbi { 11572246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 11672246da4SFelipe Balbi kfree(evt); 11772246da4SFelipe Balbi } 11872246da4SFelipe Balbi 11972246da4SFelipe Balbi /** 12072246da4SFelipe Balbi * dwc3_alloc_one_event_buffer - Allocated one event buffer structure 12172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 12272246da4SFelipe Balbi * @length: size of the event buffer 12372246da4SFelipe Balbi * 12472246da4SFelipe Balbi * Returns a pointer to the allocated event buffer structure on succes 12572246da4SFelipe Balbi * otherwise ERR_PTR(errno). 12672246da4SFelipe Balbi */ 12772246da4SFelipe Balbi static struct dwc3_event_buffer *__devinit 12872246da4SFelipe Balbi dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) 12972246da4SFelipe Balbi { 13072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 13172246da4SFelipe Balbi 13272246da4SFelipe Balbi evt = kzalloc(sizeof(*evt), GFP_KERNEL); 13372246da4SFelipe Balbi if (!evt) 13472246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 13572246da4SFelipe Balbi 13672246da4SFelipe Balbi evt->dwc = dwc; 13772246da4SFelipe Balbi evt->length = length; 13872246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 13972246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 14072246da4SFelipe Balbi if (!evt->buf) { 14172246da4SFelipe Balbi kfree(evt); 14272246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 14372246da4SFelipe Balbi } 14472246da4SFelipe Balbi 14572246da4SFelipe Balbi return evt; 14672246da4SFelipe Balbi } 14772246da4SFelipe Balbi 14872246da4SFelipe Balbi /** 14972246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 15072246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 15172246da4SFelipe Balbi */ 15272246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 15372246da4SFelipe Balbi { 15472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 15572246da4SFelipe Balbi int i; 15672246da4SFelipe Balbi 1579f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 15872246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 15972246da4SFelipe Balbi if (evt) { 16072246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 16172246da4SFelipe Balbi dwc->ev_buffs[i] = NULL; 16272246da4SFelipe Balbi } 16372246da4SFelipe Balbi } 16472246da4SFelipe Balbi } 16572246da4SFelipe Balbi 16672246da4SFelipe Balbi /** 16772246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 16872246da4SFelipe Balbi * @dwc: Pointer to out controller context structure 16972246da4SFelipe Balbi * @length: size of event buffer 17072246da4SFelipe Balbi * 17172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. In error the case, dwc 17272246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 17372246da4SFelipe Balbi */ 1749f622b2aSFelipe Balbi static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 17572246da4SFelipe Balbi { 1769f622b2aSFelipe Balbi int num; 17772246da4SFelipe Balbi int i; 17872246da4SFelipe Balbi 1799f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 1809f622b2aSFelipe Balbi dwc->num_event_buffers = num; 1819f622b2aSFelipe Balbi 18272246da4SFelipe Balbi for (i = 0; i < num; i++) { 18372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 18472246da4SFelipe Balbi 18572246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 18672246da4SFelipe Balbi if (IS_ERR(evt)) { 18772246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 18872246da4SFelipe Balbi return PTR_ERR(evt); 18972246da4SFelipe Balbi } 19072246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 19172246da4SFelipe Balbi } 19272246da4SFelipe Balbi 19372246da4SFelipe Balbi return 0; 19472246da4SFelipe Balbi } 19572246da4SFelipe Balbi 19672246da4SFelipe Balbi /** 19772246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 19872246da4SFelipe Balbi * @dwc: Pointer to out controller context structure 19972246da4SFelipe Balbi * 20072246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 20172246da4SFelipe Balbi */ 20272246da4SFelipe Balbi static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) 20372246da4SFelipe Balbi { 20472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 20572246da4SFelipe Balbi int n; 20672246da4SFelipe Balbi 2079f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 20872246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 20972246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 21072246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 21172246da4SFelipe Balbi evt->length); 21272246da4SFelipe Balbi 21372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 21472246da4SFelipe Balbi lower_32_bits(evt->dma)); 21572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 21672246da4SFelipe Balbi upper_32_bits(evt->dma)); 21772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 21872246da4SFelipe Balbi evt->length & 0xffff); 21972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 22072246da4SFelipe Balbi } 22172246da4SFelipe Balbi 22272246da4SFelipe Balbi return 0; 22372246da4SFelipe Balbi } 22472246da4SFelipe Balbi 22572246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 22672246da4SFelipe Balbi { 22772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 22872246da4SFelipe Balbi int n; 22972246da4SFelipe Balbi 2309f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 23172246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 23272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 23372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 23472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 23572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 23672246da4SFelipe Balbi } 23772246da4SFelipe Balbi } 23872246da4SFelipe Balbi 23926ceca97SFelipe Balbi static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) 24026ceca97SFelipe Balbi { 24126ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 24226ceca97SFelipe Balbi 24326ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 24426ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 24526ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 24626ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 24726ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 24826ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 24926ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 25026ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 25126ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 25226ceca97SFelipe Balbi } 25326ceca97SFelipe Balbi 25472246da4SFelipe Balbi /** 25572246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 25672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 25772246da4SFelipe Balbi * 25872246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 25972246da4SFelipe Balbi */ 26072246da4SFelipe Balbi static int __devinit dwc3_core_init(struct dwc3 *dwc) 26172246da4SFelipe Balbi { 26272246da4SFelipe Balbi unsigned long timeout; 26372246da4SFelipe Balbi u32 reg; 26472246da4SFelipe Balbi int ret; 26572246da4SFelipe Balbi 2667650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 2677650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 2687650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 2697650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 2707650bd74SSebastian Andrzej Siewior ret = -ENODEV; 2717650bd74SSebastian Andrzej Siewior goto err0; 2727650bd74SSebastian Andrzej Siewior } 2737650bd74SSebastian Andrzej Siewior dwc->revision = reg & DWC3_GSNPSREV_MASK; 2747650bd74SSebastian Andrzej Siewior 27572246da4SFelipe Balbi dwc3_core_soft_reset(dwc); 27672246da4SFelipe Balbi 27772246da4SFelipe Balbi /* issue device SoftReset too */ 27872246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 27972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 28072246da4SFelipe Balbi do { 28172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 28272246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 28372246da4SFelipe Balbi break; 28472246da4SFelipe Balbi 28572246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 28672246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 28772246da4SFelipe Balbi ret = -ETIMEDOUT; 28872246da4SFelipe Balbi goto err0; 28972246da4SFelipe Balbi } 29072246da4SFelipe Balbi 29172246da4SFelipe Balbi cpu_relax(); 29272246da4SFelipe Balbi } while (true); 29372246da4SFelipe Balbi 2949f622b2aSFelipe Balbi dwc3_cache_hwparams(dwc); 2959f622b2aSFelipe Balbi 2969f622b2aSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 29772246da4SFelipe Balbi if (ret) { 29872246da4SFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 29972246da4SFelipe Balbi ret = -ENOMEM; 30072246da4SFelipe Balbi goto err1; 30172246da4SFelipe Balbi } 30272246da4SFelipe Balbi 30372246da4SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 30472246da4SFelipe Balbi if (ret) { 30572246da4SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 30672246da4SFelipe Balbi goto err1; 30772246da4SFelipe Balbi } 30872246da4SFelipe Balbi 30972246da4SFelipe Balbi return 0; 31072246da4SFelipe Balbi 31172246da4SFelipe Balbi err1: 31272246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 31372246da4SFelipe Balbi 31472246da4SFelipe Balbi err0: 31572246da4SFelipe Balbi return ret; 31672246da4SFelipe Balbi } 31772246da4SFelipe Balbi 31872246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 31972246da4SFelipe Balbi { 32072246da4SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 32172246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 32272246da4SFelipe Balbi } 32372246da4SFelipe Balbi 32472246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 32572246da4SFelipe Balbi 32672246da4SFelipe Balbi static int __devinit dwc3_probe(struct platform_device *pdev) 32772246da4SFelipe Balbi { 32872246da4SFelipe Balbi struct resource *res; 32972246da4SFelipe Balbi struct dwc3 *dwc; 3300949e99bSFelipe Balbi 33172246da4SFelipe Balbi int ret = -ENOMEM; 33272246da4SFelipe Balbi int irq; 3330949e99bSFelipe Balbi 3340949e99bSFelipe Balbi void __iomem *regs; 33572246da4SFelipe Balbi void *mem; 33672246da4SFelipe Balbi 3370949e99bSFelipe Balbi u8 mode; 3380949e99bSFelipe Balbi 33972246da4SFelipe Balbi mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 34072246da4SFelipe Balbi if (!mem) { 34172246da4SFelipe Balbi dev_err(&pdev->dev, "not enough memory\n"); 34272246da4SFelipe Balbi goto err0; 34372246da4SFelipe Balbi } 34472246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 34572246da4SFelipe Balbi dwc->mem = mem; 34672246da4SFelipe Balbi 34772246da4SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 34872246da4SFelipe Balbi if (!res) { 34972246da4SFelipe Balbi dev_err(&pdev->dev, "missing resource\n"); 35072246da4SFelipe Balbi goto err1; 35172246da4SFelipe Balbi } 35272246da4SFelipe Balbi 35372246da4SFelipe Balbi res = request_mem_region(res->start, resource_size(res), 35472246da4SFelipe Balbi dev_name(&pdev->dev)); 35572246da4SFelipe Balbi if (!res) { 35672246da4SFelipe Balbi dev_err(&pdev->dev, "can't request mem region\n"); 35772246da4SFelipe Balbi goto err1; 35872246da4SFelipe Balbi } 35972246da4SFelipe Balbi 36072246da4SFelipe Balbi regs = ioremap(res->start, resource_size(res)); 36172246da4SFelipe Balbi if (!regs) { 36272246da4SFelipe Balbi dev_err(&pdev->dev, "ioremap failed\n"); 36372246da4SFelipe Balbi goto err2; 36472246da4SFelipe Balbi } 36572246da4SFelipe Balbi 36672246da4SFelipe Balbi irq = platform_get_irq(pdev, 0); 36772246da4SFelipe Balbi if (irq < 0) { 36872246da4SFelipe Balbi dev_err(&pdev->dev, "missing IRQ\n"); 36972246da4SFelipe Balbi goto err3; 37072246da4SFelipe Balbi } 37172246da4SFelipe Balbi 37272246da4SFelipe Balbi spin_lock_init(&dwc->lock); 37372246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 37472246da4SFelipe Balbi 37572246da4SFelipe Balbi dwc->regs = regs; 37672246da4SFelipe Balbi dwc->regs_size = resource_size(res); 37772246da4SFelipe Balbi dwc->dev = &pdev->dev; 37872246da4SFelipe Balbi dwc->irq = irq; 37972246da4SFelipe Balbi 3806c167fc9SFelipe Balbi if (!strncmp("super", maximum_speed, 5)) 3816c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 3826c167fc9SFelipe Balbi else if (!strncmp("high", maximum_speed, 4)) 3836c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; 3846c167fc9SFelipe Balbi else if (!strncmp("full", maximum_speed, 4)) 3856c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; 3866c167fc9SFelipe Balbi else if (!strncmp("low", maximum_speed, 3)) 3876c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_LOWSPEED; 3886c167fc9SFelipe Balbi else 3896c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 3906c167fc9SFelipe Balbi 39172246da4SFelipe Balbi pm_runtime_enable(&pdev->dev); 39272246da4SFelipe Balbi pm_runtime_get_sync(&pdev->dev); 39372246da4SFelipe Balbi pm_runtime_forbid(&pdev->dev); 39472246da4SFelipe Balbi 39572246da4SFelipe Balbi ret = dwc3_core_init(dwc); 39672246da4SFelipe Balbi if (ret) { 39772246da4SFelipe Balbi dev_err(&pdev->dev, "failed to initialize core\n"); 39872246da4SFelipe Balbi goto err3; 39972246da4SFelipe Balbi } 40072246da4SFelipe Balbi 4010949e99bSFelipe Balbi mode = DWC3_MODE(dwc->hwparams.hwparams0); 4020949e99bSFelipe Balbi 4030949e99bSFelipe Balbi switch (mode) { 4040949e99bSFelipe Balbi case DWC3_MODE_DRD: 4050949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 40672246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 40772246da4SFelipe Balbi if (ret) { 4080949e99bSFelipe Balbi dev_err(&pdev->dev, "failed to initialize gadget\n"); 40972246da4SFelipe Balbi goto err4; 41072246da4SFelipe Balbi } 4110949e99bSFelipe Balbi break; 4120949e99bSFelipe Balbi default: 4130949e99bSFelipe Balbi dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode); 4140949e99bSFelipe Balbi goto err4; 41572246da4SFelipe Balbi } 4160949e99bSFelipe Balbi dwc->mode = mode; 41772246da4SFelipe Balbi 41872246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 41972246da4SFelipe Balbi if (ret) { 42072246da4SFelipe Balbi dev_err(&pdev->dev, "failed to initialize debugfs\n"); 42172246da4SFelipe Balbi goto err5; 42272246da4SFelipe Balbi } 42372246da4SFelipe Balbi 42472246da4SFelipe Balbi pm_runtime_allow(&pdev->dev); 42572246da4SFelipe Balbi 42672246da4SFelipe Balbi return 0; 42772246da4SFelipe Balbi 42872246da4SFelipe Balbi err5: 4290949e99bSFelipe Balbi switch (mode) { 4300949e99bSFelipe Balbi case DWC3_MODE_DRD: 4310949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 43272246da4SFelipe Balbi dwc3_gadget_exit(dwc); 4330949e99bSFelipe Balbi break; 4340949e99bSFelipe Balbi default: 4350949e99bSFelipe Balbi /* do nothing */ 4360949e99bSFelipe Balbi break; 4370949e99bSFelipe Balbi } 43872246da4SFelipe Balbi 43972246da4SFelipe Balbi err4: 44072246da4SFelipe Balbi dwc3_core_exit(dwc); 44172246da4SFelipe Balbi 44272246da4SFelipe Balbi err3: 44372246da4SFelipe Balbi iounmap(regs); 44472246da4SFelipe Balbi 44572246da4SFelipe Balbi err2: 44672246da4SFelipe Balbi release_mem_region(res->start, resource_size(res)); 44772246da4SFelipe Balbi 44872246da4SFelipe Balbi err1: 44972246da4SFelipe Balbi kfree(dwc->mem); 45072246da4SFelipe Balbi 45172246da4SFelipe Balbi err0: 45272246da4SFelipe Balbi return ret; 45372246da4SFelipe Balbi } 45472246da4SFelipe Balbi 45572246da4SFelipe Balbi static int __devexit dwc3_remove(struct platform_device *pdev) 45672246da4SFelipe Balbi { 45772246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 45872246da4SFelipe Balbi struct resource *res; 45972246da4SFelipe Balbi 46072246da4SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 46172246da4SFelipe Balbi 46272246da4SFelipe Balbi pm_runtime_put(&pdev->dev); 46372246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 46472246da4SFelipe Balbi 46572246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 46672246da4SFelipe Balbi 4670949e99bSFelipe Balbi switch (dwc->mode) { 4680949e99bSFelipe Balbi case DWC3_MODE_DRD: 4690949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 47072246da4SFelipe Balbi dwc3_gadget_exit(dwc); 4710949e99bSFelipe Balbi break; 4720949e99bSFelipe Balbi default: 4730949e99bSFelipe Balbi /* do nothing */ 4740949e99bSFelipe Balbi break; 4750949e99bSFelipe Balbi } 47672246da4SFelipe Balbi 47772246da4SFelipe Balbi dwc3_core_exit(dwc); 47872246da4SFelipe Balbi release_mem_region(res->start, resource_size(res)); 47972246da4SFelipe Balbi iounmap(dwc->regs); 48072246da4SFelipe Balbi kfree(dwc->mem); 48172246da4SFelipe Balbi 48272246da4SFelipe Balbi return 0; 48372246da4SFelipe Balbi } 48472246da4SFelipe Balbi 48572246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 48672246da4SFelipe Balbi .probe = dwc3_probe, 48772246da4SFelipe Balbi .remove = __devexit_p(dwc3_remove), 48872246da4SFelipe Balbi .driver = { 48972246da4SFelipe Balbi .name = "dwc3", 49072246da4SFelipe Balbi }, 49172246da4SFelipe Balbi }; 49272246da4SFelipe Balbi 49372246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 49472246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL"); 49572246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 49672246da4SFelipe Balbi 49772246da4SFelipe Balbi static int __devinit dwc3_init(void) 49872246da4SFelipe Balbi { 49972246da4SFelipe Balbi return platform_driver_register(&dwc3_driver); 50072246da4SFelipe Balbi } 50172246da4SFelipe Balbi module_init(dwc3_init); 50272246da4SFelipe Balbi 50372246da4SFelipe Balbi static void __exit dwc3_exit(void) 50472246da4SFelipe Balbi { 50572246da4SFelipe Balbi platform_driver_unregister(&dwc3_driver); 50672246da4SFelipe Balbi } 50772246da4SFelipe Balbi module_exit(dwc3_exit); 508