From cf6b4fd058142766e8fea5970370b711e7b11c1d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Oct 2010 13:56:40 +0300 Subject: [PATCH] --- yaml --- r: 226983 b: refs/heads/master c: 3ca8abb84522f4b773678726db6ebd6fc277bc96 h: refs/heads/master i: 226981: e1c4e47ad13c212a401cc70f2f2fb145b7e77d3f 226979: 422b7448fa84083fb3906693b24783c0b5f58e23 226975: df174c9663b843caadb8383198d41292f0e1e763 v: v3 --- [refs] | 2 +- trunk/drivers/usb/Kconfig | 1 - trunk/drivers/usb/gadget/Kconfig | 42 +- trunk/drivers/usb/gadget/Makefile | 5 +- trunk/drivers/usb/gadget/ci13xxx_msm.c | 134 --- trunk/drivers/usb/gadget/ci13xxx_pci.c | 176 --- trunk/drivers/usb/gadget/ci13xxx_udc.c | 384 ++++--- trunk/drivers/usb/gadget/ci13xxx_udc.h | 19 - trunk/drivers/usb/gadget/f_fs.c | 4 +- trunk/drivers/usb/gadget/f_ncm.c | 1407 ----------------------- trunk/drivers/usb/gadget/gadget_chips.h | 16 +- trunk/drivers/usb/gadget/imx_udc.c | 8 +- trunk/drivers/usb/gadget/ncm.c | 248 ---- trunk/drivers/usb/gadget/pch_udc.c | 24 +- trunk/drivers/usb/gadget/u_ether.c | 14 +- trunk/drivers/usb/gadget/u_ether.h | 5 - trunk/drivers/usb/host/Kconfig | 11 - trunk/drivers/usb/host/ehci-hcd.c | 13 - trunk/drivers/usb/host/ehci-msm.c | 345 ------ trunk/drivers/usb/host/ehci-pci.c | 32 - trunk/drivers/usb/host/ehci-sched.c | 79 -- trunk/drivers/usb/host/ehci.h | 1 - trunk/drivers/usb/host/uhci-q.c | 12 +- trunk/drivers/usb/host/whci/hcd.c | 2 +- trunk/drivers/usb/musb/musb_core.h | 28 + trunk/drivers/usb/otg/Kconfig | 20 - trunk/drivers/usb/otg/Makefile | 2 - trunk/drivers/usb/otg/ab8500-usb.c | 585 ---------- trunk/drivers/usb/otg/msm72k_otg.c | 1125 ------------------ trunk/drivers/usb/serial/usb_wwan.c | 1 - trunk/include/linux/usb/msm_hsusb.h | 112 -- trunk/include/linux/usb/msm_hsusb_hw.h | 59 - trunk/include/linux/usb/otg.h | 2 +- 33 files changed, 279 insertions(+), 4639 deletions(-) delete mode 100644 trunk/drivers/usb/gadget/ci13xxx_msm.c delete mode 100644 trunk/drivers/usb/gadget/ci13xxx_pci.c delete mode 100644 trunk/drivers/usb/gadget/f_ncm.c delete mode 100644 trunk/drivers/usb/gadget/ncm.c delete mode 100644 trunk/drivers/usb/host/ehci-msm.c delete mode 100644 trunk/drivers/usb/otg/ab8500-usb.c delete mode 100644 trunk/drivers/usb/otg/msm72k_otg.c delete mode 100644 trunk/include/linux/usb/msm_hsusb.h delete mode 100644 trunk/include/linux/usb/msm_hsusb_hw.h diff --git a/[refs] b/[refs] index c31fad5987c4..321753db6318 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6c34d2888221ca3df81e29f598873b4fb6cf838d +refs/heads/master: 3ca8abb84522f4b773678726db6ebd6fc277bc96 diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index b8e70a982fd4..6585f0b67801 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -64,7 +64,6 @@ config USB_ARCH_HAS_EHCI default y if ARCH_OMAP3 default y if ARCH_VT8500 default y if PLAT_SPEAR - default y if ARCH_MSM default PCI # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. diff --git a/trunk/drivers/usb/gadget/Kconfig b/trunk/drivers/usb/gadget/Kconfig index a776c35ca980..23fac3857477 100644 --- a/trunk/drivers/usb/gadget/Kconfig +++ b/trunk/drivers/usb/gadget/Kconfig @@ -427,8 +427,8 @@ config USB_FSL_QE default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_CI13XXX_PCI - boolean "MIPS USB CI13xxx PCI UDC" +config USB_GADGET_CI13XXX + boolean "MIPS USB CI13xxx" depends on PCI select USB_GADGET_DUALSPEED help @@ -439,9 +439,9 @@ config USB_GADGET_CI13XXX_PCI dynamically linked module called "ci13xxx_udc" and force all gadget drivers to also be dynamically linked. -config USB_CI13XXX_PCI +config USB_CI13XXX tristate - depends on USB_GADGET_CI13XXX_PCI + depends on USB_GADGET_CI13XXX default USB_GADGET select USB_GADGET_SELECTED @@ -531,27 +531,6 @@ config USB_EG20T default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_CI13XXX_MSM - boolean "MIPS USB CI13xxx for MSM" - depends on ARCH_MSM - select USB_GADGET_DUALSPEED - select USB_MSM_OTG_72K - help - MSM SoC has chipidea USB controller. This driver uses - ci13xxx_udc core. - This driver depends on OTG driver for PHY initialization, - clock management, powering up VBUS, and power management. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "ci13xxx_msm" and force all - gadget drivers to also be dynamically linked. - -config USB_CI13XXX_MSM - tristate - depends on USB_GADGET_CI13XXX_MSM - default USB_GADGET - select USB_GADGET_SELECTED - # # LAST -- dummy/emulated controller # @@ -741,19 +720,6 @@ config USB_ETH_EEM If you say "y" here, the Ethernet gadget driver will use the EEM protocol rather than ECM. If unsure, say "n". -config USB_G_NCM - tristate "Network Control Model (NCM) support" - depends on NET - select CRC32 - help - This driver implements USB CDC NCM subclass standard. NCM is - an advanced protocol for Ethernet encapsulation, allows grouping - of several ethernet frames into one USB transfer and diffferent - alignment possibilities. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "g_ncm". - config USB_GADGETFS tristate "Gadget Filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/trunk/drivers/usb/gadget/Makefile b/trunk/drivers/usb/gadget/Makefile index 55f5e8ae5924..a3e6b90c11d7 100644 --- a/trunk/drivers/usb/gadget/Makefile +++ b/trunk/drivers/usb/gadget/Makefile @@ -21,13 +21,12 @@ fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o obj-$(CONFIG_USB_M66592) += m66592-udc.o obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o -obj-$(CONFIG_USB_CI13XXX_PCI) += ci13xxx_pci.o +obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o obj-$(CONFIG_USB_EG20T) += pch_udc.o obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o mv_udc-y := mv_udc_core.o mv_udc_phy.o -obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o # # USB gadget drivers @@ -47,7 +46,6 @@ g_hid-y := hid.o g_dbgp-y := dbgp.o g_nokia-y := nokia.o g_webcam-y := webcam.o -g_ncm-y := ncm.o obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_AUDIO) += g_audio.o @@ -65,4 +63,3 @@ obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o obj-$(CONFIG_USB_G_MULTI) += g_multi.o obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o -obj-$(CONFIG_USB_G_NCM) += g_ncm.o diff --git a/trunk/drivers/usb/gadget/ci13xxx_msm.c b/trunk/drivers/usb/gadget/ci13xxx_msm.c deleted file mode 100644 index 139ac9419597..000000000000 --- a/trunk/drivers/usb/gadget/ci13xxx_msm.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include - -#include "ci13xxx_udc.c" - -#define MSM_USB_BASE (udc->regs) - -static irqreturn_t msm_udc_irq(int irq, void *data) -{ - return udc_irq(); -} - -static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) -{ - struct device *dev = udc->gadget.dev.parent; - int val; - - switch (event) { - case CI13XXX_CONTROLLER_RESET_EVENT: - dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); - writel(0, USB_AHBBURST); - writel(0, USB_AHBMODE); - break; - case CI13XXX_CONTROLLER_STOPPED_EVENT: - dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); - /* - * Put the transceiver in non-driving mode. Otherwise host - * may not detect soft-disconnection. - */ - val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL); - val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; - val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); - break; - default: - dev_dbg(dev, "unknown ci13xxx_udc event\n"); - break; - } -} - -static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { - .name = "ci13xxx_msm", - .flags = CI13XXX_REGS_SHARED | - CI13XXX_REQUIRE_TRANSCEIVER | - CI13XXX_PULLUP_ON_VBUS | - CI13XXX_DISABLE_STREAMING, - - .notify_event = ci13xxx_msm_notify_event, -}; - -static int ci13xxx_msm_probe(struct platform_device *pdev) -{ - struct resource *res; - void __iomem *regs; - int irq; - int ret; - - dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get platform resource mem\n"); - return -ENXIO; - } - - regs = ioremap(res->start, resource_size(res)); - if (!regs) { - dev_err(&pdev->dev, "ioremap failed\n"); - return -ENOMEM; - } - - ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs); - if (ret < 0) { - dev_err(&pdev->dev, "udc_probe failed\n"); - goto iounmap; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "IRQ not found\n"); - ret = -ENXIO; - goto udc_remove; - } - - ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev); - if (ret < 0) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto udc_remove; - } - - pm_runtime_no_callbacks(&pdev->dev); - pm_runtime_enable(&pdev->dev); - - return 0; - -udc_remove: - udc_remove(); -iounmap: - iounmap(regs); - - return ret; -} - -static struct platform_driver ci13xxx_msm_driver = { - .probe = ci13xxx_msm_probe, - .driver = { .name = "msm_hsusb", }, -}; - -static int __init ci13xxx_msm_init(void) -{ - return platform_driver_register(&ci13xxx_msm_driver); -} -module_init(ci13xxx_msm_init); diff --git a/trunk/drivers/usb/gadget/ci13xxx_pci.c b/trunk/drivers/usb/gadget/ci13xxx_pci.c deleted file mode 100644 index 883ab5e832d1..000000000000 --- a/trunk/drivers/usb/gadget/ci13xxx_pci.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ci13xxx_pci.c - MIPS USB IP core family device controller - * - * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. - * - * Author: David Lopo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -#include "ci13xxx_udc.c" - -/* driver name */ -#define UDC_DRIVER_NAME "ci13xxx_pci" - -/****************************************************************************** - * PCI block - *****************************************************************************/ -/** - * ci13xxx_pci_irq: interrut handler - * @irq: irq number - * @pdev: USB Device Controller interrupt source - * - * This function returns IRQ_HANDLED if the IRQ has been handled - * This is an ISR don't trace, use attribute interface instead - */ -static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) -{ - if (irq == 0) { - dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); - return IRQ_HANDLED; - } - return udc_irq(); -} - -static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = { - .name = UDC_DRIVER_NAME, -}; - -/** - * ci13xxx_pci_probe: PCI probe - * @pdev: USB device controller being probed - * @id: PCI hotplug ID connecting controller to UDC framework - * - * This function returns an error code - * Allocates basic PCI resources for this USB device controller, and then - * invokes the udc_probe() method to start the UDC associated with it - */ -static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *regs = NULL; - int retval = 0; - - if (id == NULL) - return -EINVAL; - - retval = pci_enable_device(pdev); - if (retval) - goto done; - - if (!pdev->irq) { - dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); - retval = -ENODEV; - goto disable_device; - } - - retval = pci_request_regions(pdev, UDC_DRIVER_NAME); - if (retval) - goto disable_device; - - /* BAR 0 holds all the registers */ - regs = pci_iomap(pdev, 0, 0); - if (!regs) { - dev_err(&pdev->dev, "Error mapping memory!"); - retval = -EFAULT; - goto release_regions; - } - pci_set_drvdata(pdev, (__force void *)regs); - - pci_set_master(pdev); - pci_try_set_mwi(pdev); - - retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs); - if (retval) - goto iounmap; - - /* our device does not have MSI capability */ - - retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, - UDC_DRIVER_NAME, pdev); - if (retval) - goto gadget_remove; - - return 0; - - gadget_remove: - udc_remove(); - iounmap: - pci_iounmap(pdev, regs); - release_regions: - pci_release_regions(pdev); - disable_device: - pci_disable_device(pdev); - done: - return retval; -} - -/** - * ci13xxx_pci_remove: PCI remove - * @pdev: USB Device Controller being removed - * - * Reverses the effect of ci13xxx_pci_probe(), - * first invoking the udc_remove() and then releases - * all PCI resources allocated for this USB device controller - */ -static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) -{ - free_irq(pdev->irq, pdev); - udc_remove(); - pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -/** - * PCI device table - * PCI device structure - * - * Check "pci.h" for details - */ -static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { - { PCI_DEVICE(0x153F, 0x1004) }, - { PCI_DEVICE(0x153F, 0x1006) }, - { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); - -static struct pci_driver ci13xxx_pci_driver = { - .name = UDC_DRIVER_NAME, - .id_table = ci13xxx_pci_id_table, - .probe = ci13xxx_pci_probe, - .remove = __devexit_p(ci13xxx_pci_remove), -}; - -/** - * ci13xxx_pci_init: module init - * - * Driver load - */ -static int __init ci13xxx_pci_init(void) -{ - return pci_register_driver(&ci13xxx_pci_driver); -} -module_init(ci13xxx_pci_init); - -/** - * ci13xxx_pci_exit: module exit - * - * Driver unload - */ -static void __exit ci13xxx_pci_exit(void) -{ - pci_unregister_driver(&ci13xxx_pci_driver); -} -module_exit(ci13xxx_pci_exit); - -MODULE_AUTHOR("MIPS - David Lopo "); -MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("June 2008"); diff --git a/trunk/drivers/usb/gadget/ci13xxx_udc.c b/trunk/drivers/usb/gadget/ci13xxx_udc.c index f200e472e476..98b36fc88c77 100644 --- a/trunk/drivers/usb/gadget/ci13xxx_udc.c +++ b/trunk/drivers/usb/gadget/ci13xxx_udc.c @@ -22,6 +22,7 @@ * - ENDPT: endpoint operations (Gadget API) * - GADGET: gadget operations (Gadget API) * - BUS: bus glue code, bus abstraction layer + * - PCI: PCI core interface and PCI resources (interrupts, memory...) * * Compile Options * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities @@ -59,11 +60,11 @@ #include #include #include +#include +#include #include -#include #include #include -#include #include "ci13xxx_udc.h" @@ -74,6 +75,9 @@ /* ctrl register bank access */ static DEFINE_SPINLOCK(udc_lock); +/* driver name */ +#define UDC_DRIVER_NAME "ci13xxx_udc" + /* control endpoint description */ static const struct usb_endpoint_descriptor ctrl_endpt_desc = { @@ -128,9 +132,6 @@ static struct { size_t size; /* bank size */ } hw_bank; -/* MSM specific */ -#define ABS_AHBBURST (0x0090UL) -#define ABS_AHBMODE (0x0098UL) /* UDC register map */ #define ABS_CAPLENGTH (0x100UL) #define ABS_HCCPARAMS (0x108UL) @@ -247,7 +248,13 @@ static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data) return (reg & mask) >> ffs_nr(mask); } -static int hw_device_init(void __iomem *base) +/** + * hw_device_reset: resets chip (execute without interruption) + * @base: register base address + * + * This function returns an error code + */ +static int hw_device_reset(void __iomem *base) { u32 reg; @@ -264,28 +271,6 @@ static int hw_device_init(void __iomem *base) hw_bank.size += CAP_LAST; hw_bank.size /= sizeof(u32); - reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); - if (reg == 0 || reg > ENDPT_MAX) - return -ENODEV; - - hw_ep_max = reg; /* cache hw ENDPT_MAX */ - - /* setup lock mode ? */ - - /* ENDPTSETUPSTAT is '0' by default */ - - /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ - - return 0; -} -/** - * hw_device_reset: resets chip (execute without interruption) - * @base: register base address - * - * This function returns an error code - */ -static int hw_device_reset(struct ci13xxx *udc) -{ /* should flush & stop before reset */ hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); @@ -294,14 +279,6 @@ static int hw_device_reset(struct ci13xxx *udc) while (hw_cread(CAP_USBCMD, USBCMD_RST)) udelay(10); /* not RTOS friendly */ - - if (udc->udc_driver->notify_event) - udc->udc_driver->notify_event(udc, - CI13XXX_CONTROLLER_RESET_EVENT); - - if (udc->udc_driver->flags && CI13XXX_DISABLE_STREAMING) - hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS); - /* USBMODE should be configured step by step */ hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE); @@ -313,6 +290,18 @@ static int hw_device_reset(struct ci13xxx *udc) return -ENODEV; } + reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); + if (reg == 0 || reg > ENDPT_MAX) + return -ENODEV; + + hw_ep_max = reg; /* cache hw ENDPT_MAX */ + + /* setup lock mode ? */ + + /* ENDPTSETUPSTAT is '0' by default */ + + /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ + return 0; } @@ -1568,6 +1557,8 @@ __acquires(mEp->lock) * Caller must hold lock */ static int _gadget_stop_activity(struct usb_gadget *gadget) +__releases(udc->lock) +__acquires(udc->lock) { struct usb_ep *ep; struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); @@ -1579,6 +1570,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) if (gadget == NULL) return -EINVAL; + spin_unlock(udc->lock); + /* flush all endpoints */ gadget_for_each_ep(ep, gadget) { usb_ep_fifo_flush(ep); @@ -1598,6 +1591,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) mEp->status = NULL; } + spin_lock(udc->lock); + return 0; } @@ -1626,7 +1621,6 @@ __acquires(udc->lock) dbg_event(0xFF, "BUS RST", 0); - spin_unlock(udc->lock); retval = _gadget_stop_activity(&udc->gadget); if (retval) goto done; @@ -1635,9 +1629,10 @@ __acquires(udc->lock) if (retval) goto done; + spin_unlock(udc->lock); retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); if (!retval) { - mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC); + mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_KERNEL); if (mEp->status == NULL) { usb_ep_disable(&mEp->ep); retval = -ENOMEM; @@ -2066,6 +2061,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) { struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); struct ci13xxx_req *mReq = NULL; + unsigned long flags; trace("%p, %i", ep, gfp_flags); @@ -2074,6 +2070,8 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) return NULL; } + spin_lock_irqsave(mEp->lock, flags); + mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); if (mReq != NULL) { INIT_LIST_HEAD(&mReq->queue); @@ -2088,6 +2086,8 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); + spin_unlock_irqrestore(mEp->lock, flags); + return (mReq == NULL) ? NULL : &mReq->req; } @@ -2332,47 +2332,12 @@ static const struct usb_ep_ops usb_ep_ops = { /****************************************************************************** * GADGET block *****************************************************************************/ -static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) -{ - struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); - unsigned long flags; - int gadget_ready = 0; - - if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS)) - return -EOPNOTSUPP; - - spin_lock_irqsave(udc->lock, flags); - udc->vbus_active = is_active; - if (udc->driver) - gadget_ready = 1; - spin_unlock_irqrestore(udc->lock, flags); - - if (gadget_ready) { - if (is_active) { - pm_runtime_get_sync(&_gadget->dev); - hw_device_reset(udc); - hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); - } else { - hw_device_state(0); - if (udc->udc_driver->notify_event) - udc->udc_driver->notify_event(udc, - CI13XXX_CONTROLLER_STOPPED_EVENT); - _gadget_stop_activity(&udc->gadget); - pm_runtime_put_sync(&_gadget->dev); - } - } - - return 0; -} - /** * Device operations part of the API to the USB controller hardware, * which don't involve endpoints (or i/o) * Check "usb_gadget.h" for details */ -static const struct usb_gadget_ops usb_gadget_ops = { - .vbus_session = ci13xxx_vbus_session, -}; +static const struct usb_gadget_ops usb_gadget_ops; /** * usb_gadget_probe_driver: register a gadget driver @@ -2425,6 +2390,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, info("hw_ep_max = %d", hw_ep_max); udc->driver = driver; + udc->gadget.ops = NULL; udc->gadget.dev.driver = NULL; retval = 0; @@ -2444,11 +2410,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, /* this allocation cannot be random */ for (k = RX; k <= TX; k++) { INIT_LIST_HEAD(&mEp->qh[k].queue); - spin_unlock_irqrestore(udc->lock, flags); mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, &mEp->qh[k].dma); - spin_lock_irqsave(udc->lock, flags); if (mEp->qh[k].ptr == NULL) retval = -ENOMEM; else @@ -2465,6 +2429,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, /* bind gadget */ driver->driver.bus = NULL; + udc->gadget.ops = &usb_gadget_ops; udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(udc->lock, flags); @@ -2472,24 +2437,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, spin_lock_irqsave(udc->lock, flags); if (retval) { + udc->gadget.ops = NULL; udc->gadget.dev.driver = NULL; goto done; } - pm_runtime_get_sync(&udc->gadget.dev); - if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { - if (udc->vbus_active) { - if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) - hw_device_reset(udc); - } else { - pm_runtime_put_sync(&udc->gadget.dev); - goto done; - } - } - retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); - if (retval) - pm_runtime_put_sync(&udc->gadget.dev); done: spin_unlock_irqrestore(udc->lock, flags); @@ -2522,22 +2475,19 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) spin_lock_irqsave(udc->lock, flags); - if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) || - udc->vbus_active) { - hw_device_state(0); - if (udc->udc_driver->notify_event) - udc->udc_driver->notify_event(udc, - CI13XXX_CONTROLLER_STOPPED_EVENT); - _gadget_stop_activity(&udc->gadget); - pm_runtime_put(&udc->gadget.dev); - } + hw_device_state(0); /* unbind gadget */ - spin_unlock_irqrestore(udc->lock, flags); - driver->unbind(&udc->gadget); /* MAY SLEEP */ - spin_lock_irqsave(udc->lock, flags); + if (udc->gadget.ops != NULL) { + _gadget_stop_activity(&udc->gadget); - udc->gadget.dev.driver = NULL; + spin_unlock_irqrestore(udc->lock, flags); + driver->unbind(&udc->gadget); /* MAY SLEEP */ + spin_lock_irqsave(udc->lock, flags); + + udc->gadget.ops = NULL; + udc->gadget.dev.driver = NULL; + } /* free resources */ for (i = 0; i < hw_ep_max; i++) { @@ -2594,14 +2544,6 @@ static irqreturn_t udc_irq(void) } spin_lock(udc->lock); - - if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) { - if (hw_cread(CAP_USBMODE, USBMODE_CM) != - USBMODE_CM_DEVICE) { - spin_unlock(udc->lock); - return IRQ_NONE; - } - } intr = hw_test_and_clear_intr_active(); if (intr) { isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr; @@ -2660,16 +2602,14 @@ static void udc_release(struct device *dev) * No interrupts active, the IRQ has not been requested yet * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask */ -static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, - void __iomem *regs) +static int udc_probe(struct device *dev, void __iomem *regs, const char *name) { struct ci13xxx *udc; int retval = 0; trace("%p, %p, %p", dev, regs, name); - if (dev == NULL || regs == NULL || driver == NULL || - driver->name == NULL) + if (dev == NULL || regs == NULL || name == NULL) return -EINVAL; udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL); @@ -2677,77 +2617,42 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, return -ENOMEM; udc->lock = &udc_lock; - udc->regs = regs; - udc->udc_driver = driver; - udc->gadget.ops = &usb_gadget_ops; + retval = hw_device_reset(regs); + if (retval) + goto done; + + udc->gadget.ops = NULL; udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.is_dualspeed = 1; udc->gadget.is_otg = 0; - udc->gadget.name = driver->name; + udc->gadget.name = name; INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = NULL; dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.dma_mask = dev->dma_mask; - udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; udc->gadget.dev.parent = dev; udc->gadget.dev.release = udc_release; - retval = hw_device_init(regs); - if (retval < 0) - goto free_udc; - - udc->transceiver = otg_get_transceiver(); - - if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { - if (udc->transceiver == NULL) { - retval = -ENODEV; - goto free_udc; - } - } - - if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) { - retval = hw_device_reset(udc); - if (retval) - goto put_transceiver; - } - retval = device_register(&udc->gadget.dev); - if (retval) { - put_device(&udc->gadget.dev); - goto put_transceiver; - } + if (retval) + goto done; #ifdef CONFIG_USB_GADGET_DEBUG_FILES retval = dbg_create_files(&udc->gadget.dev); #endif - if (retval) - goto unreg_device; - - if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); - if (retval) - goto remove_dbg; + if (retval) { + device_unregister(&udc->gadget.dev); + goto done; } - pm_runtime_no_callbacks(&udc->gadget.dev); - pm_runtime_enable(&udc->gadget.dev); _udc = udc; return retval; + done: err("error = %i", retval); -remove_dbg: -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - dbg_remove_files(&udc->gadget.dev); -#endif -unreg_device: - device_unregister(&udc->gadget.dev); -put_transceiver: - if (udc->transceiver) - otg_put_transceiver(udc->transceiver); -free_udc: kfree(udc); _udc = NULL; return retval; @@ -2767,10 +2672,6 @@ static void udc_remove(void) return; } - if (udc->transceiver) { - otg_set_peripheral(udc->transceiver, &udc->gadget); - otg_put_transceiver(udc->transceiver); - } #ifdef CONFIG_USB_GADGET_DEBUG_FILES dbg_remove_files(&udc->gadget.dev); #endif @@ -2779,3 +2680,156 @@ static void udc_remove(void) kfree(udc); _udc = NULL; } + +/****************************************************************************** + * PCI block + *****************************************************************************/ +/** + * ci13xxx_pci_irq: interrut handler + * @irq: irq number + * @pdev: USB Device Controller interrupt source + * + * This function returns IRQ_HANDLED if the IRQ has been handled + * This is an ISR don't trace, use attribute interface instead + */ +static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) +{ + if (irq == 0) { + dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); + return IRQ_HANDLED; + } + return udc_irq(); +} + +/** + * ci13xxx_pci_probe: PCI probe + * @pdev: USB device controller being probed + * @id: PCI hotplug ID connecting controller to UDC framework + * + * This function returns an error code + * Allocates basic PCI resources for this USB device controller, and then + * invokes the udc_probe() method to start the UDC associated with it + */ +static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem *regs = NULL; + int retval = 0; + + if (id == NULL) + return -EINVAL; + + retval = pci_enable_device(pdev); + if (retval) + goto done; + + if (!pdev->irq) { + dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); + retval = -ENODEV; + goto disable_device; + } + + retval = pci_request_regions(pdev, UDC_DRIVER_NAME); + if (retval) + goto disable_device; + + /* BAR 0 holds all the registers */ + regs = pci_iomap(pdev, 0, 0); + if (!regs) { + dev_err(&pdev->dev, "Error mapping memory!"); + retval = -EFAULT; + goto release_regions; + } + pci_set_drvdata(pdev, (__force void *)regs); + + pci_set_master(pdev); + pci_try_set_mwi(pdev); + + retval = udc_probe(&pdev->dev, regs, UDC_DRIVER_NAME); + if (retval) + goto iounmap; + + /* our device does not have MSI capability */ + + retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, + UDC_DRIVER_NAME, pdev); + if (retval) + goto gadget_remove; + + return 0; + + gadget_remove: + udc_remove(); + iounmap: + pci_iounmap(pdev, regs); + release_regions: + pci_release_regions(pdev); + disable_device: + pci_disable_device(pdev); + done: + return retval; +} + +/** + * ci13xxx_pci_remove: PCI remove + * @pdev: USB Device Controller being removed + * + * Reverses the effect of ci13xxx_pci_probe(), + * first invoking the udc_remove() and then releases + * all PCI resources allocated for this USB device controller + */ +static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) +{ + free_irq(pdev->irq, pdev); + udc_remove(); + pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +/** + * PCI device table + * PCI device structure + * + * Check "pci.h" for details + */ +static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { + { PCI_DEVICE(0x153F, 0x1004) }, + { PCI_DEVICE(0x153F, 0x1006) }, + { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); + +static struct pci_driver ci13xxx_pci_driver = { + .name = UDC_DRIVER_NAME, + .id_table = ci13xxx_pci_id_table, + .probe = ci13xxx_pci_probe, + .remove = __devexit_p(ci13xxx_pci_remove), +}; + +/** + * ci13xxx_pci_init: module init + * + * Driver load + */ +static int __init ci13xxx_pci_init(void) +{ + return pci_register_driver(&ci13xxx_pci_driver); +} +module_init(ci13xxx_pci_init); + +/** + * ci13xxx_pci_exit: module exit + * + * Driver unload + */ +static void __exit ci13xxx_pci_exit(void) +{ + pci_unregister_driver(&ci13xxx_pci_driver); +} +module_exit(ci13xxx_pci_exit); + +MODULE_AUTHOR("MIPS - David Lopo "); +MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("June 2008"); diff --git a/trunk/drivers/usb/gadget/ci13xxx_udc.h b/trunk/drivers/usb/gadget/ci13xxx_udc.h index 4fd19313e238..4026e9cede34 100644 --- a/trunk/drivers/usb/gadget/ci13xxx_udc.h +++ b/trunk/drivers/usb/gadget/ci13xxx_udc.h @@ -97,24 +97,9 @@ struct ci13xxx_ep { struct dma_pool *td_pool; }; -struct ci13xxx; -struct ci13xxx_udc_driver { - const char *name; - unsigned long flags; -#define CI13XXX_REGS_SHARED BIT(0) -#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) -#define CI13XXX_PULLUP_ON_VBUS BIT(2) -#define CI13XXX_DISABLE_STREAMING BIT(3) - -#define CI13XXX_CONTROLLER_RESET_EVENT 0 -#define CI13XXX_CONTROLLER_STOPPED_EVENT 1 - void (*notify_event) (struct ci13xxx *udc, unsigned event); -}; - /* CI13XXX UDC descriptor & global resources */ struct ci13xxx { spinlock_t *lock; /* ctrl register bank access */ - void __iomem *regs; /* registers address space */ struct dma_pool *qh_pool; /* DMA pool for queue heads */ struct dma_pool *td_pool; /* DMA pool for transfer descs */ @@ -123,9 +108,6 @@ struct ci13xxx { struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ struct usb_gadget_driver *driver; /* 3rd party gadget driver */ - struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ - int vbus_active; /* is VBUS active */ - struct otg_transceiver *transceiver; /* Transceiver struct */ }; /****************************************************************************** @@ -175,7 +157,6 @@ struct ci13xxx { #define USBMODE_CM_DEVICE (0x02UL << 0) #define USBMODE_CM_HOST (0x03UL << 0) #define USBMODE_SLOM BIT(3) -#define USBMODE_SDIS BIT(4) /* ENDPTCTRL */ #define ENDPTCTRL_RXS BIT(0) diff --git a/trunk/drivers/usb/gadget/f_fs.c b/trunk/drivers/usb/gadget/f_fs.c index 1b7ae7c9d683..255969cd1639 100644 --- a/trunk/drivers/usb/gadget/f_fs.c +++ b/trunk/drivers/usb/gadget/f_fs.c @@ -427,7 +427,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, } data = ffs_prepare_buffer(buf, len); - if (IS_ERR(data)) { + if (unlikely(IS_ERR(data))) { ret = PTR_ERR(data); break; } @@ -500,7 +500,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, spin_unlock_irq(&ffs->ev.waitq.lock); data = ffs_prepare_buffer(buf, len); - if (IS_ERR(data)) { + if (unlikely(IS_ERR(data))) { ret = PTR_ERR(data); break; } diff --git a/trunk/drivers/usb/gadget/f_ncm.c b/trunk/drivers/usb/gadget/f_ncm.c deleted file mode 100644 index 130eee678c8b..000000000000 --- a/trunk/drivers/usb/gadget/f_ncm.c +++ /dev/null @@ -1,1407 +0,0 @@ -/* - * f_ncm.c -- USB CDC Network (NCM) link function driver - * - * Copyright (C) 2010 Nokia Corporation - * Contact: Yauheni Kaliuta - * - * The driver borrows from f_ecm.c which is: - * - * Copyright (C) 2003-2005,2008 David Brownell - * Copyright (C) 2008 Nokia Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include - -#include "u_ether.h" - -/* - * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. - * NCM is intended to be used with high-speed network attachments. - * - * Note that NCM requires the use of "alternate settings" for its data - * interface. This means that the set_alt() method has real work to do, - * and also means that a get_alt() method is required. - */ - -/* to trigger crc/non-crc ndp signature */ - -#define NCM_NDP_HDR_CRC_MASK 0x01000000 -#define NCM_NDP_HDR_CRC 0x01000000 -#define NCM_NDP_HDR_NOCRC 0x00000000 - -struct ncm_ep_descs { - struct usb_endpoint_descriptor *in; - struct usb_endpoint_descriptor *out; - struct usb_endpoint_descriptor *notify; -}; - -enum ncm_notify_state { - NCM_NOTIFY_NONE, /* don't notify */ - NCM_NOTIFY_CONNECT, /* issue CONNECT next */ - NCM_NOTIFY_SPEED, /* issue SPEED_CHANGE next */ -}; - -struct f_ncm { - struct gether port; - u8 ctrl_id, data_id; - - char ethaddr[14]; - - struct ncm_ep_descs fs; - struct ncm_ep_descs hs; - - struct usb_ep *notify; - struct usb_endpoint_descriptor *notify_desc; - struct usb_request *notify_req; - u8 notify_state; - bool is_open; - - struct ndp_parser_opts *parser_opts; - bool is_crc; - - /* - * for notification, it is accessed from both - * callback and ethernet open/close - */ - spinlock_t lock; -}; - -static inline struct f_ncm *func_to_ncm(struct usb_function *f) -{ - return container_of(f, struct f_ncm, port.func); -} - -/* peak (theoretical) bulk transfer rate in bits-per-second */ -static inline unsigned ncm_bitrate(struct usb_gadget *g) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return 13 * 512 * 8 * 1000 * 8; - else - return 19 * 64 * 1 * 1000 * 8; -} - -/*-------------------------------------------------------------------------*/ - -/* - * We cannot group frames so use just the minimal size which ok to put - * one max-size ethernet frame. - * If the host can group frames, allow it to do that, 16K is selected, - * because it's used by default by the current linux host driver - */ -#define NTB_DEFAULT_IN_SIZE USB_CDC_NCM_NTB_MIN_IN_SIZE -#define NTB_OUT_SIZE 16384 - -/* - * skbs of size less than that will not be alligned - * to NCM's dwNtbInMaxSize to save bus bandwidth - */ - -#define MAX_TX_NONFIXED (512 * 3) - -#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \ - USB_CDC_NCM_NTB32_SUPPORTED) - -static struct usb_cdc_ncm_ntb_parameters ntb_parameters = { - .wLength = sizeof ntb_parameters, - .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED), - .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE), - .wNdpInDivisor = cpu_to_le16(4), - .wNdpInPayloadRemainder = cpu_to_le16(0), - .wNdpInAlignment = cpu_to_le16(4), - - .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE), - .wNdpOutDivisor = cpu_to_le16(4), - .wNdpOutPayloadRemainder = cpu_to_le16(0), - .wNdpOutAlignment = cpu_to_le16(4), -}; - -/* - * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one - * packet, to simplify cancellation; and a big transfer interval, to - * waste less bandwidth. - */ - -#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ -#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ - -static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { - .bLength = sizeof ncm_iad_desc, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - - /* .bFirstInterface = DYNAMIC, */ - .bInterfaceCount = 2, /* control + data */ - .bFunctionClass = USB_CLASS_COMM, - .bFunctionSubClass = USB_CDC_SUBCLASS_NCM, - .bFunctionProtocol = USB_CDC_PROTO_NONE, - /* .iFunction = DYNAMIC */ -}; - -/* interface descriptor: */ - -static struct usb_interface_descriptor ncm_control_intf __initdata = { - .bLength = sizeof ncm_control_intf, - .bDescriptorType = USB_DT_INTERFACE, - - /* .bInterfaceNumber = DYNAMIC */ - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - /* .iInterface = DYNAMIC */ -}; - -static struct usb_cdc_header_desc ncm_header_desc __initdata = { - .bLength = sizeof ncm_header_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, - - .bcdCDC = cpu_to_le16(0x0110), -}; - -static struct usb_cdc_union_desc ncm_union_desc __initdata = { - .bLength = sizeof(ncm_union_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_UNION_TYPE, - /* .bMasterInterface0 = DYNAMIC */ - /* .bSlaveInterface0 = DYNAMIC */ -}; - -static struct usb_cdc_ether_desc ecm_desc __initdata = { - .bLength = sizeof ecm_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, - - /* this descriptor actually adds value, surprise! */ - /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = cpu_to_le16(0), - .bNumberPowerFilters = 0, -}; - -#define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) - -static struct usb_cdc_ncm_desc ncm_desc __initdata = { - .bLength = sizeof ncm_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_NCM_TYPE, - - .bcdNcmVersion = cpu_to_le16(0x0100), - /* can process SetEthernetPacketFilter */ - .bmNetworkCapabilities = NCAPS, -}; - -/* the default data interface has no endpoints ... */ - -static struct usb_interface_descriptor ncm_data_nop_intf __initdata = { - .bLength = sizeof ncm_data_nop_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = USB_CDC_NCM_PROTO_NTB, - /* .iInterface = DYNAMIC */ -}; - -/* ... but the "real" data interface has two bulk endpoints */ - -static struct usb_interface_descriptor ncm_data_intf __initdata = { - .bLength = sizeof ncm_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 1, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = USB_CDC_NCM_PROTO_NTB, - /* .iInterface = DYNAMIC */ -}; - -/* full speed support: */ - -static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), - .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, -}; - -static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_descriptor_header *ncm_fs_function[] __initdata = { - (struct usb_descriptor_header *) &ncm_iad_desc, - /* CDC NCM control descriptors */ - (struct usb_descriptor_header *) &ncm_control_intf, - (struct usb_descriptor_header *) &ncm_header_desc, - (struct usb_descriptor_header *) &ncm_union_desc, - (struct usb_descriptor_header *) &ecm_desc, - (struct usb_descriptor_header *) &ncm_desc, - (struct usb_descriptor_header *) &fs_ncm_notify_desc, - /* data interface, altsettings 0 and 1 */ - (struct usb_descriptor_header *) &ncm_data_nop_intf, - (struct usb_descriptor_header *) &ncm_data_intf, - (struct usb_descriptor_header *) &fs_ncm_in_desc, - (struct usb_descriptor_header *) &fs_ncm_out_desc, - NULL, -}; - -/* high speed support: */ - -static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), - .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, -}; -static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_descriptor_header *ncm_hs_function[] __initdata = { - (struct usb_descriptor_header *) &ncm_iad_desc, - /* CDC NCM control descriptors */ - (struct usb_descriptor_header *) &ncm_control_intf, - (struct usb_descriptor_header *) &ncm_header_desc, - (struct usb_descriptor_header *) &ncm_union_desc, - (struct usb_descriptor_header *) &ecm_desc, - (struct usb_descriptor_header *) &ncm_desc, - (struct usb_descriptor_header *) &hs_ncm_notify_desc, - /* data interface, altsettings 0 and 1 */ - (struct usb_descriptor_header *) &ncm_data_nop_intf, - (struct usb_descriptor_header *) &ncm_data_intf, - (struct usb_descriptor_header *) &hs_ncm_in_desc, - (struct usb_descriptor_header *) &hs_ncm_out_desc, - NULL, -}; - -/* string descriptors: */ - -#define STRING_CTRL_IDX 0 -#define STRING_MAC_IDX 1 -#define STRING_DATA_IDX 2 -#define STRING_IAD_IDX 3 - -static struct usb_string ncm_string_defs[] = { - [STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)", - [STRING_MAC_IDX].s = NULL /* DYNAMIC */, - [STRING_DATA_IDX].s = "CDC Network Data", - [STRING_IAD_IDX].s = "CDC NCM", - { } /* end of list */ -}; - -static struct usb_gadget_strings ncm_string_table = { - .language = 0x0409, /* en-us */ - .strings = ncm_string_defs, -}; - -static struct usb_gadget_strings *ncm_strings[] = { - &ncm_string_table, - NULL, -}; - -/* - * Here are options for NCM Datagram Pointer table (NDP) parser. - * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3), - * in NDP16 offsets and sizes fields are 1 16bit word wide, - * in NDP32 -- 2 16bit words wide. Also signatures are different. - * To make the parser code the same, put the differences in the structure, - * and switch pointers to the structures when the format is changed. - */ - -struct ndp_parser_opts { - u32 nth_sign; - u32 ndp_sign; - unsigned nth_size; - unsigned ndp_size; - unsigned ndplen_align; - /* sizes in u16 units */ - unsigned dgram_item_len; /* index or length */ - unsigned block_length; - unsigned fp_index; - unsigned reserved1; - unsigned reserved2; - unsigned next_fp_index; -}; - -#define INIT_NDP16_OPTS { \ - .nth_sign = USB_CDC_NCM_NTH16_SIGN, \ - .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \ - .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ - .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ - .ndplen_align = 4, \ - .dgram_item_len = 1, \ - .block_length = 1, \ - .fp_index = 1, \ - .reserved1 = 0, \ - .reserved2 = 0, \ - .next_fp_index = 1, \ - } - - -#define INIT_NDP32_OPTS { \ - .nth_sign = USB_CDC_NCM_NTH32_SIGN, \ - .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \ - .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ - .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ - .ndplen_align = 8, \ - .dgram_item_len = 2, \ - .block_length = 2, \ - .fp_index = 2, \ - .reserved1 = 1, \ - .reserved2 = 2, \ - .next_fp_index = 2, \ - } - -static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS; -static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS; - -static inline void put_ncm(__le16 **p, unsigned size, unsigned val) -{ - switch (size) { - case 1: - put_unaligned_le16((u16)val, *p); - break; - case 2: - put_unaligned_le32((u32)val, *p); - - break; - default: - BUG(); - } - - *p += size; -} - -static inline unsigned get_ncm(__le16 **p, unsigned size) -{ - unsigned tmp; - - switch (size) { - case 1: - tmp = get_unaligned_le16(*p); - break; - case 2: - tmp = get_unaligned_le32(*p); - break; - default: - BUG(); - } - - *p += size; - return tmp; -} - -/*-------------------------------------------------------------------------*/ - -static inline void ncm_reset_values(struct f_ncm *ncm) -{ - ncm->parser_opts = &ndp16_opts; - ncm->is_crc = false; - ncm->port.cdc_filter = DEFAULT_FILTER; - - /* doesn't make sense for ncm, fixed size used */ - ncm->port.header_len = 0; - - ncm->port.fixed_out_len = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); - ncm->port.fixed_in_len = NTB_DEFAULT_IN_SIZE; -} - -/* - * Context: ncm->lock held - */ -static void ncm_do_notify(struct f_ncm *ncm) -{ - struct usb_request *req = ncm->notify_req; - struct usb_cdc_notification *event; - struct usb_composite_dev *cdev = ncm->port.func.config->cdev; - __le32 *data; - int status; - - /* notification already in flight? */ - if (!req) - return; - - event = req->buf; - switch (ncm->notify_state) { - case NCM_NOTIFY_NONE: - return; - - case NCM_NOTIFY_CONNECT: - event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; - if (ncm->is_open) - event->wValue = cpu_to_le16(1); - else - event->wValue = cpu_to_le16(0); - event->wLength = 0; - req->length = sizeof *event; - - DBG(cdev, "notify connect %s\n", - ncm->is_open ? "true" : "false"); - ncm->notify_state = NCM_NOTIFY_NONE; - break; - - case NCM_NOTIFY_SPEED: - event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; - event->wValue = cpu_to_le16(0); - event->wLength = cpu_to_le16(8); - req->length = NCM_STATUS_BYTECOUNT; - - /* SPEED_CHANGE data is up/down speeds in bits/sec */ - data = req->buf + sizeof *event; - data[0] = cpu_to_le32(ncm_bitrate(cdev->gadget)); - data[1] = data[0]; - - DBG(cdev, "notify speed %d\n", ncm_bitrate(cdev->gadget)); - ncm->notify_state = NCM_NOTIFY_CONNECT; - break; - } - event->bmRequestType = 0xA1; - event->wIndex = cpu_to_le16(ncm->ctrl_id); - - ncm->notify_req = NULL; - /* - * In double buffering if there is a space in FIFO, - * completion callback can be called right after the call, - * so unlocking - */ - spin_unlock(&ncm->lock); - status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC); - spin_lock(&ncm->lock); - if (status < 0) { - ncm->notify_req = req; - DBG(cdev, "notify --> %d\n", status); - } -} - -/* - * Context: ncm->lock held - */ -static void ncm_notify(struct f_ncm *ncm) -{ - /* - * NOTE on most versions of Linux, host side cdc-ethernet - * won't listen for notifications until its netdevice opens. - * The first notification then sits in the FIFO for a long - * time, and the second one is queued. - * - * If ncm_notify() is called before the second (CONNECT) - * notification is sent, then it will reset to send the SPEED - * notificaion again (and again, and again), but it's not a problem - */ - ncm->notify_state = NCM_NOTIFY_SPEED; - ncm_do_notify(ncm); -} - -static void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct f_ncm *ncm = req->context; - struct usb_composite_dev *cdev = ncm->port.func.config->cdev; - struct usb_cdc_notification *event = req->buf; - - spin_lock(&ncm->lock); - switch (req->status) { - case 0: - VDBG(cdev, "Notification %02x sent\n", - event->bNotificationType); - break; - case -ECONNRESET: - case -ESHUTDOWN: - ncm->notify_state = NCM_NOTIFY_NONE; - break; - default: - DBG(cdev, "event %02x --> %d\n", - event->bNotificationType, req->status); - break; - } - ncm->notify_req = req; - ncm_do_notify(ncm); - spin_unlock(&ncm->lock); -} - -static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req) -{ - /* now for SET_NTB_INPUT_SIZE only */ - unsigned in_size; - struct usb_function *f = req->context; - struct f_ncm *ncm = func_to_ncm(f); - struct usb_composite_dev *cdev = ep->driver_data; - - req->context = NULL; - if (req->status || req->actual != req->length) { - DBG(cdev, "Bad control-OUT transfer\n"); - goto invalid; - } - - in_size = get_unaligned_le32(req->buf); - if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE || - in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) { - DBG(cdev, "Got wrong INPUT SIZE (%d) from host\n", in_size); - goto invalid; - } - - ncm->port.fixed_in_len = in_size; - VDBG(cdev, "Set NTB INPUT SIZE %d\n", in_size); - return; - -invalid: - usb_ep_set_halt(ep); - return; -} - -static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) -{ - struct f_ncm *ncm = func_to_ncm(f); - struct usb_composite_dev *cdev = f->config->cdev; - struct usb_request *req = cdev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - /* - * composite driver infrastructure handles everything except - * CDC class messages; interface activation uses set_alt(). - */ - switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_SET_ETHERNET_PACKET_FILTER: - /* - * see 6.2.30: no data, wIndex = interface, - * wValue = packet filter bitmap - */ - if (w_length != 0 || w_index != ncm->ctrl_id) - goto invalid; - DBG(cdev, "packet filter %02x\n", w_value); - /* - * REVISIT locking of cdc_filter. This assumes the UDC - * driver won't have a concurrent packet TX irq running on - * another CPU; or that if it does, this write is atomic... - */ - ncm->port.cdc_filter = w_value; - value = 0; - break; - /* - * and optionally: - * case USB_CDC_SEND_ENCAPSULATED_COMMAND: - * case USB_CDC_GET_ENCAPSULATED_RESPONSE: - * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: - * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_STATISTIC: - */ - - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_GET_NTB_PARAMETERS: - - if (w_length == 0 || w_value != 0 || w_index != ncm->ctrl_id) - goto invalid; - value = w_length > sizeof ntb_parameters ? - sizeof ntb_parameters : w_length; - memcpy(req->buf, &ntb_parameters, value); - VDBG(cdev, "Host asked NTB parameters\n"); - break; - - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_GET_NTB_INPUT_SIZE: - - if (w_length < 4 || w_value != 0 || w_index != ncm->ctrl_id) - goto invalid; - put_unaligned_le32(ncm->port.fixed_in_len, req->buf); - value = 4; - VDBG(cdev, "Host asked INPUT SIZE, sending %d\n", - ncm->port.fixed_in_len); - break; - - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_SET_NTB_INPUT_SIZE: - { - if (w_length != 4 || w_value != 0 || w_index != ncm->ctrl_id) - goto invalid; - req->complete = ncm_ep0out_complete; - req->length = w_length; - req->context = f; - - value = req->length; - break; - } - - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_GET_NTB_FORMAT: - { - uint16_t format; - - if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) - goto invalid; - format = (ncm->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001; - put_unaligned_le16(format, req->buf); - value = 2; - VDBG(cdev, "Host asked NTB FORMAT, sending %d\n", format); - break; - } - - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_SET_NTB_FORMAT: - { - if (w_length != 0 || w_index != ncm->ctrl_id) - goto invalid; - switch (w_value) { - case 0x0000: - ncm->parser_opts = &ndp16_opts; - DBG(cdev, "NCM16 selected\n"); - break; - case 0x0001: - ncm->parser_opts = &ndp32_opts; - DBG(cdev, "NCM32 selected\n"); - break; - default: - goto invalid; - } - value = 0; - break; - } - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_GET_CRC_MODE: - { - uint16_t is_crc; - - if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id) - goto invalid; - is_crc = ncm->is_crc ? 0x0001 : 0x0000; - put_unaligned_le16(is_crc, req->buf); - value = 2; - VDBG(cdev, "Host asked CRC MODE, sending %d\n", is_crc); - break; - } - - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) - | USB_CDC_SET_CRC_MODE: - { - int ndp_hdr_crc = 0; - - if (w_length != 0 || w_index != ncm->ctrl_id) - goto invalid; - switch (w_value) { - case 0x0000: - ncm->is_crc = false; - ndp_hdr_crc = NCM_NDP_HDR_NOCRC; - DBG(cdev, "non-CRC mode selected\n"); - break; - case 0x0001: - ncm->is_crc = true; - ndp_hdr_crc = NCM_NDP_HDR_CRC; - DBG(cdev, "CRC mode selected\n"); - break; - default: - goto invalid; - } - ncm->parser_opts->ndp_sign &= ~NCM_NDP_HDR_CRC_MASK; - ncm->parser_opts->ndp_sign |= ndp_hdr_crc; - value = 0; - break; - } - - /* and disabled in ncm descriptor: */ - /* case USB_CDC_GET_NET_ADDRESS: */ - /* case USB_CDC_SET_NET_ADDRESS: */ - /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */ - /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */ - - default: -invalid: - DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - } - - /* respond with data transfer or status phase? */ - if (value >= 0) { - DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - req->zero = 0; - req->length = value; - value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); - if (value < 0) - ERROR(cdev, "ncm req %02x.%02x response err %d\n", - ctrl->bRequestType, ctrl->bRequest, - value); - } - - /* device either stalls (value < 0) or reports success */ - return value; -} - - -static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -{ - struct f_ncm *ncm = func_to_ncm(f); - struct usb_composite_dev *cdev = f->config->cdev; - - /* Control interface has only altsetting 0 */ - if (intf == ncm->ctrl_id) { - if (alt != 0) - goto fail; - - if (ncm->notify->driver_data) { - DBG(cdev, "reset ncm control %d\n", intf); - usb_ep_disable(ncm->notify); - } else { - DBG(cdev, "init ncm ctrl %d\n", intf); - ncm->notify_desc = ep_choose(cdev->gadget, - ncm->hs.notify, - ncm->fs.notify); - } - usb_ep_enable(ncm->notify, ncm->notify_desc); - ncm->notify->driver_data = ncm; - - /* Data interface has two altsettings, 0 and 1 */ - } else if (intf == ncm->data_id) { - if (alt > 1) - goto fail; - - if (ncm->port.in_ep->driver_data) { - DBG(cdev, "reset ncm\n"); - gether_disconnect(&ncm->port); - ncm_reset_values(ncm); - } - - /* - * CDC Network only sends data in non-default altsettings. - * Changing altsettings resets filters, statistics, etc. - */ - if (alt == 1) { - struct net_device *net; - - if (!ncm->port.in) { - DBG(cdev, "init ncm\n"); - ncm->port.in = ep_choose(cdev->gadget, - ncm->hs.in, - ncm->fs.in); - ncm->port.out = ep_choose(cdev->gadget, - ncm->hs.out, - ncm->fs.out); - } - - /* TODO */ - /* Enable zlps by default for NCM conformance; - * override for musb_hdrc (avoids txdma ovhead) - */ - ncm->port.is_zlp_ok = !( - gadget_is_musbhdrc(cdev->gadget) - ); - ncm->port.cdc_filter = DEFAULT_FILTER; - DBG(cdev, "activate ncm\n"); - net = gether_connect(&ncm->port); - if (IS_ERR(net)) - return PTR_ERR(net); - } - - spin_lock(&ncm->lock); - ncm_notify(ncm); - spin_unlock(&ncm->lock); - } else - goto fail; - - return 0; -fail: - return -EINVAL; -} - -/* - * Because the data interface supports multiple altsettings, - * this NCM function *MUST* implement a get_alt() method. - */ -static int ncm_get_alt(struct usb_function *f, unsigned intf) -{ - struct f_ncm *ncm = func_to_ncm(f); - - if (intf == ncm->ctrl_id) - return 0; - return ncm->port.in_ep->driver_data ? 1 : 0; -} - -static struct sk_buff *ncm_wrap_ntb(struct gether *port, - struct sk_buff *skb) -{ - struct f_ncm *ncm = func_to_ncm(&port->func); - struct sk_buff *skb2; - int ncb_len = 0; - __le16 *tmp; - int div = ntb_parameters.wNdpInDivisor; - int rem = ntb_parameters.wNdpInPayloadRemainder; - int pad; - int ndp_align = ntb_parameters.wNdpInAlignment; - int ndp_pad; - unsigned max_size = ncm->port.fixed_in_len; - struct ndp_parser_opts *opts = ncm->parser_opts; - unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; - - ncb_len += opts->nth_size; - ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len; - ncb_len += ndp_pad; - ncb_len += opts->ndp_size; - ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */ - ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */ - pad = ALIGN(ncb_len, div) + rem - ncb_len; - ncb_len += pad; - - if (ncb_len + skb->len + crc_len > max_size) { - dev_kfree_skb_any(skb); - return NULL; - } - - skb2 = skb_copy_expand(skb, ncb_len, - max_size - skb->len - ncb_len - crc_len, - GFP_ATOMIC); - dev_kfree_skb_any(skb); - if (!skb2) - return NULL; - - skb = skb2; - - tmp = (void *) skb_push(skb, ncb_len); - memset(tmp, 0, ncb_len); - - put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */ - tmp += 2; - /* wHeaderLength */ - put_unaligned_le16(opts->nth_size, tmp++); - tmp++; /* skip wSequence */ - put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */ - /* (d)wFpIndex */ - /* the first pointer is right after the NTH + align */ - put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad); - - tmp = (void *)tmp + ndp_pad; - - /* NDP */ - put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */ - tmp += 2; - /* wLength */ - put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++); - - tmp += opts->reserved1; - tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */ - tmp += opts->reserved2; - - if (ncm->is_crc) { - uint32_t crc; - - crc = ~crc32_le(~0, - skb->data + ncb_len, - skb->len - ncb_len); - put_unaligned_le32(crc, skb->data + skb->len); - skb_put(skb, crc_len); - } - - /* (d)wDatagramIndex[0] */ - put_ncm(&tmp, opts->dgram_item_len, ncb_len); - /* (d)wDatagramLength[0] */ - put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len); - /* (d)wDatagramIndex[1] and (d)wDatagramLength[1] already zeroed */ - - if (skb->len > MAX_TX_NONFIXED) - memset(skb_put(skb, max_size - skb->len), - 0, max_size - skb->len); - - return skb; -} - -static int ncm_unwrap_ntb(struct gether *port, - struct sk_buff *skb, - struct sk_buff_head *list) -{ - struct f_ncm *ncm = func_to_ncm(&port->func); - __le16 *tmp = (void *) skb->data; - unsigned index, index2; - unsigned dg_len, dg_len2; - unsigned ndp_len; - struct sk_buff *skb2; - int ret = -EINVAL; - unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); - struct ndp_parser_opts *opts = ncm->parser_opts; - unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; - int dgram_counter; - - /* dwSignature */ - if (get_unaligned_le32(tmp) != opts->nth_sign) { - INFO(port->func.config->cdev, "Wrong NTH SIGN, skblen %d\n", - skb->len); - print_hex_dump(KERN_INFO, "HEAD:", DUMP_PREFIX_ADDRESS, 32, 1, - skb->data, 32, false); - - goto err; - } - tmp += 2; - /* wHeaderLength */ - if (get_unaligned_le16(tmp++) != opts->nth_size) { - INFO(port->func.config->cdev, "Wrong NTB headersize\n"); - goto err; - } - tmp++; /* skip wSequence */ - - /* (d)wBlockLength */ - if (get_ncm(&tmp, opts->block_length) > max_size) { - INFO(port->func.config->cdev, "OUT size exceeded\n"); - goto err; - } - - index = get_ncm(&tmp, opts->fp_index); - /* NCM 3.2 */ - if (((index % 4) != 0) && (index < opts->nth_size)) { - INFO(port->func.config->cdev, "Bad index: %x\n", - index); - goto err; - } - - /* walk through NDP */ - tmp = ((void *)skb->data) + index; - if (get_unaligned_le32(tmp) != opts->ndp_sign) { - INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); - goto err; - } - tmp += 2; - - ndp_len = get_unaligned_le16(tmp++); - /* - * NCM 3.3.1 - * entry is 2 items - * item size is 16/32 bits, opts->dgram_item_len * 2 bytes - * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry - */ - if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2)) - || (ndp_len % opts->ndplen_align != 0)) { - INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len); - goto err; - } - tmp += opts->reserved1; - tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */ - tmp += opts->reserved2; - - ndp_len -= opts->ndp_size; - index2 = get_ncm(&tmp, opts->dgram_item_len); - dg_len2 = get_ncm(&tmp, opts->dgram_item_len); - dgram_counter = 0; - - do { - index = index2; - dg_len = dg_len2; - if (dg_len < 14 + crc_len) { /* ethernet header + crc */ - INFO(port->func.config->cdev, "Bad dgram length: %x\n", - dg_len); - goto err; - } - if (ncm->is_crc) { - uint32_t crc, crc2; - - crc = get_unaligned_le32(skb->data + - index + dg_len - crc_len); - crc2 = ~crc32_le(~0, - skb->data + index, - dg_len - crc_len); - if (crc != crc2) { - INFO(port->func.config->cdev, "Bad CRC\n"); - goto err; - } - } - - index2 = get_ncm(&tmp, opts->dgram_item_len); - dg_len2 = get_ncm(&tmp, opts->dgram_item_len); - - if (index2 == 0 || dg_len2 == 0) { - skb2 = skb; - } else { - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - goto err; - } - - if (!skb_pull(skb2, index)) { - ret = -EOVERFLOW; - goto err; - } - - skb_trim(skb2, dg_len - crc_len); - skb_queue_tail(list, skb2); - - ndp_len -= 2 * (opts->dgram_item_len * 2); - - dgram_counter++; - - if (index2 == 0 || dg_len2 == 0) - break; - } while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */ - - VDBG(port->func.config->cdev, - "Parsed NTB with %d frames\n", dgram_counter); - return 0; -err: - skb_queue_purge(list); - dev_kfree_skb_any(skb); - return ret; -} - -static void ncm_disable(struct usb_function *f) -{ - struct f_ncm *ncm = func_to_ncm(f); - struct usb_composite_dev *cdev = f->config->cdev; - - DBG(cdev, "ncm deactivated\n"); - - if (ncm->port.in_ep->driver_data) - gether_disconnect(&ncm->port); - - if (ncm->notify->driver_data) { - usb_ep_disable(ncm->notify); - ncm->notify->driver_data = NULL; - ncm->notify_desc = NULL; - } -} - -/*-------------------------------------------------------------------------*/ - -/* - * Callbacks let us notify the host about connect/disconnect when the - * net device is opened or closed. - * - * For testing, note that link states on this side include both opened - * and closed variants of: - * - * - disconnected/unconfigured - * - configured but inactive (data alt 0) - * - configured and active (data alt 1) - * - * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and - * SET_INTERFACE (altsetting). Remember also that "configured" doesn't - * imply the host is actually polling the notification endpoint, and - * likewise that "active" doesn't imply it's actually using the data - * endpoints for traffic. - */ - -static void ncm_open(struct gether *geth) -{ - struct f_ncm *ncm = func_to_ncm(&geth->func); - - DBG(ncm->port.func.config->cdev, "%s\n", __func__); - - spin_lock(&ncm->lock); - ncm->is_open = true; - ncm_notify(ncm); - spin_unlock(&ncm->lock); -} - -static void ncm_close(struct gether *geth) -{ - struct f_ncm *ncm = func_to_ncm(&geth->func); - - DBG(ncm->port.func.config->cdev, "%s\n", __func__); - - spin_lock(&ncm->lock); - ncm->is_open = false; - ncm_notify(ncm); - spin_unlock(&ncm->lock); -} - -/*-------------------------------------------------------------------------*/ - -/* ethernet function driver setup/binding */ - -static int __init -ncm_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct usb_composite_dev *cdev = c->cdev; - struct f_ncm *ncm = func_to_ncm(f); - int status; - struct usb_ep *ep; - - /* allocate instance-specific interface IDs */ - status = usb_interface_id(c, f); - if (status < 0) - goto fail; - ncm->ctrl_id = status; - ncm_iad_desc.bFirstInterface = status; - - ncm_control_intf.bInterfaceNumber = status; - ncm_union_desc.bMasterInterface0 = status; - - status = usb_interface_id(c, f); - if (status < 0) - goto fail; - ncm->data_id = status; - - ncm_data_nop_intf.bInterfaceNumber = status; - ncm_data_intf.bInterfaceNumber = status; - ncm_union_desc.bSlaveInterface0 = status; - - status = -ENODEV; - - /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_in_desc); - if (!ep) - goto fail; - ncm->port.in_ep = ep; - ep->driver_data = cdev; /* claim */ - - ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc); - if (!ep) - goto fail; - ncm->port.out_ep = ep; - ep->driver_data = cdev; /* claim */ - - ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc); - if (!ep) - goto fail; - ncm->notify = ep; - ep->driver_data = cdev; /* claim */ - - status = -ENOMEM; - - /* allocate notification request and buffer */ - ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); - if (!ncm->notify_req) - goto fail; - ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL); - if (!ncm->notify_req->buf) - goto fail; - ncm->notify_req->context = ncm; - ncm->notify_req->complete = ncm_notify_complete; - - /* copy descriptors, and track endpoint copies */ - f->descriptors = usb_copy_descriptors(ncm_fs_function); - if (!f->descriptors) - goto fail; - - ncm->fs.in = usb_find_endpoint(ncm_fs_function, - f->descriptors, &fs_ncm_in_desc); - ncm->fs.out = usb_find_endpoint(ncm_fs_function, - f->descriptors, &fs_ncm_out_desc); - ncm->fs.notify = usb_find_endpoint(ncm_fs_function, - f->descriptors, &fs_ncm_notify_desc); - - /* - * support all relevant hardware speeds... we expect that when - * hardware is dual speed, all bulk-capable endpoints work at - * both speeds - */ - if (gadget_is_dualspeed(c->cdev->gadget)) { - hs_ncm_in_desc.bEndpointAddress = - fs_ncm_in_desc.bEndpointAddress; - hs_ncm_out_desc.bEndpointAddress = - fs_ncm_out_desc.bEndpointAddress; - hs_ncm_notify_desc.bEndpointAddress = - fs_ncm_notify_desc.bEndpointAddress; - - /* copy descriptors, and track endpoint copies */ - f->hs_descriptors = usb_copy_descriptors(ncm_hs_function); - if (!f->hs_descriptors) - goto fail; - - ncm->hs.in = usb_find_endpoint(ncm_hs_function, - f->hs_descriptors, &hs_ncm_in_desc); - ncm->hs.out = usb_find_endpoint(ncm_hs_function, - f->hs_descriptors, &hs_ncm_out_desc); - ncm->hs.notify = usb_find_endpoint(ncm_hs_function, - f->hs_descriptors, &hs_ncm_notify_desc); - } - - /* - * NOTE: all that is done without knowing or caring about - * the network link ... which is unavailable to this code - * until we're activated via set_alt(). - */ - - ncm->port.open = ncm_open; - ncm->port.close = ncm_close; - - DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n", - gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", - ncm->port.in_ep->name, ncm->port.out_ep->name, - ncm->notify->name); - return 0; - -fail: - if (f->descriptors) - usb_free_descriptors(f->descriptors); - - if (ncm->notify_req) { - kfree(ncm->notify_req->buf); - usb_ep_free_request(ncm->notify, ncm->notify_req); - } - - /* we might as well release our claims on endpoints */ - if (ncm->notify) - ncm->notify->driver_data = NULL; - if (ncm->port.out) - ncm->port.out_ep->driver_data = NULL; - if (ncm->port.in) - ncm->port.in_ep->driver_data = NULL; - - ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); - - return status; -} - -static void -ncm_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_ncm *ncm = func_to_ncm(f); - - DBG(c->cdev, "ncm unbind\n"); - - if (gadget_is_dualspeed(c->cdev->gadget)) - usb_free_descriptors(f->hs_descriptors); - usb_free_descriptors(f->descriptors); - - kfree(ncm->notify_req->buf); - usb_ep_free_request(ncm->notify, ncm->notify_req); - - ncm_string_defs[1].s = NULL; - kfree(ncm); -} - -/** - * ncm_bind_config - add CDC Network link to a configuration - * @c: the configuration to support the network link - * @ethaddr: a buffer in which the ethernet address of the host side - * side of the link was recorded - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - * Caller must have called @gether_setup(). Caller is also responsible - * for calling @gether_cleanup() before module unload. - */ -int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) -{ - struct f_ncm *ncm; - int status; - - if (!can_support_ecm(c->cdev->gadget) || !ethaddr) - return -EINVAL; - - /* maybe allocate device-global string IDs */ - if (ncm_string_defs[0].id == 0) { - - /* control interface label */ - status = usb_string_id(c->cdev); - if (status < 0) - return status; - ncm_string_defs[STRING_CTRL_IDX].id = status; - ncm_control_intf.iInterface = status; - - /* data interface label */ - status = usb_string_id(c->cdev); - if (status < 0) - return status; - ncm_string_defs[STRING_DATA_IDX].id = status; - ncm_data_nop_intf.iInterface = status; - ncm_data_intf.iInterface = status; - - /* MAC address */ - status = usb_string_id(c->cdev); - if (status < 0) - return status; - ncm_string_defs[STRING_MAC_IDX].id = status; - ecm_desc.iMACAddress = status; - - /* IAD */ - status = usb_string_id(c->cdev); - if (status < 0) - return status; - ncm_string_defs[STRING_IAD_IDX].id = status; - ncm_iad_desc.iFunction = status; - } - - /* allocate and initialize one new instance */ - ncm = kzalloc(sizeof *ncm, GFP_KERNEL); - if (!ncm) - return -ENOMEM; - - /* export host's Ethernet address in CDC format */ - snprintf(ncm->ethaddr, sizeof ncm->ethaddr, - "%02X%02X%02X%02X%02X%02X", - ethaddr[0], ethaddr[1], ethaddr[2], - ethaddr[3], ethaddr[4], ethaddr[5]); - ncm_string_defs[1].s = ncm->ethaddr; - - spin_lock_init(&ncm->lock); - ncm_reset_values(ncm); - ncm->port.is_fixed = true; - - ncm->port.func.name = "cdc_network"; - ncm->port.func.strings = ncm_strings; - /* descriptors are per-instance copies */ - ncm->port.func.bind = ncm_bind; - ncm->port.func.unbind = ncm_unbind; - ncm->port.func.set_alt = ncm_set_alt; - ncm->port.func.get_alt = ncm_get_alt; - ncm->port.func.setup = ncm_setup; - ncm->port.func.disable = ncm_disable; - - ncm->port.wrap = ncm_wrap_ntb; - ncm->port.unwrap = ncm_unwrap_ntb; - - status = usb_add_function(c, &ncm->port.func); - if (status) { - ncm_string_defs[1].s = NULL; - kfree(ncm); - } - return status; -} diff --git a/trunk/drivers/usb/gadget/gadget_chips.h b/trunk/drivers/usb/gadget/gadget_chips.h index ad2114e87511..d7b3bbe56808 100644 --- a/trunk/drivers/usb/gadget/gadget_chips.h +++ b/trunk/drivers/usb/gadget/gadget_chips.h @@ -120,10 +120,10 @@ #define gadget_is_fsl_qe(g) 0 #endif -#ifdef CONFIG_USB_GADGET_CI13XXX_PCI -#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name)) +#ifdef CONFIG_USB_GADGET_CI13XXX +#define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name)) #else -#define gadget_is_ci13xxx_pci(g) 0 +#define gadget_is_ci13xxx(g) 0 #endif // CONFIG_USB_GADGET_SX2 @@ -148,12 +148,6 @@ #define gadget_is_pch(g) 0 #endif -#ifdef CONFIG_USB_GADGET_CI13XXX_MSM -#define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) -#else -#define gadget_is_ci13xxx_msm(g) 0 -#endif - /** * usb_gadget_controller_number - support bcdDevice id convention * @gadget: the controller being driven @@ -203,7 +197,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x21; else if (gadget_is_fsl_qe(gadget)) return 0x22; - else if (gadget_is_ci13xxx_pci(gadget)) + else if (gadget_is_ci13xxx(gadget)) return 0x23; else if (gadget_is_langwell(gadget)) return 0x24; @@ -213,8 +207,6 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x26; else if (gadget_is_pch(gadget)) return 0x27; - else if (gadget_is_ci13xxx_msm(gadget)) - return 0x28; return -ENOENT; } diff --git a/trunk/drivers/usb/gadget/imx_udc.c b/trunk/drivers/usb/gadget/imx_udc.c index 1210534822d6..b30f85d70480 100644 --- a/trunk/drivers/usb/gadget/imx_udc.c +++ b/trunk/drivers/usb/gadget/imx_udc.c @@ -1191,17 +1191,13 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) return IRQ_HANDLED; } -#ifndef MX1_INT_USBD0 -#define MX1_INT_USBD0 MX1_USBD_INT0 -#endif - static irqreturn_t imx_udc_bulk_irq(int irq, void *dev) { struct imx_udc_struct *imx_usb = dev; - struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_INT_USBD0]; + struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_USBD_INT0]; int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); - dump_ep_intr(__func__, irq - MX1_INT_USBD0, intr, imx_usb->dev); + dump_ep_intr(__func__, irq - MX1_USBD_INT0, intr, imx_usb->dev); if (!imx_usb->driver) { __raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); diff --git a/trunk/drivers/usb/gadget/ncm.c b/trunk/drivers/usb/gadget/ncm.c deleted file mode 100644 index 99c179ad729d..000000000000 --- a/trunk/drivers/usb/gadget/ncm.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * ncm.c -- NCM gadget driver - * - * Copyright (C) 2010 Nokia Corporation - * Contact: Yauheni Kaliuta - * - * The driver borrows from ether.c which is: - * - * Copyright (C) 2003-2005,2008 David Brownell - * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger - * Copyright (C) 2008 Nokia Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* #define DEBUG */ -/* #define VERBOSE_DEBUG */ - -#include -#include - - -#include "u_ether.h" - -#define DRIVER_DESC "NCM Gadget" - -/*-------------------------------------------------------------------------*/ - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "composite.c" -#include "usbstring.c" -#include "config.c" -#include "epautoconf.c" - -#include "f_ncm.c" -#include "u_ether.c" - -/*-------------------------------------------------------------------------*/ - -/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. - */ - -/* Thanks to NetChip Technologies for donating this product ID. - * It's for devices with only CDC Ethernet configurations. - */ -#define CDC_VENDOR_NUM 0x0525 /* NetChip */ -#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ - -/*-------------------------------------------------------------------------*/ - -static struct usb_device_descriptor device_desc = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - - .bcdUSB = cpu_to_le16 (0x0200), - - .bDeviceClass = USB_CLASS_COMM, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - /* .bMaxPacketSize0 = f(hardware) */ - - /* Vendor and product id defaults change according to what configs - * we support. (As does bNumConfigurations.) These values can - * also be overridden by module parameters. - */ - .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), - .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), - /* .bcdDevice = f(hardware) */ - /* .iManufacturer = DYNAMIC */ - /* .iProduct = DYNAMIC */ - /* NO SERIAL NUMBER */ - .bNumConfigurations = 1, -}; - -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; - - -/* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - -static char manufacturer[50]; - -static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab_dev = { - .language = 0x0409, /* en-us */ - .strings = strings_dev, -}; - -static struct usb_gadget_strings *dev_strings[] = { - &stringtab_dev, - NULL, -}; - -static u8 hostaddr[ETH_ALEN]; - -/*-------------------------------------------------------------------------*/ - -static int __init ncm_do_config(struct usb_configuration *c) -{ - /* FIXME alloc iConfiguration string, set it in c->strings */ - - if (gadget_is_otg(c->cdev->gadget)) { - c->descriptors = otg_desc; - c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - - return ncm_bind_config(c, hostaddr); -} - -static struct usb_configuration ncm_config_driver = { - /* .label = f(hardware) */ - .label = "CDC Ethernet (NCM)", - .bConfigurationValue = 1, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init gncm_bind(struct usb_composite_dev *cdev) -{ - int gcnum; - struct usb_gadget *gadget = cdev->gadget; - int status; - - /* set up network link layer */ - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) - return status; - - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - /* We assume that can_support_ecm() tells the truth; - * but if the controller isn't recognized at all then - * that assumption is a bit more likely to be wrong. - */ - dev_warn(&gadget->dev, - "controller '%s' not recognized; trying %s\n", - gadget->name, - ncm_config_driver.label); - device_desc.bcdDevice = - cpu_to_le16(0x0300 | 0x0099); - } - - - /* Allocate string descriptor numbers ... note that string - * contents can be overridden by the composite_dev glue. - */ - - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; - - status = usb_add_config(cdev, &ncm_config_driver, - ncm_do_config); - if (status < 0) - goto fail; - - dev_info(&gadget->dev, "%s\n", DRIVER_DESC); - - return 0; - -fail: - gether_cleanup(); - return status; -} - -static int __exit gncm_unbind(struct usb_composite_dev *cdev) -{ - gether_cleanup(); - return 0; -} - -static struct usb_composite_driver ncm_driver = { - .name = "g_ncm", - .dev = &device_desc, - .strings = dev_strings, - .unbind = __exit_p(gncm_unbind), -}; - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Yauheni Kaliuta"); -MODULE_LICENSE("GPL"); - -static int __init init(void) -{ - return usb_composite_probe(&ncm_driver, gncm_bind); -} -module_init(init); - -static void __exit cleanup(void) -{ - usb_composite_unregister(&ncm_driver); -} -module_exit(cleanup); diff --git a/trunk/drivers/usb/gadget/pch_udc.c b/trunk/drivers/usb/gadget/pch_udc.c index 0c8dd81dddca..4a5256977d29 100644 --- a/trunk/drivers/usb/gadget/pch_udc.c +++ b/trunk/drivers/usb/gadget/pch_udc.c @@ -337,7 +337,7 @@ struct pch_udc_dev { struct usb_gadget_driver *driver; struct pci_dev *pdev; struct pch_udc_ep ep[PCH_UDC_EP_NUM]; - spinlock_t lock; /* protects all state */ + spinlock_t lock; unsigned active:1, stall:1, prot_stall:1, @@ -1980,7 +1980,7 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num) pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); } - if (epsts & UDC_EPSTS_RCS) { + if (epsts & UDC_EPSTS_RCS) if (!dev->prot_stall) { pch_udc_ep_clear_stall(ep); } else { @@ -1988,7 +1988,6 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num) pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); } - } if (epsts & UDC_EPSTS_TDC) pch_udc_complete_transfer(ep); /* On IN interrupt, provide data if we have any */ @@ -2029,7 +2028,7 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) pch_udc_ep_set_stall(ep); pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); - if (epsts & UDC_EPSTS_RCS) { + if (epsts & UDC_EPSTS_RCS) if (!dev->prot_stall) { pch_udc_ep_clear_stall(ep); } else { @@ -2037,7 +2036,6 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); } - } if (((epsts & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) == UDC_EPSTS_OUT_DATA) { if (ep->dev->prot_stall == 1) { @@ -2150,10 +2148,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) pch_udc_set_dma(dev, DMA_DIR_RX); } else { /* control write */ - /* next function will pickuo an clear the status */ - ep->epsts = stat; - - pch_udc_svc_data_out(dev, 0); + pch_udc_svc_data_out(dev, UDC_EP0OUT_IDX); /* re-program desc. pointer for possible ZLPs */ pch_udc_ep_set_ddptr(ep, ep->td_data_phys); pch_udc_set_dma(dev, DMA_DIR_RX); @@ -2640,13 +2635,12 @@ static int init_dma_pools(struct pch_udc_dev *dev) return 0; } -int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +int usb_gadget_register_driver(struct usb_gadget_driver *driver) { struct pch_udc_dev *dev = pch_udc; int retval; - if (!driver || (driver->speed == USB_SPEED_UNKNOWN) || !bind || + if (!driver || (driver->speed == USB_SPEED_UNKNOWN) || !driver->bind || !driver->setup || !driver->unbind || !driver->disconnect) { dev_err(&dev->pdev->dev, "%s: invalid driver parameter\n", __func__); @@ -2665,7 +2659,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, dev->gadget.dev.driver = &driver->driver; /* Invoke the bind routine of the gadget driver */ - retval = bind(&dev->gadget); + retval = driver->bind(&dev->gadget); if (retval) { dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n", @@ -2683,7 +2677,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, dev->connected = 1; return 0; } -EXPORT_SYMBOL(usb_gadget_probe_driver); +EXPORT_SYMBOL(usb_gadget_register_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { @@ -2908,7 +2902,7 @@ static int pch_udc_probe(struct pci_dev *pdev, return retval; } -static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { +static const struct pci_device_id pch_udc_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, diff --git a/trunk/drivers/usb/gadget/u_ether.c b/trunk/drivers/usb/gadget/u_ether.c index a7826a6dcd8c..cb23355f52d3 100644 --- a/trunk/drivers/usb/gadget/u_ether.c +++ b/trunk/drivers/usb/gadget/u_ether.c @@ -240,9 +240,6 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) size += out->maxpacket - 1; size -= size % out->maxpacket; - if (dev->port_usb->is_fixed) - size = max(size, dev->port_usb->fixed_out_len); - skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); if (skb == NULL) { DBG(dev, "no rx skb\n"); @@ -581,19 +578,12 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, req->context = skb; req->complete = tx_complete; - /* NCM requires no zlp if transfer is dwNtbInMaxSize */ - if (dev->port_usb->is_fixed && - length == dev->port_usb->fixed_in_len && - (length % in->maxpacket) == 0) - req->zero = 0; - else - req->zero = 1; - /* use zlp framing on tx for strict CDC-Ether conformance, * though any robust network rx path ignores extra padding. * and some hardware doesn't like to write zlps. */ - if (req->zero && !dev->zlp && (length % in->maxpacket) == 0) + req->zero = 1; + if (!dev->zlp && (length % in->maxpacket) == 0) length++; req->length = length; diff --git a/trunk/drivers/usb/gadget/u_ether.h b/trunk/drivers/usb/gadget/u_ether.h index b56e1e7d423c..3c8c0c9f9d72 100644 --- a/trunk/drivers/usb/gadget/u_ether.h +++ b/trunk/drivers/usb/gadget/u_ether.h @@ -62,10 +62,6 @@ struct gether { /* hooks for added framing, as needed for RNDIS and EEM. */ u32 header_len; - /* NCM requires fixed size bundles */ - bool is_fixed; - u32 fixed_out_len; - u32 fixed_in_len; struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *skb); int (*unwrap)(struct gether *port, @@ -107,7 +103,6 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) /* each configuration may bind one instance of an ethernet link */ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); int eem_bind_config(struct usb_configuration *c); #ifdef USB_ETH_RNDIS diff --git a/trunk/drivers/usb/host/Kconfig b/trunk/drivers/usb/host/Kconfig index b9cc31172fbd..6a7c688b4781 100644 --- a/trunk/drivers/usb/host/Kconfig +++ b/trunk/drivers/usb/host/Kconfig @@ -141,17 +141,6 @@ config USB_EHCI_HCD_OMAP Enables support for the on-chip EHCI controller on OMAP3 and later chips. -config USB_EHCI_MSM - bool "Support for MSM on-chip EHCI USB controller" - depends on USB_EHCI_HCD && ARCH_MSM - select USB_EHCI_ROOT_HUB_TT - select USB_MSM_OTG_72K - ---help--- - Enables support for the USB Host controller present on the - Qualcomm chipsets. Root Hub has inbuilt TT. - This driver depends on OTG driver for PHY initialization, - clock management, powering up VBUS, and power management. - config USB_EHCI_HCD_PPC_OF bool "EHCI support for PPC USB controller on OF platform bus" depends on USB_EHCI_HCD && PPC_OF diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 48021d26024c..abe8336ebffa 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -114,9 +114,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n"); #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) -/* for ASPM quirk of ISOC on AMD SB800 */ -static struct pci_dev *amd_nb_dev; - /*-------------------------------------------------------------------------*/ #include "ehci.h" @@ -532,11 +529,6 @@ static void ehci_stop (struct usb_hcd *hcd) spin_unlock_irq (&ehci->lock); ehci_mem_cleanup (ehci); - if (amd_nb_dev) { - pci_dev_put(amd_nb_dev); - amd_nb_dev = NULL; - } - #ifdef EHCI_STATS ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, @@ -1239,11 +1231,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER spear_ehci_hcd_driver #endif -#ifdef CONFIG_USB_EHCI_MSM -#include "ehci-msm.c" -#define PLATFORM_DRIVER ehci_msm_driver -#endif - #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ !defined(XILINX_OF_PLATFORM_DRIVER) diff --git a/trunk/drivers/usb/host/ehci-msm.c b/trunk/drivers/usb/host/ehci-msm.c deleted file mode 100644 index 413f4deca532..000000000000 --- a/trunk/drivers/usb/host/ehci-msm.c +++ /dev/null @@ -1,345 +0,0 @@ -/* ehci-msm.c - HSUSB Host Controller Driver Implementation - * - * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. - * - * Partly derived from ehci-fsl.c and ehci-hcd.c - * Copyright (c) 2000-2004 by David Brownell - * Copyright (c) 2005 MontaVista Software - * - * All source code in this file is licensed under the following license except - * where indicated. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * See the GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can find it at http://www.fsf.org - */ - -#include -#include -#include -#include - -#include -#include - -#define MSM_USB_BASE (hcd->regs) - -static struct otg_transceiver *otg; - -/* - * ehci_run defined in drivers/usb/host/ehci-hcd.c reset the controller and - * the configuration settings in ehci_msm_reset vanish after controller is - * reset. Resetting the controler in ehci_run seems to be un-necessary - * provided HCD reset the controller before calling ehci_run. Most of the HCD - * do but some are not. So this function is same as ehci_run but we don't - * reset the controller here. - */ -static int ehci_msm_run(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 temp; - u32 hcc_params; - - hcd->uses_new_polling = 1; - - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); - - /* - * hcc_params controls whether ehci->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - * streaming mappings for I/O buffers, like pci_map_single(), - * can return segments above 4GB, if the device allows. - * - * NOTE: the dma mask is visible through dma_supported(), so - * drivers can pass this info along ... like NETIF_F_HIGHDMA, - * Scsi_Host.highmem_io, and so forth. It's readonly to all - * host side drivers though. - */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); - if (HCC_64BIT_ADDR(hcc_params)) - ehci_writel(ehci, 0, &ehci->regs->segment); - - /* - * Philips, Intel, and maybe others need CMD_RUN before the - * root hub will detect new devices (why?); NEC doesn't - */ - ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - dbg_cmd(ehci, "init", ehci->command); - - /* - * Start, enabling full USB 2.0 functionality ... usb 1.1 devices - * are explicitly handed to companion controller(s), so no TT is - * involved with the root hub. (Except where one is integrated, - * and there's no companion controller unless maybe for USB OTG.) - * - * Turning on the CF flag will transfer ownership of all ports - * from the companions to the EHCI controller. If any of the - * companions are in the middle of a port reset at the time, it - * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. After we set CF, - * a short delay lets the hardware catch up; new resets shouldn't - * be started before the port switching actions could complete. - */ - down_write(&ehci_cf_port_reset_rwsem); - hcd->state = HC_STATE_RUNNING; - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - usleep_range(5000, 5500); - up_write(&ehci_cf_port_reset_rwsem); - ehci->last_periodic_enable = ktime_get_real(); - - temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci_info(ehci, - "USB %x.%x started, EHCI %x.%02x%s\n", - ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, - ignore_oc ? ", overcurrent ignored" : ""); - - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ - - /* GRR this is run-once init(), being done every time the HC starts. - * So long as they're part of class devices, we can't do it init() - * since the class device isn't created that early. - */ - create_debug_files(ehci); - create_companion_file(ehci); - - return 0; -} - -static int ehci_msm_reset(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - ehci->caps = USB_CAPLENGTH; - ehci->regs = USB_CAPLENGTH + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache the data to minimize the chip reads*/ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - hcd->has_tt = 1; - ehci->sbrn = HCD_USB2; - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - retval = ehci_reset(ehci); - if (retval) - return retval; - - /* bursts of unspecified length. */ - writel(0, USB_AHBBURST); - /* Use the AHB transactor */ - writel(0, USB_AHBMODE); - /* Disable streaming mode and select host mode */ - writel(0x13, USB_USBMODE); - - ehci_port_power(ehci, 1); - return 0; -} - -static struct hc_driver msm_hc_driver = { - .description = hcd_name, - .product_desc = "Qualcomm On-Chip EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY, - - .reset = ehci_msm_reset, - .start = ehci_msm_run, - - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - /* - * PM support - */ - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -}; - -static int ehci_msm_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int ret; - - dev_dbg(&pdev->dev, "ehci_msm proble\n"); - - hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - dev_err(&pdev->dev, "Unable to create HCD\n"); - return -ENOMEM; - } - - hcd->irq = platform_get_irq(pdev, 0); - if (hcd->irq < 0) { - dev_err(&pdev->dev, "Unable to get IRQ resource\n"); - ret = hcd->irq; - goto put_hcd; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Unable to get memory resource\n"); - ret = -ENODEV; - goto put_hcd; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto put_hcd; - } - - /* - * OTG driver takes care of PHY initialization, clock management, - * powering up VBUS, mapping of registers address space and power - * management. - */ - otg = otg_get_transceiver(); - if (!otg) { - dev_err(&pdev->dev, "unable to find transceiver\n"); - ret = -ENODEV; - goto unmap; - } - - ret = otg_set_host(otg, &hcd->self); - if (ret < 0) { - dev_err(&pdev->dev, "unable to register with transceiver\n"); - goto put_transceiver; - } - - device_init_wakeup(&pdev->dev, 1); - /* - * OTG device parent of HCD takes care of putting - * hardware into low power mode. - */ - pm_runtime_no_callbacks(&pdev->dev); - pm_runtime_enable(&pdev->dev); - - return 0; - -put_transceiver: - otg_put_transceiver(otg); -unmap: - iounmap(hcd->regs); -put_hcd: - usb_put_hcd(hcd); - - return ret; -} - -static int __devexit ehci_msm_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - device_init_wakeup(&pdev->dev, 0); - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - - otg_set_host(otg, NULL); - otg_put_transceiver(otg); - - usb_put_hcd(hcd); - - return 0; -} - -#ifdef CONFIG_PM -static int ehci_msm_pm_suspend(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - bool wakeup = device_may_wakeup(dev); - - dev_dbg(dev, "ehci-msm PM suspend\n"); - - /* - * EHCI helper function has also the same check before manipulating - * port wakeup flags. We do check here the same condition before - * calling the same helper function to avoid bringing hardware - * from Low power mode when there is no need for adjusting port - * wakeup flags. - */ - if (hcd->self.root_hub->do_remote_wakeup && !wakeup) { - pm_runtime_resume(dev); - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), - wakeup); - } - - return 0; -} - -static int ehci_msm_pm_resume(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - - dev_dbg(dev, "ehci-msm PM resume\n"); - ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); - - return 0; -} -#else -#define ehci_msm_pm_suspend NULL -#define ehci_msm_pm_resume NULL -#endif - -static const struct dev_pm_ops ehci_msm_dev_pm_ops = { - .suspend = ehci_msm_pm_suspend, - .resume = ehci_msm_pm_resume, -}; - -static struct platform_driver ehci_msm_driver = { - .probe = ehci_msm_probe, - .remove = __devexit_p(ehci_msm_remove), - .driver = { - .name = "msm_hsusb_host", - .pm = &ehci_msm_dev_pm_ops, - }, -}; diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 35a533e4c01d..56c78e93440f 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -44,35 +44,6 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } -static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) -{ - struct pci_dev *amd_smbus_dev; - u8 rev = 0; - - amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); - if (!amd_smbus_dev) - return 0; - - pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); - if (rev < 0x40) { - pci_dev_put(amd_smbus_dev); - amd_smbus_dev = NULL; - return 0; - } - - if (!amd_nb_dev) - amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (!amd_nb_dev) - ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); - - ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); - - pci_dev_put(amd_smbus_dev); - amd_smbus_dev = NULL; - - return 1; -} - /* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { @@ -131,9 +102,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (ehci_quirk_amd_SB800(ehci)) - ehci->amd_l1_fix = 1; - retval = ehci_halt(ehci); if (retval) return retval; diff --git a/trunk/drivers/usb/host/ehci-sched.c b/trunk/drivers/usb/host/ehci-sched.c index 724ba7133c4f..a92526d6e5ae 100644 --- a/trunk/drivers/usb/host/ehci-sched.c +++ b/trunk/drivers/usb/host/ehci-sched.c @@ -1583,63 +1583,6 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); } -#define AB_REG_BAR_LOW 0xe0 -#define AB_REG_BAR_HIGH 0xe1 -#define AB_INDX(addr) ((addr) + 0x00) -#define AB_DATA(addr) ((addr) + 0x04) -#define NB_PCIE_INDX_ADDR 0xe0 -#define NB_PCIE_INDX_DATA 0xe4 -#define NB_PIF0_PWRDOWN_0 0x01100012 -#define NB_PIF0_PWRDOWN_1 0x01100013 - -static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable) -{ - u32 addr, addr_low, addr_high, val; - - outb_p(AB_REG_BAR_LOW, 0xcd6); - addr_low = inb_p(0xcd7); - outb_p(AB_REG_BAR_HIGH, 0xcd6); - addr_high = inb_p(0xcd7); - addr = addr_high << 8 | addr_low; - outl_p(0x30, AB_INDX(addr)); - outl_p(0x40, AB_DATA(addr)); - outl_p(0x34, AB_INDX(addr)); - val = inl_p(AB_DATA(addr)); - - if (disable) { - val &= ~0x8; - val |= (1 << 4) | (1 << 9); - } else { - val |= 0x8; - val &= ~((1 << 4) | (1 << 9)); - } - outl_p(val, AB_DATA(addr)); - - if (amd_nb_dev) { - addr = NB_PIF0_PWRDOWN_0; - pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); - - addr = NB_PIF0_PWRDOWN_1; - pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); - } - - return; -} - /* fit urb's itds into the selected schedule slot; activate as needed */ static int itd_link_urb ( @@ -1666,12 +1609,6 @@ itd_link_urb ( urb->interval, next_uframe >> 3, next_uframe & 0x7); } - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_l1_fix == 1) - ehci_quirk_amd_L1(ehci, 1); - } - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill iTDs uframe by uframe */ @@ -1796,11 +1733,6 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_l1_fix == 1) - ehci_quirk_amd_L1(ehci, 0); - } - if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; @@ -2086,12 +2018,6 @@ sitd_link_urb ( (next_uframe >> 3) & (ehci->periodic_size - 1), stream->interval, hc32_to_cpu(ehci, stream->splits)); } - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_l1_fix == 1) - ehci_quirk_amd_L1(ehci, 1); - } - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill sITDs frame by frame */ @@ -2192,11 +2118,6 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_l1_fix == 1) - ehci_quirk_amd_L1(ehci, 0); - } - if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; diff --git a/trunk/drivers/usb/host/ehci.h b/trunk/drivers/usb/host/ehci.h index fd1c53da89e4..bde823f704e9 100644 --- a/trunk/drivers/usb/host/ehci.h +++ b/trunk/drivers/usb/host/ehci.h @@ -130,7 +130,6 @@ struct ehci_hcd { /* one per controller */ unsigned has_amcc_usb23:1; unsigned need_io_watchdog:1; unsigned broken_periodic:1; - unsigned amd_l1_fix:1; unsigned fs_i_thresh:1; /* Intel iso scheduling */ /* required for usb32 quirk */ diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index af77abb5c68b..2090b45eb606 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -29,7 +29,7 @@ static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); - uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); + uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); } static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) @@ -195,9 +195,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, } else { struct uhci_td *ntd; - ntd = list_entry(td->fl_list.next, - struct uhci_td, - fl_list); + ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); uhci->frame[td->frame] = LINK_TO_TD(ntd); uhci->frame_cpu[td->frame] = ntd; } @@ -730,7 +728,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, urbp->urb = urb; urb->hcpriv = urbp; - + INIT_LIST_HEAD(&urbp->node); INIT_LIST_HEAD(&urbp->td_list); @@ -848,7 +846,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, /* Alternate Data0/1 (start with Data1) */ destination ^= TD_TOKEN_TOGGLE; - + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(pktsze), data); @@ -859,7 +857,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, } /* - * Build the final TD for control status + * Build the final TD for control status */ td = uhci_alloc_td(uhci); if (!td) diff --git a/trunk/drivers/usb/host/whci/hcd.c b/trunk/drivers/usb/host/whci/hcd.c index 9546f6cd01f0..72b6892fda67 100644 --- a/trunk/drivers/usb/host/whci/hcd.c +++ b/trunk/drivers/usb/host/whci/hcd.c @@ -356,7 +356,7 @@ static void __exit whci_hc_driver_exit(void) module_exit(whci_hc_driver_exit); /* PCI device ID's that we handle (so it gets loaded) */ -static struct pci_device_id __used whci_hcd_id_table[] = { +static struct pci_device_id whci_hcd_id_table[] = { { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, { /* empty last entry */ } }; diff --git a/trunk/drivers/usb/musb/musb_core.h b/trunk/drivers/usb/musb/musb_core.h index 6ad72f395e28..59928a235dc5 100644 --- a/trunk/drivers/usb/musb/musb_core.h +++ b/trunk/drivers/usb/musb/musb_core.h @@ -253,6 +253,34 @@ enum musb_g_ep0_state { /******************************** TYPES *************************************/ +/** + * struct musb_platform_ops - Operations passed to musb_core by HW glue layer + * @init: turns on clocks, sets up platform-specific registers, etc + * @exit: undoes @init + * @suspend: platform-specific suspend, e.g. context save + * @resume: platform-specific resume, e.g. context restore + * @set_mode: forcefully changes operating mode + * @try_ilde: tries to idle the IP + * @vbus_status: returns vbus status if possible + * @set_vbus: forces vbus status + */ +struct musb_platform_ops { + int (*init)(struct musb *musb); + int (*exit)(struct musb *musb); + + int (*suspend)(struct musb *musb); + int (*resume)(struct musb *musb); + + void (*enable)(struct musb *musb); + void (*disable)(struct musb *musb); + + int (*set_mode)(struct musb *musb, u8 mode); + void (*try_idle)(struct musb *musb, unsigned long timeout); + + int (*vbus_status)(struct musb *musb); + void (*set_vbus)(struct musb *musb, int on); +}; + /* * struct musb_hw_ep - endpoint hardware (bidirectional) * diff --git a/trunk/drivers/usb/otg/Kconfig b/trunk/drivers/usb/otg/Kconfig index 6491717a636a..5ce07528cd0c 100644 --- a/trunk/drivers/usb/otg/Kconfig +++ b/trunk/drivers/usb/otg/Kconfig @@ -81,24 +81,4 @@ config USB_LANGWELL_OTG To compile this driver as a module, choose M here: the module will be called langwell_otg. -config USB_MSM_OTG_72K - tristate "OTG support for Qualcomm on-chip USB controller" - depends on (USB || USB_GADGET) && ARCH_MSM - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver on MSM chips. It - handles PHY initialization, clock management, and workarounds - required after resetting the hardware and power management. - This driver is required even for peripheral only or host only - mode configurations. - -config AB8500_USB - tristate "AB8500 USB Transceiver Driver" - depends on AB8500_CORE - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver in AB8500 chip. - This transceiver supports high and full speed devices plus, - in host mode, low speed. - endif # USB || OTG diff --git a/trunk/drivers/usb/otg/Makefile b/trunk/drivers/usb/otg/Makefile index 30a23f3b7a1f..66f1b83e4fa7 100644 --- a/trunk/drivers/usb/otg/Makefile +++ b/trunk/drivers/usb/otg/Makefile @@ -15,5 +15,3 @@ obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o -obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o -obj-$(CONFIG_AB8500_USB) += ab8500-usb.o diff --git a/trunk/drivers/usb/otg/ab8500-usb.c b/trunk/drivers/usb/otg/ab8500-usb.c deleted file mode 100644 index d14736b3107b..000000000000 --- a/trunk/drivers/usb/otg/ab8500-usb.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * drivers/usb/otg/ab8500_usb.c - * - * USB transceiver driver for AB8500 chip - * - * Copyright (C) 2010 ST-Ericsson AB - * Mian Yousaf Kaukab - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AB8500_MAIN_WD_CTRL_REG 0x01 -#define AB8500_USB_LINE_STAT_REG 0x80 -#define AB8500_USB_PHY_CTRL_REG 0x8A - -#define AB8500_BIT_OTG_STAT_ID (1 << 0) -#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) -#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) -#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) -#define AB8500_BIT_WD_CTRL_KICK (1 << 1) - -#define AB8500_V1x_LINK_STAT_WAIT (HZ/10) -#define AB8500_WD_KICK_DELAY_US 100 /* usec */ -#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ -#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */ - -/* Usb line status register */ -enum ab8500_usb_link_status { - USB_LINK_NOT_CONFIGURED = 0, - USB_LINK_STD_HOST_NC, - USB_LINK_STD_HOST_C_NS, - USB_LINK_STD_HOST_C_S, - USB_LINK_HOST_CHG_NM, - USB_LINK_HOST_CHG_HS, - USB_LINK_HOST_CHG_HS_CHIRP, - USB_LINK_DEDICATED_CHG, - USB_LINK_ACA_RID_A, - USB_LINK_ACA_RID_B, - USB_LINK_ACA_RID_C_NM, - USB_LINK_ACA_RID_C_HS, - USB_LINK_ACA_RID_C_HS_CHIRP, - USB_LINK_HM_IDGND, - USB_LINK_RESERVED, - USB_LINK_NOT_VALID_LINK -}; - -struct ab8500_usb { - struct otg_transceiver otg; - struct device *dev; - int irq_num_id_rise; - int irq_num_id_fall; - int irq_num_vbus_rise; - int irq_num_vbus_fall; - int irq_num_link_status; - unsigned vbus_draw; - struct delayed_work dwork; - struct work_struct phy_dis_work; - unsigned long link_status_wait; - int rev; -}; - -static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x) -{ - return container_of(x, struct ab8500_usb, otg); -} - -static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) -{ - abx500_set_register_interruptible(ab->dev, - AB8500_SYS_CTRL2_BLOCK, - AB8500_MAIN_WD_CTRL_REG, - AB8500_BIT_WD_CTRL_ENABLE); - - udelay(AB8500_WD_KICK_DELAY_US); - - abx500_set_register_interruptible(ab->dev, - AB8500_SYS_CTRL2_BLOCK, - AB8500_MAIN_WD_CTRL_REG, - (AB8500_BIT_WD_CTRL_ENABLE - | AB8500_BIT_WD_CTRL_KICK)); - - if (ab->rev > 0x10) /* v1.1 v2.0 */ - udelay(AB8500_WD_V11_DISABLE_DELAY_US); - else /* v1.0 */ - msleep(AB8500_WD_V10_DISABLE_DELAY_MS); - - abx500_set_register_interruptible(ab->dev, - AB8500_SYS_CTRL2_BLOCK, - AB8500_MAIN_WD_CTRL_REG, - 0); -} - -static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, - bool enable) -{ - u8 ctrl_reg; - abx500_get_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_PHY_CTRL_REG, - &ctrl_reg); - if (sel_host) { - if (enable) - ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN; - else - ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN; - } else { - if (enable) - ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN; - else - ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN; - } - - abx500_set_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_PHY_CTRL_REG, - ctrl_reg); - - /* Needed to enable the phy.*/ - if (enable) - ab8500_usb_wd_workaround(ab); -} - -#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true) -#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false) -#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true) -#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false) - -static int ab8500_usb_link_status_update(struct ab8500_usb *ab) -{ - u8 reg; - enum ab8500_usb_link_status lsts; - void *v = NULL; - enum usb_xceiv_events event; - - abx500_get_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_LINE_STAT_REG, - ®); - - lsts = (reg >> 3) & 0x0F; - - switch (lsts) { - case USB_LINK_NOT_CONFIGURED: - case USB_LINK_RESERVED: - case USB_LINK_NOT_VALID_LINK: - /* TODO: Disable regulators. */ - ab8500_usb_host_phy_dis(ab); - ab8500_usb_peri_phy_dis(ab); - ab->otg.state = OTG_STATE_B_IDLE; - ab->otg.default_a = false; - ab->vbus_draw = 0; - event = USB_EVENT_NONE; - break; - - case USB_LINK_STD_HOST_NC: - case USB_LINK_STD_HOST_C_NS: - case USB_LINK_STD_HOST_C_S: - case USB_LINK_HOST_CHG_NM: - case USB_LINK_HOST_CHG_HS: - case USB_LINK_HOST_CHG_HS_CHIRP: - if (ab->otg.gadget) { - /* TODO: Enable regulators. */ - ab8500_usb_peri_phy_en(ab); - v = ab->otg.gadget; - } - event = USB_EVENT_VBUS; - break; - - case USB_LINK_HM_IDGND: - if (ab->otg.host) { - /* TODO: Enable regulators. */ - ab8500_usb_host_phy_en(ab); - v = ab->otg.host; - } - ab->otg.state = OTG_STATE_A_IDLE; - ab->otg.default_a = true; - event = USB_EVENT_ID; - break; - - case USB_LINK_ACA_RID_A: - case USB_LINK_ACA_RID_B: - /* TODO */ - case USB_LINK_ACA_RID_C_NM: - case USB_LINK_ACA_RID_C_HS: - case USB_LINK_ACA_RID_C_HS_CHIRP: - case USB_LINK_DEDICATED_CHG: - /* TODO: vbus_draw */ - event = USB_EVENT_CHARGER; - break; - } - - blocking_notifier_call_chain(&ab->otg.notifier, event, v); - - return 0; -} - -static void ab8500_usb_delayed_work(struct work_struct *work) -{ - struct ab8500_usb *ab = container_of(work, struct ab8500_usb, - dwork.work); - - ab8500_usb_link_status_update(ab); -} - -static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - /* Wait for link status to become stable. */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - - return IRQ_HANDLED; -} - -static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - /* Link status will not be updated till phy is disabled. */ - ab8500_usb_peri_phy_dis(ab); - - /* Wait for link status to become stable. */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - - return IRQ_HANDLED; -} - -static irqreturn_t ab8500_usb_v20_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - ab8500_usb_link_status_update(ab); - - return IRQ_HANDLED; -} - -static void ab8500_usb_phy_disable_work(struct work_struct *work) -{ - struct ab8500_usb *ab = container_of(work, struct ab8500_usb, - phy_dis_work); - - if (!ab->otg.host) - ab8500_usb_host_phy_dis(ab); - - if (!ab->otg.gadget) - ab8500_usb_peri_phy_dis(ab); -} - -static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) -{ - struct ab8500_usb *ab; - - if (!otg) - return -ENODEV; - - ab = xceiv_to_ab(otg); - - ab->vbus_draw = mA; - - if (mA) - blocking_notifier_call_chain(&ab->otg.notifier, - USB_EVENT_ENUMERATED, ab->otg.gadget); - return 0; -} - -/* TODO: Implement some way for charging or other drivers to read - * ab->vbus_draw. - */ - -static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend) -{ - /* TODO */ - return 0; -} - -static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) -{ - struct ab8500_usb *ab; - - if (!otg) - return -ENODEV; - - ab = xceiv_to_ab(otg); - - /* Some drivers call this function in atomic context. - * Do not update ab8500 registers directly till this - * is fixed. - */ - - if (!gadget) { - /* TODO: Disable regulators. */ - ab->otg.gadget = NULL; - schedule_work(&ab->phy_dis_work); - } else { - ab->otg.gadget = gadget; - ab->otg.state = OTG_STATE_B_IDLE; - - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - } - - return 0; -} - -static int ab8500_usb_set_host(struct otg_transceiver *otg, - struct usb_bus *host) -{ - struct ab8500_usb *ab; - - if (!otg) - return -ENODEV; - - ab = xceiv_to_ab(otg); - - /* Some drivers call this function in atomic context. - * Do not update ab8500 registers directly till this - * is fixed. - */ - - if (!host) { - /* TODO: Disable regulators. */ - ab->otg.host = NULL; - schedule_work(&ab->phy_dis_work); - } else { - ab->otg.host = host; - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - } - - return 0; -} - -static void ab8500_usb_irq_free(struct ab8500_usb *ab) -{ - if (ab->rev < 0x20) { - free_irq(ab->irq_num_id_rise, ab); - free_irq(ab->irq_num_id_fall, ab); - free_irq(ab->irq_num_vbus_rise, ab); - free_irq(ab->irq_num_vbus_fall, ab); - } else { - free_irq(ab->irq_num_link_status, ab); - } -} - -static int ab8500_usb_v1x_res_setup(struct platform_device *pdev, - struct ab8500_usb *ab) -{ - int err; - - ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R"); - if (ab->irq_num_id_rise < 0) { - dev_err(&pdev->dev, "ID rise irq not found\n"); - return ab->irq_num_id_rise; - } - err = request_threaded_irq(ab->irq_num_id_rise, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-id-rise", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for ID rise irq\n"); - goto fail0; - } - - ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); - if (ab->irq_num_id_fall < 0) { - dev_err(&pdev->dev, "ID fall irq not found\n"); - return ab->irq_num_id_fall; - } - err = request_threaded_irq(ab->irq_num_id_fall, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-id-fall", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for ID fall irq\n"); - goto fail1; - } - - ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R"); - if (ab->irq_num_vbus_rise < 0) { - dev_err(&pdev->dev, "VBUS rise irq not found\n"); - return ab->irq_num_vbus_rise; - } - err = request_threaded_irq(ab->irq_num_vbus_rise, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-vbus-rise", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for Vbus rise irq\n"); - goto fail2; - } - - ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F"); - if (ab->irq_num_vbus_fall < 0) { - dev_err(&pdev->dev, "VBUS fall irq not found\n"); - return ab->irq_num_vbus_fall; - } - err = request_threaded_irq(ab->irq_num_vbus_fall, NULL, - ab8500_usb_v1x_vbus_fall_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-vbus-fall", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); - goto fail3; - } - - return 0; -fail3: - free_irq(ab->irq_num_vbus_rise, ab); -fail2: - free_irq(ab->irq_num_id_fall, ab); -fail1: - free_irq(ab->irq_num_id_rise, ab); -fail0: - return err; -} - -static int ab8500_usb_v2_res_setup(struct platform_device *pdev, - struct ab8500_usb *ab) -{ - int err; - - ab->irq_num_link_status = platform_get_irq_byname(pdev, - "USB_LINK_STATUS"); - if (ab->irq_num_link_status < 0) { - dev_err(&pdev->dev, "Link status irq not found\n"); - return ab->irq_num_link_status; - } - - err = request_threaded_irq(ab->irq_num_link_status, NULL, - ab8500_usb_v20_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-link-status", ab); - if (err < 0) { - dev_err(ab->dev, - "request_irq failed for link status irq\n"); - return err; - } - - return 0; -} - -static int __devinit ab8500_usb_probe(struct platform_device *pdev) -{ - struct ab8500_usb *ab; - int err; - int rev; - - rev = abx500_get_chip_id(&pdev->dev); - if (rev < 0) { - dev_err(&pdev->dev, "Chip id read failed\n"); - return rev; - } else if (rev < 0x10) { - dev_err(&pdev->dev, "Unsupported AB8500 chip\n"); - return -ENODEV; - } - - ab = kzalloc(sizeof *ab, GFP_KERNEL); - if (!ab) - return -ENOMEM; - - ab->dev = &pdev->dev; - ab->rev = rev; - ab->otg.dev = ab->dev; - ab->otg.label = "ab8500"; - ab->otg.state = OTG_STATE_UNDEFINED; - ab->otg.set_host = ab8500_usb_set_host; - ab->otg.set_peripheral = ab8500_usb_set_peripheral; - ab->otg.set_suspend = ab8500_usb_set_suspend; - ab->otg.set_power = ab8500_usb_set_power; - - platform_set_drvdata(pdev, ab); - - BLOCKING_INIT_NOTIFIER_HEAD(&ab->otg.notifier); - - /* v1: Wait for link status to become stable. - * all: Updates form set_host and set_peripheral as they are atomic. - */ - INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work); - - /* all: Disable phy when called from set_host and set_peripheral */ - INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); - - if (ab->rev < 0x20) { - err = ab8500_usb_v1x_res_setup(pdev, ab); - ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT; - } else { - err = ab8500_usb_v2_res_setup(pdev, ab); - } - - if (err < 0) - goto fail0; - - err = otg_set_transceiver(&ab->otg); - if (err) { - dev_err(&pdev->dev, "Can't register transceiver\n"); - goto fail1; - } - - dev_info(&pdev->dev, "AB8500 usb driver initialized\n"); - - return 0; -fail1: - ab8500_usb_irq_free(ab); -fail0: - kfree(ab); - return err; -} - -static int __devexit ab8500_usb_remove(struct platform_device *pdev) -{ - struct ab8500_usb *ab = platform_get_drvdata(pdev); - - ab8500_usb_irq_free(ab); - - cancel_delayed_work_sync(&ab->dwork); - - cancel_work_sync(&ab->phy_dis_work); - - otg_set_transceiver(NULL); - - ab8500_usb_host_phy_dis(ab); - ab8500_usb_peri_phy_dis(ab); - - platform_set_drvdata(pdev, NULL); - - kfree(ab); - - return 0; -} - -static struct platform_driver ab8500_usb_driver = { - .probe = ab8500_usb_probe, - .remove = __devexit_p(ab8500_usb_remove), - .driver = { - .name = "ab8500-usb", - .owner = THIS_MODULE, - }, -}; - -static int __init ab8500_usb_init(void) -{ - return platform_driver_register(&ab8500_usb_driver); -} -subsys_initcall(ab8500_usb_init); - -static void __exit ab8500_usb_exit(void) -{ - platform_driver_unregister(&ab8500_usb_driver); -} -module_exit(ab8500_usb_exit); - -MODULE_ALIAS("platform:ab8500_usb"); -MODULE_AUTHOR("ST-Ericsson AB"); -MODULE_DESCRIPTION("AB8500 usb transceiver driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/otg/msm72k_otg.c b/trunk/drivers/usb/otg/msm72k_otg.c deleted file mode 100644 index 1cd52edcd0c2..000000000000 --- a/trunk/drivers/usb/otg/msm72k_otg.c +++ /dev/null @@ -1,1125 +0,0 @@ -/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MSM_USB_BASE (motg->regs) -#define DRIVER_NAME "msm_otg" - -#define ULPI_IO_TIMEOUT_USEC (10 * 1000) -static int ulpi_read(struct otg_transceiver *otg, u32 reg) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - int cnt = 0; - - /* initiate read operation */ - writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg), - USB_ULPI_VIEWPORT); - - /* wait for completion */ - while (cnt < ULPI_IO_TIMEOUT_USEC) { - if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) - break; - udelay(1); - cnt++; - } - - if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_read: timeout %08x\n", - readl(USB_ULPI_VIEWPORT)); - return -ETIMEDOUT; - } - return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); -} - -static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - int cnt = 0; - - /* initiate write operation */ - writel(ULPI_RUN | ULPI_WRITE | - ULPI_ADDR(reg) | ULPI_DATA(val), - USB_ULPI_VIEWPORT); - - /* wait for completion */ - while (cnt < ULPI_IO_TIMEOUT_USEC) { - if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) - break; - udelay(1); - cnt++; - } - - if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_write: timeout\n"); - return -ETIMEDOUT; - } - return 0; -} - -static struct otg_io_access_ops msm_otg_io_ops = { - .read = ulpi_read, - .write = ulpi_write, -}; - -static void ulpi_init(struct msm_otg *motg) -{ - struct msm_otg_platform_data *pdata = motg->pdata; - int *seq = pdata->phy_init_seq; - - if (!seq) - return; - - while (seq[0] >= 0) { - dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n", - seq[0], seq[1]); - ulpi_write(&motg->otg, seq[0], seq[1]); - seq += 2; - } -} - -static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) -{ - int ret; - - if (assert) { - ret = clk_reset(motg->clk, CLK_RESET_ASSERT); - if (ret) - dev_err(motg->otg.dev, "usb hs_clk assert failed\n"); - } else { - ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); - if (ret) - dev_err(motg->otg.dev, "usb hs_clk deassert failed\n"); - } - return ret; -} - -static int msm_otg_phy_clk_reset(struct msm_otg *motg) -{ - int ret; - - ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); - if (ret) { - dev_err(motg->otg.dev, "usb phy clk assert failed\n"); - return ret; - } - usleep_range(10000, 12000); - ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); - if (ret) - dev_err(motg->otg.dev, "usb phy clk deassert failed\n"); - return ret; -} - -static int msm_otg_phy_reset(struct msm_otg *motg) -{ - u32 val; - int ret; - int retries; - - ret = msm_otg_link_clk_reset(motg, 1); - if (ret) - return ret; - ret = msm_otg_phy_clk_reset(motg); - if (ret) - return ret; - ret = msm_otg_link_clk_reset(motg, 0); - if (ret) - return ret; - - val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; - writel(val | PORTSC_PTS_ULPI, USB_PORTSC); - - for (retries = 3; retries > 0; retries--) { - ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, - ULPI_CLR(ULPI_FUNC_CTRL)); - if (!ret) - break; - ret = msm_otg_phy_clk_reset(motg); - if (ret) - return ret; - } - if (!retries) - return -ETIMEDOUT; - - /* This reset calibrates the phy, if the above write succeeded */ - ret = msm_otg_phy_clk_reset(motg); - if (ret) - return ret; - - for (retries = 3; retries > 0; retries--) { - ret = ulpi_read(&motg->otg, ULPI_DEBUG); - if (ret != -ETIMEDOUT) - break; - ret = msm_otg_phy_clk_reset(motg); - if (ret) - return ret; - } - if (!retries) - return -ETIMEDOUT; - - dev_info(motg->otg.dev, "phy_reset: success\n"); - return 0; -} - -#define LINK_RESET_TIMEOUT_USEC (250 * 1000) -static int msm_otg_reset(struct otg_transceiver *otg) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - struct msm_otg_platform_data *pdata = motg->pdata; - int cnt = 0; - int ret; - u32 val = 0; - u32 ulpi_val = 0; - - ret = msm_otg_phy_reset(motg); - if (ret) { - dev_err(otg->dev, "phy_reset failed\n"); - return ret; - } - - ulpi_init(motg); - - writel(USBCMD_RESET, USB_USBCMD); - while (cnt < LINK_RESET_TIMEOUT_USEC) { - if (!(readl(USB_USBCMD) & USBCMD_RESET)) - break; - udelay(1); - cnt++; - } - if (cnt >= LINK_RESET_TIMEOUT_USEC) - return -ETIMEDOUT; - - /* select ULPI phy */ - writel(0x80000000, USB_PORTSC); - - msleep(100); - - writel(0x0, USB_AHBBURST); - writel(0x00, USB_AHBMODE); - - if (pdata->otg_control == OTG_PHY_CONTROL) { - val = readl(USB_OTGSC); - if (pdata->mode == USB_OTG) { - ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; - val |= OTGSC_IDIE | OTGSC_BSVIE; - } else if (pdata->mode == USB_PERIPHERAL) { - ulpi_val = ULPI_INT_SESS_VALID; - val |= OTGSC_BSVIE; - } - writel(val, USB_OTGSC); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); - } - - return 0; -} - -#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) -static int msm_otg_suspend(struct msm_otg *motg) -{ - struct otg_transceiver *otg = &motg->otg; - struct usb_bus *bus = otg->host; - struct msm_otg_platform_data *pdata = motg->pdata; - int cnt = 0; - - if (atomic_read(&motg->in_lpm)) - return 0; - - disable_irq(motg->irq); - /* - * Interrupt Latch Register auto-clear feature is not present - * in all PHY versions. Latch register is clear on read type. - * Clear latch register to avoid spurious wakeup from - * low power mode (LPM). - */ - ulpi_read(otg, 0x14); - - /* - * PHY comparators are disabled when PHY enters into low power - * mode (LPM). Keep PHY comparators ON in LPM only when we expect - * VBUS/Id notifications from USB PHY. Otherwise turn off USB - * PHY comparators. This save significant amount of power. - */ - if (pdata->otg_control == OTG_PHY_CONTROL) - ulpi_write(otg, 0x01, 0x30); - - /* - * PLL is not turned off when PHY enters into low power mode (LPM). - * Disable PLL for maximum power savings. - */ - ulpi_write(otg, 0x08, 0x09); - - /* - * PHY may take some time or even fail to enter into low power - * mode (LPM). Hence poll for 500 msec and reset the PHY and link - * in failure case. - */ - writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); - while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { - if (readl(USB_PORTSC) & PORTSC_PHCD) - break; - udelay(1); - cnt++; - } - - if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { - dev_err(otg->dev, "Unable to suspend PHY\n"); - msm_otg_reset(otg); - enable_irq(motg->irq); - return -ETIMEDOUT; - } - - /* - * PHY has capability to generate interrupt asynchronously in low - * power mode (LPM). This interrupt is level triggered. So USB IRQ - * line must be disabled till async interrupt enable bit is cleared - * in USBCMD register. Assert STP (ULPI interface STOP signal) to - * block data communication from PHY. - */ - writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); - - clk_disable(motg->pclk); - clk_disable(motg->clk); - if (motg->core_clk) - clk_disable(motg->core_clk); - - if (device_may_wakeup(otg->dev)) - enable_irq_wake(motg->irq); - if (bus) - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); - - atomic_set(&motg->in_lpm, 1); - enable_irq(motg->irq); - - dev_info(otg->dev, "USB in low power mode\n"); - - return 0; -} - -#define PHY_RESUME_TIMEOUT_USEC (100 * 1000) -static int msm_otg_resume(struct msm_otg *motg) -{ - struct otg_transceiver *otg = &motg->otg; - struct usb_bus *bus = otg->host; - int cnt = 0; - unsigned temp; - - if (!atomic_read(&motg->in_lpm)) - return 0; - - clk_enable(motg->pclk); - clk_enable(motg->clk); - if (motg->core_clk) - clk_enable(motg->core_clk); - - temp = readl(USB_USBCMD); - temp &= ~ASYNC_INTR_CTRL; - temp &= ~ULPI_STP_CTRL; - writel(temp, USB_USBCMD); - - /* - * PHY comes out of low power mode (LPM) in case of wakeup - * from asynchronous interrupt. - */ - if (!(readl(USB_PORTSC) & PORTSC_PHCD)) - goto skip_phy_resume; - - writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC); - while (cnt < PHY_RESUME_TIMEOUT_USEC) { - if (!(readl(USB_PORTSC) & PORTSC_PHCD)) - break; - udelay(1); - cnt++; - } - - if (cnt >= PHY_RESUME_TIMEOUT_USEC) { - /* - * This is a fatal error. Reset the link and - * PHY. USB state can not be restored. Re-insertion - * of USB cable is the only way to get USB working. - */ - dev_err(otg->dev, "Unable to resume USB." - "Re-plugin the cable\n"); - msm_otg_reset(otg); - } - -skip_phy_resume: - if (device_may_wakeup(otg->dev)) - disable_irq_wake(motg->irq); - if (bus) - set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); - - if (motg->async_int) { - motg->async_int = 0; - pm_runtime_put(otg->dev); - enable_irq(motg->irq); - } - - atomic_set(&motg->in_lpm, 0); - - dev_info(otg->dev, "USB exited from low power mode\n"); - - return 0; -} - -static void msm_otg_start_host(struct otg_transceiver *otg, int on) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - struct msm_otg_platform_data *pdata = motg->pdata; - struct usb_hcd *hcd; - - if (!otg->host) - return; - - hcd = bus_to_hcd(otg->host); - - if (on) { - dev_dbg(otg->dev, "host on\n"); - - if (pdata->vbus_power) - pdata->vbus_power(1); - /* - * Some boards have a switch cotrolled by gpio - * to enable/disable internal HUB. Enable internal - * HUB before kicking the host. - */ - if (pdata->setup_gpio) - pdata->setup_gpio(OTG_STATE_A_HOST); -#ifdef CONFIG_USB - usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); -#endif - } else { - dev_dbg(otg->dev, "host off\n"); - -#ifdef CONFIG_USB - usb_remove_hcd(hcd); -#endif - if (pdata->setup_gpio) - pdata->setup_gpio(OTG_STATE_UNDEFINED); - if (pdata->vbus_power) - pdata->vbus_power(0); - } -} - -static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - struct usb_hcd *hcd; - - /* - * Fail host registration if this board can support - * only peripheral configuration. - */ - if (motg->pdata->mode == USB_PERIPHERAL) { - dev_info(otg->dev, "Host mode is not supported\n"); - return -ENODEV; - } - - if (!host) { - if (otg->state == OTG_STATE_A_HOST) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_host(otg, 0); - otg->host = NULL; - otg->state = OTG_STATE_UNDEFINED; - schedule_work(&motg->sm_work); - } else { - otg->host = NULL; - } - - return 0; - } - - hcd = bus_to_hcd(host); - hcd->power_budget = motg->pdata->power_budget; - - otg->host = host; - dev_dbg(otg->dev, "host driver registered w/ tranceiver\n"); - - /* - * Kick the state machine work, if peripheral is not supported - * or peripheral is already registered with us. - */ - if (motg->pdata->mode == USB_HOST || otg->gadget) { - pm_runtime_get_sync(otg->dev); - schedule_work(&motg->sm_work); - } - - return 0; -} - -static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - struct msm_otg_platform_data *pdata = motg->pdata; - - if (!otg->gadget) - return; - - if (on) { - dev_dbg(otg->dev, "gadget on\n"); - /* - * Some boards have a switch cotrolled by gpio - * to enable/disable internal HUB. Disable internal - * HUB before kicking the gadget. - */ - if (pdata->setup_gpio) - pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); - usb_gadget_vbus_connect(otg->gadget); - } else { - dev_dbg(otg->dev, "gadget off\n"); - usb_gadget_vbus_disconnect(otg->gadget); - if (pdata->setup_gpio) - pdata->setup_gpio(OTG_STATE_UNDEFINED); - } - -} - -static int msm_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) -{ - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); - - /* - * Fail peripheral registration if this board can support - * only host configuration. - */ - if (motg->pdata->mode == USB_HOST) { - dev_info(otg->dev, "Peripheral mode is not supported\n"); - return -ENODEV; - } - - if (!gadget) { - if (otg->state == OTG_STATE_B_PERIPHERAL) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_peripheral(otg, 0); - otg->gadget = NULL; - otg->state = OTG_STATE_UNDEFINED; - schedule_work(&motg->sm_work); - } else { - otg->gadget = NULL; - } - - return 0; - } - otg->gadget = gadget; - dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n"); - - /* - * Kick the state machine work, if host is not supported - * or host is already registered with us. - */ - if (motg->pdata->mode == USB_PERIPHERAL || otg->host) { - pm_runtime_get_sync(otg->dev); - schedule_work(&motg->sm_work); - } - - return 0; -} - -/* - * We support OTG, Peripheral only and Host only configurations. In case - * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen - * via Id pin status or user request (debugfs). Id/BSV interrupts are not - * enabled when switch is controlled by user and default mode is supplied - * by board file, which can be changed by userspace later. - */ -static void msm_otg_init_sm(struct msm_otg *motg) -{ - struct msm_otg_platform_data *pdata = motg->pdata; - u32 otgsc = readl(USB_OTGSC); - - switch (pdata->mode) { - case USB_OTG: - if (pdata->otg_control == OTG_PHY_CONTROL) { - if (otgsc & OTGSC_ID) - set_bit(ID, &motg->inputs); - else - clear_bit(ID, &motg->inputs); - - if (otgsc & OTGSC_BSV) - set_bit(B_SESS_VLD, &motg->inputs); - else - clear_bit(B_SESS_VLD, &motg->inputs); - } else if (pdata->otg_control == OTG_USER_CONTROL) { - if (pdata->default_mode == USB_HOST) { - clear_bit(ID, &motg->inputs); - } else if (pdata->default_mode == USB_PERIPHERAL) { - set_bit(ID, &motg->inputs); - set_bit(B_SESS_VLD, &motg->inputs); - } else { - set_bit(ID, &motg->inputs); - clear_bit(B_SESS_VLD, &motg->inputs); - } - } - break; - case USB_HOST: - clear_bit(ID, &motg->inputs); - break; - case USB_PERIPHERAL: - set_bit(ID, &motg->inputs); - if (otgsc & OTGSC_BSV) - set_bit(B_SESS_VLD, &motg->inputs); - else - clear_bit(B_SESS_VLD, &motg->inputs); - break; - default: - break; - } -} - -static void msm_otg_sm_work(struct work_struct *w) -{ - struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); - struct otg_transceiver *otg = &motg->otg; - - switch (otg->state) { - case OTG_STATE_UNDEFINED: - dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n"); - msm_otg_reset(otg); - msm_otg_init_sm(motg); - otg->state = OTG_STATE_B_IDLE; - /* FALL THROUGH */ - case OTG_STATE_B_IDLE: - dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n"); - if (!test_bit(ID, &motg->inputs) && otg->host) { - /* disable BSV bit */ - writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); - msm_otg_start_host(otg, 1); - otg->state = OTG_STATE_A_HOST; - } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) { - msm_otg_start_peripheral(otg, 1); - otg->state = OTG_STATE_B_PERIPHERAL; - } - pm_runtime_put_sync(otg->dev); - break; - case OTG_STATE_B_PERIPHERAL: - dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); - if (!test_bit(B_SESS_VLD, &motg->inputs) || - !test_bit(ID, &motg->inputs)) { - msm_otg_start_peripheral(otg, 0); - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); - schedule_work(w); - } - break; - case OTG_STATE_A_HOST: - dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n"); - if (test_bit(ID, &motg->inputs)) { - msm_otg_start_host(otg, 0); - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); - schedule_work(w); - } - break; - default: - break; - } -} - -static irqreturn_t msm_otg_irq(int irq, void *data) -{ - struct msm_otg *motg = data; - struct otg_transceiver *otg = &motg->otg; - u32 otgsc = 0; - - if (atomic_read(&motg->in_lpm)) { - disable_irq_nosync(irq); - motg->async_int = 1; - pm_runtime_get(otg->dev); - return IRQ_HANDLED; - } - - otgsc = readl(USB_OTGSC); - if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS))) - return IRQ_NONE; - - if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) { - if (otgsc & OTGSC_ID) - set_bit(ID, &motg->inputs); - else - clear_bit(ID, &motg->inputs); - dev_dbg(otg->dev, "ID set/clear\n"); - pm_runtime_get_noresume(otg->dev); - } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { - if (otgsc & OTGSC_BSV) - set_bit(B_SESS_VLD, &motg->inputs); - else - clear_bit(B_SESS_VLD, &motg->inputs); - dev_dbg(otg->dev, "BSV set/clear\n"); - pm_runtime_get_noresume(otg->dev); - } - - writel(otgsc, USB_OTGSC); - schedule_work(&motg->sm_work); - return IRQ_HANDLED; -} - -static int msm_otg_mode_show(struct seq_file *s, void *unused) -{ - struct msm_otg *motg = s->private; - struct otg_transceiver *otg = &motg->otg; - - switch (otg->state) { - case OTG_STATE_A_HOST: - seq_printf(s, "host\n"); - break; - case OTG_STATE_B_PERIPHERAL: - seq_printf(s, "peripheral\n"); - break; - default: - seq_printf(s, "none\n"); - break; - } - - return 0; -} - -static int msm_otg_mode_open(struct inode *inode, struct file *file) -{ - return single_open(file, msm_otg_mode_show, inode->i_private); -} - -static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct msm_otg *motg = file->private_data; - char buf[16]; - struct otg_transceiver *otg = &motg->otg; - int status = count; - enum usb_mode_type req_mode; - - memset(buf, 0x00, sizeof(buf)); - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) { - status = -EFAULT; - goto out; - } - - if (!strncmp(buf, "host", 4)) { - req_mode = USB_HOST; - } else if (!strncmp(buf, "peripheral", 10)) { - req_mode = USB_PERIPHERAL; - } else if (!strncmp(buf, "none", 4)) { - req_mode = USB_NONE; - } else { - status = -EINVAL; - goto out; - } - - switch (req_mode) { - case USB_NONE: - switch (otg->state) { - case OTG_STATE_A_HOST: - case OTG_STATE_B_PERIPHERAL: - set_bit(ID, &motg->inputs); - clear_bit(B_SESS_VLD, &motg->inputs); - break; - default: - goto out; - } - break; - case USB_PERIPHERAL: - switch (otg->state) { - case OTG_STATE_B_IDLE: - case OTG_STATE_A_HOST: - set_bit(ID, &motg->inputs); - set_bit(B_SESS_VLD, &motg->inputs); - break; - default: - goto out; - } - break; - case USB_HOST: - switch (otg->state) { - case OTG_STATE_B_IDLE: - case OTG_STATE_B_PERIPHERAL: - clear_bit(ID, &motg->inputs); - break; - default: - goto out; - } - break; - default: - goto out; - } - - pm_runtime_get_sync(otg->dev); - schedule_work(&motg->sm_work); -out: - return status; -} - -const struct file_operations msm_otg_mode_fops = { - .open = msm_otg_mode_open, - .read = seq_read, - .write = msm_otg_mode_write, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct dentry *msm_otg_dbg_root; -static struct dentry *msm_otg_dbg_mode; - -static int msm_otg_debugfs_init(struct msm_otg *motg) -{ - msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL); - - if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root)) - return -ENODEV; - - msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR, - msm_otg_dbg_root, motg, &msm_otg_mode_fops); - if (!msm_otg_dbg_mode) { - debugfs_remove(msm_otg_dbg_root); - msm_otg_dbg_root = NULL; - return -ENODEV; - } - - return 0; -} - -static void msm_otg_debugfs_cleanup(void) -{ - debugfs_remove(msm_otg_dbg_mode); - debugfs_remove(msm_otg_dbg_root); -} - -static int __init msm_otg_probe(struct platform_device *pdev) -{ - int ret = 0; - struct resource *res; - struct msm_otg *motg; - struct otg_transceiver *otg; - - dev_info(&pdev->dev, "msm_otg probe\n"); - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "No platform data given. Bailing out\n"); - return -ENODEV; - } - - motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL); - if (!motg) { - dev_err(&pdev->dev, "unable to allocate msm_otg\n"); - return -ENOMEM; - } - - motg->pdata = pdev->dev.platform_data; - otg = &motg->otg; - otg->dev = &pdev->dev; - - motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); - if (IS_ERR(motg->phy_reset_clk)) { - dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); - ret = PTR_ERR(motg->phy_reset_clk); - goto free_motg; - } - - motg->clk = clk_get(&pdev->dev, "usb_hs_clk"); - if (IS_ERR(motg->clk)) { - dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); - ret = PTR_ERR(motg->clk); - goto put_phy_reset_clk; - } - - motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); - if (IS_ERR(motg->pclk)) { - dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); - ret = PTR_ERR(motg->pclk); - goto put_clk; - } - - /* - * USB core clock is not present on all MSM chips. This - * clock is introduced to remove the dependency on AXI - * bus frequency. - */ - motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk"); - if (IS_ERR(motg->core_clk)) - motg->core_clk = NULL; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get platform resource mem\n"); - ret = -ENODEV; - goto put_core_clk; - } - - motg->regs = ioremap(res->start, resource_size(res)); - if (!motg->regs) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto put_core_clk; - } - dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); - - motg->irq = platform_get_irq(pdev, 0); - if (!motg->irq) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - ret = -ENODEV; - goto free_regs; - } - - clk_enable(motg->clk); - clk_enable(motg->pclk); - if (motg->core_clk) - clk_enable(motg->core_clk); - - writel(0, USB_USBINTR); - writel(0, USB_OTGSC); - - INIT_WORK(&motg->sm_work, msm_otg_sm_work); - ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, - "msm_otg", motg); - if (ret) { - dev_err(&pdev->dev, "request irq failed\n"); - goto disable_clks; - } - - otg->init = msm_otg_reset; - otg->set_host = msm_otg_set_host; - otg->set_peripheral = msm_otg_set_peripheral; - - otg->io_ops = &msm_otg_io_ops; - - ret = otg_set_transceiver(&motg->otg); - if (ret) { - dev_err(&pdev->dev, "otg_set_transceiver failed\n"); - goto free_irq; - } - - platform_set_drvdata(pdev, motg); - device_init_wakeup(&pdev->dev, 1); - - if (motg->pdata->mode == USB_OTG && - motg->pdata->otg_control == OTG_USER_CONTROL) { - ret = msm_otg_debugfs_init(motg); - if (ret) - dev_dbg(&pdev->dev, "mode debugfs file is" - "not available\n"); - } - - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - - return 0; -free_irq: - free_irq(motg->irq, motg); -disable_clks: - clk_disable(motg->pclk); - clk_disable(motg->clk); -free_regs: - iounmap(motg->regs); -put_core_clk: - if (motg->core_clk) - clk_put(motg->core_clk); - clk_put(motg->pclk); -put_clk: - clk_put(motg->clk); -put_phy_reset_clk: - clk_put(motg->phy_reset_clk); -free_motg: - kfree(motg); - return ret; -} - -static int __devexit msm_otg_remove(struct platform_device *pdev) -{ - struct msm_otg *motg = platform_get_drvdata(pdev); - struct otg_transceiver *otg = &motg->otg; - int cnt = 0; - - if (otg->host || otg->gadget) - return -EBUSY; - - msm_otg_debugfs_cleanup(); - cancel_work_sync(&motg->sm_work); - - msm_otg_resume(motg); - - device_init_wakeup(&pdev->dev, 0); - pm_runtime_disable(&pdev->dev); - - otg_set_transceiver(NULL); - free_irq(motg->irq, motg); - - /* - * Put PHY in low power mode. - */ - ulpi_read(otg, 0x14); - ulpi_write(otg, 0x08, 0x09); - - writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); - while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { - if (readl(USB_PORTSC) & PORTSC_PHCD) - break; - udelay(1); - cnt++; - } - if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) - dev_err(otg->dev, "Unable to suspend PHY\n"); - - clk_disable(motg->pclk); - clk_disable(motg->clk); - if (motg->core_clk) - clk_disable(motg->core_clk); - - iounmap(motg->regs); - pm_runtime_set_suspended(&pdev->dev); - - clk_put(motg->phy_reset_clk); - clk_put(motg->pclk); - clk_put(motg->clk); - if (motg->core_clk) - clk_put(motg->core_clk); - - kfree(motg); - - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int msm_otg_runtime_idle(struct device *dev) -{ - struct msm_otg *motg = dev_get_drvdata(dev); - struct otg_transceiver *otg = &motg->otg; - - dev_dbg(dev, "OTG runtime idle\n"); - - /* - * It is observed some times that a spurious interrupt - * comes when PHY is put into LPM immediately after PHY reset. - * This 1 sec delay also prevents entering into LPM immediately - * after asynchronous interrupt. - */ - if (otg->state != OTG_STATE_UNDEFINED) - pm_schedule_suspend(dev, 1000); - - return -EAGAIN; -} - -static int msm_otg_runtime_suspend(struct device *dev) -{ - struct msm_otg *motg = dev_get_drvdata(dev); - - dev_dbg(dev, "OTG runtime suspend\n"); - return msm_otg_suspend(motg); -} - -static int msm_otg_runtime_resume(struct device *dev) -{ - struct msm_otg *motg = dev_get_drvdata(dev); - - dev_dbg(dev, "OTG runtime resume\n"); - return msm_otg_resume(motg); -} -#else -#define msm_otg_runtime_idle NULL -#define msm_otg_runtime_suspend NULL -#define msm_otg_runtime_resume NULL -#endif - -#ifdef CONFIG_PM -static int msm_otg_pm_suspend(struct device *dev) -{ - struct msm_otg *motg = dev_get_drvdata(dev); - - dev_dbg(dev, "OTG PM suspend\n"); - return msm_otg_suspend(motg); -} - -static int msm_otg_pm_resume(struct device *dev) -{ - struct msm_otg *motg = dev_get_drvdata(dev); - int ret; - - dev_dbg(dev, "OTG PM resume\n"); - - ret = msm_otg_resume(motg); - if (ret) - return ret; - - /* - * Runtime PM Documentation recommends bringing the - * device to full powered state upon resume. - */ - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - return 0; -} -#else -#define msm_otg_pm_suspend NULL -#define msm_otg_pm_resume NULL -#endif - -static const struct dev_pm_ops msm_otg_dev_pm_ops = { - .runtime_suspend = msm_otg_runtime_suspend, - .runtime_resume = msm_otg_runtime_resume, - .runtime_idle = msm_otg_runtime_idle, - .suspend = msm_otg_pm_suspend, - .resume = msm_otg_pm_resume, -}; - -static struct platform_driver msm_otg_driver = { - .remove = __devexit_p(msm_otg_remove), - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .pm = &msm_otg_dev_pm_ops, - }, -}; - -static int __init msm_otg_init(void) -{ - return platform_driver_probe(&msm_otg_driver, msm_otg_probe); -} - -static void __exit msm_otg_exit(void) -{ - platform_driver_unregister(&msm_otg_driver); -} - -module_init(msm_otg_init); -module_exit(msm_otg_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MSM USB transceiver driver"); diff --git a/trunk/drivers/usb/serial/usb_wwan.c b/trunk/drivers/usb/serial/usb_wwan.c index b004b2a485c3..660b7caef784 100644 --- a/trunk/drivers/usb/serial/usb_wwan.c +++ b/trunk/drivers/usb/serial/usb_wwan.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/include/linux/usb/msm_hsusb.h b/trunk/include/linux/usb/msm_hsusb.h deleted file mode 100644 index 3675e03b1539..000000000000 --- a/trunk/include/linux/usb/msm_hsusb.h +++ /dev/null @@ -1,112 +0,0 @@ -/* linux/include/asm-arm/arch-msm/hsusb.h - * - * Copyright (C) 2008 Google, Inc. - * Author: Brian Swetland - * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __ASM_ARCH_MSM_HSUSB_H -#define __ASM_ARCH_MSM_HSUSB_H - -#include -#include - -/** - * Supported USB modes - * - * USB_PERIPHERAL Only peripheral mode is supported. - * USB_HOST Only host mode is supported. - * USB_OTG OTG mode is supported. - * - */ -enum usb_mode_type { - USB_NONE = 0, - USB_PERIPHERAL, - USB_HOST, - USB_OTG, -}; - -/** - * OTG control - * - * OTG_NO_CONTROL Id/VBUS notifications not required. Useful in host - * only configuration. - * OTG_PHY_CONTROL Id/VBUS notifications comes form USB PHY. - * OTG_PMIC_CONTROL Id/VBUS notifications comes from PMIC hardware. - * OTG_USER_CONTROL Id/VBUS notifcations comes from User via sysfs. - * - */ -enum otg_control_type { - OTG_NO_CONTROL = 0, - OTG_PHY_CONTROL, - OTG_PMIC_CONTROL, - OTG_USER_CONTROL, -}; - -/** - * struct msm_otg_platform_data - platform device data - * for msm72k_otg driver. - * @phy_init_seq: PHY configuration sequence. val, reg pairs - * terminated by -1. - * @vbus_power: VBUS power on/off routine. - * @power_budget: VBUS power budget in mA (0 will be treated as 500mA). - * @mode: Supported mode (OTG/peripheral/host). - * @otg_control: OTG switch controlled by user/Id pin - * @default_mode: Default operational mode. Applicable only if - * OTG switch is controller by user. - * - */ -struct msm_otg_platform_data { - int *phy_init_seq; - void (*vbus_power)(bool on); - unsigned power_budget; - enum usb_mode_type mode; - enum otg_control_type otg_control; - enum usb_mode_type default_mode; - void (*setup_gpio)(enum usb_otg_state state); -}; - -/** - * struct msm_otg: OTG driver data. Shared by HCD and DCD. - * @otg: USB OTG Transceiver structure. - * @pdata: otg device platform data. - * @irq: IRQ number assigned for HSUSB controller. - * @clk: clock struct of usb_hs_clk. - * @pclk: clock struct of usb_hs_pclk. - * @phy_reset_clk: clock struct of usb_phy_clk. - * @core_clk: clock struct of usb_hs_core_clk. - * @regs: ioremapped register base address. - * @inputs: OTG state machine inputs(Id, SessValid etc). - * @sm_work: OTG state machine work. - * @in_lpm: indicates low power mode (LPM) state. - * @async_int: Async interrupt arrived. - * - */ -struct msm_otg { - struct otg_transceiver otg; - struct msm_otg_platform_data *pdata; - int irq; - struct clk *clk; - struct clk *pclk; - struct clk *phy_reset_clk; - struct clk *core_clk; - void __iomem *regs; -#define ID 0 -#define B_SESS_VLD 1 - unsigned long inputs; - struct work_struct sm_work; - atomic_t in_lpm; - int async_int; -}; - -#endif diff --git a/trunk/include/linux/usb/msm_hsusb_hw.h b/trunk/include/linux/usb/msm_hsusb_hw.h deleted file mode 100644 index b92e17349c7b..000000000000 --- a/trunk/include/linux/usb/msm_hsusb_hw.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007 Google, Inc. - * Author: Brian Swetland - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __LINUX_USB_GADGET_MSM72K_UDC_H__ -#define __LINUX_USB_GADGET_MSM72K_UDC_H__ - -#ifdef CONFIG_ARCH_MSM7X00A -#define USB_SBUSCFG (MSM_USB_BASE + 0x0090) -#else -#define USB_AHBBURST (MSM_USB_BASE + 0x0090) -#define USB_AHBMODE (MSM_USB_BASE + 0x0098) -#endif -#define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */ - -#define USB_USBCMD (MSM_USB_BASE + 0x0140) -#define USB_PORTSC (MSM_USB_BASE + 0x0184) -#define USB_OTGSC (MSM_USB_BASE + 0x01A4) -#define USB_USBMODE (MSM_USB_BASE + 0x01A8) - -#define USBCMD_RESET 2 -#define USB_USBINTR (MSM_USB_BASE + 0x0148) - -#define PORTSC_PHCD (1 << 23) /* phy suspend mode */ -#define PORTSC_PTS_MASK (3 << 30) -#define PORTSC_PTS_ULPI (3 << 30) - -#define USB_ULPI_VIEWPORT (MSM_USB_BASE + 0x0170) -#define ULPI_RUN (1 << 30) -#define ULPI_WRITE (1 << 29) -#define ULPI_READ (0 << 29) -#define ULPI_ADDR(n) (((n) & 255) << 16) -#define ULPI_DATA(n) ((n) & 255) -#define ULPI_DATA_READ(n) (((n) >> 8) & 255) - -#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */ -#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ - -/* OTG definitions */ -#define OTGSC_INTSTS_MASK (0x7f << 16) -#define OTGSC_ID (1 << 8) -#define OTGSC_BSV (1 << 11) -#define OTGSC_IDIS (1 << 16) -#define OTGSC_BSVIS (1 << 19) -#define OTGSC_IDIE (1 << 24) -#define OTGSC_BSVIE (1 << 27) - -#endif /* __LINUX_USB_GADGET_MSM72K_UDC_H__ */ diff --git a/trunk/include/linux/usb/otg.h b/trunk/include/linux/usb/otg.h index a1a1e7a73ec9..0a5b3711e502 100644 --- a/trunk/include/linux/usb/otg.h +++ b/trunk/include/linux/usb/otg.h @@ -116,7 +116,7 @@ struct otg_transceiver { /* for board-specific init logic */ extern int otg_set_transceiver(struct otg_transceiver *); -#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) +#if defined(CONFIG_NOP_USB_XCEIV) || defined(CONFIG_NOP_USB_XCEIV_MODULE) /* sometimes transceivers are accessed only through e.g. ULPI */ extern void usb_nop_xceiv_register(void); extern void usb_nop_xceiv_unregister(void);