diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/usb/dwc3')
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/Kconfig | 28 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/Makefile | 47 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/core.c | 605 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/core.h | 784 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/debug.h | 50 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/debugfs.c | 710 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/dwc3-exynos.c | 151 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/dwc3-omap.c | 392 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/dwc3-pci.c | 173 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/ep0.c | 873 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/gadget.c | 2396 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/gadget.h | 187 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/host.c | 102 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/dwc3/io.h | 54 |
14 files changed, 0 insertions, 6552 deletions
diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/Kconfig b/ANDROID_3.4.5/drivers/usb/dwc3/Kconfig deleted file mode 100644 index d8f741f9..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/Kconfig +++ /dev/null @@ -1,28 +0,0 @@ -config USB_DWC3 - tristate "DesignWare USB3 DRD Core Support" - depends on (USB && USB_GADGET) - select USB_OTG_UTILS - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED - select USB_XHCI_PLATFORM - help - Say Y or M here if your system has a Dual Role SuperSpeed - USB controller based on the DesignWare USB3 IP Core. - - If you choose to build this driver is a dynamically linked - module, the module will be called dwc3.ko. - -if USB_DWC3 - -config USB_DWC3_DEBUG - bool "Enable Debugging Messages" - help - Say Y here to enable debugging messages on DWC3 Driver. - -config USB_DWC3_VERBOSE - bool "Enable Verbose Debugging Messages" - depends on USB_DWC3_DEBUG - help - Say Y here to enable verbose debugging messages on DWC3 Driver. - -endif diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/Makefile b/ANDROID_3.4.5/drivers/usb/dwc3/Makefile deleted file mode 100644 index d441fe4c..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG -ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG - -obj-$(CONFIG_USB_DWC3) += dwc3.o - -dwc3-y := core.o -dwc3-y += host.o -dwc3-y += gadget.o ep0.o - -ifneq ($(CONFIG_DEBUG_FS),) - dwc3-y += debugfs.o -endif - -## -# Platform-specific glue layers go here -# -# NOTICE: Make sure your glue layer doesn't depend on anything -# which is arch-specific and that it compiles on all situations. -# -# We want to keep this requirement in order to be able to compile -# the entire driver (with all its glue layers) on several architectures -# and make sure it compiles fine. This will also help with allmodconfig -# and allyesconfig builds. -# -# The only exception is the PCI glue layer, but that's only because -# PCI doesn't provide nops if CONFIG_PCI isn't enabled. -## - -obj-$(CONFIG_USB_DWC3) += dwc3-omap.o - -## -# REVISIT Samsung Exynos platform needs the clk API which isn't -# defined on all architectures. If we allow dwc3-exynos.c compile -# always we will fail the linking phase on those architectures -# which don't provide clk api implementation and that's unnaceptable. -# -# When Samsung's platform start supporting pm_runtime, this check -# for HAVE_CLK should be removed. -## -ifneq ($(CONFIG_HAVE_CLK),) - obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o -endif - -ifneq ($(CONFIG_PCI),) - obj-$(CONFIG_USB_DWC3) += dwc3-pci.o -endif - diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/core.c b/ANDROID_3.4.5/drivers/usb/dwc3/core.c deleted file mode 100644 index 99b58d84..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/core.c +++ /dev/null @@ -1,605 +0,0 @@ -/** - * core.c - DesignWare USB3 DRD Controller Core file - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/list.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/of.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include "core.h" -#include "gadget.h" -#include "io.h" - -#include "debug.h" - -static char *maximum_speed = "super"; -module_param(maximum_speed, charp, 0); -MODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); - -/* -------------------------------------------------------------------------- */ - -#define DWC3_DEVS_POSSIBLE 32 - -static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE); - -int dwc3_get_device_id(void) -{ - int id; - -again: - id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE); - if (id < DWC3_DEVS_POSSIBLE) { - int old; - - old = test_and_set_bit(id, dwc3_devs); - if (old) - goto again; - } else { - pr_err("dwc3: no space for new device\n"); - id = -ENOMEM; - } - - return id; -} -EXPORT_SYMBOL_GPL(dwc3_get_device_id); - -void dwc3_put_device_id(int id) -{ - int ret; - - if (id < 0) - return; - - ret = test_bit(id, dwc3_devs); - WARN(!ret, "dwc3: ID %d not in use\n", id); - clear_bit(id, dwc3_devs); -} -EXPORT_SYMBOL_GPL(dwc3_put_device_id); - -void dwc3_set_mode(struct dwc3 *dwc, u32 mode) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); - reg |= DWC3_GCTL_PRTCAPDIR(mode); - dwc3_writel(dwc->regs, DWC3_GCTL, reg); -} - -/** - * dwc3_core_soft_reset - Issues core soft reset and PHY reset - * @dwc: pointer to our context structure - */ -static void dwc3_core_soft_reset(struct dwc3 *dwc) -{ - u32 reg; - - /* Before Resetting PHY, put Core in Reset */ - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg |= DWC3_GCTL_CORESOFTRESET; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); - - /* Assert USB3 PHY reset */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); - - /* Assert USB2 PHY reset */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); - - mdelay(100); - - /* Clear USB3 PHY reset */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); - - /* Clear USB2 PHY reset */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); - - /* After PHYs are stable we can take Core out of reset state */ - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg &= ~DWC3_GCTL_CORESOFTRESET; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); -} - -/** - * dwc3_free_one_event_buffer - Frees one event buffer - * @dwc: Pointer to our controller context structure - * @evt: Pointer to event buffer to be freed - */ -static void dwc3_free_one_event_buffer(struct dwc3 *dwc, - struct dwc3_event_buffer *evt) -{ - dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); - kfree(evt); -} - -/** - * dwc3_alloc_one_event_buffer - Allocates one event buffer structure - * @dwc: Pointer to our controller context structure - * @length: size of the event buffer - * - * Returns a pointer to the allocated event buffer structure on success - * otherwise ERR_PTR(errno). - */ -static struct dwc3_event_buffer *__devinit -dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) -{ - struct dwc3_event_buffer *evt; - - evt = kzalloc(sizeof(*evt), GFP_KERNEL); - if (!evt) - return ERR_PTR(-ENOMEM); - - evt->dwc = dwc; - evt->length = length; - evt->buf = dma_alloc_coherent(dwc->dev, length, - &evt->dma, GFP_KERNEL); - if (!evt->buf) { - kfree(evt); - return ERR_PTR(-ENOMEM); - } - - return evt; -} - -/** - * dwc3_free_event_buffers - frees all allocated event buffers - * @dwc: Pointer to our controller context structure - */ -static void dwc3_free_event_buffers(struct dwc3 *dwc) -{ - struct dwc3_event_buffer *evt; - int i; - - for (i = 0; i < dwc->num_event_buffers; i++) { - evt = dwc->ev_buffs[i]; - if (evt) - dwc3_free_one_event_buffer(dwc, evt); - } - - kfree(dwc->ev_buffs); -} - -/** - * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length - * @dwc: pointer to our controller context structure - * @length: size of event buffer - * - * Returns 0 on success otherwise negative errno. In the error case, dwc - * may contain some buffers allocated but not all which were requested. - */ -static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) -{ - int num; - int i; - - num = DWC3_NUM_INT(dwc->hwparams.hwparams1); - dwc->num_event_buffers = num; - - dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); - if (!dwc->ev_buffs) { - dev_err(dwc->dev, "can't allocate event buffers array\n"); - return -ENOMEM; - } - - for (i = 0; i < num; i++) { - struct dwc3_event_buffer *evt; - - evt = dwc3_alloc_one_event_buffer(dwc, length); - if (IS_ERR(evt)) { - dev_err(dwc->dev, "can't allocate event buffer\n"); - return PTR_ERR(evt); - } - dwc->ev_buffs[i] = evt; - } - - return 0; -} - -/** - * dwc3_event_buffers_setup - setup our allocated event buffers - * @dwc: pointer to our controller context structure - * - * Returns 0 on success otherwise negative errno. - */ -static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc) -{ - struct dwc3_event_buffer *evt; - int n; - - for (n = 0; n < dwc->num_event_buffers; n++) { - evt = dwc->ev_buffs[n]; - dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", - evt->buf, (unsigned long long) evt->dma, - evt->length); - - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), - lower_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), - upper_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), - evt->length & 0xffff); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); - } - - return 0; -} - -static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) -{ - struct dwc3_event_buffer *evt; - int n; - - for (n = 0; n < dwc->num_event_buffers; n++) { - evt = dwc->ev_buffs[n]; - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); - } -} - -static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) -{ - struct dwc3_hwparams *parms = &dwc->hwparams; - - parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); - parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); - parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); - parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); - parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); - parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); - parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); - parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); - parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); -} - -/** - * dwc3_core_init - Low-level initialization of DWC3 Core - * @dwc: Pointer to our controller context structure - * - * Returns 0 on success otherwise negative errno. - */ -static int __devinit dwc3_core_init(struct dwc3 *dwc) -{ - unsigned long timeout; - u32 reg; - int ret; - - reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); - /* This should read as U3 followed by revision number */ - if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { - dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); - ret = -ENODEV; - goto err0; - } - dwc->revision = reg; - - dwc3_core_soft_reset(dwc); - - /* issue device SoftReset too */ - timeout = jiffies + msecs_to_jiffies(500); - dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); - do { - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (!(reg & DWC3_DCTL_CSFTRST)) - break; - - if (time_after(jiffies, timeout)) { - dev_err(dwc->dev, "Reset Timed Out\n"); - ret = -ETIMEDOUT; - goto err0; - } - - cpu_relax(); - } while (true); - - dwc3_cache_hwparams(dwc); - - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { - case DWC3_GHWPARAMS1_EN_PWROPT_CLK: - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - break; - default: - dev_dbg(dwc->dev, "No power optimization available\n"); - } - - /* - * WORKAROUND: DWC3 revisions <1.90a have a bug - * where the device can fail to connect at SuperSpeed - * and falls back to high-speed mode which causes - * the device to enter a Connect/Disconnect loop - */ - if (dwc->revision < DWC3_REVISION_190A) - reg |= DWC3_GCTL_U2RSTECN; - - dwc3_writel(dwc->regs, DWC3_GCTL, reg); - - ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); - if (ret) { - dev_err(dwc->dev, "failed to allocate event buffers\n"); - ret = -ENOMEM; - goto err1; - } - - ret = dwc3_event_buffers_setup(dwc); - if (ret) { - dev_err(dwc->dev, "failed to setup event buffers\n"); - goto err1; - } - - return 0; - -err1: - dwc3_free_event_buffers(dwc); - -err0: - return ret; -} - -static void dwc3_core_exit(struct dwc3 *dwc) -{ - dwc3_event_buffers_cleanup(dwc); - dwc3_free_event_buffers(dwc); -} - -#define DWC3_ALIGN_MASK (16 - 1) - -static int __devinit dwc3_probe(struct platform_device *pdev) -{ - struct device_node *node = pdev->dev.of_node; - struct resource *res; - struct dwc3 *dwc; - struct device *dev = &pdev->dev; - - int ret = -ENOMEM; - int irq; - - void __iomem *regs; - void *mem; - - u8 mode; - - mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); - if (!mem) { - dev_err(dev, "not enough memory\n"); - return -ENOMEM; - } - dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); - dwc->mem = mem; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "missing resource\n"); - return -ENODEV; - } - - dwc->res = res; - - res = devm_request_mem_region(dev, res->start, resource_size(res), - dev_name(dev)); - if (!res) { - dev_err(dev, "can't request mem region\n"); - return -ENOMEM; - } - - regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!regs) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "missing IRQ\n"); - return -ENODEV; - } - - spin_lock_init(&dwc->lock); - platform_set_drvdata(pdev, dwc); - - dwc->regs = regs; - dwc->regs_size = resource_size(res); - dwc->dev = dev; - dwc->irq = irq; - - if (!strncmp("super", maximum_speed, 5)) - dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; - else if (!strncmp("high", maximum_speed, 4)) - dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; - else if (!strncmp("full", maximum_speed, 4)) - dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; - else if (!strncmp("low", maximum_speed, 3)) - dwc->maximum_speed = DWC3_DCFG_LOWSPEED; - else - dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; - - if (of_get_property(node, "tx-fifo-resize", NULL)) - dwc->needs_fifo_resize = true; - - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - pm_runtime_forbid(dev); - - ret = dwc3_core_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize core\n"); - return ret; - } - - mode = DWC3_MODE(dwc->hwparams.hwparams0); - - switch (mode) { - case DWC3_MODE_DEVICE: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); - ret = dwc3_gadget_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize gadget\n"); - goto err1; - } - break; - case DWC3_MODE_HOST: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); - ret = dwc3_host_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - goto err1; - } - break; - case DWC3_MODE_DRD: - dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); - ret = dwc3_host_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - goto err1; - } - - ret = dwc3_gadget_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize gadget\n"); - goto err1; - } - break; - default: - dev_err(dev, "Unsupported mode of operation %d\n", mode); - goto err1; - } - dwc->mode = mode; - - ret = dwc3_debugfs_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize debugfs\n"); - goto err2; - } - - pm_runtime_allow(dev); - - return 0; - -err2: - switch (mode) { - case DWC3_MODE_DEVICE: - dwc3_gadget_exit(dwc); - break; - case DWC3_MODE_HOST: - dwc3_host_exit(dwc); - break; - case DWC3_MODE_DRD: - dwc3_host_exit(dwc); - dwc3_gadget_exit(dwc); - break; - default: - /* do nothing */ - break; - } - -err1: - dwc3_core_exit(dwc); - - return ret; -} - -static int __devexit dwc3_remove(struct platform_device *pdev) -{ - struct dwc3 *dwc = platform_get_drvdata(pdev); - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - - dwc3_debugfs_exit(dwc); - - switch (dwc->mode) { - case DWC3_MODE_DEVICE: - dwc3_gadget_exit(dwc); - break; - case DWC3_MODE_HOST: - dwc3_host_exit(dwc); - break; - case DWC3_MODE_DRD: - dwc3_host_exit(dwc); - dwc3_gadget_exit(dwc); - break; - default: - /* do nothing */ - break; - } - - dwc3_core_exit(dwc); - - return 0; -} - -static struct platform_driver dwc3_driver = { - .probe = dwc3_probe, - .remove = __devexit_p(dwc3_remove), - .driver = { - .name = "dwc3", - }, -}; - -module_platform_driver(dwc3_driver); - -MODULE_ALIAS("platform:dwc3"); -MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/core.h b/ANDROID_3.4.5/drivers/usb/dwc3/core.h deleted file mode 100644 index 6c7945b4..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/core.h +++ /dev/null @@ -1,784 +0,0 @@ -/** - * core.h - DesignWare USB3 DRD Core Header - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DRIVERS_USB_DWC3_CORE_H -#define __DRIVERS_USB_DWC3_CORE_H - -#include <linux/device.h> -#include <linux/spinlock.h> -#include <linux/ioport.h> -#include <linux/list.h> -#include <linux/dma-mapping.h> -#include <linux/mm.h> -#include <linux/debugfs.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -/* Global constants */ -#define DWC3_ENDPOINTS_NUM 32 - -#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE -#define DWC3_EVENT_TYPE_MASK 0xfe - -#define DWC3_EVENT_TYPE_DEV 0 -#define DWC3_EVENT_TYPE_CARKIT 3 -#define DWC3_EVENT_TYPE_I2C 4 - -#define DWC3_DEVICE_EVENT_DISCONNECT 0 -#define DWC3_DEVICE_EVENT_RESET 1 -#define DWC3_DEVICE_EVENT_CONNECT_DONE 2 -#define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE 3 -#define DWC3_DEVICE_EVENT_WAKEUP 4 -#define DWC3_DEVICE_EVENT_EOPF 6 -#define DWC3_DEVICE_EVENT_SOF 7 -#define DWC3_DEVICE_EVENT_ERRATIC_ERROR 9 -#define DWC3_DEVICE_EVENT_CMD_CMPL 10 -#define DWC3_DEVICE_EVENT_OVERFLOW 11 - -#define DWC3_GEVNTCOUNT_MASK 0xfffc -#define DWC3_GSNPSID_MASK 0xffff0000 -#define DWC3_GSNPSREV_MASK 0xffff - -/* Global Registers */ -#define DWC3_GSBUSCFG0 0xc100 -#define DWC3_GSBUSCFG1 0xc104 -#define DWC3_GTXTHRCFG 0xc108 -#define DWC3_GRXTHRCFG 0xc10c -#define DWC3_GCTL 0xc110 -#define DWC3_GEVTEN 0xc114 -#define DWC3_GSTS 0xc118 -#define DWC3_GSNPSID 0xc120 -#define DWC3_GGPIO 0xc124 -#define DWC3_GUID 0xc128 -#define DWC3_GUCTL 0xc12c -#define DWC3_GBUSERRADDR0 0xc130 -#define DWC3_GBUSERRADDR1 0xc134 -#define DWC3_GPRTBIMAP0 0xc138 -#define DWC3_GPRTBIMAP1 0xc13c -#define DWC3_GHWPARAMS0 0xc140 -#define DWC3_GHWPARAMS1 0xc144 -#define DWC3_GHWPARAMS2 0xc148 -#define DWC3_GHWPARAMS3 0xc14c -#define DWC3_GHWPARAMS4 0xc150 -#define DWC3_GHWPARAMS5 0xc154 -#define DWC3_GHWPARAMS6 0xc158 -#define DWC3_GHWPARAMS7 0xc15c -#define DWC3_GDBGFIFOSPACE 0xc160 -#define DWC3_GDBGLTSSM 0xc164 -#define DWC3_GPRTBIMAP_HS0 0xc180 -#define DWC3_GPRTBIMAP_HS1 0xc184 -#define DWC3_GPRTBIMAP_FS0 0xc188 -#define DWC3_GPRTBIMAP_FS1 0xc18c - -#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) -#define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) - -#define DWC3_GUSB2PHYACC(n) (0xc280 + (n * 0x04)) - -#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04)) - -#define DWC3_GTXFIFOSIZ(n) (0xc300 + (n * 0x04)) -#define DWC3_GRXFIFOSIZ(n) (0xc380 + (n * 0x04)) - -#define DWC3_GEVNTADRLO(n) (0xc400 + (n * 0x10)) -#define DWC3_GEVNTADRHI(n) (0xc404 + (n * 0x10)) -#define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10)) -#define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) - -#define DWC3_GHWPARAMS8 0xc600 - -/* Device Registers */ -#define DWC3_DCFG 0xc700 -#define DWC3_DCTL 0xc704 -#define DWC3_DEVTEN 0xc708 -#define DWC3_DSTS 0xc70c -#define DWC3_DGCMDPAR 0xc710 -#define DWC3_DGCMD 0xc714 -#define DWC3_DALEPENA 0xc720 -#define DWC3_DEPCMDPAR2(n) (0xc800 + (n * 0x10)) -#define DWC3_DEPCMDPAR1(n) (0xc804 + (n * 0x10)) -#define DWC3_DEPCMDPAR0(n) (0xc808 + (n * 0x10)) -#define DWC3_DEPCMD(n) (0xc80c + (n * 0x10)) - -/* OTG Registers */ -#define DWC3_OCFG 0xcc00 -#define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN 0xcc08 -#define DWC3_OSTS 0xcc0C - -/* Bit fields */ - -/* Global Configuration Register */ -#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) -#define DWC3_GCTL_U2RSTECN (1 << 16) -#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6) -#define DWC3_GCTL_CLK_BUS (0) -#define DWC3_GCTL_CLK_PIPE (1) -#define DWC3_GCTL_CLK_PIPEHALF (2) -#define DWC3_GCTL_CLK_MASK (3) - -#define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12) -#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) -#define DWC3_GCTL_PRTCAP_HOST 1 -#define DWC3_GCTL_PRTCAP_DEVICE 2 -#define DWC3_GCTL_PRTCAP_OTG 3 - -#define DWC3_GCTL_CORESOFTRESET (1 << 11) -#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) -#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) -#define DWC3_GCTL_DISSCRAMBLE (1 << 3) -#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) - -/* Global USB2 PHY Configuration Register */ -#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) -#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) - -/* Global USB3 PIPE Control Register */ -#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) -#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) - -/* Global TX Fifo Size Register */ -#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) -#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) - -/* Global HWPARAMS1 Register */ -#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) -#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 -#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 - -/* Device Configuration Register */ -#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) -#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) - -#define DWC3_DCFG_SPEED_MASK (7 << 0) -#define DWC3_DCFG_SUPERSPEED (4 << 0) -#define DWC3_DCFG_HIGHSPEED (0 << 0) -#define DWC3_DCFG_FULLSPEED2 (1 << 0) -#define DWC3_DCFG_LOWSPEED (2 << 0) -#define DWC3_DCFG_FULLSPEED1 (3 << 0) - -/* Device Control Register */ -#define DWC3_DCTL_RUN_STOP (1 << 31) -#define DWC3_DCTL_CSFTRST (1 << 30) -#define DWC3_DCTL_LSFTRST (1 << 29) - -#define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) -#define DWC3_DCTL_HIRD_THRES(n) (((n) & DWC3_DCTL_HIRD_THRES_MASK) >> 24) - -#define DWC3_DCTL_APPL1RES (1 << 23) - -#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) -#define DWC3_DCTL_TRGTULST(n) ((n) << 17) - -#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) -#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) -#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) -#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) -#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) - -#define DWC3_DCTL_INITU2ENA (1 << 12) -#define DWC3_DCTL_ACCEPTU2ENA (1 << 11) -#define DWC3_DCTL_INITU1ENA (1 << 10) -#define DWC3_DCTL_ACCEPTU1ENA (1 << 9) -#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1) - -#define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5) -#define DWC3_DCTL_ULSTCHNGREQ(n) (((n) << 5) & DWC3_DCTL_ULSTCHNGREQ_MASK) - -#define DWC3_DCTL_ULSTCHNG_NO_ACTION (DWC3_DCTL_ULSTCHNGREQ(0)) -#define DWC3_DCTL_ULSTCHNG_SS_DISABLED (DWC3_DCTL_ULSTCHNGREQ(4)) -#define DWC3_DCTL_ULSTCHNG_RX_DETECT (DWC3_DCTL_ULSTCHNGREQ(5)) -#define DWC3_DCTL_ULSTCHNG_SS_INACTIVE (DWC3_DCTL_ULSTCHNGREQ(6)) -#define DWC3_DCTL_ULSTCHNG_RECOVERY (DWC3_DCTL_ULSTCHNGREQ(8)) -#define DWC3_DCTL_ULSTCHNG_COMPLIANCE (DWC3_DCTL_ULSTCHNGREQ(10)) -#define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11)) - -/* Device Event Enable Register */ -#define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12) -#define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11) -#define DWC3_DEVTEN_CMDCMPLTEN (1 << 10) -#define DWC3_DEVTEN_ERRTICERREN (1 << 9) -#define DWC3_DEVTEN_SOFEN (1 << 7) -#define DWC3_DEVTEN_EOPFEN (1 << 6) -#define DWC3_DEVTEN_WKUPEVTEN (1 << 4) -#define DWC3_DEVTEN_ULSTCNGEN (1 << 3) -#define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) -#define DWC3_DEVTEN_USBRSTEN (1 << 1) -#define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) - -/* Device Status Register */ -#define DWC3_DSTS_PWRUPREQ (1 << 24) -#define DWC3_DSTS_COREIDLE (1 << 23) -#define DWC3_DSTS_DEVCTRLHLT (1 << 22) - -#define DWC3_DSTS_USBLNKST_MASK (0x0f << 18) -#define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18) - -#define DWC3_DSTS_RXFIFOEMPTY (1 << 17) - -#define DWC3_DSTS_SOFFN_MASK (0x3ff << 3) -#define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) - -#define DWC3_DSTS_CONNECTSPD (7 << 0) - -#define DWC3_DSTS_SUPERSPEED (4 << 0) -#define DWC3_DSTS_HIGHSPEED (0 << 0) -#define DWC3_DSTS_FULLSPEED2 (1 << 0) -#define DWC3_DSTS_LOWSPEED (2 << 0) -#define DWC3_DSTS_FULLSPEED1 (3 << 0) - -/* Device Generic Command Register */ -#define DWC3_DGCMD_SET_LMP 0x01 -#define DWC3_DGCMD_SET_PERIODIC_PAR 0x02 -#define DWC3_DGCMD_XMIT_FUNCTION 0x03 -#define DWC3_DGCMD_SELECTED_FIFO_FLUSH 0x09 -#define DWC3_DGCMD_ALL_FIFO_FLUSH 0x0a -#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c -#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 - -/* Device Endpoint Command Register */ -#define DWC3_DEPCMD_PARAM_SHIFT 16 -#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) -#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) -#define DWC3_DEPCMD_STATUS_MASK (0x0f << 12) -#define DWC3_DEPCMD_STATUS(x) (((x) & DWC3_DEPCMD_STATUS_MASK) >> 12) -#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) -#define DWC3_DEPCMD_CMDACT (1 << 10) -#define DWC3_DEPCMD_CMDIOC (1 << 8) - -#define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0) -#define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0) -#define DWC3_DEPCMD_UPDATETRANSFER (0x07 << 0) -#define DWC3_DEPCMD_STARTTRANSFER (0x06 << 0) -#define DWC3_DEPCMD_CLEARSTALL (0x05 << 0) -#define DWC3_DEPCMD_SETSTALL (0x04 << 0) -#define DWC3_DEPCMD_GETSEQNUMBER (0x03 << 0) -#define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) -#define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) - -/* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ -#define DWC3_DALEPENA_EP(n) (1 << n) - -#define DWC3_DEPCMD_TYPE_CONTROL 0 -#define DWC3_DEPCMD_TYPE_ISOC 1 -#define DWC3_DEPCMD_TYPE_BULK 2 -#define DWC3_DEPCMD_TYPE_INTR 3 - -/* Structures */ - -struct dwc3_trb; - -/** - * struct dwc3_event_buffer - Software event buffer representation - * @list: a list of event buffers - * @buf: _THE_ buffer - * @length: size of this buffer - * @dma: dma_addr_t - * @dwc: pointer to DWC controller - */ -struct dwc3_event_buffer { - void *buf; - unsigned length; - unsigned int lpos; - - dma_addr_t dma; - - struct dwc3 *dwc; -}; - -#define DWC3_EP_FLAG_STALLED (1 << 0) -#define DWC3_EP_FLAG_WEDGED (1 << 1) - -#define DWC3_EP_DIRECTION_TX true -#define DWC3_EP_DIRECTION_RX false - -#define DWC3_TRB_NUM 32 -#define DWC3_TRB_MASK (DWC3_TRB_NUM - 1) - -/** - * struct dwc3_ep - device side endpoint representation - * @endpoint: usb endpoint - * @request_list: list of requests for this endpoint - * @req_queued: list of requests on this ep which have TRBs setup - * @trb_pool: array of transaction buffers - * @trb_pool_dma: dma address of @trb_pool - * @free_slot: next slot which is going to be used - * @busy_slot: first slot which is owned by HW - * @desc: usb_endpoint_descriptor pointer - * @dwc: pointer to DWC controller - * @flags: endpoint flags (wedged, stalled, ...) - * @current_trb: index of current used trb - * @number: endpoint number (1 - 15) - * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK - * @res_trans_idx: Resource transfer index - * @interval: the intervall on which the ISOC transfer is started - * @name: a human readable name e.g. ep1out-bulk - * @direction: true for TX, false for RX - * @stream_capable: true when streams are enabled - */ -struct dwc3_ep { - struct usb_ep endpoint; - struct list_head request_list; - struct list_head req_queued; - - struct dwc3_trb *trb_pool; - dma_addr_t trb_pool_dma; - u32 free_slot; - u32 busy_slot; - const struct usb_endpoint_descriptor *desc; - const struct usb_ss_ep_comp_descriptor *comp_desc; - struct dwc3 *dwc; - - unsigned flags; -#define DWC3_EP_ENABLED (1 << 0) -#define DWC3_EP_STALL (1 << 1) -#define DWC3_EP_WEDGE (1 << 2) -#define DWC3_EP_BUSY (1 << 4) -#define DWC3_EP_PENDING_REQUEST (1 << 5) - - /* This last one is specific to EP0 */ -#define DWC3_EP0_DIR_IN (1 << 31) - - unsigned current_trb; - - u8 number; - u8 type; - u8 res_trans_idx; - u32 interval; - - char name[20]; - - unsigned direction:1; - unsigned stream_capable:1; -}; - -enum dwc3_phy { - DWC3_PHY_UNKNOWN = 0, - DWC3_PHY_USB3, - DWC3_PHY_USB2, -}; - -enum dwc3_ep0_next { - DWC3_EP0_UNKNOWN = 0, - DWC3_EP0_COMPLETE, - DWC3_EP0_NRDY_SETUP, - DWC3_EP0_NRDY_DATA, - DWC3_EP0_NRDY_STATUS, -}; - -enum dwc3_ep0_state { - EP0_UNCONNECTED = 0, - EP0_SETUP_PHASE, - EP0_DATA_PHASE, - EP0_STATUS_PHASE, -}; - -enum dwc3_link_state { - /* In SuperSpeed */ - DWC3_LINK_STATE_U0 = 0x00, /* in HS, means ON */ - DWC3_LINK_STATE_U1 = 0x01, - DWC3_LINK_STATE_U2 = 0x02, /* in HS, means SLEEP */ - DWC3_LINK_STATE_U3 = 0x03, /* in HS, means SUSPEND */ - DWC3_LINK_STATE_SS_DIS = 0x04, - DWC3_LINK_STATE_RX_DET = 0x05, /* in HS, means Early Suspend */ - DWC3_LINK_STATE_SS_INACT = 0x06, - DWC3_LINK_STATE_POLL = 0x07, - DWC3_LINK_STATE_RECOV = 0x08, - DWC3_LINK_STATE_HRESET = 0x09, - DWC3_LINK_STATE_CMPLY = 0x0a, - DWC3_LINK_STATE_LPBK = 0x0b, - DWC3_LINK_STATE_MASK = 0x0f, -}; - -enum dwc3_device_state { - DWC3_DEFAULT_STATE, - DWC3_ADDRESS_STATE, - DWC3_CONFIGURED_STATE, -}; - -/* TRB Length, PCM and Status */ -#define DWC3_TRB_SIZE_MASK (0x00ffffff) -#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) -#define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24) -#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28) >> 28)) - -#define DWC3_TRBSTS_OK 0 -#define DWC3_TRBSTS_MISSED_ISOC 1 -#define DWC3_TRBSTS_SETUP_PENDING 2 - -/* TRB Control */ -#define DWC3_TRB_CTRL_HWO (1 << 0) -#define DWC3_TRB_CTRL_LST (1 << 1) -#define DWC3_TRB_CTRL_CHN (1 << 2) -#define DWC3_TRB_CTRL_CSP (1 << 3) -#define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4) -#define DWC3_TRB_CTRL_ISP_IMI (1 << 10) -#define DWC3_TRB_CTRL_IOC (1 << 11) -#define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) - -#define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1) -#define DWC3_TRBCTL_CONTROL_SETUP DWC3_TRB_CTRL_TRBCTL(2) -#define DWC3_TRBCTL_CONTROL_STATUS2 DWC3_TRB_CTRL_TRBCTL(3) -#define DWC3_TRBCTL_CONTROL_STATUS3 DWC3_TRB_CTRL_TRBCTL(4) -#define DWC3_TRBCTL_CONTROL_DATA DWC3_TRB_CTRL_TRBCTL(5) -#define DWC3_TRBCTL_ISOCHRONOUS_FIRST DWC3_TRB_CTRL_TRBCTL(6) -#define DWC3_TRBCTL_ISOCHRONOUS DWC3_TRB_CTRL_TRBCTL(7) -#define DWC3_TRBCTL_LINK_TRB DWC3_TRB_CTRL_TRBCTL(8) - -/** - * struct dwc3_trb - transfer request block (hw format) - * @bpl: DW0-3 - * @bph: DW4-7 - * @size: DW8-B - * @trl: DWC-F - */ -struct dwc3_trb { - u32 bpl; - u32 bph; - u32 size; - u32 ctrl; -} __packed; - -/** - * dwc3_hwparams - copy of HWPARAMS registers - * @hwparams0 - GHWPARAMS0 - * @hwparams1 - GHWPARAMS1 - * @hwparams2 - GHWPARAMS2 - * @hwparams3 - GHWPARAMS3 - * @hwparams4 - GHWPARAMS4 - * @hwparams5 - GHWPARAMS5 - * @hwparams6 - GHWPARAMS6 - * @hwparams7 - GHWPARAMS7 - * @hwparams8 - GHWPARAMS8 - */ -struct dwc3_hwparams { - u32 hwparams0; - u32 hwparams1; - u32 hwparams2; - u32 hwparams3; - u32 hwparams4; - u32 hwparams5; - u32 hwparams6; - u32 hwparams7; - u32 hwparams8; -}; - -/* HWPARAMS0 */ -#define DWC3_MODE(n) ((n) & 0x7) - -#define DWC3_MODE_DEVICE 0 -#define DWC3_MODE_HOST 1 -#define DWC3_MODE_DRD 2 -#define DWC3_MODE_HUB 3 - -#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8) - -/* HWPARAMS1 */ -#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) - -/* HWPARAMS7 */ -#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) - -struct dwc3_request { - struct usb_request request; - struct list_head list; - struct dwc3_ep *dep; - - u8 epnum; - struct dwc3_trb *trb; - dma_addr_t trb_dma; - - unsigned direction:1; - unsigned mapped:1; - unsigned queued:1; -}; - -/** - * struct dwc3 - representation of our controller - * @ctrl_req: usb control request which is used for ep0 - * @ep0_trb: trb which is used for the ctrl_req - * @ep0_bounce: bounce buffer for ep0 - * @setup_buf: used while precessing STD USB requests - * @ctrl_req_addr: dma address of ctrl_req - * @ep0_trb: dma address of ep0_trb - * @ep0_usb_req: dummy req used while handling STD USB requests - * @ep0_bounce_addr: dma address of ep0_bounce - * @lock: for synchronizing - * @dev: pointer to our struct device - * @xhci: pointer to our xHCI child - * @event_buffer_list: a list of event buffers - * @gadget: device side representation of the peripheral controller - * @gadget_driver: pointer to the gadget driver - * @regs: base address for our registers - * @regs_size: address space size - * @irq: IRQ number - * @num_event_buffers: calculated number of event buffers - * @u1u2: only used on revisions <1.83a for workaround - * @maximum_speed: maximum speed requested (mainly for testing purposes) - * @revision: revision register contents - * @mode: mode of operation - * @is_selfpowered: true when we are selfpowered - * @three_stage_setup: set if we perform a three phase setup - * @ep0_bounced: true when we used bounce buffer - * @ep0_expect_in: true when we expect a DATA IN transfer - * @start_config_issued: true when StartConfig command has been issued - * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround - * @needs_fifo_resize: not all users might want fifo resizing, flag it - * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes. - * @ep0_next_event: hold the next expected event - * @ep0state: state of endpoint zero - * @link_state: link state - * @speed: device speed (super, high, full, low) - * @mem: points to start of memory which is used for this struct. - * @hwparams: copy of hwparams registers - * @root: debugfs root folder pointer - */ -struct dwc3 { - struct usb_ctrlrequest *ctrl_req; - struct dwc3_trb *ep0_trb; - void *ep0_bounce; - u8 *setup_buf; - dma_addr_t ctrl_req_addr; - dma_addr_t ep0_trb_addr; - dma_addr_t ep0_bounce_addr; - struct dwc3_request ep0_usb_req; - /* device lock */ - spinlock_t lock; - struct device *dev; - - struct platform_device *xhci; - struct resource *res; - - struct dwc3_event_buffer **ev_buffs; - struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; - - struct usb_gadget gadget; - struct usb_gadget_driver *gadget_driver; - - void __iomem *regs; - size_t regs_size; - - int irq; - - u32 num_event_buffers; - u32 u1u2; - u32 maximum_speed; - u32 revision; - u32 mode; - -#define DWC3_REVISION_173A 0x5533173a -#define DWC3_REVISION_175A 0x5533175a -#define DWC3_REVISION_180A 0x5533180a -#define DWC3_REVISION_183A 0x5533183a -#define DWC3_REVISION_185A 0x5533185a -#define DWC3_REVISION_188A 0x5533188a -#define DWC3_REVISION_190A 0x5533190a - - unsigned is_selfpowered:1; - unsigned three_stage_setup:1; - unsigned ep0_bounced:1; - unsigned ep0_expect_in:1; - unsigned start_config_issued:1; - unsigned setup_packet_pending:1; - unsigned delayed_status:1; - unsigned needs_fifo_resize:1; - unsigned resize_fifos:1; - - enum dwc3_ep0_next ep0_next_event; - enum dwc3_ep0_state ep0state; - enum dwc3_link_state link_state; - enum dwc3_device_state dev_state; - - u8 speed; - void *mem; - - struct dwc3_hwparams hwparams; - struct dentry *root; - - u8 test_mode; - u8 test_mode_nr; -}; - -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ - -struct dwc3_event_type { - u32 is_devspec:1; - u32 type:6; - u32 reserved8_31:25; -} __packed; - -#define DWC3_DEPEVT_XFERCOMPLETE 0x01 -#define DWC3_DEPEVT_XFERINPROGRESS 0x02 -#define DWC3_DEPEVT_XFERNOTREADY 0x03 -#define DWC3_DEPEVT_RXTXFIFOEVT 0x04 -#define DWC3_DEPEVT_STREAMEVT 0x06 -#define DWC3_DEPEVT_EPCMDCMPLT 0x07 - -/** - * struct dwc3_event_depvt - Device Endpoint Events - * @one_bit: indicates this is an endpoint event (not used) - * @endpoint_number: number of the endpoint - * @endpoint_event: The event we have: - * 0x00 - Reserved - * 0x01 - XferComplete - * 0x02 - XferInProgress - * 0x03 - XferNotReady - * 0x04 - RxTxFifoEvt (IN->Underrun, OUT->Overrun) - * 0x05 - Reserved - * 0x06 - StreamEvt - * 0x07 - EPCmdCmplt - * @reserved11_10: Reserved, don't use. - * @status: Indicates the status of the event. Refer to databook for - * more information. - * @parameters: Parameters of the current event. Refer to databook for - * more information. - */ -struct dwc3_event_depevt { - u32 one_bit:1; - u32 endpoint_number:5; - u32 endpoint_event:4; - u32 reserved11_10:2; - u32 status:4; - -/* Within XferNotReady */ -#define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3) - -/* Within XferComplete */ -#define DEPEVT_STATUS_BUSERR (1 << 0) -#define DEPEVT_STATUS_SHORT (1 << 1) -#define DEPEVT_STATUS_IOC (1 << 2) -#define DEPEVT_STATUS_LST (1 << 3) - -/* Stream event only */ -#define DEPEVT_STREAMEVT_FOUND 1 -#define DEPEVT_STREAMEVT_NOTFOUND 2 - -/* Control-only Status */ -#define DEPEVT_STATUS_CONTROL_SETUP 0 -#define DEPEVT_STATUS_CONTROL_DATA 1 -#define DEPEVT_STATUS_CONTROL_STATUS 2 - - u32 parameters:16; -} __packed; - -/** - * struct dwc3_event_devt - Device Events - * @one_bit: indicates this is a non-endpoint event (not used) - * @device_event: indicates it's a device event. Should read as 0x00 - * @type: indicates the type of device event. - * 0 - DisconnEvt - * 1 - USBRst - * 2 - ConnectDone - * 3 - ULStChng - * 4 - WkUpEvt - * 5 - Reserved - * 6 - EOPF - * 7 - SOF - * 8 - Reserved - * 9 - ErrticErr - * 10 - CmdCmplt - * 11 - EvntOverflow - * 12 - VndrDevTstRcved - * @reserved15_12: Reserved, not used - * @event_info: Information about this event - * @reserved31_24: Reserved, not used - */ -struct dwc3_event_devt { - u32 one_bit:1; - u32 device_event:7; - u32 type:4; - u32 reserved15_12:4; - u32 event_info:8; - u32 reserved31_24:8; -} __packed; - -/** - * struct dwc3_event_gevt - Other Core Events - * @one_bit: indicates this is a non-endpoint event (not used) - * @device_event: indicates it's (0x03) Carkit or (0x04) I2C event. - * @phy_port_number: self-explanatory - * @reserved31_12: Reserved, not used. - */ -struct dwc3_event_gevt { - u32 one_bit:1; - u32 device_event:7; - u32 phy_port_number:4; - u32 reserved31_12:20; -} __packed; - -/** - * union dwc3_event - representation of Event Buffer contents - * @raw: raw 32-bit event - * @type: the type of the event - * @depevt: Device Endpoint Event - * @devt: Device Event - * @gevt: Global Event - */ -union dwc3_event { - u32 raw; - struct dwc3_event_type type; - struct dwc3_event_depevt depevt; - struct dwc3_event_devt devt; - struct dwc3_event_gevt gevt; -}; - -/* - * DWC3 Features to be used as Driver Data - */ - -#define DWC3_HAS_PERIPHERAL BIT(0) -#define DWC3_HAS_XHCI BIT(1) -#define DWC3_HAS_OTG BIT(3) - -/* prototypes */ -void dwc3_set_mode(struct dwc3 *dwc, u32 mode); -int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); - -int dwc3_host_init(struct dwc3 *dwc); -void dwc3_host_exit(struct dwc3 *dwc); - -int dwc3_gadget_init(struct dwc3 *dwc); -void dwc3_gadget_exit(struct dwc3 *dwc); - -extern int dwc3_get_device_id(void); -extern void dwc3_put_device_id(int id); - -#endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/debug.h b/ANDROID_3.4.5/drivers/usb/dwc3/debug.h deleted file mode 100644 index 5894ee82..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/debug.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * debug.h - DesignWare USB3 DRD Controller Debug Header - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core.h" - -#ifdef CONFIG_DEBUG_FS -extern int dwc3_debugfs_init(struct dwc3 *); -extern void dwc3_debugfs_exit(struct dwc3 *); -#else -static inline int dwc3_debugfs_init(struct dwc3 *d) -{ return 0; } -static inline void dwc3_debugfs_exit(struct dwc3 *d) -{ } -#endif - diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/debugfs.c b/ANDROID_3.4.5/drivers/usb/dwc3/debugfs.c deleted file mode 100644 index d4a30f11..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/debugfs.c +++ /dev/null @@ -1,710 +0,0 @@ -/** - * debugfs.c - DesignWare USB3 DRD Controller DebugFS file - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/ptrace.h> -#include <linux/types.h> -#include <linux/spinlock.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/delay.h> -#include <linux/uaccess.h> - -#include <linux/usb/ch9.h> - -#include "core.h" -#include "gadget.h" -#include "io.h" -#include "debug.h" - -#define dump_register(nm) \ -{ \ - .name = __stringify(nm), \ - .offset = DWC3_ ##nm, \ -} - -static const struct debugfs_reg32 dwc3_regs[] = { - dump_register(GSBUSCFG0), - dump_register(GSBUSCFG1), - dump_register(GTXTHRCFG), - dump_register(GRXTHRCFG), - dump_register(GCTL), - dump_register(GEVTEN), - dump_register(GSTS), - dump_register(GSNPSID), - dump_register(GGPIO), - dump_register(GUID), - dump_register(GUCTL), - dump_register(GBUSERRADDR0), - dump_register(GBUSERRADDR1), - dump_register(GPRTBIMAP0), - dump_register(GPRTBIMAP1), - dump_register(GHWPARAMS0), - dump_register(GHWPARAMS1), - dump_register(GHWPARAMS2), - dump_register(GHWPARAMS3), - dump_register(GHWPARAMS4), - dump_register(GHWPARAMS5), - dump_register(GHWPARAMS6), - dump_register(GHWPARAMS7), - dump_register(GDBGFIFOSPACE), - dump_register(GDBGLTSSM), - dump_register(GPRTBIMAP_HS0), - dump_register(GPRTBIMAP_HS1), - dump_register(GPRTBIMAP_FS0), - dump_register(GPRTBIMAP_FS1), - - dump_register(GUSB2PHYCFG(0)), - dump_register(GUSB2PHYCFG(1)), - dump_register(GUSB2PHYCFG(2)), - dump_register(GUSB2PHYCFG(3)), - dump_register(GUSB2PHYCFG(4)), - dump_register(GUSB2PHYCFG(5)), - dump_register(GUSB2PHYCFG(6)), - dump_register(GUSB2PHYCFG(7)), - dump_register(GUSB2PHYCFG(8)), - dump_register(GUSB2PHYCFG(9)), - dump_register(GUSB2PHYCFG(10)), - dump_register(GUSB2PHYCFG(11)), - dump_register(GUSB2PHYCFG(12)), - dump_register(GUSB2PHYCFG(13)), - dump_register(GUSB2PHYCFG(14)), - dump_register(GUSB2PHYCFG(15)), - - dump_register(GUSB2I2CCTL(0)), - dump_register(GUSB2I2CCTL(1)), - dump_register(GUSB2I2CCTL(2)), - dump_register(GUSB2I2CCTL(3)), - dump_register(GUSB2I2CCTL(4)), - dump_register(GUSB2I2CCTL(5)), - dump_register(GUSB2I2CCTL(6)), - dump_register(GUSB2I2CCTL(7)), - dump_register(GUSB2I2CCTL(8)), - dump_register(GUSB2I2CCTL(9)), - dump_register(GUSB2I2CCTL(10)), - dump_register(GUSB2I2CCTL(11)), - dump_register(GUSB2I2CCTL(12)), - dump_register(GUSB2I2CCTL(13)), - dump_register(GUSB2I2CCTL(14)), - dump_register(GUSB2I2CCTL(15)), - - dump_register(GUSB2PHYACC(0)), - dump_register(GUSB2PHYACC(1)), - dump_register(GUSB2PHYACC(2)), - dump_register(GUSB2PHYACC(3)), - dump_register(GUSB2PHYACC(4)), - dump_register(GUSB2PHYACC(5)), - dump_register(GUSB2PHYACC(6)), - dump_register(GUSB2PHYACC(7)), - dump_register(GUSB2PHYACC(8)), - dump_register(GUSB2PHYACC(9)), - dump_register(GUSB2PHYACC(10)), - dump_register(GUSB2PHYACC(11)), - dump_register(GUSB2PHYACC(12)), - dump_register(GUSB2PHYACC(13)), - dump_register(GUSB2PHYACC(14)), - dump_register(GUSB2PHYACC(15)), - - dump_register(GUSB3PIPECTL(0)), - dump_register(GUSB3PIPECTL(1)), - dump_register(GUSB3PIPECTL(2)), - dump_register(GUSB3PIPECTL(3)), - dump_register(GUSB3PIPECTL(4)), - dump_register(GUSB3PIPECTL(5)), - dump_register(GUSB3PIPECTL(6)), - dump_register(GUSB3PIPECTL(7)), - dump_register(GUSB3PIPECTL(8)), - dump_register(GUSB3PIPECTL(9)), - dump_register(GUSB3PIPECTL(10)), - dump_register(GUSB3PIPECTL(11)), - dump_register(GUSB3PIPECTL(12)), - dump_register(GUSB3PIPECTL(13)), - dump_register(GUSB3PIPECTL(14)), - dump_register(GUSB3PIPECTL(15)), - - dump_register(GTXFIFOSIZ(0)), - dump_register(GTXFIFOSIZ(1)), - dump_register(GTXFIFOSIZ(2)), - dump_register(GTXFIFOSIZ(3)), - dump_register(GTXFIFOSIZ(4)), - dump_register(GTXFIFOSIZ(5)), - dump_register(GTXFIFOSIZ(6)), - dump_register(GTXFIFOSIZ(7)), - dump_register(GTXFIFOSIZ(8)), - dump_register(GTXFIFOSIZ(9)), - dump_register(GTXFIFOSIZ(10)), - dump_register(GTXFIFOSIZ(11)), - dump_register(GTXFIFOSIZ(12)), - dump_register(GTXFIFOSIZ(13)), - dump_register(GTXFIFOSIZ(14)), - dump_register(GTXFIFOSIZ(15)), - dump_register(GTXFIFOSIZ(16)), - dump_register(GTXFIFOSIZ(17)), - dump_register(GTXFIFOSIZ(18)), - dump_register(GTXFIFOSIZ(19)), - dump_register(GTXFIFOSIZ(20)), - dump_register(GTXFIFOSIZ(21)), - dump_register(GTXFIFOSIZ(22)), - dump_register(GTXFIFOSIZ(23)), - dump_register(GTXFIFOSIZ(24)), - dump_register(GTXFIFOSIZ(25)), - dump_register(GTXFIFOSIZ(26)), - dump_register(GTXFIFOSIZ(27)), - dump_register(GTXFIFOSIZ(28)), - dump_register(GTXFIFOSIZ(29)), - dump_register(GTXFIFOSIZ(30)), - dump_register(GTXFIFOSIZ(31)), - - dump_register(GRXFIFOSIZ(0)), - dump_register(GRXFIFOSIZ(1)), - dump_register(GRXFIFOSIZ(2)), - dump_register(GRXFIFOSIZ(3)), - dump_register(GRXFIFOSIZ(4)), - dump_register(GRXFIFOSIZ(5)), - dump_register(GRXFIFOSIZ(6)), - dump_register(GRXFIFOSIZ(7)), - dump_register(GRXFIFOSIZ(8)), - dump_register(GRXFIFOSIZ(9)), - dump_register(GRXFIFOSIZ(10)), - dump_register(GRXFIFOSIZ(11)), - dump_register(GRXFIFOSIZ(12)), - dump_register(GRXFIFOSIZ(13)), - dump_register(GRXFIFOSIZ(14)), - dump_register(GRXFIFOSIZ(15)), - dump_register(GRXFIFOSIZ(16)), - dump_register(GRXFIFOSIZ(17)), - dump_register(GRXFIFOSIZ(18)), - dump_register(GRXFIFOSIZ(19)), - dump_register(GRXFIFOSIZ(20)), - dump_register(GRXFIFOSIZ(21)), - dump_register(GRXFIFOSIZ(22)), - dump_register(GRXFIFOSIZ(23)), - dump_register(GRXFIFOSIZ(24)), - dump_register(GRXFIFOSIZ(25)), - dump_register(GRXFIFOSIZ(26)), - dump_register(GRXFIFOSIZ(27)), - dump_register(GRXFIFOSIZ(28)), - dump_register(GRXFIFOSIZ(29)), - dump_register(GRXFIFOSIZ(30)), - dump_register(GRXFIFOSIZ(31)), - - dump_register(GEVNTADRLO(0)), - dump_register(GEVNTADRHI(0)), - dump_register(GEVNTSIZ(0)), - dump_register(GEVNTCOUNT(0)), - - dump_register(GHWPARAMS8), - dump_register(DCFG), - dump_register(DCTL), - dump_register(DEVTEN), - dump_register(DSTS), - dump_register(DGCMDPAR), - dump_register(DGCMD), - dump_register(DALEPENA), - - dump_register(DEPCMDPAR2(0)), - dump_register(DEPCMDPAR2(1)), - dump_register(DEPCMDPAR2(2)), - dump_register(DEPCMDPAR2(3)), - dump_register(DEPCMDPAR2(4)), - dump_register(DEPCMDPAR2(5)), - dump_register(DEPCMDPAR2(6)), - dump_register(DEPCMDPAR2(7)), - dump_register(DEPCMDPAR2(8)), - dump_register(DEPCMDPAR2(9)), - dump_register(DEPCMDPAR2(10)), - dump_register(DEPCMDPAR2(11)), - dump_register(DEPCMDPAR2(12)), - dump_register(DEPCMDPAR2(13)), - dump_register(DEPCMDPAR2(14)), - dump_register(DEPCMDPAR2(15)), - dump_register(DEPCMDPAR2(16)), - dump_register(DEPCMDPAR2(17)), - dump_register(DEPCMDPAR2(18)), - dump_register(DEPCMDPAR2(19)), - dump_register(DEPCMDPAR2(20)), - dump_register(DEPCMDPAR2(21)), - dump_register(DEPCMDPAR2(22)), - dump_register(DEPCMDPAR2(23)), - dump_register(DEPCMDPAR2(24)), - dump_register(DEPCMDPAR2(25)), - dump_register(DEPCMDPAR2(26)), - dump_register(DEPCMDPAR2(27)), - dump_register(DEPCMDPAR2(28)), - dump_register(DEPCMDPAR2(29)), - dump_register(DEPCMDPAR2(30)), - dump_register(DEPCMDPAR2(31)), - - dump_register(DEPCMDPAR1(0)), - dump_register(DEPCMDPAR1(1)), - dump_register(DEPCMDPAR1(2)), - dump_register(DEPCMDPAR1(3)), - dump_register(DEPCMDPAR1(4)), - dump_register(DEPCMDPAR1(5)), - dump_register(DEPCMDPAR1(6)), - dump_register(DEPCMDPAR1(7)), - dump_register(DEPCMDPAR1(8)), - dump_register(DEPCMDPAR1(9)), - dump_register(DEPCMDPAR1(10)), - dump_register(DEPCMDPAR1(11)), - dump_register(DEPCMDPAR1(12)), - dump_register(DEPCMDPAR1(13)), - dump_register(DEPCMDPAR1(14)), - dump_register(DEPCMDPAR1(15)), - dump_register(DEPCMDPAR1(16)), - dump_register(DEPCMDPAR1(17)), - dump_register(DEPCMDPAR1(18)), - dump_register(DEPCMDPAR1(19)), - dump_register(DEPCMDPAR1(20)), - dump_register(DEPCMDPAR1(21)), - dump_register(DEPCMDPAR1(22)), - dump_register(DEPCMDPAR1(23)), - dump_register(DEPCMDPAR1(24)), - dump_register(DEPCMDPAR1(25)), - dump_register(DEPCMDPAR1(26)), - dump_register(DEPCMDPAR1(27)), - dump_register(DEPCMDPAR1(28)), - dump_register(DEPCMDPAR1(29)), - dump_register(DEPCMDPAR1(30)), - dump_register(DEPCMDPAR1(31)), - - dump_register(DEPCMDPAR0(0)), - dump_register(DEPCMDPAR0(1)), - dump_register(DEPCMDPAR0(2)), - dump_register(DEPCMDPAR0(3)), - dump_register(DEPCMDPAR0(4)), - dump_register(DEPCMDPAR0(5)), - dump_register(DEPCMDPAR0(6)), - dump_register(DEPCMDPAR0(7)), - dump_register(DEPCMDPAR0(8)), - dump_register(DEPCMDPAR0(9)), - dump_register(DEPCMDPAR0(10)), - dump_register(DEPCMDPAR0(11)), - dump_register(DEPCMDPAR0(12)), - dump_register(DEPCMDPAR0(13)), - dump_register(DEPCMDPAR0(14)), - dump_register(DEPCMDPAR0(15)), - dump_register(DEPCMDPAR0(16)), - dump_register(DEPCMDPAR0(17)), - dump_register(DEPCMDPAR0(18)), - dump_register(DEPCMDPAR0(19)), - dump_register(DEPCMDPAR0(20)), - dump_register(DEPCMDPAR0(21)), - dump_register(DEPCMDPAR0(22)), - dump_register(DEPCMDPAR0(23)), - dump_register(DEPCMDPAR0(24)), - dump_register(DEPCMDPAR0(25)), - dump_register(DEPCMDPAR0(26)), - dump_register(DEPCMDPAR0(27)), - dump_register(DEPCMDPAR0(28)), - dump_register(DEPCMDPAR0(29)), - dump_register(DEPCMDPAR0(30)), - dump_register(DEPCMDPAR0(31)), - - dump_register(DEPCMD(0)), - dump_register(DEPCMD(1)), - dump_register(DEPCMD(2)), - dump_register(DEPCMD(3)), - dump_register(DEPCMD(4)), - dump_register(DEPCMD(5)), - dump_register(DEPCMD(6)), - dump_register(DEPCMD(7)), - dump_register(DEPCMD(8)), - dump_register(DEPCMD(9)), - dump_register(DEPCMD(10)), - dump_register(DEPCMD(11)), - dump_register(DEPCMD(12)), - dump_register(DEPCMD(13)), - dump_register(DEPCMD(14)), - dump_register(DEPCMD(15)), - dump_register(DEPCMD(16)), - dump_register(DEPCMD(17)), - dump_register(DEPCMD(18)), - dump_register(DEPCMD(19)), - dump_register(DEPCMD(20)), - dump_register(DEPCMD(21)), - dump_register(DEPCMD(22)), - dump_register(DEPCMD(23)), - dump_register(DEPCMD(24)), - dump_register(DEPCMD(25)), - dump_register(DEPCMD(26)), - dump_register(DEPCMD(27)), - dump_register(DEPCMD(28)), - dump_register(DEPCMD(29)), - dump_register(DEPCMD(30)), - dump_register(DEPCMD(31)), - - dump_register(OCFG), - dump_register(OCTL), - dump_register(OEVTEN), - dump_register(OSTS), -}; - -static int dwc3_regdump_show(struct seq_file *s, void *unused) -{ - struct dwc3 *dwc = s->private; - - seq_printf(s, "DesignWare USB3 Core Register Dump\n"); - debugfs_print_regs32(s, dwc3_regs, ARRAY_SIZE(dwc3_regs), - dwc->regs, ""); - return 0; -} - -static int dwc3_regdump_open(struct inode *inode, struct file *file) -{ - return single_open(file, dwc3_regdump_show, inode->i_private); -} - -static const struct file_operations dwc3_regdump_fops = { - .open = dwc3_regdump_open, - .read = seq_read, - .release = single_release, -}; - -static int dwc3_mode_show(struct seq_file *s, void *unused) -{ - struct dwc3 *dwc = s->private; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - spin_unlock_irqrestore(&dwc->lock, flags); - - switch (DWC3_GCTL_PRTCAP(reg)) { - case DWC3_GCTL_PRTCAP_HOST: - seq_printf(s, "host\n"); - break; - case DWC3_GCTL_PRTCAP_DEVICE: - seq_printf(s, "device\n"); - break; - case DWC3_GCTL_PRTCAP_OTG: - seq_printf(s, "OTG\n"); - break; - default: - seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); - } - - return 0; -} - -static int dwc3_mode_open(struct inode *inode, struct file *file) -{ - return single_open(file, dwc3_mode_show, inode->i_private); -} - -static ssize_t dwc3_mode_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct dwc3 *dwc = s->private; - unsigned long flags; - u32 mode = 0; - char buf[32]; - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - if (!strncmp(buf, "host", 4)) - mode |= DWC3_GCTL_PRTCAP_HOST; - - if (!strncmp(buf, "device", 6)) - mode |= DWC3_GCTL_PRTCAP_DEVICE; - - if (!strncmp(buf, "otg", 3)) - mode |= DWC3_GCTL_PRTCAP_OTG; - - if (mode) { - spin_lock_irqsave(&dwc->lock, flags); - dwc3_set_mode(dwc, mode); - spin_unlock_irqrestore(&dwc->lock, flags); - } - return count; -} - -static const struct file_operations dwc3_mode_fops = { - .open = dwc3_mode_open, - .write = dwc3_mode_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int dwc3_testmode_show(struct seq_file *s, void *unused) -{ - struct dwc3 *dwc = s->private; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= DWC3_DCTL_TSTCTRL_MASK; - reg >>= 1; - spin_unlock_irqrestore(&dwc->lock, flags); - - switch (reg) { - case 0: - seq_printf(s, "no test\n"); - break; - case TEST_J: - seq_printf(s, "test_j\n"); - break; - case TEST_K: - seq_printf(s, "test_k\n"); - break; - case TEST_SE0_NAK: - seq_printf(s, "test_se0_nak\n"); - break; - case TEST_PACKET: - seq_printf(s, "test_packet\n"); - break; - case TEST_FORCE_EN: - seq_printf(s, "test_force_enable\n"); - break; - default: - seq_printf(s, "UNKNOWN %d\n", reg); - } - - return 0; -} - -static int dwc3_testmode_open(struct inode *inode, struct file *file) -{ - return single_open(file, dwc3_testmode_show, inode->i_private); -} - -static ssize_t dwc3_testmode_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct dwc3 *dwc = s->private; - unsigned long flags; - u32 testmode = 0; - char buf[32]; - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - if (!strncmp(buf, "test_j", 6)) - testmode = TEST_J; - else if (!strncmp(buf, "test_k", 6)) - testmode = TEST_K; - else if (!strncmp(buf, "test_se0_nak", 12)) - testmode = TEST_SE0_NAK; - else if (!strncmp(buf, "test_packet", 11)) - testmode = TEST_PACKET; - else if (!strncmp(buf, "test_force_enable", 17)) - testmode = TEST_FORCE_EN; - else - testmode = 0; - - spin_lock_irqsave(&dwc->lock, flags); - dwc3_gadget_set_test_mode(dwc, testmode); - spin_unlock_irqrestore(&dwc->lock, flags); - - return count; -} - -static const struct file_operations dwc3_testmode_fops = { - .open = dwc3_testmode_open, - .write = dwc3_testmode_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int dwc3_link_state_show(struct seq_file *s, void *unused) -{ - struct dwc3 *dwc = s->private; - unsigned long flags; - enum dwc3_link_state state; - u32 reg; - - spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - state = DWC3_DSTS_USBLNKST(reg); - spin_unlock_irqrestore(&dwc->lock, flags); - - switch (state) { - case DWC3_LINK_STATE_U0: - seq_printf(s, "U0\n"); - break; - case DWC3_LINK_STATE_U1: - seq_printf(s, "U1\n"); - break; - case DWC3_LINK_STATE_U2: - seq_printf(s, "U2\n"); - break; - case DWC3_LINK_STATE_U3: - seq_printf(s, "U3\n"); - break; - case DWC3_LINK_STATE_SS_DIS: - seq_printf(s, "SS.Disabled\n"); - break; - case DWC3_LINK_STATE_RX_DET: - seq_printf(s, "Rx.Detect\n"); - break; - case DWC3_LINK_STATE_SS_INACT: - seq_printf(s, "SS.Inactive\n"); - break; - case DWC3_LINK_STATE_POLL: - seq_printf(s, "Poll\n"); - break; - case DWC3_LINK_STATE_RECOV: - seq_printf(s, "Recovery\n"); - break; - case DWC3_LINK_STATE_HRESET: - seq_printf(s, "HRESET\n"); - break; - case DWC3_LINK_STATE_CMPLY: - seq_printf(s, "Compliance\n"); - break; - case DWC3_LINK_STATE_LPBK: - seq_printf(s, "Loopback\n"); - break; - default: - seq_printf(s, "UNKNOWN %d\n", reg); - } - - return 0; -} - -static int dwc3_link_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, dwc3_link_state_show, inode->i_private); -} - -static ssize_t dwc3_link_state_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct dwc3 *dwc = s->private; - unsigned long flags; - enum dwc3_link_state state = 0; - char buf[32]; - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - if (!strncmp(buf, "SS.Disabled", 11)) - state = DWC3_LINK_STATE_SS_DIS; - else if (!strncmp(buf, "Rx.Detect", 9)) - state = DWC3_LINK_STATE_RX_DET; - else if (!strncmp(buf, "SS.Inactive", 11)) - state = DWC3_LINK_STATE_SS_INACT; - else if (!strncmp(buf, "Recovery", 8)) - state = DWC3_LINK_STATE_RECOV; - else if (!strncmp(buf, "Compliance", 10)) - state = DWC3_LINK_STATE_CMPLY; - else if (!strncmp(buf, "Loopback", 8)) - state = DWC3_LINK_STATE_LPBK; - else - return -EINVAL; - - spin_lock_irqsave(&dwc->lock, flags); - dwc3_gadget_set_link_state(dwc, state); - spin_unlock_irqrestore(&dwc->lock, flags); - - return count; -} - -static const struct file_operations dwc3_link_state_fops = { - .open = dwc3_link_state_open, - .write = dwc3_link_state_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int __devinit dwc3_debugfs_init(struct dwc3 *dwc) -{ - struct dentry *root; - struct dentry *file; - int ret; - - root = debugfs_create_dir(dev_name(dwc->dev), NULL); - if (!root) { - ret = -ENOMEM; - goto err0; - } - - dwc->root = root; - - file = debugfs_create_file("regdump", S_IRUGO, root, dwc, - &dwc3_regdump_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_mode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_testmode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_link_state_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - return 0; - -err1: - debugfs_remove_recursive(root); - -err0: - return ret; -} - -void __devexit dwc3_debugfs_exit(struct dwc3 *dwc) -{ - debugfs_remove_recursive(dwc->root); - dwc->root = NULL; -} diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-exynos.c b/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-exynos.c deleted file mode 100644 index d1903019..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-exynos.c +++ /dev/null @@ -1,151 +0,0 @@ -/** - * dwc3-exynos.c - Samsung EXYNOS DWC3 Specific Glue layer - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Author: Anton Tikhomirov <av.tikhomirov@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/platform_data/dwc3-exynos.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <linux/clk.h> - -#include "core.h" - -struct dwc3_exynos { - struct platform_device *dwc3; - struct device *dev; - - struct clk *clk; -}; - -static int __devinit dwc3_exynos_probe(struct platform_device *pdev) -{ - struct dwc3_exynos_data *pdata = pdev->dev.platform_data; - struct platform_device *dwc3; - struct dwc3_exynos *exynos; - struct clk *clk; - - int devid; - int ret = -ENOMEM; - - exynos = kzalloc(sizeof(*exynos), GFP_KERNEL); - if (!exynos) { - dev_err(&pdev->dev, "not enough memory\n"); - goto err0; - } - - platform_set_drvdata(pdev, exynos); - - devid = dwc3_get_device_id(); - if (devid < 0) - goto err1; - - dwc3 = platform_device_alloc("dwc3", devid); - if (!dwc3) { - dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); - goto err2; - } - - clk = clk_get(&pdev->dev, "usbdrd30"); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "couldn't get clock\n"); - ret = -EINVAL; - goto err3; - } - - dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask); - - dwc3->dev.parent = &pdev->dev; - dwc3->dev.dma_mask = pdev->dev.dma_mask; - dwc3->dev.dma_parms = pdev->dev.dma_parms; - exynos->dwc3 = dwc3; - exynos->dev = &pdev->dev; - exynos->clk = clk; - - clk_enable(exynos->clk); - - /* PHY initialization */ - if (!pdata) { - dev_dbg(&pdev->dev, "missing platform data\n"); - } else { - if (pdata->phy_init) - pdata->phy_init(pdev, pdata->phy_type); - } - - ret = platform_device_add_resources(dwc3, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n"); - goto err4; - } - - ret = platform_device_add(dwc3); - if (ret) { - dev_err(&pdev->dev, "failed to register dwc3 device\n"); - goto err4; - } - - return 0; - -err4: - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, pdata->phy_type); - - clk_disable(clk); - clk_put(clk); -err3: - platform_device_put(dwc3); -err2: - dwc3_put_device_id(devid); -err1: - kfree(exynos); -err0: - return ret; -} - -static int __devexit dwc3_exynos_remove(struct platform_device *pdev) -{ - struct dwc3_exynos *exynos = platform_get_drvdata(pdev); - struct dwc3_exynos_data *pdata = pdev->dev.platform_data; - - platform_device_unregister(exynos->dwc3); - - dwc3_put_device_id(exynos->dwc3->id); - - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, pdata->phy_type); - - clk_disable(exynos->clk); - clk_put(exynos->clk); - - kfree(exynos); - - return 0; -} - -static struct platform_driver dwc3_exynos_driver = { - .probe = dwc3_exynos_probe, - .remove = __devexit_p(dwc3_exynos_remove), - .driver = { - .name = "exynos-dwc3", - }, -}; - -module_platform_driver(dwc3_exynos_driver); - -MODULE_ALIAS("platform:exynos-dwc3"); -MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer"); diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-omap.c b/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-omap.c deleted file mode 100644 index d7d9c0ec..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-omap.c +++ /dev/null @@ -1,392 +0,0 @@ -/** - * dwc3-omap.c - OMAP Specific Glue layer - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/platform_data/dwc3-omap.h> -#include <linux/dma-mapping.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/of.h> - -#include "core.h" -#include "io.h" - -/* - * All these registers belong to OMAP's Wrapper around the - * DesignWare USB3 Core. - */ - -#define USBOTGSS_REVISION 0x0000 -#define USBOTGSS_SYSCONFIG 0x0010 -#define USBOTGSS_IRQ_EOI 0x0020 -#define USBOTGSS_IRQSTATUS_RAW_0 0x0024 -#define USBOTGSS_IRQSTATUS_0 0x0028 -#define USBOTGSS_IRQENABLE_SET_0 0x002c -#define USBOTGSS_IRQENABLE_CLR_0 0x0030 -#define USBOTGSS_IRQSTATUS_RAW_1 0x0034 -#define USBOTGSS_IRQSTATUS_1 0x0038 -#define USBOTGSS_IRQENABLE_SET_1 0x003c -#define USBOTGSS_IRQENABLE_CLR_1 0x0040 -#define USBOTGSS_UTMI_OTG_CTRL 0x0080 -#define USBOTGSS_UTMI_OTG_STATUS 0x0084 -#define USBOTGSS_MMRAM_OFFSET 0x0100 -#define USBOTGSS_FLADJ 0x0104 -#define USBOTGSS_DEBUG_CFG 0x0108 -#define USBOTGSS_DEBUG_DATA 0x010c - -/* SYSCONFIG REGISTER */ -#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) -#define USBOTGSS_SYSCONFIG_STANDBYMODE(x) ((x) << 4) - -#define USBOTGSS_STANDBYMODE_FORCE_STANDBY 0 -#define USBOTGSS_STANDBYMODE_NO_STANDBY 1 -#define USBOTGSS_STANDBYMODE_SMART_STANDBY 2 -#define USBOTGSS_STANDBYMODE_SMART_WAKEUP 3 - -#define USBOTGSS_STANDBYMODE_MASK (0x03 << 4) - -#define USBOTGSS_SYSCONFIG_IDLEMODE(x) ((x) << 2) - -#define USBOTGSS_IDLEMODE_FORCE_IDLE 0 -#define USBOTGSS_IDLEMODE_NO_IDLE 1 -#define USBOTGSS_IDLEMODE_SMART_IDLE 2 -#define USBOTGSS_IDLEMODE_SMART_WAKEUP 3 - -#define USBOTGSS_IDLEMODE_MASK (0x03 << 2) - -/* IRQ_EOI REGISTER */ -#define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0) - -/* IRQS0 BITS */ -#define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) - -/* IRQ1 BITS */ -#define USBOTGSS_IRQ1_DMADISABLECLR (1 << 17) -#define USBOTGSS_IRQ1_OEVT (1 << 16) -#define USBOTGSS_IRQ1_DRVVBUS_RISE (1 << 13) -#define USBOTGSS_IRQ1_CHRGVBUS_RISE (1 << 12) -#define USBOTGSS_IRQ1_DISCHRGVBUS_RISE (1 << 11) -#define USBOTGSS_IRQ1_IDPULLUP_RISE (1 << 8) -#define USBOTGSS_IRQ1_DRVVBUS_FALL (1 << 5) -#define USBOTGSS_IRQ1_CHRGVBUS_FALL (1 << 4) -#define USBOTGSS_IRQ1_DISCHRGVBUS_FALL (1 << 3) -#define USBOTGSS_IRQ1_IDPULLUP_FALL (1 << 0) - -/* UTMI_OTG_CTRL REGISTER */ -#define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS (1 << 5) -#define USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS (1 << 4) -#define USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS (1 << 3) -#define USBOTGSS_UTMI_OTG_CTRL_IDPULLUP (1 << 0) - -/* UTMI_OTG_STATUS REGISTER */ -#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE (1 << 31) -#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT (1 << 9) -#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE (1 << 8) -#define USBOTGSS_UTMI_OTG_STATUS_IDDIG (1 << 4) -#define USBOTGSS_UTMI_OTG_STATUS_SESSEND (1 << 3) -#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID (1 << 2) -#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1) - -struct dwc3_omap { - /* device lock */ - spinlock_t lock; - - struct platform_device *dwc3; - struct device *dev; - - int irq; - void __iomem *base; - - void *context; - u32 resource_size; - - u32 dma_status:1; -}; - -static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) -{ - struct dwc3_omap *omap = _omap; - u32 reg; - - spin_lock(&omap->lock); - - reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_1); - - if (reg & USBOTGSS_IRQ1_DMADISABLECLR) { - dev_dbg(omap->dev, "DMA Disable was Cleared\n"); - omap->dma_status = false; - } - - if (reg & USBOTGSS_IRQ1_OEVT) - dev_dbg(omap->dev, "OTG Event\n"); - - if (reg & USBOTGSS_IRQ1_DRVVBUS_RISE) - dev_dbg(omap->dev, "DRVVBUS Rise\n"); - - if (reg & USBOTGSS_IRQ1_CHRGVBUS_RISE) - dev_dbg(omap->dev, "CHRGVBUS Rise\n"); - - if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_RISE) - dev_dbg(omap->dev, "DISCHRGVBUS Rise\n"); - - if (reg & USBOTGSS_IRQ1_IDPULLUP_RISE) - dev_dbg(omap->dev, "IDPULLUP Rise\n"); - - if (reg & USBOTGSS_IRQ1_DRVVBUS_FALL) - dev_dbg(omap->dev, "DRVVBUS Fall\n"); - - if (reg & USBOTGSS_IRQ1_CHRGVBUS_FALL) - dev_dbg(omap->dev, "CHRGVBUS Fall\n"); - - if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_FALL) - dev_dbg(omap->dev, "DISCHRGVBUS Fall\n"); - - if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL) - dev_dbg(omap->dev, "IDPULLUP Fall\n"); - - dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg); - - reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_0); - dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg); - - spin_unlock(&omap->lock); - - return IRQ_HANDLED; -} - -static int __devinit dwc3_omap_probe(struct platform_device *pdev) -{ - struct dwc3_omap_data *pdata = pdev->dev.platform_data; - struct device_node *node = pdev->dev.of_node; - - struct platform_device *dwc3; - struct dwc3_omap *omap; - struct resource *res; - struct device *dev = &pdev->dev; - - int devid; - int size; - int ret = -ENOMEM; - int irq; - - const u32 *utmi_mode; - u32 reg; - - void __iomem *base; - void *context; - - omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); - if (!omap) { - dev_err(dev, "not enough memory\n"); - return -ENOMEM; - } - - platform_set_drvdata(pdev, omap); - - irq = platform_get_irq(pdev, 1); - if (irq < 0) { - dev_err(dev, "missing IRQ resource\n"); - return -EINVAL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(dev, "missing memory base resource\n"); - return -EINVAL; - } - - base = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!base) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } - - devid = dwc3_get_device_id(); - if (devid < 0) - return -ENODEV; - - dwc3 = platform_device_alloc("dwc3", devid); - if (!dwc3) { - dev_err(dev, "couldn't allocate dwc3 device\n"); - goto err1; - } - - context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); - if (!context) { - dev_err(dev, "couldn't allocate dwc3 context memory\n"); - goto err2; - } - - spin_lock_init(&omap->lock); - dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - - dwc3->dev.parent = dev; - dwc3->dev.dma_mask = dev->dma_mask; - dwc3->dev.dma_parms = dev->dma_parms; - omap->resource_size = resource_size(res); - omap->context = context; - omap->dev = dev; - omap->irq = irq; - omap->base = base; - omap->dwc3 = dwc3; - - reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); - - utmi_mode = of_get_property(node, "utmi-mode", &size); - if (utmi_mode && size == sizeof(*utmi_mode)) { - reg |= *utmi_mode; - } else { - if (!pdata) { - dev_dbg(dev, "missing platform data\n"); - } else { - switch (pdata->utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(dev, "UNKNOWN utmi mode %d\n", - pdata->utmi_mode); - } - } - } - - dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); - - /* check the DMA Status */ - reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG); - omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); - - /* Set No-Idle and No-Standby */ - reg &= ~(USBOTGSS_STANDBYMODE_MASK - | USBOTGSS_IDLEMODE_MASK); - - reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY) - | USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE)); - - dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg); - - ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, - "dwc3-omap", omap); - if (ret) { - dev_err(dev, "failed to request IRQ #%d --> %d\n", - omap->irq, ret); - goto err2; - } - - /* enable all IRQs */ - reg = USBOTGSS_IRQO_COREIRQ_ST; - dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg); - - reg = (USBOTGSS_IRQ1_OEVT | - USBOTGSS_IRQ1_DRVVBUS_RISE | - USBOTGSS_IRQ1_CHRGVBUS_RISE | - USBOTGSS_IRQ1_DISCHRGVBUS_RISE | - USBOTGSS_IRQ1_IDPULLUP_RISE | - USBOTGSS_IRQ1_DRVVBUS_FALL | - USBOTGSS_IRQ1_CHRGVBUS_FALL | - USBOTGSS_IRQ1_DISCHRGVBUS_FALL | - USBOTGSS_IRQ1_IDPULLUP_FALL); - - dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); - - ret = platform_device_add_resources(dwc3, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(dev, "couldn't add resources to dwc3 device\n"); - goto err2; - } - - ret = platform_device_add(dwc3); - if (ret) { - dev_err(dev, "failed to register dwc3 device\n"); - goto err2; - } - - return 0; - -err2: - platform_device_put(dwc3); - -err1: - dwc3_put_device_id(devid); - - return ret; -} - -static int __devexit dwc3_omap_remove(struct platform_device *pdev) -{ - struct dwc3_omap *omap = platform_get_drvdata(pdev); - - platform_device_unregister(omap->dwc3); - - dwc3_put_device_id(omap->dwc3->id); - - return 0; -} - -static const struct of_device_id of_dwc3_matach[] = { - { - "ti,dwc3", - }, - { }, -}; -MODULE_DEVICE_TABLE(of, of_dwc3_matach); - -static struct platform_driver dwc3_omap_driver = { - .probe = dwc3_omap_probe, - .remove = __devexit_p(dwc3_omap_remove), - .driver = { - .name = "omap-dwc3", - .of_match_table = of_dwc3_matach, - }, -}; - -module_platform_driver(dwc3_omap_driver); - -MODULE_ALIAS("platform:omap-dwc3"); -MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer"); diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-pci.c b/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-pci.c deleted file mode 100644 index a9ca9adb..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/dwc3-pci.c +++ /dev/null @@ -1,173 +0,0 @@ -/** - * dwc3-pci.c - PCI Specific glue layer - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/platform_device.h> - -#include "core.h" - -/* FIXME define these in <linux/pci_ids.h> */ -#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 -#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd - -struct dwc3_pci { - struct device *dev; - struct platform_device *dwc3; -}; - -static int __devinit dwc3_pci_probe(struct pci_dev *pci, - const struct pci_device_id *id) -{ - struct resource res[2]; - struct platform_device *dwc3; - struct dwc3_pci *glue; - int ret = -ENOMEM; - int devid; - struct device *dev = &pci->dev; - - glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(dev, "not enough memory\n"); - return -ENOMEM; - } - - glue->dev = dev; - - ret = pci_enable_device(pci); - if (ret) { - dev_err(dev, "failed to enable pci device\n"); - return -ENODEV; - } - - pci_set_power_state(pci, PCI_D0); - pci_set_master(pci); - - devid = dwc3_get_device_id(); - if (devid < 0) { - ret = -ENOMEM; - goto err1; - } - - dwc3 = platform_device_alloc("dwc3", devid); - if (!dwc3) { - dev_err(dev, "couldn't allocate dwc3 device\n"); - ret = -ENOMEM; - goto err1; - } - - memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); - - res[0].start = pci_resource_start(pci, 0); - res[0].end = pci_resource_end(pci, 0); - res[0].name = "dwc_usb3"; - res[0].flags = IORESOURCE_MEM; - - res[1].start = pci->irq; - res[1].name = "dwc_usb3"; - res[1].flags = IORESOURCE_IRQ; - - ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); - if (ret) { - dev_err(dev, "couldn't add resources to dwc3 device\n"); - goto err2; - } - - pci_set_drvdata(pci, glue); - - dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - - dwc3->dev.dma_mask = dev->dma_mask; - dwc3->dev.dma_parms = dev->dma_parms; - dwc3->dev.parent = dev; - glue->dwc3 = dwc3; - - ret = platform_device_add(dwc3); - if (ret) { - dev_err(dev, "failed to register dwc3 device\n"); - goto err3; - } - - return 0; - -err3: - pci_set_drvdata(pci, NULL); - platform_device_put(dwc3); - -err2: - dwc3_put_device_id(devid); - -err1: - pci_disable_device(pci); - - return ret; -} - -static void __devexit dwc3_pci_remove(struct pci_dev *pci) -{ - struct dwc3_pci *glue = pci_get_drvdata(pci); - - dwc3_put_device_id(glue->dwc3->id); - platform_device_unregister(glue->dwc3); - pci_set_drvdata(pci, NULL); - pci_disable_device(pci); -} - -static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { - { - PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, - PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), - }, - { } /* Terminating Entry */ -}; -MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); - -static struct pci_driver dwc3_pci_driver = { - .name = "dwc3-pci", - .id_table = dwc3_pci_id_table, - .probe = dwc3_pci_probe, - .remove = __devexit_p(dwc3_pci_remove), -}; - -MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); - -module_pci_driver(dwc3_pci_driver); diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/ep0.c b/ANDROID_3.4.5/drivers/usb/dwc3/ep0.c deleted file mode 100644 index 3584a169..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/ep0.c +++ /dev/null @@ -1,873 +0,0 @@ -/** - * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/list.h> -#include <linux/dma-mapping.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/composite.h> - -#include "core.h" -#include "gadget.h" -#include "io.h" - -static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum); - -static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) -{ - switch (state) { - case EP0_UNCONNECTED: - return "Unconnected"; - case EP0_SETUP_PHASE: - return "Setup Phase"; - case EP0_DATA_PHASE: - return "Data Phase"; - case EP0_STATUS_PHASE: - return "Status Phase"; - default: - return "UNKNOWN"; - } -} - -static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, - u32 len, u32 type) -{ - struct dwc3_gadget_ep_cmd_params params; - struct dwc3_trb *trb; - struct dwc3_ep *dep; - - int ret; - - dep = dwc->eps[epnum]; - if (dep->flags & DWC3_EP_BUSY) { - dev_vdbg(dwc->dev, "%s: still busy\n", dep->name); - return 0; - } - - trb = dwc->ep0_trb; - - trb->bpl = lower_32_bits(buf_dma); - trb->bph = upper_32_bits(buf_dma); - trb->size = len; - trb->ctrl = type; - - trb->ctrl |= (DWC3_TRB_CTRL_HWO - | DWC3_TRB_CTRL_LST - | DWC3_TRB_CTRL_IOC - | DWC3_TRB_CTRL_ISP_IMI); - - memset(¶ms, 0, sizeof(params)); - params.param0 = upper_32_bits(dwc->ep0_trb_addr); - params.param1 = lower_32_bits(dwc->ep0_trb_addr); - - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_STARTTRANSFER, ¶ms); - if (ret < 0) { - dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n"); - return ret; - } - - dep->flags |= DWC3_EP_BUSY; - dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, - dep->number); - - dwc->ep0_next_event = DWC3_EP0_COMPLETE; - - return 0; -} - -static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, - struct dwc3_request *req) -{ - struct dwc3 *dwc = dep->dwc; - int ret = 0; - - req->request.actual = 0; - req->request.status = -EINPROGRESS; - req->epnum = dep->number; - - list_add_tail(&req->list, &dep->request_list); - - /* - * Gadget driver might not be quick enough to queue a request - * before we get a Transfer Not Ready event on this endpoint. - * - * In that case, we will set DWC3_EP_PENDING_REQUEST. When that - * flag is set, it's telling us that as soon as Gadget queues the - * required request, we should kick the transfer here because the - * IRQ we were waiting for is long gone. - */ - if (dep->flags & DWC3_EP_PENDING_REQUEST) { - unsigned direction; - - direction = !!(dep->flags & DWC3_EP0_DIR_IN); - - if (dwc->ep0state != EP0_DATA_PHASE) { - dev_WARN(dwc->dev, "Unexpected pending request\n"); - return 0; - } - - ret = dwc3_ep0_start_trans(dwc, direction, - req->request.dma, req->request.length, - DWC3_TRBCTL_CONTROL_DATA); - dep->flags &= ~(DWC3_EP_PENDING_REQUEST | - DWC3_EP0_DIR_IN); - } else if (dwc->delayed_status) { - dwc->delayed_status = false; - - if (dwc->ep0state == EP0_STATUS_PHASE) - dwc3_ep0_do_control_status(dwc, 1); - else - dev_dbg(dwc->dev, "too early for delayed status\n"); - } - - return ret; -} - -int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, - gfp_t gfp_flags) -{ - struct dwc3_request *req = to_dwc3_request(request); - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - - unsigned long flags; - - int ret; - - spin_lock_irqsave(&dwc->lock, flags); - if (!dep->desc) { - dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", - request, dep->name); - ret = -ESHUTDOWN; - goto out; - } - - /* we share one TRB for ep0/1 */ - if (!list_empty(&dep->request_list)) { - ret = -EBUSY; - goto out; - } - - dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", - request, dep->name, request->length, - dwc3_ep0_state_string(dwc->ep0state)); - - ret = __dwc3_gadget_ep0_queue(dep, req); - -out: - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) -{ - struct dwc3_ep *dep = dwc->eps[0]; - - /* stall is always issued on EP0 */ - __dwc3_gadget_ep_set_halt(dep, 1); - dep->flags = DWC3_EP_ENABLED; - dwc->delayed_status = false; - - if (!list_empty(&dep->request_list)) { - struct dwc3_request *req; - - req = next_request(&dep->request_list); - dwc3_gadget_giveback(dep, req, -ECONNRESET); - } - - dwc->ep0state = EP0_SETUP_PHASE; - dwc3_ep0_out_start(dwc); -} - -void dwc3_ep0_out_start(struct dwc3 *dwc) -{ - int ret; - - ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, - DWC3_TRBCTL_CONTROL_SETUP); - WARN_ON(ret < 0); -} - -static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le) -{ - struct dwc3_ep *dep; - u32 windex = le16_to_cpu(wIndex_le); - u32 epnum; - - epnum = (windex & USB_ENDPOINT_NUMBER_MASK) << 1; - if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) - epnum |= 1; - - dep = dwc->eps[epnum]; - if (dep->flags & DWC3_EP_ENABLED) - return dep; - - return NULL; -} - -static void dwc3_ep0_status_cmpl(struct usb_ep *ep, struct usb_request *req) -{ -} -/* - * ch 9.4.5 - */ -static int dwc3_ep0_handle_status(struct dwc3 *dwc, - struct usb_ctrlrequest *ctrl) -{ - struct dwc3_ep *dep; - u32 recip; - u16 usb_status = 0; - __le16 *response_pkt; - - recip = ctrl->bRequestType & USB_RECIP_MASK; - switch (recip) { - case USB_RECIP_DEVICE: - /* - * We are self-powered. U1/U2/LTM will be set later - * once we handle this states. RemoteWakeup is 0 on SS - */ - usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; - break; - - case USB_RECIP_INTERFACE: - /* - * Function Remote Wake Capable D0 - * Function Remote Wakeup D1 - */ - break; - - case USB_RECIP_ENDPOINT: - dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); - if (!dep) - return -EINVAL; - - if (dep->flags & DWC3_EP_STALL) - usb_status = 1 << USB_ENDPOINT_HALT; - break; - default: - return -EINVAL; - }; - - response_pkt = (__le16 *) dwc->setup_buf; - *response_pkt = cpu_to_le16(usb_status); - - dep = dwc->eps[0]; - dwc->ep0_usb_req.dep = dep; - dwc->ep0_usb_req.request.length = sizeof(*response_pkt); - dwc->ep0_usb_req.request.buf = dwc->setup_buf; - dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl; - - return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); -} - -static int dwc3_ep0_handle_feature(struct dwc3 *dwc, - struct usb_ctrlrequest *ctrl, int set) -{ - struct dwc3_ep *dep; - u32 recip; - u32 wValue; - u32 wIndex; - int ret; - - wValue = le16_to_cpu(ctrl->wValue); - wIndex = le16_to_cpu(ctrl->wIndex); - recip = ctrl->bRequestType & USB_RECIP_MASK; - switch (recip) { - case USB_RECIP_DEVICE: - - /* - * 9.4.1 says only only for SS, in AddressState only for - * default control pipe - */ - switch (wValue) { - case USB_DEVICE_U1_ENABLE: - case USB_DEVICE_U2_ENABLE: - case USB_DEVICE_LTM_ENABLE: - if (dwc->dev_state != DWC3_CONFIGURED_STATE) - return -EINVAL; - if (dwc->speed != DWC3_DSTS_SUPERSPEED) - return -EINVAL; - } - - /* XXX add U[12] & LTM */ - switch (wValue) { - case USB_DEVICE_REMOTE_WAKEUP: - break; - case USB_DEVICE_U1_ENABLE: - break; - case USB_DEVICE_U2_ENABLE: - break; - case USB_DEVICE_LTM_ENABLE: - break; - - case USB_DEVICE_TEST_MODE: - if ((wIndex & 0xff) != 0) - return -EINVAL; - if (!set) - return -EINVAL; - - dwc->test_mode_nr = wIndex >> 8; - dwc->test_mode = true; - break; - default: - return -EINVAL; - } - break; - - case USB_RECIP_INTERFACE: - switch (wValue) { - case USB_INTRF_FUNC_SUSPEND: - if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) - /* XXX enable Low power suspend */ - ; - if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) - /* XXX enable remote wakeup */ - ; - break; - default: - return -EINVAL; - } - break; - - case USB_RECIP_ENDPOINT: - switch (wValue) { - case USB_ENDPOINT_HALT: - dep = dwc3_wIndex_to_dep(dwc, wIndex); - if (!dep) - return -EINVAL; - ret = __dwc3_gadget_ep_set_halt(dep, set); - if (ret) - return -EINVAL; - break; - default: - return -EINVAL; - } - break; - - default: - return -EINVAL; - }; - - return 0; -} - -static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) -{ - u32 addr; - u32 reg; - - addr = le16_to_cpu(ctrl->wValue); - if (addr > 127) { - dev_dbg(dwc->dev, "invalid device address %d\n", addr); - return -EINVAL; - } - - if (dwc->dev_state == DWC3_CONFIGURED_STATE) { - dev_dbg(dwc->dev, "trying to set address when configured\n"); - return -EINVAL; - } - - reg = dwc3_readl(dwc->regs, DWC3_DCFG); - reg &= ~(DWC3_DCFG_DEVADDR_MASK); - reg |= DWC3_DCFG_DEVADDR(addr); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); - - if (addr) - dwc->dev_state = DWC3_ADDRESS_STATE; - else - dwc->dev_state = DWC3_DEFAULT_STATE; - - return 0; -} - -static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) -{ - int ret; - - spin_unlock(&dwc->lock); - ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); - spin_lock(&dwc->lock); - return ret; -} - -static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) -{ - u32 cfg; - int ret; - - dwc->start_config_issued = false; - cfg = le16_to_cpu(ctrl->wValue); - - switch (dwc->dev_state) { - case DWC3_DEFAULT_STATE: - return -EINVAL; - break; - - case DWC3_ADDRESS_STATE: - ret = dwc3_ep0_delegate_req(dwc, ctrl); - /* if the cfg matches and the cfg is non zero */ - if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { - dwc->dev_state = DWC3_CONFIGURED_STATE; - dwc->resize_fifos = true; - dev_dbg(dwc->dev, "resize fifos flag SET\n"); - } - break; - - case DWC3_CONFIGURED_STATE: - ret = dwc3_ep0_delegate_req(dwc, ctrl); - if (!cfg) - dwc->dev_state = DWC3_ADDRESS_STATE; - break; - default: - ret = -EINVAL; - } - return ret; -} - -static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) -{ - int ret; - - switch (ctrl->bRequest) { - case USB_REQ_GET_STATUS: - dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n"); - ret = dwc3_ep0_handle_status(dwc, ctrl); - break; - case USB_REQ_CLEAR_FEATURE: - dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n"); - ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); - break; - case USB_REQ_SET_FEATURE: - dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n"); - ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); - break; - case USB_REQ_SET_ADDRESS: - dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n"); - ret = dwc3_ep0_set_address(dwc, ctrl); - break; - case USB_REQ_SET_CONFIGURATION: - dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n"); - ret = dwc3_ep0_set_config(dwc, ctrl); - break; - default: - dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); - ret = dwc3_ep0_delegate_req(dwc, ctrl); - break; - }; - - return ret; -} - -static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct usb_ctrlrequest *ctrl = dwc->ctrl_req; - int ret; - u32 len; - - if (!dwc->gadget_driver) - goto err; - - len = le16_to_cpu(ctrl->wLength); - if (!len) { - dwc->three_stage_setup = false; - dwc->ep0_expect_in = false; - dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; - } else { - dwc->three_stage_setup = true; - dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN); - dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; - } - - if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) - ret = dwc3_ep0_std_request(dwc, ctrl); - else - ret = dwc3_ep0_delegate_req(dwc, ctrl); - - if (ret == USB_GADGET_DELAYED_STATUS) - dwc->delayed_status = true; - - if (ret >= 0) - return; - -err: - dwc3_ep0_stall_and_restart(dwc); -} - -static void dwc3_ep0_complete_data(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_request *r = NULL; - struct usb_request *ur; - struct dwc3_trb *trb; - struct dwc3_ep *ep0; - u32 transferred; - u32 length; - u8 epnum; - - epnum = event->endpoint_number; - ep0 = dwc->eps[0]; - - dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; - - r = next_request(&ep0->request_list); - ur = &r->request; - - trb = dwc->ep0_trb; - length = trb->size & DWC3_TRB_SIZE_MASK; - - if (dwc->ep0_bounced) { - unsigned transfer_size = ur->length; - unsigned maxp = ep0->endpoint.maxpacket; - - transfer_size += (maxp - (transfer_size % maxp)); - transferred = min_t(u32, ur->length, - transfer_size - length); - memcpy(ur->buf, dwc->ep0_bounce, transferred); - dwc->ep0_bounced = false; - } else { - transferred = ur->length - length; - } - - ur->actual += transferred; - - if ((epnum & 1) && ur->actual < ur->length) { - /* for some reason we did not get everything out */ - - dwc3_ep0_stall_and_restart(dwc); - } else { - /* - * handle the case where we have to send a zero packet. This - * seems to be case when req.length > maxpacket. Could it be? - */ - if (r) - dwc3_gadget_giveback(ep0, r, 0); - } -} - -static void dwc3_ep0_complete_req(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_request *r; - struct dwc3_ep *dep; - - dep = dwc->eps[0]; - - if (!list_empty(&dep->request_list)) { - r = next_request(&dep->request_list); - - dwc3_gadget_giveback(dep, r, 0); - } - - if (dwc->test_mode) { - int ret; - - ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); - if (ret < 0) { - dev_dbg(dwc->dev, "Invalid Test #%d\n", - dwc->test_mode_nr); - dwc3_ep0_stall_and_restart(dwc); - } - } - - dwc->ep0state = EP0_SETUP_PHASE; - dwc3_ep0_out_start(dwc); -} - -static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; - - dep->flags &= ~DWC3_EP_BUSY; - dep->res_trans_idx = 0; - dwc->setup_packet_pending = false; - - switch (dwc->ep0state) { - case EP0_SETUP_PHASE: - dev_vdbg(dwc->dev, "Inspecting Setup Bytes\n"); - dwc3_ep0_inspect_setup(dwc, event); - break; - - case EP0_DATA_PHASE: - dev_vdbg(dwc->dev, "Data Phase\n"); - dwc3_ep0_complete_data(dwc, event); - break; - - case EP0_STATUS_PHASE: - dev_vdbg(dwc->dev, "Status Phase\n"); - dwc3_ep0_complete_req(dwc, event); - break; - default: - WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state); - } -} - -static void dwc3_ep0_do_control_setup(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - dwc3_ep0_out_start(dwc); -} - -static void dwc3_ep0_do_control_data(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_ep *dep; - struct dwc3_request *req; - int ret; - - dep = dwc->eps[0]; - - if (list_empty(&dep->request_list)) { - dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); - dep->flags |= DWC3_EP_PENDING_REQUEST; - - if (event->endpoint_number) - dep->flags |= DWC3_EP0_DIR_IN; - return; - } - - req = next_request(&dep->request_list); - req->direction = !!event->endpoint_number; - - if (req->request.length == 0) { - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, - dwc->ctrl_req_addr, 0, - DWC3_TRBCTL_CONTROL_DATA); - } else if ((req->request.length % dep->endpoint.maxpacket) - && (event->endpoint_number == 0)) { - ret = usb_gadget_map_request(&dwc->gadget, &req->request, - event->endpoint_number); - if (ret) { - dev_dbg(dwc->dev, "failed to map request\n"); - return; - } - - WARN_ON(req->request.length > dep->endpoint.maxpacket); - - dwc->ep0_bounced = true; - - /* - * REVISIT in case request length is bigger than EP0 - * wMaxPacketSize, we will need two chained TRBs to handle - * the transfer. - */ - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, - dwc->ep0_bounce_addr, dep->endpoint.maxpacket, - DWC3_TRBCTL_CONTROL_DATA); - } else { - ret = usb_gadget_map_request(&dwc->gadget, &req->request, - event->endpoint_number); - if (ret) { - dev_dbg(dwc->dev, "failed to map request\n"); - return; - } - - ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, - req->request.dma, req->request.length, - DWC3_TRBCTL_CONTROL_DATA); - } - - WARN_ON(ret < 0); -} - -static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) -{ - struct dwc3 *dwc = dep->dwc; - u32 type; - - type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 - : DWC3_TRBCTL_CONTROL_STATUS2; - - return dwc3_ep0_start_trans(dwc, dep->number, - dwc->ctrl_req_addr, 0, type); -} - -static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) -{ - struct dwc3_ep *dep = dwc->eps[epnum]; - - if (dwc->resize_fifos) { - dev_dbg(dwc->dev, "starting to resize fifos\n"); - dwc3_gadget_resize_tx_fifos(dwc); - dwc->resize_fifos = 0; - } - - WARN_ON(dwc3_ep0_start_control_status(dep)); -} - -static void dwc3_ep0_xfernotready(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - dwc->setup_packet_pending = true; - - /* - * This part is very tricky: If we has just handled - * XferNotReady(Setup) and we're now expecting a - * XferComplete but, instead, we receive another - * XferNotReady(Setup), we should STALL and restart - * the state machine. - * - * In all other cases, we just continue waiting - * for the XferComplete event. - * - * We are a little bit unsafe here because we're - * not trying to ensure that last event was, indeed, - * XferNotReady(Setup). - * - * Still, we don't expect any condition where that - * should happen and, even if it does, it would be - * another error condition. - */ - if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) { - switch (event->status) { - case DEPEVT_STATUS_CONTROL_SETUP: - dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n"); - dwc3_ep0_stall_and_restart(dwc); - break; - case DEPEVT_STATUS_CONTROL_DATA: - /* FALLTHROUGH */ - case DEPEVT_STATUS_CONTROL_STATUS: - /* FALLTHROUGH */ - default: - dev_vdbg(dwc->dev, "waiting for XferComplete\n"); - } - - return; - } - - switch (event->status) { - case DEPEVT_STATUS_CONTROL_SETUP: - dev_vdbg(dwc->dev, "Control Setup\n"); - - dwc->ep0state = EP0_SETUP_PHASE; - - dwc3_ep0_do_control_setup(dwc, event); - break; - - case DEPEVT_STATUS_CONTROL_DATA: - dev_vdbg(dwc->dev, "Control Data\n"); - - dwc->ep0state = EP0_DATA_PHASE; - - if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { - dev_vdbg(dwc->dev, "Expected %d got %d\n", - dwc->ep0_next_event, - DWC3_EP0_NRDY_DATA); - - dwc3_ep0_stall_and_restart(dwc); - return; - } - - /* - * One of the possible error cases is when Host _does_ - * request for Data Phase, but it does so on the wrong - * direction. - * - * Here, we already know ep0_next_event is DATA (see above), - * so we only need to check for direction. - */ - if (dwc->ep0_expect_in != event->endpoint_number) { - dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); - dwc3_ep0_stall_and_restart(dwc); - return; - } - - dwc3_ep0_do_control_data(dwc, event); - break; - - case DEPEVT_STATUS_CONTROL_STATUS: - dev_vdbg(dwc->dev, "Control Status\n"); - - dwc->ep0state = EP0_STATUS_PHASE; - - if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { - dev_vdbg(dwc->dev, "Expected %d got %d\n", - dwc->ep0_next_event, - DWC3_EP0_NRDY_STATUS); - - dwc3_ep0_stall_and_restart(dwc); - return; - } - - if (dwc->delayed_status) { - WARN_ON_ONCE(event->endpoint_number != 1); - dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); - return; - } - - dwc3_ep0_do_control_status(dwc, event->endpoint_number); - } -} - -void dwc3_ep0_interrupt(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - u8 epnum = event->endpoint_number; - - dev_dbg(dwc->dev, "%s while ep%d%s in state '%s'\n", - dwc3_ep_event_string(event->endpoint_event), - epnum >> 1, (epnum & 1) ? "in" : "out", - dwc3_ep0_state_string(dwc->ep0state)); - - switch (event->endpoint_event) { - case DWC3_DEPEVT_XFERCOMPLETE: - dwc3_ep0_xfer_complete(dwc, event); - break; - - case DWC3_DEPEVT_XFERNOTREADY: - dwc3_ep0_xfernotready(dwc, event); - break; - - case DWC3_DEPEVT_XFERINPROGRESS: - case DWC3_DEPEVT_RXTXFIFOEVT: - case DWC3_DEPEVT_STREAMEVT: - case DWC3_DEPEVT_EPCMDCMPLT: - break; - } -} diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/gadget.c b/ANDROID_3.4.5/drivers/usb/dwc3/gadget.c deleted file mode 100644 index 5255fe97..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/gadget.c +++ /dev/null @@ -1,2396 +0,0 @@ -/** - * gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/list.h> -#include <linux/dma-mapping.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include "core.h" -#include "gadget.h" -#include "io.h" - -/** - * dwc3_gadget_set_test_mode - Enables USB2 Test Modes - * @dwc: pointer to our context structure - * @mode: the mode to set (J, K SE0 NAK, Force Enable) - * - * Caller should take care of locking. This function will - * return 0 on success or -EINVAL if wrong Test Selector - * is passed - */ -int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= ~DWC3_DCTL_TSTCTRL_MASK; - - switch (mode) { - case TEST_J: - case TEST_K: - case TEST_SE0_NAK: - case TEST_PACKET: - case TEST_FORCE_EN: - reg |= mode << 1; - break; - default: - return -EINVAL; - } - - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - return 0; -} - -/** - * dwc3_gadget_set_link_state - Sets USB Link to a particular State - * @dwc: pointer to our context structure - * @state: the state to put link into - * - * Caller should take care of locking. This function will - * return 0 on success or -ETIMEDOUT. - */ -int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) -{ - int retries = 10000; - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; - - /* set requested state */ - reg |= DWC3_DCTL_ULSTCHNGREQ(state); - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - /* wait for a change in DSTS */ - while (--retries) { - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - - if (DWC3_DSTS_USBLNKST(reg) == state) - return 0; - - udelay(5); - } - - dev_vdbg(dwc->dev, "link state change request timed out\n"); - - return -ETIMEDOUT; -} - -/** - * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case - * @dwc: pointer to our context structure - * - * This function will a best effort FIFO allocation in order - * to improve FIFO usage and throughput, while still allowing - * us to enable as many endpoints as possible. - * - * Keep in mind that this operation will be highly dependent - * on the configured size for RAM1 - which contains TxFifo -, - * the amount of endpoints enabled on coreConsultant tool, and - * the width of the Master Bus. - * - * In the ideal world, we would always be able to satisfy the - * following equation: - * - * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \ - * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes - * - * Unfortunately, due to many variables that's not always the case. - */ -int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) -{ - int last_fifo_depth = 0; - int ram1_depth; - int fifo_size; - int mdwidth; - int num; - - if (!dwc->needs_fifo_resize) - return 0; - - ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); - mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); - - /* MDWIDTH is represented in bits, we need it in bytes */ - mdwidth >>= 3; - - /* - * FIXME For now we will only allocate 1 wMaxPacketSize space - * for each enabled endpoint, later patches will come to - * improve this algorithm so that we better use the internal - * FIFO space - */ - for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) { - struct dwc3_ep *dep = dwc->eps[num]; - int fifo_number = dep->number >> 1; - int mult = 1; - int tmp; - - if (!(dep->number & 1)) - continue; - - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - if (usb_endpoint_xfer_bulk(dep->desc) - || usb_endpoint_xfer_isoc(dep->desc)) - mult = 3; - - /* - * REVISIT: the following assumes we will always have enough - * space available on the FIFO RAM for all possible use cases. - * Make sure that's true somehow and change FIFO allocation - * accordingly. - * - * If we have Bulk or Isochronous endpoints, we want - * them to be able to be very, very fast. So we're giving - * those endpoints a fifo_size which is enough for 3 full - * packets - */ - tmp = mult * (dep->endpoint.maxpacket + mdwidth); - tmp += mdwidth; - - fifo_size = DIV_ROUND_UP(tmp, mdwidth); - - fifo_size |= (last_fifo_depth << 16); - - dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n", - dep->name, last_fifo_depth, fifo_size & 0xffff); - - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number), - fifo_size); - - last_fifo_depth += (fifo_size & 0xffff); - } - - return 0; -} - -void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, - int status) -{ - struct dwc3 *dwc = dep->dwc; - - if (req->queued) { - if (req->request.num_mapped_sgs) - dep->busy_slot += req->request.num_mapped_sgs; - else - dep->busy_slot++; - - /* - * Skip LINK TRB. We can't use req->trb and check for - * DWC3_TRBCTL_LINK_TRB because it points the TRB we just - * completed (not the LINK TRB). - */ - if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) - dep->busy_slot++; - } - list_del(&req->list); - req->trb = NULL; - - if (req->request.status == -EINPROGRESS) - req->request.status = status; - - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); - - dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", - req, dep->name, req->request.actual, - req->request.length, status); - - spin_unlock(&dwc->lock); - req->request.complete(&dep->endpoint, &req->request); - spin_lock(&dwc->lock); -} - -static const char *dwc3_gadget_ep_cmd_string(u8 cmd) -{ - switch (cmd) { - case DWC3_DEPCMD_DEPSTARTCFG: - return "Start New Configuration"; - case DWC3_DEPCMD_ENDTRANSFER: - return "End Transfer"; - case DWC3_DEPCMD_UPDATETRANSFER: - return "Update Transfer"; - case DWC3_DEPCMD_STARTTRANSFER: - return "Start Transfer"; - case DWC3_DEPCMD_CLEARSTALL: - return "Clear Stall"; - case DWC3_DEPCMD_SETSTALL: - return "Set Stall"; - case DWC3_DEPCMD_GETSEQNUMBER: - return "Get Data Sequence Number"; - case DWC3_DEPCMD_SETTRANSFRESOURCE: - return "Set Endpoint Transfer Resource"; - case DWC3_DEPCMD_SETEPCONFIG: - return "Set Endpoint Configuration"; - default: - return "UNKNOWN command"; - } -} - -int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, - unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) -{ - struct dwc3_ep *dep = dwc->eps[ep]; - u32 timeout = 500; - u32 reg; - - dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n", - dep->name, - dwc3_gadget_ep_cmd_string(cmd), params->param0, - params->param1, params->param2); - - dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); - dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1); - dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2); - - dwc3_writel(dwc->regs, DWC3_DEPCMD(ep), cmd | DWC3_DEPCMD_CMDACT); - do { - reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(ep)); - if (!(reg & DWC3_DEPCMD_CMDACT)) { - dev_vdbg(dwc->dev, "Command Complete --> %d\n", - DWC3_DEPCMD_STATUS(reg)); - return 0; - } - - /* - * We can't sleep here, because it is also called from - * interrupt context. - */ - timeout--; - if (!timeout) - return -ETIMEDOUT; - - udelay(1); - } while (1); -} - -static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, - struct dwc3_trb *trb) -{ - u32 offset = (char *) trb - (char *) dep->trb_pool; - - return dep->trb_pool_dma + offset; -} - -static int dwc3_alloc_trb_pool(struct dwc3_ep *dep) -{ - struct dwc3 *dwc = dep->dwc; - - if (dep->trb_pool) - return 0; - - if (dep->number == 0 || dep->number == 1) - return 0; - - dep->trb_pool = dma_alloc_coherent(dwc->dev, - sizeof(struct dwc3_trb) * DWC3_TRB_NUM, - &dep->trb_pool_dma, GFP_KERNEL); - if (!dep->trb_pool) { - dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n", - dep->name); - return -ENOMEM; - } - - return 0; -} - -static void dwc3_free_trb_pool(struct dwc3_ep *dep) -{ - struct dwc3 *dwc = dep->dwc; - - dma_free_coherent(dwc->dev, sizeof(struct dwc3_trb) * DWC3_TRB_NUM, - dep->trb_pool, dep->trb_pool_dma); - - dep->trb_pool = NULL; - dep->trb_pool_dma = 0; -} - -static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) -{ - struct dwc3_gadget_ep_cmd_params params; - u32 cmd; - - memset(¶ms, 0x00, sizeof(params)); - - if (dep->number != 1) { - cmd = DWC3_DEPCMD_DEPSTARTCFG; - /* XferRscIdx == 0 for ep0 and 2 for the remaining */ - if (dep->number > 1) { - if (dwc->start_config_issued) - return 0; - dwc->start_config_issued = true; - cmd |= DWC3_DEPCMD_PARAM(2); - } - - return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); - } - - return 0; -} - -static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, - const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) -{ - struct dwc3_gadget_ep_cmd_params params; - - memset(¶ms, 0x00, sizeof(params)); - - params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) - | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) - | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst); - - params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN - | DWC3_DEPCFG_XFER_NOT_READY_EN; - - if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) { - params.param1 |= DWC3_DEPCFG_STREAM_CAPABLE - | DWC3_DEPCFG_STREAM_EVENT_EN; - dep->stream_capable = true; - } - - if (usb_endpoint_xfer_isoc(desc)) - params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; - - /* - * We are doing 1:1 mapping for endpoints, meaning - * Physical Endpoints 2 maps to Logical Endpoint 2 and - * so on. We consider the direction bit as part of the physical - * endpoint number. So USB endpoint 0x81 is 0x03. - */ - params.param1 |= DWC3_DEPCFG_EP_NUMBER(dep->number); - - /* - * We must use the lower 16 TX FIFOs even though - * HW might have more - */ - if (dep->direction) - params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1); - - if (desc->bInterval) { - params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1); - dep->interval = 1 << (desc->bInterval - 1); - } - - return dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_SETEPCONFIG, ¶ms); -} - -static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) -{ - struct dwc3_gadget_ep_cmd_params params; - - memset(¶ms, 0x00, sizeof(params)); - - params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1); - - return dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_SETTRANSFRESOURCE, ¶ms); -} - -/** - * __dwc3_gadget_ep_enable - Initializes a HW endpoint - * @dep: endpoint to be initialized - * @desc: USB Endpoint Descriptor - * - * Caller should take care of locking - */ -static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, - const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) -{ - struct dwc3 *dwc = dep->dwc; - u32 reg; - int ret = -ENOMEM; - - if (!(dep->flags & DWC3_EP_ENABLED)) { - ret = dwc3_gadget_start_config(dwc, dep); - if (ret) - return ret; - } - - ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc); - if (ret) - return ret; - - if (!(dep->flags & DWC3_EP_ENABLED)) { - struct dwc3_trb *trb_st_hw; - struct dwc3_trb *trb_link; - - ret = dwc3_gadget_set_xfer_resource(dwc, dep); - if (ret) - return ret; - - dep->desc = desc; - dep->comp_desc = comp_desc; - dep->type = usb_endpoint_type(desc); - dep->flags |= DWC3_EP_ENABLED; - - reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); - reg |= DWC3_DALEPENA_EP(dep->number); - dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); - - if (!usb_endpoint_xfer_isoc(desc)) - return 0; - - memset(&trb_link, 0, sizeof(trb_link)); - - /* Link TRB for ISOC. The HWO bit is never reset */ - trb_st_hw = &dep->trb_pool[0]; - - trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; - - trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); - trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); - trb_link->ctrl |= DWC3_TRBCTL_LINK_TRB; - trb_link->ctrl |= DWC3_TRB_CTRL_HWO; - } - - return 0; -} - -static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum); -static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) -{ - struct dwc3_request *req; - - if (!list_empty(&dep->req_queued)) - dwc3_stop_active_transfer(dwc, dep->number); - - while (!list_empty(&dep->request_list)) { - req = next_request(&dep->request_list); - - dwc3_gadget_giveback(dep, req, -ESHUTDOWN); - } -} - -/** - * __dwc3_gadget_ep_disable - Disables a HW endpoint - * @dep: the endpoint to disable - * - * This function also removes requests which are currently processed ny the - * hardware and those which are not yet scheduled. - * Caller should take care of locking. - */ -static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) -{ - struct dwc3 *dwc = dep->dwc; - u32 reg; - - dwc3_remove_requests(dwc, dep); - - reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); - reg &= ~DWC3_DALEPENA_EP(dep->number); - dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); - - dep->stream_capable = false; - dep->desc = NULL; - dep->endpoint.desc = NULL; - dep->comp_desc = NULL; - dep->type = 0; - dep->flags = 0; - - return 0; -} - -/* -------------------------------------------------------------------------- */ - -static int dwc3_gadget_ep0_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc) -{ - return -EINVAL; -} - -static int dwc3_gadget_ep0_disable(struct usb_ep *ep) -{ - return -EINVAL; -} - -/* -------------------------------------------------------------------------- */ - -static int dwc3_gadget_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc) -{ - struct dwc3_ep *dep; - struct dwc3 *dwc; - unsigned long flags; - int ret; - - if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { - pr_debug("dwc3: invalid parameters\n"); - return -EINVAL; - } - - if (!desc->wMaxPacketSize) { - pr_debug("dwc3: missing wMaxPacketSize\n"); - return -EINVAL; - } - - dep = to_dwc3_ep(ep); - dwc = dep->dwc; - - switch (usb_endpoint_type(desc)) { - case USB_ENDPOINT_XFER_CONTROL: - strlcat(dep->name, "-control", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_ISOC: - strlcat(dep->name, "-isoc", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_BULK: - strlcat(dep->name, "-bulk", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_INT: - strlcat(dep->name, "-int", sizeof(dep->name)); - break; - default: - dev_err(dwc->dev, "invalid endpoint transfer type\n"); - } - - if (dep->flags & DWC3_EP_ENABLED) { - dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", - dep->name); - return 0; - } - - dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); - - spin_lock_irqsave(&dwc->lock, flags); - ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc); - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static int dwc3_gadget_ep_disable(struct usb_ep *ep) -{ - struct dwc3_ep *dep; - struct dwc3 *dwc; - unsigned long flags; - int ret; - - if (!ep) { - pr_debug("dwc3: invalid parameters\n"); - return -EINVAL; - } - - dep = to_dwc3_ep(ep); - dwc = dep->dwc; - - if (!(dep->flags & DWC3_EP_ENABLED)) { - dev_WARN_ONCE(dwc->dev, true, "%s is already disabled\n", - dep->name); - return 0; - } - - snprintf(dep->name, sizeof(dep->name), "ep%d%s", - dep->number >> 1, - (dep->number & 1) ? "in" : "out"); - - spin_lock_irqsave(&dwc->lock, flags); - ret = __dwc3_gadget_ep_disable(dep); - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, - gfp_t gfp_flags) -{ - struct dwc3_request *req; - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - - req = kzalloc(sizeof(*req), gfp_flags); - if (!req) { - dev_err(dwc->dev, "not enough memory\n"); - return NULL; - } - - req->epnum = dep->number; - req->dep = dep; - - return &req->request; -} - -static void dwc3_gadget_ep_free_request(struct usb_ep *ep, - struct usb_request *request) -{ - struct dwc3_request *req = to_dwc3_request(request); - - kfree(req); -} - -/** - * dwc3_prepare_one_trb - setup one TRB from one request - * @dep: endpoint for which this request is prepared - * @req: dwc3_request pointer - */ -static void dwc3_prepare_one_trb(struct dwc3_ep *dep, - struct dwc3_request *req, dma_addr_t dma, - unsigned length, unsigned last, unsigned chain) -{ - struct dwc3 *dwc = dep->dwc; - struct dwc3_trb *trb; - - unsigned int cur_slot; - - dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", - dep->name, req, (unsigned long long) dma, - length, last ? " last" : "", - chain ? " chain" : ""); - - trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; - cur_slot = dep->free_slot; - dep->free_slot++; - - /* Skip the LINK-TRB on ISOC */ - if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) - return; - - if (!req->trb) { - dwc3_gadget_move_request_queued(req); - req->trb = trb; - req->trb_dma = dwc3_trb_dma_offset(dep, trb); - } - - trb->size = DWC3_TRB_SIZE_LENGTH(length); - trb->bpl = lower_32_bits(dma); - trb->bph = upper_32_bits(dma); - - switch (usb_endpoint_type(dep->desc)) { - case USB_ENDPOINT_XFER_CONTROL: - trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; - break; - - case USB_ENDPOINT_XFER_ISOC: - trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; - - /* IOC every DWC3_TRB_NUM / 4 so we can refill */ - if (!(cur_slot % (DWC3_TRB_NUM / 4))) - trb->ctrl |= DWC3_TRB_CTRL_IOC; - break; - - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - trb->ctrl = DWC3_TRBCTL_NORMAL; - break; - default: - /* - * This is only possible with faulty memory because we - * checked it already :) - */ - BUG(); - } - - if (usb_endpoint_xfer_isoc(dep->desc)) { - trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; - trb->ctrl |= DWC3_TRB_CTRL_CSP; - } else { - if (chain) - trb->ctrl |= DWC3_TRB_CTRL_CHN; - - if (last) - trb->ctrl |= DWC3_TRB_CTRL_LST; - } - - if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) - trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); - - trb->ctrl |= DWC3_TRB_CTRL_HWO; -} - -/* - * dwc3_prepare_trbs - setup TRBs from requests - * @dep: endpoint for which requests are being prepared - * @starting: true if the endpoint is idle and no requests are queued. - * - * The function goes through the requests list and sets up TRBs for the - * transfers. The function returns once there are no more TRBs available or - * it runs out of requests. - */ -static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) -{ - struct dwc3_request *req, *n; - u32 trbs_left; - u32 max; - unsigned int last_one = 0; - - BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); - - /* the first request must not be queued */ - trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; - - /* Can't wrap around on a non-isoc EP since there's no link TRB */ - if (!usb_endpoint_xfer_isoc(dep->desc)) { - max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); - if (trbs_left > max) - trbs_left = max; - } - - /* - * If busy & slot are equal than it is either full or empty. If we are - * starting to process requests then we are empty. Otherwise we are - * full and don't do anything - */ - if (!trbs_left) { - if (!starting) - return; - trbs_left = DWC3_TRB_NUM; - /* - * In case we start from scratch, we queue the ISOC requests - * starting from slot 1. This is done because we use ring - * buffer and have no LST bit to stop us. Instead, we place - * IOC bit every TRB_NUM/4. We try to avoid having an interrupt - * after the first request so we start at slot 1 and have - * 7 requests proceed before we hit the first IOC. - * Other transfer types don't use the ring buffer and are - * processed from the first TRB until the last one. Since we - * don't wrap around we have to start at the beginning. - */ - if (usb_endpoint_xfer_isoc(dep->desc)) { - dep->busy_slot = 1; - dep->free_slot = 1; - } else { - dep->busy_slot = 0; - dep->free_slot = 0; - } - } - - /* The last TRB is a link TRB, not used for xfer */ - if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) - return; - - list_for_each_entry_safe(req, n, &dep->request_list, list) { - unsigned length; - dma_addr_t dma; - - if (req->request.num_mapped_sgs > 0) { - struct usb_request *request = &req->request; - struct scatterlist *sg = request->sg; - struct scatterlist *s; - int i; - - for_each_sg(sg, s, request->num_mapped_sgs, i) { - unsigned chain = true; - - length = sg_dma_len(s); - dma = sg_dma_address(s); - - if (i == (request->num_mapped_sgs - 1) || - sg_is_last(s)) { - last_one = true; - chain = false; - } - - trbs_left--; - if (!trbs_left) - last_one = true; - - if (last_one) - chain = false; - - dwc3_prepare_one_trb(dep, req, dma, length, - last_one, chain); - - if (last_one) - break; - } - } else { - dma = req->request.dma; - length = req->request.length; - trbs_left--; - - if (!trbs_left) - last_one = 1; - - /* Is this the last request? */ - if (list_is_last(&req->list, &dep->request_list)) - last_one = 1; - - dwc3_prepare_one_trb(dep, req, dma, length, - last_one, false); - - if (last_one) - break; - } - } -} - -static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, - int start_new) -{ - struct dwc3_gadget_ep_cmd_params params; - struct dwc3_request *req; - struct dwc3 *dwc = dep->dwc; - int ret; - u32 cmd; - - if (start_new && (dep->flags & DWC3_EP_BUSY)) { - dev_vdbg(dwc->dev, "%s: endpoint busy\n", dep->name); - return -EBUSY; - } - dep->flags &= ~DWC3_EP_PENDING_REQUEST; - - /* - * If we are getting here after a short-out-packet we don't enqueue any - * new requests as we try to set the IOC bit only on the last request. - */ - if (start_new) { - if (list_empty(&dep->req_queued)) - dwc3_prepare_trbs(dep, start_new); - - /* req points to the first request which will be sent */ - req = next_request(&dep->req_queued); - } else { - dwc3_prepare_trbs(dep, start_new); - - /* - * req points to the first request where HWO changed from 0 to 1 - */ - req = next_request(&dep->req_queued); - } - if (!req) { - dep->flags |= DWC3_EP_PENDING_REQUEST; - return 0; - } - - memset(¶ms, 0, sizeof(params)); - params.param0 = upper_32_bits(req->trb_dma); - params.param1 = lower_32_bits(req->trb_dma); - - if (start_new) - cmd = DWC3_DEPCMD_STARTTRANSFER; - else - cmd = DWC3_DEPCMD_UPDATETRANSFER; - - cmd |= DWC3_DEPCMD_PARAM(cmd_param); - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); - if (ret < 0) { - dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n"); - - /* - * FIXME we need to iterate over the list of requests - * here and stop, unmap, free and del each of the linked - * requests instead of what we do now. - */ - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); - list_del(&req->list); - return ret; - } - - dep->flags |= DWC3_EP_BUSY; - dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, - dep->number); - - WARN_ON_ONCE(!dep->res_trans_idx); - - return 0; -} - -static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) -{ - struct dwc3 *dwc = dep->dwc; - int ret; - - req->request.actual = 0; - req->request.status = -EINPROGRESS; - req->direction = dep->direction; - req->epnum = dep->number; - - /* - * We only add to our list of requests now and - * start consuming the list once we get XferNotReady - * IRQ. - * - * That way, we avoid doing anything that we don't need - * to do now and defer it until the point we receive a - * particular token from the Host side. - * - * This will also avoid Host cancelling URBs due to too - * many NAKs. - */ - ret = usb_gadget_map_request(&dwc->gadget, &req->request, - dep->direction); - if (ret) - return ret; - - list_add_tail(&req->list, &dep->request_list); - - /* - * There is one special case: XferNotReady with - * empty list of requests. We need to kick the - * transfer here in that situation, otherwise - * we will be NAKing forever. - * - * If we get XferNotReady before gadget driver - * has a chance to queue a request, we will ACK - * the IRQ but won't be able to receive the data - * until the next request is queued. The following - * code is handling exactly that. - */ - if (dep->flags & DWC3_EP_PENDING_REQUEST) { - int ret; - int start_trans; - - start_trans = 1; - if (usb_endpoint_xfer_isoc(dep->desc) && - (dep->flags & DWC3_EP_BUSY)) - start_trans = 0; - - ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans); - if (ret && ret != -EBUSY) { - struct dwc3 *dwc = dep->dwc; - - dev_dbg(dwc->dev, "%s: failed to kick transfers\n", - dep->name); - } - }; - - return 0; -} - -static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, - gfp_t gfp_flags) -{ - struct dwc3_request *req = to_dwc3_request(request); - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - - unsigned long flags; - - int ret; - - if (!dep->desc) { - dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", - request, ep->name); - return -ESHUTDOWN; - } - - dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", - request, ep->name, request->length); - - spin_lock_irqsave(&dwc->lock, flags); - ret = __dwc3_gadget_ep_queue(dep, req); - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, - struct usb_request *request) -{ - struct dwc3_request *req = to_dwc3_request(request); - struct dwc3_request *r = NULL; - - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dwc->lock, flags); - - list_for_each_entry(r, &dep->request_list, list) { - if (r == req) - break; - } - - if (r != req) { - list_for_each_entry(r, &dep->req_queued, list) { - if (r == req) - break; - } - if (r == req) { - /* wait until it is processed */ - dwc3_stop_active_transfer(dwc, dep->number); - goto out0; - } - dev_err(dwc->dev, "request %p was not queued to %s\n", - request, ep->name); - ret = -EINVAL; - goto out0; - } - - /* giveback the request */ - dwc3_gadget_giveback(dep, req, -ECONNRESET); - -out0: - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) -{ - struct dwc3_gadget_ep_cmd_params params; - struct dwc3 *dwc = dep->dwc; - int ret; - - memset(¶ms, 0x00, sizeof(params)); - - if (value) { - if (dep->number == 0 || dep->number == 1) { - /* - * Whenever EP0 is stalled, we will restart - * the state machine, thus moving back to - * Setup Phase - */ - dwc->ep0state = EP0_SETUP_PHASE; - } - - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_SETSTALL, ¶ms); - if (ret) - dev_err(dwc->dev, "failed to %s STALL on %s\n", - value ? "set" : "clear", - dep->name); - else - dep->flags |= DWC3_EP_STALL; - } else { - if (dep->flags & DWC3_EP_WEDGE) - return 0; - - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_CLEARSTALL, ¶ms); - if (ret) - dev_err(dwc->dev, "failed to %s STALL on %s\n", - value ? "set" : "clear", - dep->name); - else - dep->flags &= ~DWC3_EP_STALL; - } - - return ret; -} - -static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) -{ - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - - unsigned long flags; - - int ret; - - spin_lock_irqsave(&dwc->lock, flags); - - if (usb_endpoint_xfer_isoc(dep->desc)) { - dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); - ret = -EINVAL; - goto out; - } - - ret = __dwc3_gadget_ep_set_halt(dep, value); -out: - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) -{ - struct dwc3_ep *dep = to_dwc3_ep(ep); - struct dwc3 *dwc = dep->dwc; - unsigned long flags; - - spin_lock_irqsave(&dwc->lock, flags); - dep->flags |= DWC3_EP_WEDGE; - spin_unlock_irqrestore(&dwc->lock, flags); - - return dwc3_gadget_ep_set_halt(ep, 1); -} - -/* -------------------------------------------------------------------------- */ - -static struct usb_endpoint_descriptor dwc3_gadget_ep0_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, -}; - -static const struct usb_ep_ops dwc3_gadget_ep0_ops = { - .enable = dwc3_gadget_ep0_enable, - .disable = dwc3_gadget_ep0_disable, - .alloc_request = dwc3_gadget_ep_alloc_request, - .free_request = dwc3_gadget_ep_free_request, - .queue = dwc3_gadget_ep0_queue, - .dequeue = dwc3_gadget_ep_dequeue, - .set_halt = dwc3_gadget_ep_set_halt, - .set_wedge = dwc3_gadget_ep_set_wedge, -}; - -static const struct usb_ep_ops dwc3_gadget_ep_ops = { - .enable = dwc3_gadget_ep_enable, - .disable = dwc3_gadget_ep_disable, - .alloc_request = dwc3_gadget_ep_alloc_request, - .free_request = dwc3_gadget_ep_free_request, - .queue = dwc3_gadget_ep_queue, - .dequeue = dwc3_gadget_ep_dequeue, - .set_halt = dwc3_gadget_ep_set_halt, - .set_wedge = dwc3_gadget_ep_set_wedge, -}; - -/* -------------------------------------------------------------------------- */ - -static int dwc3_gadget_get_frame(struct usb_gadget *g) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - return DWC3_DSTS_SOFFN(reg); -} - -static int dwc3_gadget_wakeup(struct usb_gadget *g) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - - unsigned long timeout; - unsigned long flags; - - u32 reg; - - int ret = 0; - - u8 link_state; - u8 speed; - - spin_lock_irqsave(&dwc->lock, flags); - - /* - * According to the Databook Remote wakeup request should - * be issued only when the device is in early suspend state. - * - * We can check that via USB Link State bits in DSTS register. - */ - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - - speed = reg & DWC3_DSTS_CONNECTSPD; - if (speed == DWC3_DSTS_SUPERSPEED) { - dev_dbg(dwc->dev, "no wakeup on SuperSpeed\n"); - ret = -EINVAL; - goto out; - } - - link_state = DWC3_DSTS_USBLNKST(reg); - - switch (link_state) { - case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */ - case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */ - break; - default: - dev_dbg(dwc->dev, "can't wakeup from link state %d\n", - link_state); - ret = -EINVAL; - goto out; - } - - ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); - if (ret < 0) { - dev_err(dwc->dev, "failed to put link in Recovery\n"); - goto out; - } - - /* write zeroes to Link Change Request */ - reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - /* poll until Link State changes to ON */ - timeout = jiffies + msecs_to_jiffies(100); - - while (!time_after(jiffies, timeout)) { - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - - /* in HS, means ON */ - if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) - break; - } - - if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { - dev_err(dwc->dev, "failed to send remote wakeup\n"); - ret = -EINVAL; - } - -out: - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, - int is_selfpowered) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - unsigned long flags; - - spin_lock_irqsave(&dwc->lock, flags); - dwc->is_selfpowered = !!is_selfpowered; - spin_unlock_irqrestore(&dwc->lock, flags); - - return 0; -} - -static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) -{ - u32 reg; - u32 timeout = 500; - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (is_on) { - reg &= ~DWC3_DCTL_TRGTULST_MASK; - reg |= (DWC3_DCTL_RUN_STOP - | DWC3_DCTL_TRGTULST_RX_DET); - } else { - reg &= ~DWC3_DCTL_RUN_STOP; - } - - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - do { - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - if (is_on) { - if (!(reg & DWC3_DSTS_DEVCTRLHLT)) - break; - } else { - if (reg & DWC3_DSTS_DEVCTRLHLT) - break; - } - timeout--; - if (!timeout) - break; - udelay(1); - } while (1); - - dev_vdbg(dwc->dev, "gadget %s data soft-%s\n", - dwc->gadget_driver - ? dwc->gadget_driver->function : "no-function", - is_on ? "connect" : "disconnect"); -} - -static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - unsigned long flags; - - is_on = !!is_on; - - spin_lock_irqsave(&dwc->lock, flags); - dwc3_gadget_run_stop(dwc, is_on); - spin_unlock_irqrestore(&dwc->lock, flags); - - return 0; -} - -static int dwc3_gadget_start(struct usb_gadget *g, - struct usb_gadget_driver *driver) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - struct dwc3_ep *dep; - unsigned long flags; - int ret = 0; - u32 reg; - - spin_lock_irqsave(&dwc->lock, flags); - - if (dwc->gadget_driver) { - dev_err(dwc->dev, "%s is already bound to %s\n", - dwc->gadget.name, - dwc->gadget_driver->driver.name); - ret = -EBUSY; - goto err0; - } - - dwc->gadget_driver = driver; - dwc->gadget.dev.driver = &driver->driver; - - reg = dwc3_readl(dwc->regs, DWC3_DCFG); - reg &= ~(DWC3_DCFG_SPEED_MASK); - reg |= dwc->maximum_speed; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); - - dwc->start_config_issued = false; - - /* Start with SuperSpeed Default */ - dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); - - dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); - if (ret) { - dev_err(dwc->dev, "failed to enable %s\n", dep->name); - goto err0; - } - - dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); - if (ret) { - dev_err(dwc->dev, "failed to enable %s\n", dep->name); - goto err1; - } - - /* begin to receive SETUP packets */ - dwc->ep0state = EP0_SETUP_PHASE; - dwc3_ep0_out_start(dwc); - - spin_unlock_irqrestore(&dwc->lock, flags); - - return 0; - -err1: - __dwc3_gadget_ep_disable(dwc->eps[0]); - -err0: - spin_unlock_irqrestore(&dwc->lock, flags); - - return ret; -} - -static int dwc3_gadget_stop(struct usb_gadget *g, - struct usb_gadget_driver *driver) -{ - struct dwc3 *dwc = gadget_to_dwc(g); - unsigned long flags; - - spin_lock_irqsave(&dwc->lock, flags); - - __dwc3_gadget_ep_disable(dwc->eps[0]); - __dwc3_gadget_ep_disable(dwc->eps[1]); - - dwc->gadget_driver = NULL; - dwc->gadget.dev.driver = NULL; - - spin_unlock_irqrestore(&dwc->lock, flags); - - return 0; -} -static const struct usb_gadget_ops dwc3_gadget_ops = { - .get_frame = dwc3_gadget_get_frame, - .wakeup = dwc3_gadget_wakeup, - .set_selfpowered = dwc3_gadget_set_selfpowered, - .pullup = dwc3_gadget_pullup, - .udc_start = dwc3_gadget_start, - .udc_stop = dwc3_gadget_stop, -}; - -/* -------------------------------------------------------------------------- */ - -static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc) -{ - struct dwc3_ep *dep; - u8 epnum; - - INIT_LIST_HEAD(&dwc->gadget.ep_list); - - for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - dep = kzalloc(sizeof(*dep), GFP_KERNEL); - if (!dep) { - dev_err(dwc->dev, "can't allocate endpoint %d\n", - epnum); - return -ENOMEM; - } - - dep->dwc = dwc; - dep->number = epnum; - dwc->eps[epnum] = dep; - - snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, - (epnum & 1) ? "in" : "out"); - dep->endpoint.name = dep->name; - dep->direction = (epnum & 1); - - if (epnum == 0 || epnum == 1) { - dep->endpoint.maxpacket = 512; - dep->endpoint.ops = &dwc3_gadget_ep0_ops; - if (!epnum) - dwc->gadget.ep0 = &dep->endpoint; - } else { - int ret; - - dep->endpoint.maxpacket = 1024; - dep->endpoint.max_streams = 15; - dep->endpoint.ops = &dwc3_gadget_ep_ops; - list_add_tail(&dep->endpoint.ep_list, - &dwc->gadget.ep_list); - - ret = dwc3_alloc_trb_pool(dep); - if (ret) - return ret; - } - - INIT_LIST_HEAD(&dep->request_list); - INIT_LIST_HEAD(&dep->req_queued); - } - - return 0; -} - -static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) -{ - struct dwc3_ep *dep; - u8 epnum; - - for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - dep = dwc->eps[epnum]; - dwc3_free_trb_pool(dep); - - if (epnum != 0 && epnum != 1) - list_del(&dep->endpoint.ep_list); - - kfree(dep); - } -} - -static void dwc3_gadget_release(struct device *dev) -{ - dev_dbg(dev, "%s\n", __func__); -} - -/* -------------------------------------------------------------------------- */ -static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, - const struct dwc3_event_depevt *event, int status) -{ - struct dwc3_request *req; - struct dwc3_trb *trb; - unsigned int count; - unsigned int s_pkt = 0; - - do { - req = next_request(&dep->req_queued); - if (!req) { - WARN_ON_ONCE(1); - return 1; - } - - trb = req->trb; - - if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) - /* - * We continue despite the error. There is not much we - * can do. If we don't clean it up we loop forever. If - * we skip the TRB then it gets overwritten after a - * while since we use them in a ring buffer. A BUG() - * would help. Lets hope that if this occurs, someone - * fixes the root cause instead of looking away :) - */ - dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", - dep->name, req->trb); - count = trb->size & DWC3_TRB_SIZE_MASK; - - if (dep->direction) { - if (count) { - dev_err(dwc->dev, "incomplete IN transfer %s\n", - dep->name); - status = -ECONNRESET; - } - } else { - if (count && (event->status & DEPEVT_STATUS_SHORT)) - s_pkt = 1; - } - - /* - * We assume here we will always receive the entire data block - * which we should receive. Meaning, if we program RX to - * receive 4K but we receive only 2K, we assume that's all we - * should receive and we simply bounce the request back to the - * gadget driver for further processing. - */ - req->request.actual += req->request.length - count; - dwc3_gadget_giveback(dep, req, status); - if (s_pkt) - break; - if ((event->status & DEPEVT_STATUS_LST) && - (trb->ctrl & DWC3_TRB_CTRL_LST)) - break; - if ((event->status & DEPEVT_STATUS_IOC) && - (trb->ctrl & DWC3_TRB_CTRL_IOC)) - break; - } while (1); - - if ((event->status & DEPEVT_STATUS_IOC) && - (trb->ctrl & DWC3_TRB_CTRL_IOC)) - return 0; - return 1; -} - -static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, - struct dwc3_ep *dep, const struct dwc3_event_depevt *event, - int start_new) -{ - unsigned status = 0; - int clean_busy; - - if (event->status & DEPEVT_STATUS_BUSERR) - status = -ECONNRESET; - - clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); - if (clean_busy) - dep->flags &= ~DWC3_EP_BUSY; - - /* - * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround. - * See dwc3_gadget_linksts_change_interrupt() for 1st half. - */ - if (dwc->revision < DWC3_REVISION_183A) { - u32 reg; - int i; - - for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { - struct dwc3_ep *dep = dwc->eps[i]; - - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - if (!list_empty(&dep->req_queued)) - return; - } - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg |= dwc->u1u2; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - dwc->u1u2 = 0; - } -} - -static void dwc3_gadget_start_isoc(struct dwc3 *dwc, - struct dwc3_ep *dep, const struct dwc3_event_depevt *event) -{ - u32 uf, mask; - - if (list_empty(&dep->request_list)) { - dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", - dep->name); - return; - } - - mask = ~(dep->interval - 1); - uf = event->parameters & mask; - /* 4 micro frames in the future */ - uf += dep->interval * 4; - - __dwc3_gadget_kick_transfer(dep, uf, 1); -} - -static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, - const struct dwc3_event_depevt *event) -{ - struct dwc3 *dwc = dep->dwc; - struct dwc3_event_depevt mod_ev = *event; - - /* - * We were asked to remove one request. It is possible that this - * request and a few others were started together and have the same - * transfer index. Since we stopped the complete endpoint we don't - * know how many requests were already completed (and not yet) - * reported and how could be done (later). We purge them all until - * the end of the list. - */ - mod_ev.status = DEPEVT_STATUS_LST; - dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); - dep->flags &= ~DWC3_EP_BUSY; - /* pending requests are ignored and are queued on XferNotReady */ -} - -static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, - const struct dwc3_event_depevt *event) -{ - u32 param = event->parameters; - u32 cmd_type = (param >> 8) & ((1 << 5) - 1); - - switch (cmd_type) { - case DWC3_DEPCMD_ENDTRANSFER: - dwc3_process_ep_cmd_complete(dep, event); - break; - case DWC3_DEPCMD_STARTTRANSFER: - dep->res_trans_idx = param & 0x7f; - break; - default: - printk(KERN_ERR "%s() unknown /unexpected type: %d\n", - __func__, cmd_type); - break; - }; -} - -static void dwc3_endpoint_interrupt(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_ep *dep; - u8 epnum = event->endpoint_number; - - dep = dwc->eps[epnum]; - - dev_vdbg(dwc->dev, "%s: %s\n", dep->name, - dwc3_ep_event_string(event->endpoint_event)); - - if (epnum == 0 || epnum == 1) { - dwc3_ep0_interrupt(dwc, event); - return; - } - - switch (event->endpoint_event) { - case DWC3_DEPEVT_XFERCOMPLETE: - dep->res_trans_idx = 0; - - if (usb_endpoint_xfer_isoc(dep->desc)) { - dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", - dep->name); - return; - } - - dwc3_endpoint_transfer_complete(dwc, dep, event, 1); - break; - case DWC3_DEPEVT_XFERINPROGRESS: - if (!usb_endpoint_xfer_isoc(dep->desc)) { - dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", - dep->name); - return; - } - - dwc3_endpoint_transfer_complete(dwc, dep, event, 0); - break; - case DWC3_DEPEVT_XFERNOTREADY: - if (usb_endpoint_xfer_isoc(dep->desc)) { - dwc3_gadget_start_isoc(dwc, dep, event); - } else { - int ret; - - dev_vdbg(dwc->dev, "%s: reason %s\n", - dep->name, event->status & - DEPEVT_STATUS_TRANSFER_ACTIVE - ? "Transfer Active" - : "Transfer Not Active"); - - ret = __dwc3_gadget_kick_transfer(dep, 0, 1); - if (!ret || ret == -EBUSY) - return; - - dev_dbg(dwc->dev, "%s: failed to kick transfers\n", - dep->name); - } - - break; - case DWC3_DEPEVT_STREAMEVT: - if (!usb_endpoint_xfer_bulk(dep->desc)) { - dev_err(dwc->dev, "Stream event for non-Bulk %s\n", - dep->name); - return; - } - - switch (event->status) { - case DEPEVT_STREAMEVT_FOUND: - dev_vdbg(dwc->dev, "Stream %d found and started\n", - event->parameters); - - break; - case DEPEVT_STREAMEVT_NOTFOUND: - /* FALLTHROUGH */ - default: - dev_dbg(dwc->dev, "Couldn't find suitable stream\n"); - } - break; - case DWC3_DEPEVT_RXTXFIFOEVT: - dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); - break; - case DWC3_DEPEVT_EPCMDCMPLT: - dwc3_ep_cmd_compl(dep, event); - break; - } -} - -static void dwc3_disconnect_gadget(struct dwc3 *dwc) -{ - if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { - spin_unlock(&dwc->lock); - dwc->gadget_driver->disconnect(&dwc->gadget); - spin_lock(&dwc->lock); - } -} - -static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) -{ - struct dwc3_ep *dep; - struct dwc3_gadget_ep_cmd_params params; - u32 cmd; - int ret; - - dep = dwc->eps[epnum]; - - WARN_ON(!dep->res_trans_idx); - if (dep->res_trans_idx) { - cmd = DWC3_DEPCMD_ENDTRANSFER; - cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; - cmd |= DWC3_DEPCMD_PARAM(dep->res_trans_idx); - memset(¶ms, 0, sizeof(params)); - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); - WARN_ON_ONCE(ret); - dep->res_trans_idx = 0; - } -} - -static void dwc3_stop_active_transfers(struct dwc3 *dwc) -{ - u32 epnum; - - for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - struct dwc3_ep *dep; - - dep = dwc->eps[epnum]; - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - dwc3_remove_requests(dwc, dep); - } -} - -static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) -{ - u32 epnum; - - for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - struct dwc3_ep *dep; - struct dwc3_gadget_ep_cmd_params params; - int ret; - - dep = dwc->eps[epnum]; - - if (!(dep->flags & DWC3_EP_STALL)) - continue; - - dep->flags &= ~DWC3_EP_STALL; - - memset(¶ms, 0, sizeof(params)); - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_CLEARSTALL, ¶ms); - WARN_ON_ONCE(ret); - } -} - -static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) -{ - dev_vdbg(dwc->dev, "%s\n", __func__); -#if 0 - XXX - U1/U2 is powersave optimization. Skip it for now. Anyway we need to - enable it before we can disable it. - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= ~DWC3_DCTL_INITU1ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - reg &= ~DWC3_DCTL_INITU2ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); -#endif - - dwc3_stop_active_transfers(dwc); - dwc3_disconnect_gadget(dwc); - dwc->start_config_issued = false; - - dwc->gadget.speed = USB_SPEED_UNKNOWN; - dwc->setup_packet_pending = false; -} - -static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - - if (on) - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - else - reg |= DWC3_GUSB3PIPECTL_SUSPHY; - - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); -} - -static void dwc3_gadget_usb2_phy_power(struct dwc3 *dwc, int on) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - - if (on) - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - else - reg |= DWC3_GUSB2PHYCFG_SUSPHY; - - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); -} - -static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) -{ - u32 reg; - - dev_vdbg(dwc->dev, "%s\n", __func__); - - /* - * WORKAROUND: DWC3 revisions <1.88a have an issue which - * would cause a missing Disconnect Event if there's a - * pending Setup Packet in the FIFO. - * - * There's no suggested workaround on the official Bug - * report, which states that "unless the driver/application - * is doing any special handling of a disconnect event, - * there is no functional issue". - * - * Unfortunately, it turns out that we _do_ some special - * handling of a disconnect event, namely complete all - * pending transfers, notify gadget driver of the - * disconnection, and so on. - * - * Our suggested workaround is to follow the Disconnect - * Event steps here, instead, based on a setup_packet_pending - * flag. Such flag gets set whenever we have a XferNotReady - * event on EP0 and gets cleared on XferComplete for the - * same endpoint. - * - * Refers to: - * - * STAR#9000466709: RTL: Device : Disconnect event not - * generated if setup packet pending in FIFO - */ - if (dwc->revision < DWC3_REVISION_188A) { - if (dwc->setup_packet_pending) - dwc3_gadget_disconnect_interrupt(dwc); - } - - /* after reset -> Default State */ - dwc->dev_state = DWC3_DEFAULT_STATE; - - /* Enable PHYs */ - dwc3_gadget_usb2_phy_power(dwc, true); - dwc3_gadget_usb3_phy_power(dwc, true); - - if (dwc->gadget.speed != USB_SPEED_UNKNOWN) - dwc3_disconnect_gadget(dwc); - - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= ~DWC3_DCTL_TSTCTRL_MASK; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - dwc->test_mode = false; - - dwc3_stop_active_transfers(dwc); - dwc3_clear_stall_all_ep(dwc); - dwc->start_config_issued = false; - - /* Reset device address to zero */ - reg = dwc3_readl(dwc->regs, DWC3_DCFG); - reg &= ~(DWC3_DCFG_DEVADDR_MASK); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); -} - -static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) -{ - u32 reg; - u32 usb30_clock = DWC3_GCTL_CLK_BUS; - - /* - * We change the clock only at SS but I dunno why I would want to do - * this. Maybe it becomes part of the power saving plan. - */ - - if (speed != DWC3_DSTS_SUPERSPEED) - return; - - /* - * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed - * each time on Connect Done. - */ - if (!usb30_clock) - return; - - reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg |= DWC3_GCTL_RAMCLKSEL(usb30_clock); - dwc3_writel(dwc->regs, DWC3_GCTL, reg); -} - -static void dwc3_gadget_disable_phy(struct dwc3 *dwc, u8 speed) -{ - switch (speed) { - case USB_SPEED_SUPER: - dwc3_gadget_usb2_phy_power(dwc, false); - break; - case USB_SPEED_HIGH: - case USB_SPEED_FULL: - case USB_SPEED_LOW: - dwc3_gadget_usb3_phy_power(dwc, false); - break; - } -} - -static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) -{ - struct dwc3_gadget_ep_cmd_params params; - struct dwc3_ep *dep; - int ret; - u32 reg; - u8 speed; - - dev_vdbg(dwc->dev, "%s\n", __func__); - - memset(¶ms, 0x00, sizeof(params)); - - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - speed = reg & DWC3_DSTS_CONNECTSPD; - dwc->speed = speed; - - dwc3_update_ram_clk_sel(dwc, speed); - - switch (speed) { - case DWC3_DCFG_SUPERSPEED: - /* - * WORKAROUND: DWC3 revisions <1.90a have an issue which - * would cause a missing USB3 Reset event. - * - * In such situations, we should force a USB3 Reset - * event by calling our dwc3_gadget_reset_interrupt() - * routine. - * - * Refers to: - * - * STAR#9000483510: RTL: SS : USB3 reset event may - * not be generated always when the link enters poll - */ - if (dwc->revision < DWC3_REVISION_190A) - dwc3_gadget_reset_interrupt(dwc); - - dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); - dwc->gadget.ep0->maxpacket = 512; - dwc->gadget.speed = USB_SPEED_SUPER; - break; - case DWC3_DCFG_HIGHSPEED: - dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); - dwc->gadget.ep0->maxpacket = 64; - dwc->gadget.speed = USB_SPEED_HIGH; - break; - case DWC3_DCFG_FULLSPEED2: - case DWC3_DCFG_FULLSPEED1: - dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); - dwc->gadget.ep0->maxpacket = 64; - dwc->gadget.speed = USB_SPEED_FULL; - break; - case DWC3_DCFG_LOWSPEED: - dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); - dwc->gadget.ep0->maxpacket = 8; - dwc->gadget.speed = USB_SPEED_LOW; - break; - } - - /* Disable unneded PHY */ - dwc3_gadget_disable_phy(dwc, dwc->gadget.speed); - - dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); - if (ret) { - dev_err(dwc->dev, "failed to enable %s\n", dep->name); - return; - } - - dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); - if (ret) { - dev_err(dwc->dev, "failed to enable %s\n", dep->name); - return; - } - - /* - * Configure PHY via GUSB3PIPECTLn if required. - * - * Update GTXFIFOSIZn - * - * In both cases reset values should be sufficient. - */ -} - -static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) -{ - dev_vdbg(dwc->dev, "%s\n", __func__); - - /* - * TODO take core out of low power mode when that's - * implemented. - */ - - dwc->gadget_driver->resume(&dwc->gadget); -} - -static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, - unsigned int evtinfo) -{ - enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; - - /* - * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending - * on the link partner, the USB session might do multiple entry/exit - * of low power states before a transfer takes place. - * - * Due to this problem, we might experience lower throughput. The - * suggested workaround is to disable DCTL[12:9] bits if we're - * transitioning from U1/U2 to U0 and enable those bits again - * after a transfer completes and there are no pending transfers - * on any of the enabled endpoints. - * - * This is the first half of that workaround. - * - * Refers to: - * - * STAR#9000446952: RTL: Device SS : if U1/U2 ->U0 takes >128us - * core send LGO_Ux entering U0 - */ - if (dwc->revision < DWC3_REVISION_183A) { - if (next == DWC3_LINK_STATE_U0) { - u32 u1u2; - u32 reg; - - switch (dwc->link_state) { - case DWC3_LINK_STATE_U1: - case DWC3_LINK_STATE_U2: - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - u1u2 = reg & (DWC3_DCTL_INITU2ENA - | DWC3_DCTL_ACCEPTU2ENA - | DWC3_DCTL_INITU1ENA - | DWC3_DCTL_ACCEPTU1ENA); - - if (!dwc->u1u2) - dwc->u1u2 = reg & u1u2; - - reg &= ~u1u2; - - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - break; - default: - /* do nothing */ - break; - } - } - } - - dwc->link_state = next; - - dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); -} - -static void dwc3_gadget_interrupt(struct dwc3 *dwc, - const struct dwc3_event_devt *event) -{ - switch (event->type) { - case DWC3_DEVICE_EVENT_DISCONNECT: - dwc3_gadget_disconnect_interrupt(dwc); - break; - case DWC3_DEVICE_EVENT_RESET: - dwc3_gadget_reset_interrupt(dwc); - break; - case DWC3_DEVICE_EVENT_CONNECT_DONE: - dwc3_gadget_conndone_interrupt(dwc); - break; - case DWC3_DEVICE_EVENT_WAKEUP: - dwc3_gadget_wakeup_interrupt(dwc); - break; - case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: - dwc3_gadget_linksts_change_interrupt(dwc, event->event_info); - break; - case DWC3_DEVICE_EVENT_EOPF: - dev_vdbg(dwc->dev, "End of Periodic Frame\n"); - break; - case DWC3_DEVICE_EVENT_SOF: - dev_vdbg(dwc->dev, "Start of Periodic Frame\n"); - break; - case DWC3_DEVICE_EVENT_ERRATIC_ERROR: - dev_vdbg(dwc->dev, "Erratic Error\n"); - break; - case DWC3_DEVICE_EVENT_CMD_CMPL: - dev_vdbg(dwc->dev, "Command Complete\n"); - break; - case DWC3_DEVICE_EVENT_OVERFLOW: - dev_vdbg(dwc->dev, "Overflow\n"); - break; - default: - dev_dbg(dwc->dev, "UNKNOWN IRQ %d\n", event->type); - } -} - -static void dwc3_process_event_entry(struct dwc3 *dwc, - const union dwc3_event *event) -{ - /* Endpoint IRQ, handle it and return early */ - if (event->type.is_devspec == 0) { - /* depevt */ - return dwc3_endpoint_interrupt(dwc, &event->depevt); - } - - switch (event->type.type) { - case DWC3_EVENT_TYPE_DEV: - dwc3_gadget_interrupt(dwc, &event->devt); - break; - /* REVISIT what to do with Carkit and I2C events ? */ - default: - dev_err(dwc->dev, "UNKNOWN IRQ type %d\n", event->raw); - } -} - -static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) -{ - struct dwc3_event_buffer *evt; - int left; - u32 count; - - count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); - count &= DWC3_GEVNTCOUNT_MASK; - if (!count) - return IRQ_NONE; - - evt = dwc->ev_buffs[buf]; - left = count; - - while (left > 0) { - union dwc3_event event; - - event.raw = *(u32 *) (evt->buf + evt->lpos); - - dwc3_process_event_entry(dwc, &event); - /* - * XXX we wrap around correctly to the next entry as almost all - * entries are 4 bytes in size. There is one entry which has 12 - * bytes which is a regular entry followed by 8 bytes data. ATM - * I don't know how things are organized if were get next to the - * a boundary so I worry about that once we try to handle that. - */ - evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; - left -= 4; - - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); - } - - return IRQ_HANDLED; -} - -static irqreturn_t dwc3_interrupt(int irq, void *_dwc) -{ - struct dwc3 *dwc = _dwc; - int i; - irqreturn_t ret = IRQ_NONE; - - spin_lock(&dwc->lock); - - for (i = 0; i < dwc->num_event_buffers; i++) { - irqreturn_t status; - - status = dwc3_process_event_buf(dwc, i); - if (status == IRQ_HANDLED) - ret = status; - } - - spin_unlock(&dwc->lock); - - return ret; -} - -/** - * dwc3_gadget_init - Initializes gadget related registers - * @dwc: pointer to our controller context structure - * - * Returns 0 on success otherwise negative errno. - */ -int __devinit dwc3_gadget_init(struct dwc3 *dwc) -{ - u32 reg; - int ret; - int irq; - - dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), - &dwc->ctrl_req_addr, GFP_KERNEL); - if (!dwc->ctrl_req) { - dev_err(dwc->dev, "failed to allocate ctrl request\n"); - ret = -ENOMEM; - goto err0; - } - - dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb), - &dwc->ep0_trb_addr, GFP_KERNEL); - if (!dwc->ep0_trb) { - dev_err(dwc->dev, "failed to allocate ep0 trb\n"); - ret = -ENOMEM; - goto err1; - } - - dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2, - GFP_KERNEL); - if (!dwc->setup_buf) { - dev_err(dwc->dev, "failed to allocate setup buffer\n"); - ret = -ENOMEM; - goto err2; - } - - dwc->ep0_bounce = dma_alloc_coherent(dwc->dev, - 512, &dwc->ep0_bounce_addr, GFP_KERNEL); - if (!dwc->ep0_bounce) { - dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); - ret = -ENOMEM; - goto err3; - } - - dev_set_name(&dwc->gadget.dev, "gadget"); - - dwc->gadget.ops = &dwc3_gadget_ops; - dwc->gadget.max_speed = USB_SPEED_SUPER; - dwc->gadget.speed = USB_SPEED_UNKNOWN; - dwc->gadget.dev.parent = dwc->dev; - dwc->gadget.sg_supported = true; - - dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); - - dwc->gadget.dev.dma_parms = dwc->dev->dma_parms; - dwc->gadget.dev.dma_mask = dwc->dev->dma_mask; - dwc->gadget.dev.release = dwc3_gadget_release; - dwc->gadget.name = "dwc3-gadget"; - - /* - * REVISIT: Here we should clear all pending IRQs to be - * sure we're starting from a well known location. - */ - - ret = dwc3_gadget_init_endpoints(dwc); - if (ret) - goto err4; - - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - - ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, - "dwc3", dwc); - if (ret) { - dev_err(dwc->dev, "failed to request irq #%d --> %d\n", - irq, ret); - goto err5; - } - - /* Enable all but Start and End of Frame IRQs */ - reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | - DWC3_DEVTEN_EVNTOVERFLOWEN | - DWC3_DEVTEN_CMDCMPLTEN | - DWC3_DEVTEN_ERRTICERREN | - DWC3_DEVTEN_WKUPEVTEN | - DWC3_DEVTEN_ULSTCNGEN | - DWC3_DEVTEN_CONNECTDONEEN | - DWC3_DEVTEN_USBRSTEN | - DWC3_DEVTEN_DISCONNEVTEN); - dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); - - ret = device_register(&dwc->gadget.dev); - if (ret) { - dev_err(dwc->dev, "failed to register gadget device\n"); - put_device(&dwc->gadget.dev); - goto err6; - } - - ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); - if (ret) { - dev_err(dwc->dev, "failed to register udc\n"); - goto err7; - } - - return 0; - -err7: - device_unregister(&dwc->gadget.dev); - -err6: - dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); - free_irq(irq, dwc); - -err5: - dwc3_gadget_free_endpoints(dwc); - -err4: - dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, - dwc->ep0_bounce_addr); - -err3: - kfree(dwc->setup_buf); - -err2: - dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), - dwc->ep0_trb, dwc->ep0_trb_addr); - -err1: - dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), - dwc->ctrl_req, dwc->ctrl_req_addr); - -err0: - return ret; -} - -void dwc3_gadget_exit(struct dwc3 *dwc) -{ - int irq; - - usb_del_gadget_udc(&dwc->gadget); - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - - dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); - free_irq(irq, dwc); - - dwc3_gadget_free_endpoints(dwc); - - dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, - dwc->ep0_bounce_addr); - - kfree(dwc->setup_buf); - - dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), - dwc->ep0_trb, dwc->ep0_trb_addr); - - dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), - dwc->ctrl_req, dwc->ctrl_req_addr); - - device_unregister(&dwc->gadget.dev); -} diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/gadget.h b/ANDROID_3.4.5/drivers/usb/dwc3/gadget.h deleted file mode 100644 index a8600084..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/gadget.h +++ /dev/null @@ -1,187 +0,0 @@ -/** - * gadget.h - DesignWare USB3 DRD Gadget Header - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DRIVERS_USB_DWC3_GADGET_H -#define __DRIVERS_USB_DWC3_GADGET_H - -#include <linux/list.h> -#include <linux/usb/gadget.h> -#include "io.h" - -struct dwc3; -#define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint)) -#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) - -/* DEPCFG parameter 1 */ -#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0) -#define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) -#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) -#define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) -#define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) -#define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) -#define DWC3_DEPCFG_BINTERVAL_M1(n) ((n) << 16) -#define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) -#define DWC3_DEPCFG_EP_NUMBER(n) ((n) << 25) -#define DWC3_DEPCFG_BULK_BASED (1 << 30) -#define DWC3_DEPCFG_FIFO_BASED (1 << 31) - -/* DEPCFG parameter 0 */ -#define DWC3_DEPCFG_EP_TYPE(n) ((n) << 1) -#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) ((n) << 3) -#define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) -#define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) -#define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) -#define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) - -/* DEPXFERCFG parameter 0 */ -#define DWC3_DEPXFERCFG_NUM_XFER_RES(n) ((n) & 0xffff) - -struct dwc3_gadget_ep_cmd_params { - u32 param2; - u32 param1; - u32 param0; -}; - -/* -------------------------------------------------------------------------- */ - -#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request)) - -static inline struct dwc3_request *next_request(struct list_head *list) -{ - if (list_empty(list)) - return NULL; - - return list_first_entry(list, struct dwc3_request, list); -} - -static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) -{ - struct dwc3_ep *dep = req->dep; - - req->queued = true; - list_move_tail(&req->list, &dep->req_queued); -} - -void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, - int status); - -int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); -int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); - -void dwc3_ep0_interrupt(struct dwc3 *dwc, - const struct dwc3_event_depevt *event); -void dwc3_ep0_out_start(struct dwc3 *dwc); -int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, - gfp_t gfp_flags); -int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); -int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, - unsigned cmd, struct dwc3_gadget_ep_cmd_params *params); - -/** - * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW - * @dwc: DesignWare USB3 Pointer - * @number: DWC endpoint number - * - * Caller should take care of locking - */ -static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3 *dwc, u8 number) -{ - u32 res_id; - - res_id = dwc3_readl(dwc->regs, DWC3_DEPCMD(number)); - - return DWC3_DEPCMD_GET_RSC_IDX(res_id); -} - -/** - * dwc3_gadget_event_string - returns event name - * @event: the event code - */ -static inline const char *dwc3_gadget_event_string(u8 event) -{ - switch (event) { - case DWC3_DEVICE_EVENT_DISCONNECT: - return "Disconnect"; - case DWC3_DEVICE_EVENT_RESET: - return "Reset"; - case DWC3_DEVICE_EVENT_CONNECT_DONE: - return "Connection Done"; - case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: - return "Link Status Change"; - case DWC3_DEVICE_EVENT_WAKEUP: - return "WakeUp"; - case DWC3_DEVICE_EVENT_EOPF: - return "End-Of-Frame"; - case DWC3_DEVICE_EVENT_SOF: - return "Start-Of-Frame"; - case DWC3_DEVICE_EVENT_ERRATIC_ERROR: - return "Erratic Error"; - case DWC3_DEVICE_EVENT_CMD_CMPL: - return "Command Complete"; - case DWC3_DEVICE_EVENT_OVERFLOW: - return "Overflow"; - } - - return "UNKNOWN"; -} - -/** - * dwc3_ep_event_string - returns event name - * @event: then event code - */ -static inline const char *dwc3_ep_event_string(u8 event) -{ - switch (event) { - case DWC3_DEPEVT_XFERCOMPLETE: - return "Transfer Complete"; - case DWC3_DEPEVT_XFERINPROGRESS: - return "Transfer In-Progress"; - case DWC3_DEPEVT_XFERNOTREADY: - return "Transfer Not Ready"; - case DWC3_DEPEVT_RXTXFIFOEVT: - return "FIFO"; - case DWC3_DEPEVT_STREAMEVT: - return "Stream"; - case DWC3_DEPEVT_EPCMDCMPLT: - return "Endpoint Command Complete"; - } - - return "UNKNOWN"; -} - -#endif /* __DRIVERS_USB_DWC3_GADGET_H */ diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/host.c b/ANDROID_3.4.5/drivers/usb/dwc3/host.c deleted file mode 100644 index b108d18f..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/host.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * host.c - DesignWare USB3 DRD Controller Host Glue - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <linux/platform_device.h> - -#include "core.h" - -static struct resource generic_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, - { - .flags = IORESOURCE_MEM, - }, -}; - -int dwc3_host_init(struct dwc3 *dwc) -{ - struct platform_device *xhci; - int ret; - - xhci = platform_device_alloc("xhci-hcd", -1); - if (!xhci) { - dev_err(dwc->dev, "couldn't allocate xHCI device\n"); - ret = -ENOMEM; - goto err0; - } - - dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask); - - xhci->dev.parent = dwc->dev; - xhci->dev.dma_mask = dwc->dev->dma_mask; - xhci->dev.dma_parms = dwc->dev->dma_parms; - - dwc->xhci = xhci; - - /* setup resources */ - generic_resources[0].start = dwc->irq; - - generic_resources[1].start = dwc->res->start; - generic_resources[1].end = dwc->res->start + 0x7fff; - - ret = platform_device_add_resources(xhci, generic_resources, - ARRAY_SIZE(generic_resources)); - if (ret) { - dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); - goto err1; - } - - ret = platform_device_add(xhci); - if (ret) { - dev_err(dwc->dev, "failed to register xHCI device\n"); - goto err1; - } - - return 0; - -err1: - platform_device_put(xhci); - -err0: - return ret; -} - -void dwc3_host_exit(struct dwc3 *dwc) -{ - platform_device_unregister(dwc->xhci); -} diff --git a/ANDROID_3.4.5/drivers/usb/dwc3/io.h b/ANDROID_3.4.5/drivers/usb/dwc3/io.h deleted file mode 100644 index 071d561f..00000000 --- a/ANDROID_3.4.5/drivers/usb/dwc3/io.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * io.h - DesignWare USB3 DRD IO Header - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * - * Authors: Felipe Balbi <balbi@ti.com>, - * Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DRIVERS_USB_DWC3_IO_H -#define __DRIVERS_USB_DWC3_IO_H - -#include <linux/io.h> - -static inline u32 dwc3_readl(void __iomem *base, u32 offset) -{ - return readl(base + offset); -} - -static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) -{ - writel(value, base + offset); -} - -#endif /* __DRIVERS_USB_DWC3_IO_H */ |