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> 54*2204fdeeSPaul 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 6272246da4SFelipe Balbi /** 6372246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6472246da4SFelipe Balbi * @dwc: pointer to our context structure 6572246da4SFelipe Balbi */ 6672246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc) 6772246da4SFelipe Balbi { 6872246da4SFelipe Balbi u32 reg; 6972246da4SFelipe Balbi 7072246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7272246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7472246da4SFelipe Balbi 7572246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7672246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7772246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 7872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 7972246da4SFelipe Balbi 8072246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8272246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8472246da4SFelipe Balbi 8572246da4SFelipe Balbi mdelay(100); 8672246da4SFelipe Balbi 8772246da4SFelipe Balbi /* Clear USB3 PHY reset */ 8872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 8972246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 9072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 9172246da4SFelipe Balbi 9272246da4SFelipe Balbi /* Clear USB2 PHY reset */ 9372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 9472246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 9572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 9672246da4SFelipe Balbi 9772246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 9872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 9972246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 10072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 10172246da4SFelipe Balbi } 10272246da4SFelipe Balbi 10372246da4SFelipe Balbi /** 10472246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 10572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 10672246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 10772246da4SFelipe Balbi */ 10872246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 10972246da4SFelipe Balbi struct dwc3_event_buffer *evt) 11072246da4SFelipe Balbi { 11172246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 11272246da4SFelipe Balbi kfree(evt); 11372246da4SFelipe Balbi } 11472246da4SFelipe Balbi 11572246da4SFelipe Balbi /** 11672246da4SFelipe Balbi * dwc3_alloc_one_event_buffer - Allocated one event buffer structure 11772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 11872246da4SFelipe Balbi * @length: size of the event buffer 11972246da4SFelipe Balbi * 12072246da4SFelipe Balbi * Returns a pointer to the allocated event buffer structure on succes 12172246da4SFelipe Balbi * otherwise ERR_PTR(errno). 12272246da4SFelipe Balbi */ 12372246da4SFelipe Balbi static struct dwc3_event_buffer *__devinit 12472246da4SFelipe Balbi dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) 12572246da4SFelipe Balbi { 12672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 12772246da4SFelipe Balbi 12872246da4SFelipe Balbi evt = kzalloc(sizeof(*evt), GFP_KERNEL); 12972246da4SFelipe Balbi if (!evt) 13072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 13172246da4SFelipe Balbi 13272246da4SFelipe Balbi evt->dwc = dwc; 13372246da4SFelipe Balbi evt->length = length; 13472246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 13572246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 13672246da4SFelipe Balbi if (!evt->buf) { 13772246da4SFelipe Balbi kfree(evt); 13872246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 13972246da4SFelipe Balbi } 14072246da4SFelipe Balbi 14172246da4SFelipe Balbi return evt; 14272246da4SFelipe Balbi } 14372246da4SFelipe Balbi 14472246da4SFelipe Balbi /** 14572246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 14672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 14772246da4SFelipe Balbi */ 14872246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 14972246da4SFelipe Balbi { 15072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 15172246da4SFelipe Balbi int i; 15272246da4SFelipe Balbi 15372246da4SFelipe Balbi for (i = 0; i < DWC3_EVENT_BUFFERS_NUM; i++) { 15472246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 15572246da4SFelipe Balbi if (evt) { 15672246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 15772246da4SFelipe Balbi dwc->ev_buffs[i] = NULL; 15872246da4SFelipe Balbi } 15972246da4SFelipe Balbi } 16072246da4SFelipe Balbi } 16172246da4SFelipe Balbi 16272246da4SFelipe Balbi /** 16372246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 16472246da4SFelipe Balbi * @dwc: Pointer to out controller context structure 16572246da4SFelipe Balbi * @num: number of event buffers to allocate 16672246da4SFelipe Balbi * @length: size of event buffer 16772246da4SFelipe Balbi * 16872246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. In error the case, dwc 16972246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 17072246da4SFelipe Balbi */ 17172246da4SFelipe Balbi static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned num, 17272246da4SFelipe Balbi unsigned length) 17372246da4SFelipe Balbi { 17472246da4SFelipe Balbi int i; 17572246da4SFelipe Balbi 17672246da4SFelipe Balbi for (i = 0; i < num; i++) { 17772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 17872246da4SFelipe Balbi 17972246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 18072246da4SFelipe Balbi if (IS_ERR(evt)) { 18172246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 18272246da4SFelipe Balbi return PTR_ERR(evt); 18372246da4SFelipe Balbi } 18472246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 18572246da4SFelipe Balbi } 18672246da4SFelipe Balbi 18772246da4SFelipe Balbi return 0; 18872246da4SFelipe Balbi } 18972246da4SFelipe Balbi 19072246da4SFelipe Balbi /** 19172246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 19272246da4SFelipe Balbi * @dwc: Pointer to out controller context structure 19372246da4SFelipe Balbi * 19472246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 19572246da4SFelipe Balbi */ 19672246da4SFelipe Balbi static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) 19772246da4SFelipe Balbi { 19872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19972246da4SFelipe Balbi int n; 20072246da4SFelipe Balbi 20172246da4SFelipe Balbi for (n = 0; n < DWC3_EVENT_BUFFERS_NUM; n++) { 20272246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 20372246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 20472246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 20572246da4SFelipe Balbi evt->length); 20672246da4SFelipe Balbi 20772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 20872246da4SFelipe Balbi lower_32_bits(evt->dma)); 20972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 21072246da4SFelipe Balbi upper_32_bits(evt->dma)); 21172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 21272246da4SFelipe Balbi evt->length & 0xffff); 21372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 21472246da4SFelipe Balbi } 21572246da4SFelipe Balbi 21672246da4SFelipe Balbi return 0; 21772246da4SFelipe Balbi } 21872246da4SFelipe Balbi 21972246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 22072246da4SFelipe Balbi { 22172246da4SFelipe Balbi struct dwc3_event_buffer *evt; 22272246da4SFelipe Balbi int n; 22372246da4SFelipe Balbi 22472246da4SFelipe Balbi for (n = 0; n < DWC3_EVENT_BUFFERS_NUM; n++) { 22572246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 22672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 22772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 22872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 22972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 23072246da4SFelipe Balbi } 23172246da4SFelipe Balbi } 23272246da4SFelipe Balbi 23326ceca97SFelipe Balbi static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) 23426ceca97SFelipe Balbi { 23526ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 23626ceca97SFelipe Balbi 23726ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 23826ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 23926ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 24026ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 24126ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 24226ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 24326ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 24426ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 24526ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 24626ceca97SFelipe Balbi } 24726ceca97SFelipe Balbi 24872246da4SFelipe Balbi /** 24972246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 25072246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 25172246da4SFelipe Balbi * 25272246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 25372246da4SFelipe Balbi */ 25472246da4SFelipe Balbi static int __devinit dwc3_core_init(struct dwc3 *dwc) 25572246da4SFelipe Balbi { 25672246da4SFelipe Balbi unsigned long timeout; 25772246da4SFelipe Balbi u32 reg; 25872246da4SFelipe Balbi int ret; 25972246da4SFelipe Balbi 2607650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 2617650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 2627650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 2637650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 2647650bd74SSebastian Andrzej Siewior ret = -ENODEV; 2657650bd74SSebastian Andrzej Siewior goto err0; 2667650bd74SSebastian Andrzej Siewior } 2677650bd74SSebastian Andrzej Siewior dwc->revision = reg & DWC3_GSNPSREV_MASK; 2687650bd74SSebastian Andrzej Siewior 26972246da4SFelipe Balbi dwc3_core_soft_reset(dwc); 27072246da4SFelipe Balbi 27172246da4SFelipe Balbi /* issue device SoftReset too */ 27272246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 27372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 27472246da4SFelipe Balbi do { 27572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 27672246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 27772246da4SFelipe Balbi break; 27872246da4SFelipe Balbi 27972246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 28072246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 28172246da4SFelipe Balbi ret = -ETIMEDOUT; 28272246da4SFelipe Balbi goto err0; 28372246da4SFelipe Balbi } 28472246da4SFelipe Balbi 28572246da4SFelipe Balbi cpu_relax(); 28672246da4SFelipe Balbi } while (true); 28772246da4SFelipe Balbi 28872246da4SFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_NUM, 28972246da4SFelipe Balbi DWC3_EVENT_BUFFERS_SIZE); 29072246da4SFelipe Balbi if (ret) { 29172246da4SFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 29272246da4SFelipe Balbi ret = -ENOMEM; 29372246da4SFelipe Balbi goto err1; 29472246da4SFelipe Balbi } 29572246da4SFelipe Balbi 29672246da4SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 29772246da4SFelipe Balbi if (ret) { 29872246da4SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 29972246da4SFelipe Balbi goto err1; 30072246da4SFelipe Balbi } 30172246da4SFelipe Balbi 30226ceca97SFelipe Balbi dwc3_cache_hwparams(dwc); 30326ceca97SFelipe Balbi 30472246da4SFelipe Balbi return 0; 30572246da4SFelipe Balbi 30672246da4SFelipe Balbi err1: 30772246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 30872246da4SFelipe Balbi 30972246da4SFelipe Balbi err0: 31072246da4SFelipe Balbi return ret; 31172246da4SFelipe Balbi } 31272246da4SFelipe Balbi 31372246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 31472246da4SFelipe Balbi { 31572246da4SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 31672246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 31772246da4SFelipe Balbi } 31872246da4SFelipe Balbi 31972246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 32072246da4SFelipe Balbi 32172246da4SFelipe Balbi static int __devinit dwc3_probe(struct platform_device *pdev) 32272246da4SFelipe Balbi { 32372246da4SFelipe Balbi const struct platform_device_id *id = platform_get_device_id(pdev); 32472246da4SFelipe Balbi struct resource *res; 32572246da4SFelipe Balbi struct dwc3 *dwc; 32672246da4SFelipe Balbi void __iomem *regs; 32772246da4SFelipe Balbi unsigned int features = id->driver_data; 32872246da4SFelipe Balbi int ret = -ENOMEM; 32972246da4SFelipe Balbi int irq; 33072246da4SFelipe Balbi void *mem; 33172246da4SFelipe Balbi 33272246da4SFelipe Balbi mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 33372246da4SFelipe Balbi if (!mem) { 33472246da4SFelipe Balbi dev_err(&pdev->dev, "not enough memory\n"); 33572246da4SFelipe Balbi goto err0; 33672246da4SFelipe Balbi } 33772246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 33872246da4SFelipe Balbi dwc->mem = mem; 33972246da4SFelipe Balbi 34072246da4SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 34172246da4SFelipe Balbi if (!res) { 34272246da4SFelipe Balbi dev_err(&pdev->dev, "missing resource\n"); 34372246da4SFelipe Balbi goto err1; 34472246da4SFelipe Balbi } 34572246da4SFelipe Balbi 34672246da4SFelipe Balbi res = request_mem_region(res->start, resource_size(res), 34772246da4SFelipe Balbi dev_name(&pdev->dev)); 34872246da4SFelipe Balbi if (!res) { 34972246da4SFelipe Balbi dev_err(&pdev->dev, "can't request mem region\n"); 35072246da4SFelipe Balbi goto err1; 35172246da4SFelipe Balbi } 35272246da4SFelipe Balbi 35372246da4SFelipe Balbi regs = ioremap(res->start, resource_size(res)); 35472246da4SFelipe Balbi if (!regs) { 35572246da4SFelipe Balbi dev_err(&pdev->dev, "ioremap failed\n"); 35672246da4SFelipe Balbi goto err2; 35772246da4SFelipe Balbi } 35872246da4SFelipe Balbi 35972246da4SFelipe Balbi irq = platform_get_irq(pdev, 0); 36072246da4SFelipe Balbi if (irq < 0) { 36172246da4SFelipe Balbi dev_err(&pdev->dev, "missing IRQ\n"); 36272246da4SFelipe Balbi goto err3; 36372246da4SFelipe Balbi } 36472246da4SFelipe Balbi 36572246da4SFelipe Balbi spin_lock_init(&dwc->lock); 36672246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 36772246da4SFelipe Balbi 36872246da4SFelipe Balbi dwc->regs = regs; 36972246da4SFelipe Balbi dwc->regs_size = resource_size(res); 37072246da4SFelipe Balbi dwc->dev = &pdev->dev; 37172246da4SFelipe Balbi dwc->irq = irq; 37272246da4SFelipe Balbi 37372246da4SFelipe Balbi pm_runtime_enable(&pdev->dev); 37472246da4SFelipe Balbi pm_runtime_get_sync(&pdev->dev); 37572246da4SFelipe Balbi pm_runtime_forbid(&pdev->dev); 37672246da4SFelipe Balbi 37772246da4SFelipe Balbi ret = dwc3_core_init(dwc); 37872246da4SFelipe Balbi if (ret) { 37972246da4SFelipe Balbi dev_err(&pdev->dev, "failed to initialize core\n"); 38072246da4SFelipe Balbi goto err3; 38172246da4SFelipe Balbi } 38272246da4SFelipe Balbi 38372246da4SFelipe Balbi if (features & DWC3_HAS_PERIPHERAL) { 38472246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 38572246da4SFelipe Balbi if (ret) { 38672246da4SFelipe Balbi dev_err(&pdev->dev, "failed to initialized gadget\n"); 38772246da4SFelipe Balbi goto err4; 38872246da4SFelipe Balbi } 38972246da4SFelipe Balbi } 39072246da4SFelipe Balbi 39172246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 39272246da4SFelipe Balbi if (ret) { 39372246da4SFelipe Balbi dev_err(&pdev->dev, "failed to initialize debugfs\n"); 39472246da4SFelipe Balbi goto err5; 39572246da4SFelipe Balbi } 39672246da4SFelipe Balbi 39772246da4SFelipe Balbi pm_runtime_allow(&pdev->dev); 39872246da4SFelipe Balbi 39972246da4SFelipe Balbi return 0; 40072246da4SFelipe Balbi 40172246da4SFelipe Balbi err5: 40272246da4SFelipe Balbi if (features & DWC3_HAS_PERIPHERAL) 40372246da4SFelipe Balbi dwc3_gadget_exit(dwc); 40472246da4SFelipe Balbi 40572246da4SFelipe Balbi err4: 40672246da4SFelipe Balbi dwc3_core_exit(dwc); 40772246da4SFelipe Balbi 40872246da4SFelipe Balbi err3: 40972246da4SFelipe Balbi iounmap(regs); 41072246da4SFelipe Balbi 41172246da4SFelipe Balbi err2: 41272246da4SFelipe Balbi release_mem_region(res->start, resource_size(res)); 41372246da4SFelipe Balbi 41472246da4SFelipe Balbi err1: 41572246da4SFelipe Balbi kfree(dwc->mem); 41672246da4SFelipe Balbi 41772246da4SFelipe Balbi err0: 41872246da4SFelipe Balbi return ret; 41972246da4SFelipe Balbi } 42072246da4SFelipe Balbi 42172246da4SFelipe Balbi static int __devexit dwc3_remove(struct platform_device *pdev) 42272246da4SFelipe Balbi { 42372246da4SFelipe Balbi const struct platform_device_id *id = platform_get_device_id(pdev); 42472246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 42572246da4SFelipe Balbi struct resource *res; 42672246da4SFelipe Balbi unsigned int features = id->driver_data; 42772246da4SFelipe Balbi 42872246da4SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 42972246da4SFelipe Balbi 43072246da4SFelipe Balbi pm_runtime_put(&pdev->dev); 43172246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 43272246da4SFelipe Balbi 43372246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 43472246da4SFelipe Balbi 43572246da4SFelipe Balbi if (features & DWC3_HAS_PERIPHERAL) 43672246da4SFelipe Balbi dwc3_gadget_exit(dwc); 43772246da4SFelipe Balbi 43872246da4SFelipe Balbi dwc3_core_exit(dwc); 43972246da4SFelipe Balbi release_mem_region(res->start, resource_size(res)); 44072246da4SFelipe Balbi iounmap(dwc->regs); 44172246da4SFelipe Balbi kfree(dwc->mem); 44272246da4SFelipe Balbi 44372246da4SFelipe Balbi return 0; 44472246da4SFelipe Balbi } 44572246da4SFelipe Balbi 44672246da4SFelipe Balbi static const struct platform_device_id dwc3_id_table[] __devinitconst = { 44772246da4SFelipe Balbi { 44872246da4SFelipe Balbi .name = "dwc3-omap", 44972246da4SFelipe Balbi .driver_data = (DWC3_HAS_PERIPHERAL 45072246da4SFelipe Balbi | DWC3_HAS_XHCI 45172246da4SFelipe Balbi | DWC3_HAS_OTG), 45272246da4SFelipe Balbi }, 45372246da4SFelipe Balbi { 45472246da4SFelipe Balbi .name = "dwc3-pci", 45572246da4SFelipe Balbi .driver_data = DWC3_HAS_PERIPHERAL, 45672246da4SFelipe Balbi }, 45772246da4SFelipe Balbi { }, /* Terminating Entry */ 45872246da4SFelipe Balbi }; 45972246da4SFelipe Balbi MODULE_DEVICE_TABLE(platform, dwc3_id_table); 46072246da4SFelipe Balbi 46172246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 46272246da4SFelipe Balbi .probe = dwc3_probe, 46372246da4SFelipe Balbi .remove = __devexit_p(dwc3_remove), 46472246da4SFelipe Balbi .driver = { 46572246da4SFelipe Balbi .name = "dwc3", 46672246da4SFelipe Balbi }, 46772246da4SFelipe Balbi .id_table = dwc3_id_table, 46872246da4SFelipe Balbi }; 46972246da4SFelipe Balbi 47072246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 47172246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL"); 47272246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 47372246da4SFelipe Balbi 47472246da4SFelipe Balbi static int __devinit dwc3_init(void) 47572246da4SFelipe Balbi { 47672246da4SFelipe Balbi return platform_driver_register(&dwc3_driver); 47772246da4SFelipe Balbi } 47872246da4SFelipe Balbi module_init(dwc3_init); 47972246da4SFelipe Balbi 48072246da4SFelipe Balbi static void __exit dwc3_exit(void) 48172246da4SFelipe Balbi { 48272246da4SFelipe Balbi platform_driver_unregister(&dwc3_driver); 48372246da4SFelipe Balbi } 48472246da4SFelipe Balbi module_exit(dwc3_exit); 485