core.c revision 457d3f214f97783c392dd4d64e2427c121b1a4d6
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 1068300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi/* -------------------------------------------------------------------------- */ 1078300dd236e957429acfb36be0ce8fe276dbe823cFelipe Balbi 10872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 10972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 11072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: pointer to our context structure 11172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 11272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_core_soft_reset(struct dwc3 *dwc) 11372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 11472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi u32 reg; 11572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 11672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Before Resetting PHY, put Core in Reset */ 11772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 11872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 11972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 12072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 12172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Assert USB3 PHY reset */ 12272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 12372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 12472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 12572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 12672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Assert USB2 PHY reset */ 12772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 12872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 12972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 13072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 13172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi mdelay(100); 13272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 13372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Clear USB3 PHY reset */ 13472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 13572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 13672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 13772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 13872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* Clear USB2 PHY reset */ 13972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 14072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 14172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 14272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 14372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* After PHYs are stable we can take Core out of reset state */ 14472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 14572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 14672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 14772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 14872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 14972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 15072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 15172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 15272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @evt: Pointer to event buffer to be freed 15372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 15472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_free_one_event_buffer(struct dwc3 *dwc, 15572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt) 15672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 15772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 15872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(evt); 15972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 16072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 16172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 16272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_alloc_one_event_buffer - Allocated one event buffer structure 16372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 16472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @length: size of the event buffer 16572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 16672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns a pointer to the allocated event buffer structure on succes 16772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * otherwise ERR_PTR(errno). 16872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 16972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic struct dwc3_event_buffer *__devinit 17072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbidwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) 17172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 17272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 17372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 17472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = kzalloc(sizeof(*evt), GFP_KERNEL); 17572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!evt) 17672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ERR_PTR(-ENOMEM); 17772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 17872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->dwc = dwc; 17972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length = length; 18072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 18172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi &evt->dma, GFP_KERNEL); 18272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!evt->buf) { 18372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(evt); 18472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ERR_PTR(-ENOMEM); 18572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 18672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 18772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return evt; 18872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 18972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 19072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 19172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 19272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 19372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 19472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_free_event_buffers(struct dwc3 *dwc) 19572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 19672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 19772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int i; 19872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 1999f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 20072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[i]; 20172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (evt) { 20272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_one_event_buffer(dwc, evt); 20372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->ev_buffs[i] = NULL; 20472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 20572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 20672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 20772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 20872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 20972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 21072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to out controller context structure 21172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @length: size of event buffer 21272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 21372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. In error the case, dwc 21472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * may contain some buffers allocated but not all which were requested. 21572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 2169f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbistatic int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 21772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 2189f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi int num; 21972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int i; 22072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2219f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 2229f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi dwc->num_event_buffers = num; 2239f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi 224457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); 225457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi if (!dwc->ev_buffs) { 226457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi dev_err(dwc->dev, "can't allocate event buffers array\n"); 227457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi return -ENOMEM; 228457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi } 229457d3f214f97783c392dd4d64e2427c121b1a4d6Felipe Balbi 23072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi for (i = 0; i < num; i++) { 23172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 23272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 23372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 23472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (IS_ERR(evt)) { 23572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 23672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return PTR_ERR(evt); 23772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 23872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->ev_buffs[i] = evt; 23972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 24072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 24172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 24272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 24372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 24472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 24572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 24672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to out controller context structure 24772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 24872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. 24972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 25072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) 25172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 25272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 25372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int n; 25472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2559f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 25672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[n]; 25772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 25872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->buf, (unsigned long long) evt->dma, 25972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length); 26072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 26172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 26272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi lower_32_bits(evt->dma)); 26372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 26472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi upper_32_bits(evt->dma)); 26572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 26672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt->length & 0xffff); 26772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 26872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 26972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 27072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 27172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 27272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 27372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 27472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 27572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3_event_buffer *evt; 27672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int n; 27772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 2789f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 27972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi evt = dwc->ev_buffs[n]; 28072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 28172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 28272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); 28372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 28472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 28572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 28672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 28726ceca9750260997ab82bb84dac122de1e441658Felipe Balbistatic void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) 28826ceca9750260997ab82bb84dac122de1e441658Felipe Balbi{ 28926ceca9750260997ab82bb84dac122de1e441658Felipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 29026ceca9750260997ab82bb84dac122de1e441658Felipe Balbi 29126ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 29226ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 29326ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 29426ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 29526ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 29626ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 29726ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 29826ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 29926ceca9750260997ab82bb84dac122de1e441658Felipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 30026ceca9750260997ab82bb84dac122de1e441658Felipe Balbi} 30126ceca9750260997ab82bb84dac122de1e441658Felipe Balbi 30272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi/** 30372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 30472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * @dwc: Pointer to our controller context structure 30572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * 30672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi * Returns 0 on success otherwise negative errno. 30772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi */ 30872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_core_init(struct dwc3 *dwc) 30972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 31072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi unsigned long timeout; 31172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi u32 reg; 31272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int ret; 31372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 3147650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3157650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3167650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3177650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3187650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior ret = -ENODEV; 3197650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior goto err0; 3207650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior } 3217650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior dwc->revision = reg & DWC3_GSNPSREV_MASK; 3227650bd74d3441907867276dc381b2ee0dc355c65Sebastian Andrzej Siewior 32372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_soft_reset(dwc); 32472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 32572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi /* issue device SoftReset too */ 32672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi timeout = jiffies + msecs_to_jiffies(500); 32772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 32872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi do { 32972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 33072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 33172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi break; 33272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 33372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (time_after(jiffies, timeout)) { 33472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 33572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = -ETIMEDOUT; 33672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err0; 33772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 33872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 33972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi cpu_relax(); 34072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } while (true); 34172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 3429f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi dwc3_cache_hwparams(dwc); 3439f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi 3449f622b2a407d8b34a5a7f5b4abd8b29b25cf4f32Felipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 34572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 34672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 34772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = -ENOMEM; 34872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 34972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 35072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 35172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_event_buffers_setup(dwc); 35272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 35372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 35472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 35572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 35672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 35772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 35872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 35972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr1: 36072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_event_buffers(dwc); 36172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 36272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr0: 36372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ret; 36472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 36572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 36672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void dwc3_core_exit(struct dwc3 *dwc) 36772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 36872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_event_buffers_cleanup(dwc); 36972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_free_event_buffers(dwc); 37072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 37172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 37272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi#define DWC3_ALIGN_MASK (16 - 1) 37372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 37472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_probe(struct platform_device *pdev) 37572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 37672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct resource *res; 37772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3 *dwc; 3780949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 37972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int ret = -ENOMEM; 38072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi int irq; 3810949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 3820949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi void __iomem *regs; 38372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi void *mem; 38472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 3850949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi u8 mode; 3860949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 38772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 38872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!mem) { 38972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "not enough memory\n"); 39072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err0; 39172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 39272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 39372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->mem = mem; 39472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 39572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 39672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!res) { 39772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "missing resource\n"); 39872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 39972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 40072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 401d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc->res = res; 402d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi 40372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = request_mem_region(res->start, resource_size(res), 40472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_name(&pdev->dev)); 40572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!res) { 40672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "can't request mem region\n"); 40772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err1; 40872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 40972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 41072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi regs = ioremap(res->start, resource_size(res)); 41172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (!regs) { 41272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "ioremap failed\n"); 41372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err2; 41472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 41572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 41672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi irq = platform_get_irq(pdev, 0); 41772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (irq < 0) { 41872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "missing IRQ\n"); 41972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err3; 42072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 42172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 42272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi spin_lock_init(&dwc->lock); 42372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi platform_set_drvdata(pdev, dwc); 42472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 42572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->regs = regs; 42672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->regs_size = resource_size(res); 42772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->dev = &pdev->dev; 42872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc->irq = irq; 42972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 4306c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi if (!strncmp("super", maximum_speed, 5)) 4316c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4326c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("high", maximum_speed, 4)) 4336c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; 4346c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("full", maximum_speed, 4)) 4356c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; 4366c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else if (!strncmp("low", maximum_speed, 3)) 4376c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_LOWSPEED; 4386c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi else 4396c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 4406c167fc9b0c23ead791edb94cf4debb6b8e534b5Felipe Balbi 44172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_enable(&pdev->dev); 44272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_get_sync(&pdev->dev); 44372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_forbid(&pdev->dev); 44472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 44572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_core_init(dwc); 44672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 44772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "failed to initialize core\n"); 44872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err3; 44972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 45072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 4510949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi mode = DWC3_MODE(dwc->hwparams.hwparams0); 4520949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi 4530949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (mode) { 4540949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 45572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_gadget_init(dwc); 45672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 4570949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dev_err(&pdev->dev, "failed to initialize gadget\n"); 45872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err4; 45972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 4600949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 461d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 462d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_host_init(dwc); 463d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 464d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize host\n"); 465d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 466d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 467d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 468d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 469d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_host_init(dwc); 470d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 471d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize host\n"); 472d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 473d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 474d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi 475d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi ret = dwc3_gadget_init(dwc); 476d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi if (ret) { 477d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dev_err(&pdev->dev, "failed to initialize gadget\n"); 478d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi goto err4; 479d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi } 480d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 4810949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 4820949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode); 4830949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi goto err4; 48472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 4850949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi dwc->mode = mode; 48672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 48772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi ret = dwc3_debugfs_init(dwc); 48872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi if (ret) { 48972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dev_err(&pdev->dev, "failed to initialize debugfs\n"); 49072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi goto err5; 49172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi } 49272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 49372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_allow(&pdev->dev); 49472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 49572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 49672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 49772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr5: 4980949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (mode) { 4990949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 50072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 5010949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 502d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 503d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 504d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 505d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 506d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 507d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_gadget_exit(dwc); 508d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 5090949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 5100949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi /* do nothing */ 5110949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 5120949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi } 51372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 51472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr4: 51572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_exit(dwc); 51672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 51772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr3: 51872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi iounmap(regs); 51972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr2: 52172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi release_mem_region(res->start, resource_size(res)); 52272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr1: 52472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(dwc->mem); 52572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 52672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbierr0: 52772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return ret; 52872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 52972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 53072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devexit dwc3_remove(struct platform_device *pdev) 53172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 53272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 53372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi struct resource *res; 53472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 53572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 53672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 53772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_put(&pdev->dev); 53872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi pm_runtime_disable(&pdev->dev); 53972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 54072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_debugfs_exit(dwc); 54172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 5420949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi switch (dwc->mode) { 5430949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi case DWC3_MODE_DEVICE: 54472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_gadget_exit(dwc); 5450949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 546d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_HOST: 547d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 548d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 549d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi case DWC3_MODE_DRD: 550d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_host_exit(dwc); 551d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi dwc3_gadget_exit(dwc); 552d07e8819a03dc2d1f03f725194ae56544e6c680bFelipe Balbi break; 5530949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi default: 5540949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi /* do nothing */ 5550949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi break; 5560949e99b05736946cf0ac78e37194be0807e497eFelipe Balbi } 55772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 55872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi dwc3_core_exit(dwc); 55972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi release_mem_region(res->start, resource_size(res)); 56072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi iounmap(dwc->regs); 56172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi kfree(dwc->mem); 56272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 56372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return 0; 56472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 56572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 56672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic struct platform_driver dwc3_driver = { 56772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .probe = dwc3_probe, 56872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .remove = __devexit_p(dwc3_remove), 56972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .driver = { 57072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi .name = "dwc3", 57172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi }, 57272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi}; 57372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 5747ae4fc4dc835033067096639bd26416b3df744c7Sebastian Andrzej SiewiorMODULE_ALIAS("platform:dwc3"); 57572246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 57672246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_LICENSE("Dual BSD/GPL"); 57772246da40f3719af3bfd104a2365b32537c27d83Felipe BalbiMODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 57872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 57972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic int __devinit dwc3_init(void) 58072246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 58172246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi return platform_driver_register(&dwc3_driver); 58272246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 58372246da40f3719af3bfd104a2365b32537c27d83Felipe Balbimodule_init(dwc3_init); 58472246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi 58572246da40f3719af3bfd104a2365b32537c27d83Felipe Balbistatic void __exit dwc3_exit(void) 58672246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi{ 58772246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi platform_driver_unregister(&dwc3_driver); 58872246da40f3719af3bfd104a2365b32537c27d83Felipe Balbi} 58972246da40f3719af3bfd104a2365b32537c27d83Felipe Balbimodule_exit(dwc3_exit); 590