172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com 572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Authors: Felipe Balbi <balbi@ti.com>, 772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Redistribution and use in source and binary forms, with or without 1072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * modification, are permitted provided that the following conditions 1172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * are met: 1272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 1. Redistributions of source code must retain the above copyright 1372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * notice, this list of conditions, and the following disclaimer, 1472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * without modification. 1572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 2. Redistributions in binary form must reproduce the above copyright 1672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * notice, this list of conditions and the following disclaimer in the 1772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * documentation and/or other materials provided with the distribution. 1872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 3. The names of the above-listed copyright holders may not be used 1972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * to endorse or promote products derived from this software without 2072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * specific prior written permission. 2172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 2272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * ALTERNATIVELY, this software may be distributed under the terms of the 2372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * GNU General Public License ("GPL") version 2, as published by the Free 2472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Software Foundation. 2572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 2672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 2772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 3072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 3172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 3272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 3872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 39a72e658bcdddead01b8a3580124debe60eb2aca8Felipe Balbi#include <linux/module.h> 4072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/kernel.h> 4172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/slab.h> 4272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/spinlock.h> 4372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/platform_device.h> 4472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/pm_runtime.h> 4572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/interrupt.h> 4672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/ioport.h> 4772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/io.h> 4872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/list.h> 4972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/delay.h> 5072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/dma-mapping.h> 5172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 5272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/usb/ch9.h> 5372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include <linux/usb/gadget.h> 542204fdee84eba175d58b6f78a9659dcd7806f532Paul Gortmaker#include <linux/module.h> 5572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 5672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include "core.h" 5772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include "gadget.h" 5872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include "io.h" 5972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 6072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#include "debug.h" 6172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 626c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbistatic char *maximum_speed = "super"; 636c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbimodule_param(maximum_speed, charp, 0); 646c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe BalbiMODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); 656c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi 668300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi/* -------------------------------------------------------------------------- */ 678300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 688300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi#define DWC3_DEVS_POSSIBLE 32 698300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 708300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbistatic DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE); 718300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 728300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbiint dwc3_get_device_id(void) 738300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi{ 748300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi int id; 758300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 768300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbiagain: 778300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE); 788300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi if (id < DWC3_DEVS_POSSIBLE) { 798300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi int old; 808300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 818300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi old = test_and_set_bit(id, dwc3_devs); 828300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi if (old) 838300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi goto again; 848300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi } else { 858300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi pr_err("dwc3: no space for new device\n"); 868300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi id = -ENOMEM; 878300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi } 888300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 898300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi return 0; 908300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi} 918300dd236e957429acfb36be0ce8fe276dbe823cFelipe BalbiEXPORT_SYMBOL_GPL(dwc3_get_device_id); 928300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 938300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbivoid dwc3_put_device_id(int id) 948300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi{ 958300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi int ret; 968300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 978300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi if (id < 0) 988300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi return; 998300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 1008300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi ret = test_bit(id, dwc3_devs); 1018300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi WARN(!ret, "dwc3: ID %d not in use\n", id); 1028300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi clear_bit(id, dwc3_devs); 1038300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi} 1048300dd236e957429acfb36be0ce8fe276dbe823cFelipe BalbiEXPORT_SYMBOL_GPL(dwc3_put_device_id); 1058300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 1063140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewiorvoid dwc3_set_mode(struct dwc3 *dwc, u32 mode) 1073140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior{ 1083140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior u32 reg; 1093140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior 1103140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 1113140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 1123140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 1133140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 1143140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior} 1158300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 11672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 11772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 11872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: pointer to our context structure 11972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 12072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_core_soft_reset(struct dwc3 *dwc) 12172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 12272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi u32 reg; 12372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 12472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Before Resetting PHY, put Core in Reset */ 12572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 12672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 12772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 12872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 12972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Assert USB3 PHY reset */ 13072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 13172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 13272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 13372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 13472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Assert USB2 PHY reset */ 13572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 13672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 13772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 13872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 13972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi mdelay(100); 14072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 14172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Clear USB3 PHY reset */ 14272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 14372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 14472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 14572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 14672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Clear USB2 PHY reset */ 14772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 14872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 14972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 15072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 15172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* After PHYs are stable we can take Core out of reset state */ 15272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 15372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 15472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 15572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 15672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 15772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 15872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 15972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 16072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @evt: Pointer to event buffer to be freed 16172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 16272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_free_one_event_buffer(struct dwc3 *dwc, 16372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt) 16472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 16572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 16672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(evt); 16772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 16872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 16972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 17072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_alloc_one_event_buffer - Allocated one event buffer structure 17172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 17272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @length: size of the event buffer 17372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 17472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns a pointer to the allocated event buffer structure on succes 17572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * otherwise ERR_PTR(errno). 17672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 17772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic struct dwc3_event_buffer *__devinit 17872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbidwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) 17972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 18072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 18172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 18272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = kzalloc(sizeof(*evt), GFP_KERNEL); 18372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!evt) 18472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ERR_PTR(-ENOMEM); 18572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 18672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->dwc = dwc; 18772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length = length; 18872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 18972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi &evt->dma, GFP_KERNEL); 19072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!evt->buf) { 19172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(evt); 19272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ERR_PTR(-ENOMEM); 19372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 19472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 19572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return evt; 19672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 19772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 19872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 19972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 20072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 20172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 20272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_free_event_buffers(struct dwc3 *dwc) 20372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 20472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 20572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int i; 20672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2079f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 20872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[i]; 20972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (evt) { 21072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_one_event_buffer(dwc, evt); 21172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->ev_buffs[i] = NULL; 21272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 21372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 21472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 21572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 21672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 21772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 21872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to out controller context structure 21972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @length: size of event buffer 22072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 22172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. In error the case, dwc 22272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * may contain some buffers allocated but not all which were requested. 22372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 2249f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbistatic int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 22572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 2269f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi int num; 22772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int i; 22872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2299f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 2309f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi dwc->num_event_buffers = num; 2319f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi 232457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); 233457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi if (!dwc->ev_buffs) { 234457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi dev_err(dwc->dev, "can't allocate event buffers array\n"); 235457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi return -ENOMEM; 236457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi } 237457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi 23872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi for (i = 0; i < num; i++) { 23972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 24072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 24172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 24272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (IS_ERR(evt)) { 24372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 24472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return PTR_ERR(evt); 24572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 24672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->ev_buffs[i] = evt; 24772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 24872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 24972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 25072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 25172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 25272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 25372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 25472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to out controller context structure 25572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 25672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. 25772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 25872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) 25972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 26072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 26172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int n; 26272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2639f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 26472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[n]; 26572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 26672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->buf, (unsigned long long) evt->dma, 26772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length); 26872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 26972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 27072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi lower_32_bits(evt->dma)); 27172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 27272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi upper_32_bits(evt->dma)); 27372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 27472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length & 0xffff); 27572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 27672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 27772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 27872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 27972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 28072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 28172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 28272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 28372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 28472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int n; 28572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2869f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 28772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[n]; 28872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 28972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 29072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 29172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 29272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 29372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 29472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 29526ceca9750260997ab82bb84dac122de1e441658Felipe Balbistatic void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) 29626ceca9750260997ab82bb84dac122de1e441658Felipe Balbi{ 29726ceca9750260997ab82bb84dac122de1e441658Felipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 29826ceca9750260997ab82bb84dac122de1e441658Felipe Balbi 29926ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 30026ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 30126ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 30226ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 30326ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 30426ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 30526ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 30626ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 30726ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 30826ceca9750260997ab82bb84dac122de1e441658Felipe Balbi} 30926ceca9750260997ab82bb84dac122de1e441658Felipe Balbi 31072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 31172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 31272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 31372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 31472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. 31572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 31672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_core_init(struct dwc3 *dwc) 31772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 31872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi unsigned long timeout; 31972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi u32 reg; 32072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int ret; 32172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 3227650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3237650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3247650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3257650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3267650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior ret = -ENODEV; 3277650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior goto err0; 3287650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior } 329248b122b131202de95aaa3670e48465619bdff14Felipe Balbi dwc->revision = reg; 3307650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior 33172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_soft_reset(dwc); 33272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 33372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* issue device SoftReset too */ 33472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi timeout = jiffies + msecs_to_jiffies(500); 33572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 33672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi do { 33772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 33872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 33972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi break; 34072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 34172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (time_after(jiffies, timeout)) { 34272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 34372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = -ETIMEDOUT; 34472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err0; 34572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 34672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 34772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi cpu_relax(); 34872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } while (true); 34972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 3509f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi dwc3_cache_hwparams(dwc); 3519f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi 3524878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 3534878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior reg &= ~DWC3_GCTL_SCALEDOWN(3); 3544878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 3554878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior 356164d773168d7f09ecd46d9ce9b07f194ea97bf33Sebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 3574878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 3584878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 3594878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior break; 3604878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior default: 3614878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 3624878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior } 3634878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior 3644878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior /* 3654878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 3664878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior * when The device fails to connect at SuperSpeed 3674878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior * and falls back to high-speed mode which causes 3684878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior * the device to enter in a Connect/Disconnect loop 3694878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior */ 3704878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 3714878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 3724878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior 3734878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 3744878a02898bab1a988206341e529997cb46e5f29Sebastian Andrzej Siewior 3759f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 37672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 37772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 37872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = -ENOMEM; 37972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 38072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 38172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 38272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_event_buffers_setup(dwc); 38372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 38472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 38572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 38672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 38772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 38872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 38972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 39072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr1: 39172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_event_buffers(dwc); 39272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 39372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr0: 39472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ret; 39572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 39672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 39772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_core_exit(struct dwc3 *dwc) 39872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 39972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_event_buffers_cleanup(dwc); 40072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_event_buffers(dwc); 40172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 40272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 40372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#define DWC3_ALIGN_MASK (16 - 1) 40472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 40572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_probe(struct platform_device *pdev) 40672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 40772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct resource *res; 40872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3 *dwc; 4090949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 41072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int ret = -ENOMEM; 41172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int irq; 4120949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 4130949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi void __iomem *regs; 41472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi void *mem; 41572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 4160949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi u8 mode; 4170949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 41872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 41972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!mem) { 42072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "not enough memory\n"); 42172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err0; 42272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 42372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 42472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->mem = mem; 42572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 42672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 42772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!res) { 42872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "missing resource\n"); 42972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 43072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 43172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 432d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc->res = res; 433d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi 43472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = request_mem_region(res->start, resource_size(res), 43572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_name(&pdev->dev)); 43672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!res) { 43772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "can't request mem region\n"); 43872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 43972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 44072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 44172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi regs = ioremap(res->start, resource_size(res)); 44272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!regs) { 44372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "ioremap failed\n"); 44472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err2; 44572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 44672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 44772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi irq = platform_get_irq(pdev, 0); 44872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (irq < 0) { 44972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "missing IRQ\n"); 45072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err3; 45172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 45272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 45372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi spin_lock_init(&dwc->lock); 45472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi platform_set_drvdata(pdev, dwc); 45572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 45672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->regs = regs; 45772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->regs_size = resource_size(res); 45872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->dev = &pdev->dev; 45972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->irq = irq; 46072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 4616c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi if (!strncmp("super", maximum_speed, 5)) 4626c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4636c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("high", maximum_speed, 4)) 4646c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; 4656c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("full", maximum_speed, 4)) 4666c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; 4676c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("low", maximum_speed, 3)) 4686c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_LOWSPEED; 4696c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else 4706c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4716c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi 47272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_enable(&pdev->dev); 47372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_get_sync(&pdev->dev); 47472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_forbid(&pdev->dev); 47572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 47672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_core_init(dwc); 47772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 47872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "failed to initialize core\n"); 47972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err3; 48072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 48172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 4820949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi mode = DWC3_MODE(dwc->hwparams.hwparams0); 4830949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 4840949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (mode) { 4850949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 4863140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 48772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_gadget_init(dwc); 48872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 4890949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dev_err(&pdev->dev, "failed to initialize gadget\n"); 49072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err4; 49172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 4920949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 493d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 4943140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 495d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_host_init(dwc); 496d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 497d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize host\n"); 498d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 499d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 500d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 501d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 5023140e8cbfec18ecb9c9ef856933fdb98c09af1e8Sebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 503d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_host_init(dwc); 504d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 505d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize host\n"); 506d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 507d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 508d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi 509d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_gadget_init(dwc); 510d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 511d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize gadget\n"); 512d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 513d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 514d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 5150949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 5160949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode); 5170949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi goto err4; 51872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 5190949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dwc->mode = mode; 52072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_debugfs_init(dwc); 52272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 52372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "failed to initialize debugfs\n"); 52472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err5; 52572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 52672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_allow(&pdev->dev); 52872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 53072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 53172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr5: 5320949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (mode) { 5330949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 53472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 5350949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 536d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 537d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 538d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 539d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 540d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 54172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 542d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 5430949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 5440949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi /* do nothing */ 5450949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 5460949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi } 54772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 54872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr4: 54972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_exit(dwc); 55072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 55172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr3: 55272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi iounmap(regs); 55372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 55472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr2: 55572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi release_mem_region(res->start, resource_size(res)); 55672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 55772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr1: 55872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(dwc->mem); 55972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 56072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr0: 56172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ret; 56272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 56372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 56472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devexit dwc3_remove(struct platform_device *pdev) 56572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 56672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 56772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct resource *res; 56872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 56972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 57072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 57172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_put(&pdev->dev); 57272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_disable(&pdev->dev); 57372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 57472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_debugfs_exit(dwc); 57572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 5760949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (dwc->mode) { 5770949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 57872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 5790949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 580d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 581d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 582d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 583d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 584d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 58572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 586d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 5870949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 5880949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi /* do nothing */ 5890949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 5900949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi } 59172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 59272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_exit(dwc); 59372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi release_mem_region(res->start, resource_size(res)); 59472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi iounmap(dwc->regs); 59572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(dwc->mem); 59672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 59772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 59872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 59972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 60072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic struct platform_driver dwc3_driver = { 60172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .probe = dwc3_probe, 60272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .remove = __devexit_p(dwc3_remove), 60372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .driver = { 60472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .name = "dwc3", 60572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi }, 60672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi}; 60772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 6087ae4fc4dc835033067096639bd26416b3df744c7Sebastian Andrzej SiewiorMODULE_ALIAS("platform:dwc3"); 60972246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 61072246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_LICENSE("Dual BSD/GPL"); 61172246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 61272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 61372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_init(void) 61472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 61572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return platform_driver_register(&dwc3_driver); 61672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 61772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbimodule_init(dwc3_init); 61872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 61972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void __exit dwc3_exit(void) 62072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 62172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi platform_driver_unregister(&dwc3_driver); 62272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 62372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbimodule_exit(dwc3_exit); 624