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 5372246da4SFelipe Balbi #include <linux/usb/ch9.h> 5472246da4SFelipe Balbi #include <linux/usb/gadget.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 668300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 678300dd23SFelipe Balbi 688300dd23SFelipe Balbi #define DWC3_DEVS_POSSIBLE 32 698300dd23SFelipe Balbi 708300dd23SFelipe Balbi static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE); 718300dd23SFelipe Balbi 728300dd23SFelipe Balbi int dwc3_get_device_id(void) 738300dd23SFelipe Balbi { 748300dd23SFelipe Balbi int id; 758300dd23SFelipe Balbi 768300dd23SFelipe Balbi again: 778300dd23SFelipe Balbi id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE); 788300dd23SFelipe Balbi if (id < DWC3_DEVS_POSSIBLE) { 798300dd23SFelipe Balbi int old; 808300dd23SFelipe Balbi 818300dd23SFelipe Balbi old = test_and_set_bit(id, dwc3_devs); 828300dd23SFelipe Balbi if (old) 838300dd23SFelipe Balbi goto again; 848300dd23SFelipe Balbi } else { 858300dd23SFelipe Balbi pr_err("dwc3: no space for new device\n"); 868300dd23SFelipe Balbi id = -ENOMEM; 878300dd23SFelipe Balbi } 888300dd23SFelipe Balbi 89075cd14dSDan Carpenter return id; 908300dd23SFelipe Balbi } 918300dd23SFelipe Balbi EXPORT_SYMBOL_GPL(dwc3_get_device_id); 928300dd23SFelipe Balbi 938300dd23SFelipe Balbi void dwc3_put_device_id(int id) 948300dd23SFelipe Balbi { 958300dd23SFelipe Balbi int ret; 968300dd23SFelipe Balbi 978300dd23SFelipe Balbi if (id < 0) 988300dd23SFelipe Balbi return; 998300dd23SFelipe Balbi 1008300dd23SFelipe Balbi ret = test_bit(id, dwc3_devs); 1018300dd23SFelipe Balbi WARN(!ret, "dwc3: ID %d not in use\n", id); 1028300dd23SFelipe Balbi clear_bit(id, dwc3_devs); 1038300dd23SFelipe Balbi } 1048300dd23SFelipe Balbi EXPORT_SYMBOL_GPL(dwc3_put_device_id); 1058300dd23SFelipe Balbi 1063140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 1073140e8cbSSebastian Andrzej Siewior { 1083140e8cbSSebastian Andrzej Siewior u32 reg; 1093140e8cbSSebastian Andrzej Siewior 1103140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 1113140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 1123140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 1133140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 1143140e8cbSSebastian Andrzej Siewior } 1158300dd23SFelipe Balbi 11672246da4SFelipe Balbi /** 11772246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 11872246da4SFelipe Balbi * @dwc: pointer to our context structure 11972246da4SFelipe Balbi */ 12072246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc) 12172246da4SFelipe Balbi { 12272246da4SFelipe Balbi u32 reg; 12372246da4SFelipe Balbi 12472246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 12572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 12672246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 12772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 12872246da4SFelipe Balbi 12972246da4SFelipe Balbi /* Assert USB3 PHY reset */ 13072246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 13172246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 13272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 13372246da4SFelipe Balbi 13472246da4SFelipe Balbi /* Assert USB2 PHY reset */ 13572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 13672246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 13772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 13872246da4SFelipe Balbi 13972246da4SFelipe Balbi mdelay(100); 14072246da4SFelipe Balbi 14172246da4SFelipe Balbi /* Clear USB3 PHY reset */ 14272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 14372246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 14472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 14572246da4SFelipe Balbi 14672246da4SFelipe Balbi /* Clear USB2 PHY reset */ 14772246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 14872246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 14972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 15072246da4SFelipe Balbi 151*45627ac6SPratyush Anand mdelay(100); 152*45627ac6SPratyush Anand 15372246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 15472246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 15572246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 15672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 15772246da4SFelipe Balbi } 15872246da4SFelipe Balbi 15972246da4SFelipe Balbi /** 16072246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 16172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 16272246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 16372246da4SFelipe Balbi */ 16472246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 16572246da4SFelipe Balbi struct dwc3_event_buffer *evt) 16672246da4SFelipe Balbi { 16772246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 16872246da4SFelipe Balbi kfree(evt); 16972246da4SFelipe Balbi } 17072246da4SFelipe Balbi 17172246da4SFelipe Balbi /** 1721d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 17372246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 17472246da4SFelipe Balbi * @length: size of the event buffer 17572246da4SFelipe Balbi * 1761d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 17772246da4SFelipe Balbi * otherwise ERR_PTR(errno). 17872246da4SFelipe Balbi */ 17972246da4SFelipe Balbi static struct dwc3_event_buffer *__devinit 18072246da4SFelipe Balbi dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) 18172246da4SFelipe Balbi { 18272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 18372246da4SFelipe Balbi 18472246da4SFelipe Balbi evt = kzalloc(sizeof(*evt), GFP_KERNEL); 18572246da4SFelipe Balbi if (!evt) 18672246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 18772246da4SFelipe Balbi 18872246da4SFelipe Balbi evt->dwc = dwc; 18972246da4SFelipe Balbi evt->length = length; 19072246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 19172246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 19272246da4SFelipe Balbi if (!evt->buf) { 19372246da4SFelipe Balbi kfree(evt); 19472246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 19572246da4SFelipe Balbi } 19672246da4SFelipe Balbi 19772246da4SFelipe Balbi return evt; 19872246da4SFelipe Balbi } 19972246da4SFelipe Balbi 20072246da4SFelipe Balbi /** 20172246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 20272246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 20372246da4SFelipe Balbi */ 20472246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 20572246da4SFelipe Balbi { 20672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 20772246da4SFelipe Balbi int i; 20872246da4SFelipe Balbi 2099f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 21072246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 21164b6c8a7SAnton Tikhomirov if (evt) 21272246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 21372246da4SFelipe Balbi } 21464b6c8a7SAnton Tikhomirov 21564b6c8a7SAnton Tikhomirov kfree(dwc->ev_buffs); 21672246da4SFelipe Balbi } 21772246da4SFelipe Balbi 21872246da4SFelipe Balbi /** 21972246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2201d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 22172246da4SFelipe Balbi * @length: size of event buffer 22272246da4SFelipe Balbi * 2231d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 22472246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 22572246da4SFelipe Balbi */ 2269f622b2aSFelipe Balbi static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 22772246da4SFelipe Balbi { 2289f622b2aSFelipe Balbi int num; 22972246da4SFelipe Balbi int i; 23072246da4SFelipe Balbi 2319f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 2329f622b2aSFelipe Balbi dwc->num_event_buffers = num; 2339f622b2aSFelipe Balbi 234457d3f21SFelipe Balbi dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); 235457d3f21SFelipe Balbi if (!dwc->ev_buffs) { 236457d3f21SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffers array\n"); 237457d3f21SFelipe Balbi return -ENOMEM; 238457d3f21SFelipe Balbi } 239457d3f21SFelipe Balbi 24072246da4SFelipe Balbi for (i = 0; i < num; i++) { 24172246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24272246da4SFelipe Balbi 24372246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 24472246da4SFelipe Balbi if (IS_ERR(evt)) { 24572246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 24672246da4SFelipe Balbi return PTR_ERR(evt); 24772246da4SFelipe Balbi } 24872246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 24972246da4SFelipe Balbi } 25072246da4SFelipe Balbi 25172246da4SFelipe Balbi return 0; 25272246da4SFelipe Balbi } 25372246da4SFelipe Balbi 25472246da4SFelipe Balbi /** 25572246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2561d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 25772246da4SFelipe Balbi * 25872246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 25972246da4SFelipe Balbi */ 2607acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 26172246da4SFelipe Balbi { 26272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 26372246da4SFelipe Balbi int n; 26472246da4SFelipe Balbi 2659f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 26672246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 26772246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 26872246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 26972246da4SFelipe Balbi evt->length); 27072246da4SFelipe Balbi 2717acd85e0SPaul Zimmerman evt->lpos = 0; 2727acd85e0SPaul Zimmerman 27372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 27472246da4SFelipe Balbi lower_32_bits(evt->dma)); 27572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 27672246da4SFelipe Balbi upper_32_bits(evt->dma)); 27772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 27872246da4SFelipe Balbi evt->length & 0xffff); 27972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 28072246da4SFelipe Balbi } 28172246da4SFelipe Balbi 28272246da4SFelipe Balbi return 0; 28372246da4SFelipe Balbi } 28472246da4SFelipe Balbi 28572246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 28672246da4SFelipe Balbi { 28772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 28872246da4SFelipe Balbi int n; 28972246da4SFelipe Balbi 2909f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 29172246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2927acd85e0SPaul Zimmerman 2937acd85e0SPaul Zimmerman evt->lpos = 0; 2947acd85e0SPaul Zimmerman 29572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 29672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 29772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 29872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 29972246da4SFelipe Balbi } 30072246da4SFelipe Balbi } 30172246da4SFelipe Balbi 30226ceca97SFelipe Balbi static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) 30326ceca97SFelipe Balbi { 30426ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 30526ceca97SFelipe Balbi 30626ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 30726ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 30826ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 30926ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 31026ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 31126ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 31226ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 31326ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 31426ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 31526ceca97SFelipe Balbi } 31626ceca97SFelipe Balbi 31772246da4SFelipe Balbi /** 31872246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 31972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 32072246da4SFelipe Balbi * 32172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 32272246da4SFelipe Balbi */ 32372246da4SFelipe Balbi static int __devinit dwc3_core_init(struct dwc3 *dwc) 32472246da4SFelipe Balbi { 32572246da4SFelipe Balbi unsigned long timeout; 32672246da4SFelipe Balbi u32 reg; 32772246da4SFelipe Balbi int ret; 32872246da4SFelipe Balbi 3297650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3307650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3317650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3327650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3337650bd74SSebastian Andrzej Siewior ret = -ENODEV; 3347650bd74SSebastian Andrzej Siewior goto err0; 3357650bd74SSebastian Andrzej Siewior } 336248b122bSFelipe Balbi dwc->revision = reg; 3377650bd74SSebastian Andrzej Siewior 33872246da4SFelipe Balbi dwc3_core_soft_reset(dwc); 33972246da4SFelipe Balbi 34072246da4SFelipe Balbi /* issue device SoftReset too */ 34172246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 34272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 34372246da4SFelipe Balbi do { 34472246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 34572246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 34672246da4SFelipe Balbi break; 34772246da4SFelipe Balbi 34872246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 34972246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 35072246da4SFelipe Balbi ret = -ETIMEDOUT; 35172246da4SFelipe Balbi goto err0; 35272246da4SFelipe Balbi } 35372246da4SFelipe Balbi 35472246da4SFelipe Balbi cpu_relax(); 35572246da4SFelipe Balbi } while (true); 35672246da4SFelipe Balbi 3579f622b2aSFelipe Balbi dwc3_cache_hwparams(dwc); 3589f622b2aSFelipe Balbi 3594878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 3603e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 3614878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 3624878a028SSebastian Andrzej Siewior 363164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 3644878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 3654878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 3664878a028SSebastian Andrzej Siewior break; 3674878a028SSebastian Andrzej Siewior default: 3684878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 3694878a028SSebastian Andrzej Siewior } 3704878a028SSebastian Andrzej Siewior 3714878a028SSebastian Andrzej Siewior /* 3724878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 3731d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 3744878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 3751d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 3764878a028SSebastian Andrzej Siewior */ 3774878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 3784878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 3794878a028SSebastian Andrzej Siewior 3804878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 3814878a028SSebastian Andrzej Siewior 3829f622b2aSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 38372246da4SFelipe Balbi if (ret) { 38472246da4SFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 38572246da4SFelipe Balbi ret = -ENOMEM; 38672246da4SFelipe Balbi goto err1; 38772246da4SFelipe Balbi } 38872246da4SFelipe Balbi 38972246da4SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 39072246da4SFelipe Balbi if (ret) { 39172246da4SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 39272246da4SFelipe Balbi goto err1; 39372246da4SFelipe Balbi } 39472246da4SFelipe Balbi 39572246da4SFelipe Balbi return 0; 39672246da4SFelipe Balbi 39772246da4SFelipe Balbi err1: 39872246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 39972246da4SFelipe Balbi 40072246da4SFelipe Balbi err0: 40172246da4SFelipe Balbi return ret; 40272246da4SFelipe Balbi } 40372246da4SFelipe Balbi 40472246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 40572246da4SFelipe Balbi { 40672246da4SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 40772246da4SFelipe Balbi dwc3_free_event_buffers(dwc); 40872246da4SFelipe Balbi } 40972246da4SFelipe Balbi 41072246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 41172246da4SFelipe Balbi 41272246da4SFelipe Balbi static int __devinit dwc3_probe(struct platform_device *pdev) 41372246da4SFelipe Balbi { 414457e84b6SFelipe Balbi struct device_node *node = pdev->dev.of_node; 41572246da4SFelipe Balbi struct resource *res; 41672246da4SFelipe Balbi struct dwc3 *dwc; 417802ca850SChanho Park struct device *dev = &pdev->dev; 4180949e99bSFelipe Balbi 41972246da4SFelipe Balbi int ret = -ENOMEM; 4200949e99bSFelipe Balbi 4210949e99bSFelipe Balbi void __iomem *regs; 42272246da4SFelipe Balbi void *mem; 42372246da4SFelipe Balbi 4240949e99bSFelipe Balbi u8 mode; 4250949e99bSFelipe Balbi 426802ca850SChanho Park mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 42772246da4SFelipe Balbi if (!mem) { 428802ca850SChanho Park dev_err(dev, "not enough memory\n"); 429802ca850SChanho Park return -ENOMEM; 43072246da4SFelipe Balbi } 43172246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 43272246da4SFelipe Balbi dwc->mem = mem; 43372246da4SFelipe Balbi 43451249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 43572246da4SFelipe Balbi if (!res) { 43651249dcaSIdo Shayevitz dev_err(dev, "missing IRQ\n"); 437802ca850SChanho Park return -ENODEV; 43872246da4SFelipe Balbi } 43951249dcaSIdo Shayevitz dwc->xhci_resources[1] = *res; 44072246da4SFelipe Balbi 44151249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 44251249dcaSIdo Shayevitz if (!res) { 44351249dcaSIdo Shayevitz dev_err(dev, "missing memory resource\n"); 44451249dcaSIdo Shayevitz return -ENODEV; 44551249dcaSIdo Shayevitz } 44651249dcaSIdo Shayevitz dwc->xhci_resources[0] = *res; 44751249dcaSIdo Shayevitz dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 44851249dcaSIdo Shayevitz DWC3_XHCI_REGS_END; 449d07e8819SFelipe Balbi 45051249dcaSIdo Shayevitz /* 45151249dcaSIdo Shayevitz * Request memory region but exclude xHCI regs, 45251249dcaSIdo Shayevitz * since it will be requested by the xhci-plat driver. 45351249dcaSIdo Shayevitz */ 45451249dcaSIdo Shayevitz res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START, 45551249dcaSIdo Shayevitz resource_size(res) - DWC3_GLOBALS_REGS_START, 456802ca850SChanho Park dev_name(dev)); 45772246da4SFelipe Balbi if (!res) { 458802ca850SChanho Park dev_err(dev, "can't request mem region\n"); 459802ca850SChanho Park return -ENOMEM; 46072246da4SFelipe Balbi } 46172246da4SFelipe Balbi 462802ca850SChanho Park regs = devm_ioremap(dev, res->start, resource_size(res)); 46372246da4SFelipe Balbi if (!regs) { 464802ca850SChanho Park dev_err(dev, "ioremap failed\n"); 465802ca850SChanho Park return -ENOMEM; 46672246da4SFelipe Balbi } 46772246da4SFelipe Balbi 46872246da4SFelipe Balbi spin_lock_init(&dwc->lock); 46972246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 47072246da4SFelipe Balbi 47172246da4SFelipe Balbi dwc->regs = regs; 47272246da4SFelipe Balbi dwc->regs_size = resource_size(res); 473802ca850SChanho Park dwc->dev = dev; 47472246da4SFelipe Balbi 4756c167fc9SFelipe Balbi if (!strncmp("super", maximum_speed, 5)) 4766c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4776c167fc9SFelipe Balbi else if (!strncmp("high", maximum_speed, 4)) 4786c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; 4796c167fc9SFelipe Balbi else if (!strncmp("full", maximum_speed, 4)) 4806c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; 4816c167fc9SFelipe Balbi else if (!strncmp("low", maximum_speed, 3)) 4826c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_LOWSPEED; 4836c167fc9SFelipe Balbi else 4846c167fc9SFelipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4856c167fc9SFelipe Balbi 486457e84b6SFelipe Balbi if (of_get_property(node, "tx-fifo-resize", NULL)) 487457e84b6SFelipe Balbi dwc->needs_fifo_resize = true; 488457e84b6SFelipe Balbi 489802ca850SChanho Park pm_runtime_enable(dev); 490802ca850SChanho Park pm_runtime_get_sync(dev); 491802ca850SChanho Park pm_runtime_forbid(dev); 49272246da4SFelipe Balbi 49372246da4SFelipe Balbi ret = dwc3_core_init(dwc); 49472246da4SFelipe Balbi if (ret) { 495802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 496802ca850SChanho Park return ret; 49772246da4SFelipe Balbi } 49872246da4SFelipe Balbi 4990949e99bSFelipe Balbi mode = DWC3_MODE(dwc->hwparams.hwparams0); 5000949e99bSFelipe Balbi 5010949e99bSFelipe Balbi switch (mode) { 5020949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 5033140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 50472246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 50572246da4SFelipe Balbi if (ret) { 506802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 507802ca850SChanho Park goto err1; 50872246da4SFelipe Balbi } 5090949e99bSFelipe Balbi break; 510d07e8819SFelipe Balbi case DWC3_MODE_HOST: 5113140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 512d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 513d07e8819SFelipe Balbi if (ret) { 514802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 515802ca850SChanho Park goto err1; 51672246da4SFelipe Balbi } 517d07e8819SFelipe Balbi break; 518d07e8819SFelipe Balbi case DWC3_MODE_DRD: 5193140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 520d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 521d07e8819SFelipe Balbi if (ret) { 522802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 523802ca850SChanho Park goto err1; 524d07e8819SFelipe Balbi } 525d07e8819SFelipe Balbi 526d07e8819SFelipe Balbi ret = dwc3_gadget_init(dwc); 527d07e8819SFelipe Balbi if (ret) { 528802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 529802ca850SChanho Park goto err1; 530d07e8819SFelipe Balbi } 531d07e8819SFelipe Balbi break; 5320949e99bSFelipe Balbi default: 533802ca850SChanho Park dev_err(dev, "Unsupported mode of operation %d\n", mode); 534802ca850SChanho Park goto err1; 53572246da4SFelipe Balbi } 5360949e99bSFelipe Balbi dwc->mode = mode; 53772246da4SFelipe Balbi 53872246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 53972246da4SFelipe Balbi if (ret) { 540802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 541802ca850SChanho Park goto err2; 54272246da4SFelipe Balbi } 54372246da4SFelipe Balbi 544802ca850SChanho Park pm_runtime_allow(dev); 54572246da4SFelipe Balbi 54672246da4SFelipe Balbi return 0; 54772246da4SFelipe Balbi 548802ca850SChanho Park err2: 5490949e99bSFelipe Balbi switch (mode) { 5500949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 55172246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5520949e99bSFelipe Balbi break; 553d07e8819SFelipe Balbi case DWC3_MODE_HOST: 554d07e8819SFelipe Balbi dwc3_host_exit(dwc); 555d07e8819SFelipe Balbi break; 556d07e8819SFelipe Balbi case DWC3_MODE_DRD: 557d07e8819SFelipe Balbi dwc3_host_exit(dwc); 558d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 559d07e8819SFelipe Balbi break; 5600949e99bSFelipe Balbi default: 5610949e99bSFelipe Balbi /* do nothing */ 5620949e99bSFelipe Balbi break; 5630949e99bSFelipe Balbi } 56472246da4SFelipe Balbi 565802ca850SChanho Park err1: 56672246da4SFelipe Balbi dwc3_core_exit(dwc); 56772246da4SFelipe Balbi 56872246da4SFelipe Balbi return ret; 56972246da4SFelipe Balbi } 57072246da4SFelipe Balbi 57172246da4SFelipe Balbi static int __devexit dwc3_remove(struct platform_device *pdev) 57272246da4SFelipe Balbi { 57372246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 57472246da4SFelipe Balbi struct resource *res; 57572246da4SFelipe Balbi 57672246da4SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 57772246da4SFelipe Balbi 57872246da4SFelipe Balbi pm_runtime_put(&pdev->dev); 57972246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 58072246da4SFelipe Balbi 58172246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 58272246da4SFelipe Balbi 5830949e99bSFelipe Balbi switch (dwc->mode) { 5840949e99bSFelipe Balbi case DWC3_MODE_DEVICE: 58572246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5860949e99bSFelipe Balbi break; 587d07e8819SFelipe Balbi case DWC3_MODE_HOST: 588d07e8819SFelipe Balbi dwc3_host_exit(dwc); 589d07e8819SFelipe Balbi break; 590d07e8819SFelipe Balbi case DWC3_MODE_DRD: 591d07e8819SFelipe Balbi dwc3_host_exit(dwc); 592d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 593d07e8819SFelipe Balbi break; 5940949e99bSFelipe Balbi default: 5950949e99bSFelipe Balbi /* do nothing */ 5960949e99bSFelipe Balbi break; 5970949e99bSFelipe Balbi } 59872246da4SFelipe Balbi 59972246da4SFelipe Balbi dwc3_core_exit(dwc); 60072246da4SFelipe Balbi 60172246da4SFelipe Balbi return 0; 60272246da4SFelipe Balbi } 60372246da4SFelipe Balbi 60472246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 60572246da4SFelipe Balbi .probe = dwc3_probe, 60672246da4SFelipe Balbi .remove = __devexit_p(dwc3_remove), 60772246da4SFelipe Balbi .driver = { 60872246da4SFelipe Balbi .name = "dwc3", 60972246da4SFelipe Balbi }, 61072246da4SFelipe Balbi }; 61172246da4SFelipe Balbi 612b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 613b1116dccSTobias Klauser 6147ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 61572246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 61672246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL"); 61772246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 618